mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 05:00:55 +01:00
Adds an alternate greentext objective for Wizards known as the "Grand Ritual". This was initially the gimmick of a different wizard-related antagonist downstream. I didn't get permission to port it, so I'm attaching it to regular Wizards instead. Wizards will spawn in with a new Grand Ritual button next to their antagonist info button. Pressing it will pinpoint them towards their next Ritual Location (a randomly chosen region of the space station). Once within that location, pressing it will summon a magic circle and obliterate any dense objects which are in the way. This also puts the ability on a two minute cooldown. Clicking on the magic circle with an empty hand will begin a three-stage invocation to gather magical power. You can interrupt this invocation at any time and will resume from the last stage you completed (if you finished two stages you only need to do one more). Once you complete a ritual, a random event will be triggered based on how many rituals you have performed so far. These tend to be ones which annoy the crew in some manner, and Wizard Events are included in the list. Additionally, something weird will usually happen to the room you are in. Then you are assigned a new location and can toddle off to do it again. Once you have done this three times, you will be picked up by the station's sensors every time you start a subsequent ritual and should expect annoyed company to come investigate. Once you have done this six times, you can finally spend all of that accumulated power on the seventh Grand Finale ritual. Completing this grants you victory at the end of the round and will have a larger, flashier effect which you can pick from a list of options, think of it like a wizard equivalent of a Traitor Final Objective or Heretic Ascension. After that you can still keep doing rituals if you want to pester the crew further by summoning more random events, you've already "won" at this point so now it's your job to make them want to go home. I think it'd be more fun to just find out what the Finale ritual can do by seeing it happen but maintainers will probably want a list of its precise capabilities, so here it is: Currently completing a ritual also has a chance to create Heretic Reality Tears (of both varieties, available for Heretics to eat and visible to crew) as a kind of cross-antagonist interaction which seemed to make sense to me but if this seems thematically or mechanically inappropriate it's easy to strip out.
170 lines
7.4 KiB
Plaintext
170 lines
7.4 KiB
Plaintext
/datum/round_event_control/radiation_leak
|
|
name = "Radiation Leak"
|
|
description = "A radiation leak happens somewhere on the station, emanating radiation around a machine in the area. \
|
|
Engineering can stop the leak by using certain tools on it."
|
|
typepath = /datum/round_event/radiation_leak
|
|
weight = 15
|
|
max_occurrences = 3
|
|
category = EVENT_CATEGORY_ENGINEERING
|
|
min_wizard_trigger_potency = 3
|
|
max_wizard_trigger_potency = 7
|
|
|
|
/datum/round_event/radiation_leak
|
|
start_when = 1 // 2 seconds in
|
|
announce_when = 10 // 20 seconds in
|
|
end_when = 150 // 300 seconds / ~5 minutes in
|
|
|
|
/// Weakref to the machine spitting out rads
|
|
var/datum/weakref/picked_machine_ref
|
|
/// List of signals added to the picked machine, so we can clear them later
|
|
var/list/signals_to_add
|
|
|
|
/datum/round_event/radiation_leak/setup()
|
|
// Pick a generic event spawn somewhere in the world.
|
|
// We will try to find a machine within a few turfs of it to start spewing rads from.
|
|
var/list/possible_locs = GLOB.generic_event_spawns.Copy()
|
|
while(length(possible_locs))
|
|
var/turf/chosen_loc = get_turf(pick_n_take(possible_locs))
|
|
for(var/obj/machinery/sick_device in range(3, chosen_loc))
|
|
// Look for dense machinery. Basically stops stuff like wall mounts and pipes, silly ones.
|
|
// But keep in vents and scrubbers. I think it's funny if they start spitting out radiation
|
|
if(!sick_device.density && !istype(sick_device, /obj/machinery/atmospherics/components/unary))
|
|
continue
|
|
// Skip invisible stuff
|
|
if(sick_device.invisibility || !sick_device.alpha || !sick_device.mouse_opacity)
|
|
continue
|
|
// Skip undertiles
|
|
if(sick_device.IsObscured())
|
|
continue
|
|
// Very basic check for atmos passability here
|
|
// We don't want to put our smoke inside something that can't spread it out, like airlocks
|
|
if(sick_device.can_atmos_pass() != ATMOS_PASS_YES)
|
|
continue
|
|
|
|
// We found something, we can just return now
|
|
picked_machine_ref = WEAKREF(sick_device)
|
|
return
|
|
|
|
/datum/round_event/radiation_leak/announce(fake)
|
|
var/obj/machinery/the_source_of_our_problems = picked_machine_ref?.resolve()
|
|
var/area/station/location_descriptor
|
|
|
|
if(fake)
|
|
location_descriptor = GLOB.areas_by_type[pick(GLOB.the_station_areas)]
|
|
|
|
else if(the_source_of_our_problems)
|
|
location_descriptor = get_area(the_source_of_our_problems)
|
|
|
|
priority_announce("A radiation leak has been detected in [location_descriptor || "an unknown area"]. \
|
|
All crew are to evacuate the affected area. Our [pick("mechanics", "engineers", "scientists", "interns", "sensors", "readings")] \
|
|
report that a machine within is causing it - repair it quickly to stop the leak.")
|
|
|
|
/datum/round_event/radiation_leak/start()
|
|
var/obj/machinery/the_source_of_our_problems = picked_machine_ref?.resolve()
|
|
if(!the_source_of_our_problems)
|
|
return
|
|
|
|
// We'll add some tool acts to the thing that allow people to "repair the machine"
|
|
// The key of this assoc list is the "method" of how they're fixing the thing (just flavor for examine),
|
|
// and the value is what tool they actually need to use on the thing to fix it
|
|
var/list/how_do_we_fix_it = list(
|
|
"wrenching a few valves" = TOOL_WRENCH,
|
|
"tightening its bolts" = TOOL_WRENCH,
|
|
"crowbaring its panel [pick("down", "up")]" = TOOL_CROWBAR,
|
|
"tightening some screws" = TOOL_SCREWDRIVER,
|
|
"checking its [pick("wires", "circuits")]" = TOOL_MULTITOOL,
|
|
"welding its panel [pick("open", "shut")]" = TOOL_WELDER,
|
|
"analyzing its readings" = TOOL_ANALYZER,
|
|
"cutting some excess wires" = TOOL_WIRECUTTER,
|
|
)
|
|
var/list/fix_it_keys = assoc_to_keys(how_do_we_fix_it) // Returns a copy that we can pick and take from, fortunately
|
|
|
|
// Select a few methods of how to fix it
|
|
var/list/methods_to_fix = list()
|
|
for(var/i in 1 to rand(1, 3))
|
|
methods_to_fix += pick_n_take(fix_it_keys)
|
|
|
|
// Construct the signals
|
|
signals_to_add = list()
|
|
for(var/tool_method in methods_to_fix)
|
|
signals_to_add += COMSIG_ATOM_TOOL_ACT(how_do_we_fix_it[tool_method])
|
|
|
|
the_source_of_our_problems.visible_message(span_danger("[the_source_of_our_problems] starts to emanate a horrible green gas!"))
|
|
// Add the component that makes the thing radioactive
|
|
the_source_of_our_problems.AddComponent(
|
|
/datum/component/radioactive_emitter, \
|
|
cooldown_time = 2 SECONDS, \
|
|
range = 5, \
|
|
threshold = RAD_MEDIUM_INSULATION, \
|
|
examine_text = span_green("<i>It's emanating a green gas... You could probably stop it by [english_list(methods_to_fix, and_text = " or ")].</i>"), \
|
|
)
|
|
// Register signals to make it fixable
|
|
if(length(signals_to_add))
|
|
RegisterSignals(the_source_of_our_problems, signals_to_add, PROC_REF(on_machine_tooled))
|
|
|
|
// And yknow puffs some nasty reagents into the air, just to seal the deal
|
|
puff_some_smoke(the_source_of_our_problems)
|
|
// Let ghosts know
|
|
announce_to_ghosts(the_source_of_our_problems)
|
|
|
|
/datum/round_event/radiation_leak/tick()
|
|
// Puff some smoke into the air around our machine roughly 3 times before we stop
|
|
if(activeFor % (end_when / 3) != 0)
|
|
return
|
|
|
|
var/obj/machinery/impromptu_smoke_machine = picked_machine_ref?.resolve()
|
|
if(!impromptu_smoke_machine)
|
|
return
|
|
|
|
puff_some_smoke(impromptu_smoke_machine)
|
|
|
|
/datum/round_event/radiation_leak/end()
|
|
var/obj/machinery/the_end_of_our_problems = picked_machine_ref?.resolve()
|
|
if(!the_end_of_our_problems)
|
|
return
|
|
|
|
the_end_of_our_problems.visible_message(span_notice("The gas emanating from [the_end_of_our_problems] dissipates."))
|
|
qdel(the_end_of_our_problems.GetComponent(/datum/component/radioactive_emitter))
|
|
if(length(signals_to_add))
|
|
UnregisterSignal(the_end_of_our_problems, signals_to_add)
|
|
picked_machine_ref = null
|
|
signals_to_add = null
|
|
|
|
/// Helper to shoot some smoke into the air around the passed atom
|
|
/datum/round_event/radiation_leak/proc/puff_some_smoke(atom/where)
|
|
var/turf/below_where = get_turf(where)
|
|
var/datum/effect_system/fluid_spread/smoke/chem/gross_smoke = new()
|
|
gross_smoke.chemholder.add_reagent(/datum/reagent/toxin/polonium, 10) // Polonium (it causes radiation)
|
|
gross_smoke.chemholder.add_reagent(/datum/reagent/toxin/mutagen, 10) // Mutagen (it causes mutations. Also it's green... Primarily because it's green.)
|
|
gross_smoke.attach(below_where)
|
|
gross_smoke.set_up(2, holder = where, location = below_where, silent = TRUE)
|
|
gross_smoke.start()
|
|
playsound(below_where, 'sound/effects/smoke.ogg', 50, vary = TRUE)
|
|
|
|
/**
|
|
* Signal proc for [COMSIG_ATOM_TOOL_ACT], from a variety of signals, registered on the machine spitting radiation
|
|
*
|
|
* We allow for someone to stop the event early by using the proper tools, hinted at in examine, on the machine
|
|
*/
|
|
/datum/round_event/radiation_leak/proc/on_machine_tooled(obj/machinery/source, mob/living/user, obj/item/tool)
|
|
SIGNAL_HANDLER
|
|
|
|
INVOKE_ASYNC(src, PROC_REF(try_remove_radiation), source, user, tool)
|
|
return COMPONENT_BLOCK_TOOL_ATTACK
|
|
|
|
/// Attempts a do_after, and if successful, stops the event
|
|
/datum/round_event/radiation_leak/proc/try_remove_radiation(obj/machinery/source, mob/living/user, obj/item/tool)
|
|
source.balloon_alert(user, "fixing leak...")
|
|
// Fairly long do after. It shouldn't be SUPER easy to just run in and stop it.
|
|
// A tider can fix it if they want to soak a bunch of rads and inhale noxious fumes,
|
|
// but only an equipped engineer should be able to handle it painlessly.
|
|
if(!tool.use_tool(source, user, 30 SECONDS, amount = (tool.tool_behaviour == TOOL_WELDER ? 2 : 0), volume = 50))
|
|
source.balloon_alert(user, "interrupted!")
|
|
return
|
|
|
|
source.balloon_alert(user, "leak repaired")
|
|
// Force end the event
|
|
processing = FALSE
|
|
end()
|
|
kill()
|