From 0b4e32ec598664fccb50e0574f737236f4cc65ab Mon Sep 17 00:00:00 2001 From: lessthanthree <83487515+lessthnthree@users.noreply.github.com> Date: Sun, 12 Feb 2023 11:37:52 -0800 Subject: [PATCH] [MANUAL MIRROR] Refactors Admin Setups on Forced Events + Refactors Vending Sentience (#19068) * Refactors Admin Setups on Forced Events + Refactors Vending Sentience + Refactors Shuttle Loans (#72998) - [x] TEST EVERYTHING tested: - Pirates - Vending Machines - Shuttle Catastrophe - Anomalies - Immovable Rod - Sandstorms - Scrubber Overflow - Stray Meteor - Madness - Department Revolt (Well obviously, it is my super robust code after all) - Shuttle Loan - Mass Hallucination - Heart Attack - False Alarm Disease Outbreak is probably fine aha... It correctly reports that there are no candidates before aborting. allow you to let the game decide where previously you had to choose! I need to refactor and datumize how admins set up special conditions on forced events, so I did! Now `/datum/event_admin_setup` handles admin settings, with a few prototypes to make it easier to give events admin options in the future. This was exhausting and what 90% of the pr is. The code was so bad I could not datumize the admin part of it so I cleaned it up, making a lot of things in the event get decided in `setup()` where they should. The code was so bad I could not datumize the admin part of it so I cleaned it up AS WELL, by datumizing the shuttle loans. Should be easier to add more types in the future, actually kinda stoked. This is preparation for a tgui change to ForceEvent.ts an admin has requested. Phew! :cl: refactor: Refactored a bunch of admin-related event code, hopefully you won't notice much admin: ... But you specifically may notice some minor differences. Raw inputs changed into tgui ones, minor soul removal, etc. /:cl: * remove override * merge conflict * dm update * merge conflict --------- Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com> --- code/__HELPERS/hallucinations.dm | 18 +- code/modules/admin/force_event.dm | 2 +- code/modules/admin/topic.dm | 25 -- .../antagonists/pirate/pirate_event.dm | 239 +--------- .../pirate/pirate_shuttle_equipment.dm | 408 ++++++++++++++++++ code/modules/events/_event.dm | 34 +- code/modules/events/_event_admin_setup.dm | 83 ++++ code/modules/events/anomaly/_anomaly.dm | 41 +- code/modules/events/brand_intelligence.dm | 109 +++-- code/modules/events/disease_outbreak.dm | 97 +++-- code/modules/events/false_alarm.dm | 39 +- code/modules/events/heart_attack.dm | 46 +- .../{ => immovable_rod}/immovable_rod.dm | 49 +-- .../immovable_rod/immovable_rod_event.dm | 47 ++ code/modules/events/mass_hallucination.dm | 109 +++-- code/modules/events/sandstorm.dm | 42 +- code/modules/events/scrubber_overflow.dm | 17 +- code/modules/events/shuttle_catastrophe.dm | 15 +- code/modules/events/shuttle_loan.dm | 345 --------------- .../events/shuttle_loan/shuttle_loan_datum.dm | 213 +++++++++ .../events/shuttle_loan/shuttle_loan_event.dm | 106 +++++ .../events/shuttle_loan/shuttle_loan_items.dm | 23 + code/modules/events/stray_meteor.dm | 33 +- .../modules/events/wizard/departmentrevolt.dm | 44 +- code/modules/events/wizard/madness.dm | 31 +- .../code/modules/events/disease_outbreak.dm | 31 -- tgstation.dme | 10 +- 27 files changed, 1255 insertions(+), 1001 deletions(-) create mode 100644 code/modules/antagonists/pirate/pirate_shuttle_equipment.dm create mode 100644 code/modules/events/_event_admin_setup.dm rename code/modules/events/{ => immovable_rod}/immovable_rod.dm (82%) create mode 100644 code/modules/events/immovable_rod/immovable_rod_event.dm delete mode 100644 code/modules/events/shuttle_loan.dm create mode 100644 code/modules/events/shuttle_loan/shuttle_loan_datum.dm create mode 100644 code/modules/events/shuttle_loan/shuttle_loan_event.dm create mode 100644 code/modules/events/shuttle_loan/shuttle_loan_items.dm delete mode 100644 modular_skyrat/master_files/code/modules/events/disease_outbreak.dm diff --git a/code/__HELPERS/hallucinations.dm b/code/__HELPERS/hallucinations.dm index 412a35935ce..809ff475fc9 100644 --- a/code/__HELPERS/hallucinations.dm +++ b/code/__HELPERS/hallucinations.dm @@ -1,6 +1,14 @@ /// A global list of all ongoing hallucinations, primarily for easy access to be able to stop (delete) hallucinations. GLOBAL_LIST_EMPTY(all_ongoing_hallucinations) +/// What typepath of the hallucination +#define HALLUCINATION_ARG_TYPE 1 +/// Where the hallucination came from, for logging +#define HALLUCINATION_ARG_SOURCE 2 + +/// Onwards from this index, it's the arglist that gets passed into the hallucination created. +#define HALLUCINATION_ARGLIST 3 + /// Biotypes which cannot hallucinate for balance and logic reasons (not code) #define NO_HALLUCINATION_BIOTYPES (MOB_ROBOTIC|MOB_SPIRIT|MOB_EPIC) @@ -20,16 +28,16 @@ GLOBAL_LIST_EMPTY(all_ongoing_hallucinations) if(!length(raw_args)) CRASH("cause_hallucination called with no arguments.") - var/datum/hallucination/hallucination_type = raw_args[1] // first arg is the type always + var/datum/hallucination/hallucination_type = raw_args[HALLUCINATION_ARG_TYPE] // first arg is the type always if(!ispath(hallucination_type)) CRASH("cause_hallucination was given a non-hallucination type.") - var/hallucination_source = raw_args[2] // and second arg, the source + var/hallucination_source = raw_args[HALLUCINATION_ARG_SOURCE] // and second arg, the source var/datum/hallucination/new_hallucination - if(length(raw_args) > 2) - var/list/passed_args = raw_args.Copy(3) - passed_args.Insert(1, src) + if(length(raw_args) >= HALLUCINATION_ARGLIST) + var/list/passed_args = raw_args.Copy(HALLUCINATION_ARGLIST) + passed_args.Insert(HALLUCINATION_ARG_TYPE, src) new_hallucination = new hallucination_type(arglist(passed_args)) else diff --git a/code/modules/admin/force_event.dm b/code/modules/admin/force_event.dm index 4e4338d019c..d0d332b7d6c 100644 --- a/code/modules/admin/force_event.dm +++ b/code/modules/admin/force_event.dm @@ -88,7 +88,7 @@ var/datum/round_event_control/event = locate(event_to_run_type) in SSevents.control if(!event) return - if(event.admin_setup(usr) == ADMIN_CANCEL_EVENT) + if(event.admin_setup && event.admin_setup.prompt_admins() == ADMIN_CANCEL_EVENT) return var/always_announce_chance = 100 var/no_announce_chance = 0 diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm index c5a77df1b46..6c8fcbba9ca 100644 --- a/code/modules/admin/topic.dm +++ b/code/modules/admin/topic.dm @@ -83,31 +83,6 @@ else message_admins("[key_name_admin(usr)] FAILED to create '[href_list["makeAntag"]]' with a parameter of '[opt]'.") // SKYRAT EDIT END -- ONE CLICK ANTAG - else if(href_list["forceevent"]) - if(!check_rights(R_FUN)) - return - var/datum/round_event_control/E = locate(href_list["forceevent"]) in SSevents.control - if(E) - E.admin_setup(usr) - var/datum/round_event/event = E.runEvent() - if(event.cancel_event) - return - if(event.announce_when>0) - event.processing = FALSE - var/prompt = tgui_alert(usr, "Would you like to alert the crew?", "Alert", list("Yes", "No", "Cancel")) - switch(prompt) - if("Yes") - event.announce_chance = 100 - if("Cancel") - event.kill() - return - if("No") - event.announce_chance = 0 - event.processing = TRUE - message_admins("[key_name_admin(usr)] has triggered an event. ([E.name])") - log_admin("[key_name(usr)] has triggered an event. ([E.name])") - return - else if(href_list["editrightsbrowser"]) edit_admin_permissions(0) diff --git a/code/modules/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index 9bc7f6bbdb4..78b5ff6d61e 100644 --- a/code/modules/antagonists/pirate/pirate_event.dm +++ b/code/modules/antagonists/pirate/pirate_event.dm @@ -7,30 +7,19 @@ dynamic_should_hijack = TRUE category = EVENT_CATEGORY_INVASION description = "The crew will either pay up, or face a pirate assault." - ///admin chosen pirate team - var/datum/pirate_gang/chosen_gang - -/datum/round_event_control/pirates/admin_setup(mob/admin) - var/list/gang_choices = list("Random") - - for(var/datum/pirate_gang/possible_gang as anything in GLOB.pirate_gangs) - gang_choices[possible_gang.name] = possible_gang - - var/chosen = tgui_input_list(usr, "Select pirate gang", "TICKETS TO THE SPONGEBOB MOVIE!!", gang_choices) - if(!chosen) - return ADMIN_CANCEL_EVENT - if(chosen == "Random") - return //still do the event, but chosen_gang is still null, so it will pick from the choices - chosen_gang = gang_choices[chosen] + admin_setup = /datum/event_admin_setup/pirates /datum/round_event_control/pirates/preRunEvent() if (!SSmapping.empty_space) return EVENT_CANT_RUN return ..() +/datum/round_event/pirates + ///admin chosen pirate team + var/datum/pirate_gang/chosen_gang + /datum/round_event/pirates/start() - var/datum/round_event_control/pirates/pirate_control = control - send_pirate_threat(pirate_control.chosen_gang) + send_pirate_threat(chosen_gang) /proc/send_pirate_threat(datum/pirate_gang/chosen_gang) if(!chosen_gang) @@ -91,43 +80,25 @@ priority_announce("Unidentified armed ship detected near the station.") -//Shuttle equipment +/datum/event_admin_setup/pirates + ///admin chosen pirate team + var/datum/pirate_gang/chosen_gang -/obj/machinery/shuttle_scrambler - name = "Data Siphon" - desc = "This heap of machinery steals credits and data from unprotected systems and locks down cargo shuttles." - icon = 'icons/obj/machines/dominator.dmi' - icon_state = "dominator" - density = TRUE - var/active = FALSE - var/credits_stored = 0 - var/siphon_per_tick = 5 +/datum/event_admin_setup/pirates/prompt_admins() -/obj/machinery/shuttle_scrambler/Initialize(mapload) - . = ..() - update_appearance() + var/list/gang_choices = list("Random") -/obj/machinery/shuttle_scrambler/process() - if(active) - if(is_station_level(z)) - var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) - if(D) - var/siphoned = min(D.account_balance,siphon_per_tick) - D.adjust_money(-siphoned) - credits_stored += siphoned - interrupt_research() - else - return - else - STOP_PROCESSING(SSobj,src) + for(var/datum/pirate_gang/possible_gang as anything in GLOB.pirate_gangs) + gang_choices[possible_gang.name] = possible_gang -/obj/machinery/shuttle_scrambler/proc/toggle_on(mob/user) - SSshuttle.registerTradeBlockade(src) - AddComponent(/datum/component/gps, "Nautical Signal") - active = TRUE - to_chat(user,span_notice("You toggle [src] [active ? "on":"off"].")) - to_chat(user,span_warning("The scrambling signal can be now tracked by GPS.")) - START_PROCESSING(SSobj,src) + var/chosen = tgui_input_list(usr, "Select pirate gang", "TICKETS TO THE SPONGEBOB MOVIE!!", gang_choices) + if(!chosen) + return ADMIN_CANCEL_EVENT + if(chosen == "Random") + return //still do the event, but chosen_gang is still null, so it will pick from the choices + chosen_gang = gang_choices[chosen] + +/datum/event_admin_setup/pirates/apply_to_event(datum/round_event/pirates/event) /obj/machinery/shuttle_scrambler/interact(mob/user) if(active) @@ -142,30 +113,6 @@ update_appearance() send_notification() -//interrupt_research -/obj/machinery/shuttle_scrambler/proc/interrupt_research() - for(var/obj/machinery/rnd/server/S as anything in SSresearch.science_tech.techweb_servers) - if(S.machine_stat & (NOPOWER|BROKEN)) - continue - S.emp_act() - new /obj/effect/temp_visual/emp(get_turf(S)) - -/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user) - if(credits_stored) // Prevents spamming empty holochips - new /obj/item/holochip(drop_location(), credits_stored) - to_chat(user,span_notice("You retrieve the siphoned credits!")) - credits_stored = 0 - else - to_chat(user,span_notice("There's nothing to withdraw.")) - -/obj/machinery/shuttle_scrambler/proc/send_notification() - priority_announce("Data theft signal detected, source registered on local gps units.") - -/obj/machinery/shuttle_scrambler/proc/toggle_off(mob/user) - SSshuttle.clearTradeBlockade(src) - active = FALSE - STOP_PROCESSING(SSobj,src) - /obj/machinery/shuttle_scrambler/update_icon_state() icon_state = active ? "dominator-Blue" : "dominator" return ..() @@ -211,15 +158,6 @@ mask_type = /obj/item/clothing/mask/breath storage_type = /obj/item/tank/internals/oxygen -/obj/machinery/loot_locator - name = "Booty Locator" - desc = "This sophisticated machine scans the nearby space for items of value." - icon = 'icons/obj/machines/research.dmi' - icon_state = "tdoppler" - density = TRUE - var/cooldown = 300 - var/next_use = 0 - /obj/machinery/loot_locator/interact(mob/user) if(world.time <= next_use) to_chat(user,span_warning("[src] is recharging.")) @@ -231,33 +169,6 @@ else say("Located: [AM.name] at [get_area_name(AM)]") -/obj/machinery/loot_locator/proc/find_random_loot() - if(!GLOB.exports_list.len) - setupExports() - var/list/possible_loot = list() - for(var/datum/export/pirate/E in GLOB.exports_list) - possible_loot += E - var/datum/export/pirate/P - var/atom/movable/AM - while(!AM && possible_loot.len) - P = pick_n_take(possible_loot) - AM = P.find_loot() - return AM - -//Pad & Pad Terminal -/obj/machinery/piratepad - name = "cargo hold pad" - icon = 'icons/obj/telescience.dmi' - icon_state = "lpad-idle-off" - ///This is the icon_state that this telepad uses when it's not in use. - var/idle_state = "lpad-idle-off" - ///This is the icon_state that this telepad uses when it's warming up for goods teleportation. - var/warmup_state = "lpad-idle" - ///This is the icon_state to flick when the goods are being sent off by the telepad. - var/sending_state = "lpad-beam" - ///This is the cargo hold ID used by the piratepad_control. Match these two to link them together. - var/cargo_hold_id - /obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/multitool/I) . = ..() if (istype(I)) @@ -275,27 +186,6 @@ default_deconstruction_crowbar(tool) return TRUE -/obj/machinery/computer/piratepad_control - name = "cargo hold control terminal" - ///Message to display on the TGUI window. - var/status_report = "Ready for delivery." - ///Reference to the specific pad that the control computer is linked up to. - var/datum/weakref/pad_ref - ///How long does it take to warmup the pad to teleport? - var/warmup_time = 100 - ///Is the teleport pad/computer sending something right now? TRUE/FALSE - var/sending = FALSE - ///For the purposes of space pirates, how many points does the control pad have collected. - var/points = 0 - ///Reference to the export report totaling all sent objects and mobs. - var/datum/export_report/total_report - ///Callback holding the sending timer for sending the goods after a delay. - var/sending_timer - ///This is the cargo hold ID used by the piratepad machine. Match these two to link them together. - var/cargo_hold_id - ///Interface name for the ui_interact call for different subtypes. - var/interface_type = "CargoHoldTerminal" - /obj/machinery/computer/piratepad_control/Initialize(mapload) ..() return INITIALIZE_HINT_LATELOAD @@ -351,10 +241,6 @@ stop_sending() . = TRUE -/obj/machinery/computer/piratepad_control/proc/recalc() - if(sending) - return - status_report = "Predicted value: " var/value = 0 var/datum/export_report/ex = new @@ -362,10 +248,6 @@ for(var/atom/movable/AM in get_turf(pad)) if(AM == pad) continue - //SKYRAT EDIT ADDITION - NO MOBS! - if(ismob(AM)) - continue - //SKYRAT EDIT END export_item_and_contents(AM, apply_elastic = FALSE, dry_run = TRUE, external_report = ex) for(var/datum/export/E in ex.total_amount) @@ -376,85 +258,6 @@ if(!value) status_report += "0" -/obj/machinery/computer/piratepad_control/proc/send() - if(!sending) - return - - var/datum/export_report/ex = new - var/obj/machinery/piratepad/pad = pad_ref?.resolve() - - for(var/atom/movable/AM in get_turf(pad)) - if(AM == pad) - continue - //SKYRAT EDIT ADDITION - NO MOBS! - if(ismob(AM)) - continue - //SKYRAT EDIT END - export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex) - - status_report = "Sold: " - var/value = 0 - for(var/datum/export/E in ex.total_amount) - var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here. - if(!export_text) - continue - - status_report += export_text - status_report += " " - value += ex.total_value[E] - - if(!total_report) - total_report = ex - else - total_report.exported_atoms += ex.exported_atoms - for(var/datum/export/E in ex.total_amount) - total_report.total_amount[E] += ex.total_amount[E] - total_report.total_value[E] += ex.total_value[E] - playsound(loc, 'sound/machines/wewewew.ogg', 70, TRUE) - - points += value - - if(!value) - status_report += "Nothing" - - pad.visible_message(span_notice("[pad] activates!")) - flick(pad.sending_state,pad) - pad.icon_state = pad.idle_state - sending = FALSE - -/obj/machinery/computer/piratepad_control/proc/start_sending() - var/obj/machinery/piratepad/pad = pad_ref?.resolve() - if(!pad) - status_report = "No pad detected. Build or link a pad." - pad.audible_message(span_notice("[pad] beeps.")) - return - if(pad?.panel_open) - status_report = "Please screwdrive pad closed to send. " - pad.audible_message(span_notice("[pad] beeps.")) - return - if(sending) - return - sending = TRUE - status_report = "Sending... " - pad.visible_message(span_notice("[pad] starts charging up.")) - pad.icon_state = pad.warmup_state - sending_timer = addtimer(CALLBACK(src, PROC_REF(send)),warmup_time, TIMER_STOPPABLE) - -/obj/machinery/computer/piratepad_control/proc/stop_sending(custom_report) - if(!sending) - return - sending = FALSE - status_report = "Ready for delivery." - if(custom_report) - status_report = custom_report - var/obj/machinery/piratepad/pad = pad_ref?.resolve() - pad.icon_state = pad.idle_state - deltimer(sending_timer) - -//Attempts to find the thing on station -/datum/export/pirate/proc/find_loot() - return - /datum/export/pirate/ransom cost = 3000 unit_name = "hostage" diff --git a/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm new file mode 100644 index 00000000000..e1bef982f62 --- /dev/null +++ b/code/modules/antagonists/pirate/pirate_shuttle_equipment.dm @@ -0,0 +1,408 @@ +//Shuttle equipment + +/obj/machinery/shuttle_scrambler + name = "Data Siphon" + desc = "This heap of machinery steals credits and data from unprotected systems and locks down cargo shuttles." + icon = 'icons/obj/machines/dominator.dmi' + icon_state = "dominator" + density = TRUE + var/active = FALSE + var/credits_stored = 0 + var/siphon_per_tick = 5 + +/obj/machinery/shuttle_scrambler/Initialize(mapload) + . = ..() + update_appearance() + +/obj/machinery/shuttle_scrambler/process() + if(active) + if(is_station_level(z)) + var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) + if(D) + var/siphoned = min(D.account_balance,siphon_per_tick) + D.adjust_money(-siphoned) + credits_stored += siphoned + interrupt_research() + else + return + else + STOP_PROCESSING(SSobj,src) + +/obj/machinery/shuttle_scrambler/proc/toggle_on(mob/user) + SSshuttle.registerTradeBlockade(src) + AddComponent(/datum/component/gps, "Nautical Signal") + active = TRUE + to_chat(user,span_notice("You toggle [src] [active ? "on":"off"].")) + to_chat(user,span_warning("The scrambling signal can be now tracked by GPS.")) + START_PROCESSING(SSobj,src) + +/obj/machinery/shuttle_scrambler/interact(mob/user) + if(active) + dump_loot(user) + return + var/scramble_response = tgui_alert(user, "Turning the scrambler on will make the shuttle trackable by GPS. Are you sure you want to do it?", "Scrambler", list("Yes", "Cancel")) + if(scramble_response != "Yes") + return + if(active || !user.canUseTopic(src, be_close = TRUE)) + return + toggle_on(user) + update_appearance() + send_notification() + +//interrupt_research +/obj/machinery/shuttle_scrambler/proc/interrupt_research() + for(var/obj/machinery/rnd/server/S as anything in SSresearch.science_tech.techweb_servers) + if(S.machine_stat & (NOPOWER|BROKEN)) + continue + S.emp_act() + new /obj/effect/temp_visual/emp(get_turf(S)) + +/obj/machinery/shuttle_scrambler/proc/dump_loot(mob/user) + if(credits_stored) // Prevents spamming empty holochips + new /obj/item/holochip(drop_location(), credits_stored) + to_chat(user,span_notice("You retrieve the siphoned credits!")) + credits_stored = 0 + else + to_chat(user,span_notice("There's nothing to withdraw.")) + +/obj/machinery/shuttle_scrambler/proc/send_notification() + priority_announce("Data theft signal detected, source registered on local gps units.") + +/obj/machinery/shuttle_scrambler/proc/toggle_off(mob/user) + SSshuttle.clearTradeBlockade(src) + active = FALSE + STOP_PROCESSING(SSobj,src) + +/obj/machinery/shuttle_scrambler/update_icon_state() + icon_state = active ? "dominator-Blue" : "dominator" + return ..() + +/obj/machinery/shuttle_scrambler/Destroy() + toggle_off() + return ..() + +/obj/machinery/computer/shuttle/pirate + name = "pirate shuttle console" + shuttleId = "pirate" + icon_screen = "syndishuttle" + icon_keyboard = "syndie_key" + light_color = COLOR_SOFT_RED + possible_destinations = "pirate_away;pirate_home;pirate_custom" + +/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate + name = "pirate shuttle navigation computer" + desc = "Used to designate a precise transit location for the pirate shuttle." + shuttleId = "pirate" + lock_override = CAMERA_LOCK_STATION + shuttlePortId = "pirate_custom" + x_offset = 9 + y_offset = 0 + see_hidden = FALSE + +/obj/machinery/computer/camera_advanced/shuttle_docker/syndicate/pirate/psyker + name = "psyker navigation warper" + desc = "Used to designate a precise transit location for the psyker shuttle, using sent out brainwaves as detailed sight." + icon_screen = "recharge_comp_on" + interaction_flags_machine = INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_SET_MACHINE //blind friendly + x_offset = 0 + y_offset = 11 + +/obj/docking_port/mobile/pirate + name = "pirate shuttle" + shuttle_id = "pirate" + rechargeTime = 3 MINUTES + +/obj/machinery/suit_storage_unit/pirate + suit_type = /obj/item/clothing/suit/space + helmet_type = /obj/item/clothing/head/helmet/space + mask_type = /obj/item/clothing/mask/breath + storage_type = /obj/item/tank/internals/oxygen + +/obj/machinery/loot_locator + name = "Booty Locator" + desc = "This sophisticated machine scans the nearby space for items of value." + icon = 'icons/obj/machines/research.dmi' + icon_state = "tdoppler" + density = TRUE + var/cooldown = 300 + var/next_use = 0 + +/obj/machinery/loot_locator/interact(mob/user) + if(world.time <= next_use) + to_chat(user,span_warning("[src] is recharging.")) + return + next_use = world.time + cooldown + var/atom/movable/AM = find_random_loot() + if(!AM) + say("No valuables located. Try again later.") + else + say("Located: [AM.name] at [get_area_name(AM)]") + +/obj/machinery/loot_locator/proc/find_random_loot() + if(!GLOB.exports_list.len) + setupExports() + var/list/possible_loot = list() + for(var/datum/export/pirate/E in GLOB.exports_list) + possible_loot += E + var/datum/export/pirate/P + var/atom/movable/AM + while(!AM && possible_loot.len) + P = pick_n_take(possible_loot) + AM = P.find_loot() + return AM + +//Pad & Pad Terminal +/obj/machinery/piratepad + name = "cargo hold pad" + icon = 'icons/obj/telescience.dmi' + icon_state = "lpad-idle-off" + ///This is the icon_state that this telepad uses when it's not in use. + var/idle_state = "lpad-idle-off" + ///This is the icon_state that this telepad uses when it's warming up for goods teleportation. + var/warmup_state = "lpad-idle" + ///This is the icon_state to flick when the goods are being sent off by the telepad. + var/sending_state = "lpad-beam" + ///This is the cargo hold ID used by the piratepad_control. Match these two to link them together. + var/cargo_hold_id + +/obj/machinery/piratepad/multitool_act(mob/living/user, obj/item/multitool/I) + . = ..() + if (istype(I)) + to_chat(user, span_notice("You register [src] in [I]s buffer.")) + I.buffer = src + return TRUE + +/obj/machinery/piratepad/screwdriver_act_secondary(mob/living/user, obj/item/screwdriver/screw) + . = ..() + if(!.) + return default_deconstruction_screwdriver(user, "lpad-idle-open", "lpad-idle-off", screw) + +/obj/machinery/piratepad/crowbar_act_secondary(mob/living/user, obj/item/tool) + . = ..() + default_deconstruction_crowbar(tool) + return TRUE + +/obj/machinery/computer/piratepad_control + name = "cargo hold control terminal" + ///Message to display on the TGUI window. + var/status_report = "Ready for delivery." + ///Reference to the specific pad that the control computer is linked up to. + var/datum/weakref/pad_ref + ///How long does it take to warmup the pad to teleport? + var/warmup_time = 100 + ///Is the teleport pad/computer sending something right now? TRUE/FALSE + var/sending = FALSE + ///For the purposes of space pirates, how many points does the control pad have collected. + var/points = 0 + ///Reference to the export report totaling all sent objects and mobs. + var/datum/export_report/total_report + ///Callback holding the sending timer for sending the goods after a delay. + var/sending_timer + ///This is the cargo hold ID used by the piratepad machine. Match these two to link them together. + var/cargo_hold_id + ///Interface name for the ui_interact call for different subtypes. + var/interface_type = "CargoHoldTerminal" + +/obj/machinery/computer/piratepad_control/Initialize(mapload) + ..() + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/computer/piratepad_control/multitool_act(mob/living/user, obj/item/multitool/I) + . = ..() + if (istype(I) && istype(I.buffer,/obj/machinery/piratepad)) + to_chat(user, span_notice("You link [src] with [I.buffer] in [I] buffer.")) + pad_ref = WEAKREF(I.buffer) + return TRUE + +/obj/machinery/computer/piratepad_control/LateInitialize() + . = ..() + if(cargo_hold_id) + for(var/obj/machinery/piratepad/P in GLOB.machines) + if(P.cargo_hold_id == cargo_hold_id) + pad_ref = WEAKREF(P) + return + else + var/obj/machinery/piratepad/pad = locate() in range(4, src) + pad_ref = WEAKREF(pad) + +/obj/machinery/computer/piratepad_control/ui_interact(mob/user, datum/tgui/ui) + . = ..() + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, interface_type, name) + ui.open() + +/obj/machinery/computer/piratepad_control/ui_data(mob/user) + var/list/data = list() + data["points"] = points + data["pad"] = pad_ref?.resolve() ? TRUE : FALSE + data["sending"] = sending + data["status_report"] = status_report + return data + +/obj/machinery/computer/piratepad_control/ui_act(action, params) + . = ..() + if(.) + return + if(!pad_ref?.resolve()) + return + + switch(action) + if("recalc") + recalc() + . = TRUE + if("send") + start_sending() + . = TRUE + if("stop") + stop_sending() + . = TRUE + +/obj/machinery/computer/piratepad_control/proc/recalc() + if(sending) + return + + status_report = "Predicted value: " + var/value = 0 + var/datum/export_report/ex = new + var/obj/machinery/piratepad/pad = pad_ref?.resolve() + for(var/atom/movable/AM in get_turf(pad)) + if(AM == pad) + continue + export_item_and_contents(AM, apply_elastic = FALSE, dry_run = TRUE, external_report = ex) + + for(var/datum/export/E in ex.total_amount) + status_report += E.total_printout(ex,notes = FALSE) + status_report += " " + value += ex.total_value[E] + + if(!value) + status_report += "0" + +/obj/machinery/computer/piratepad_control/proc/send() + if(!sending) + return + + var/datum/export_report/ex = new + var/obj/machinery/piratepad/pad = pad_ref?.resolve() + + for(var/atom/movable/AM in get_turf(pad)) + if(AM == pad) + continue + export_item_and_contents(AM, EXPORT_PIRATE | EXPORT_CARGO | EXPORT_CONTRABAND | EXPORT_EMAG, apply_elastic = FALSE, delete_unsold = FALSE, external_report = ex) + + status_report = "Sold: " + var/value = 0 + for(var/datum/export/E in ex.total_amount) + var/export_text = E.total_printout(ex,notes = FALSE) //Don't want nanotrasen messages, makes no sense here. + if(!export_text) + continue + + status_report += export_text + status_report += " " + value += ex.total_value[E] + + if(!total_report) + total_report = ex + else + total_report.exported_atoms += ex.exported_atoms + for(var/datum/export/E in ex.total_amount) + total_report.total_amount[E] += ex.total_amount[E] + total_report.total_value[E] += ex.total_value[E] + playsound(loc, 'sound/machines/wewewew.ogg', 70, TRUE) + + points += value + + if(!value) + status_report += "Nothing" + + pad.visible_message(span_notice("[pad] activates!")) + flick(pad.sending_state,pad) + pad.icon_state = pad.idle_state + sending = FALSE + +/obj/machinery/computer/piratepad_control/proc/start_sending() + var/obj/machinery/piratepad/pad = pad_ref?.resolve() + if(!pad) + status_report = "No pad detected. Build or link a pad." + pad.audible_message(span_notice("[pad] beeps.")) + return + if(pad?.panel_open) + status_report = "Please screwdrive pad closed to send. " + pad.audible_message(span_notice("[pad] beeps.")) + return + if(sending) + return + sending = TRUE + status_report = "Sending... " + pad.visible_message(span_notice("[pad] starts charging up.")) + pad.icon_state = pad.warmup_state + sending_timer = addtimer(CALLBACK(src, PROC_REF(send)),warmup_time, TIMER_STOPPABLE) + +/obj/machinery/computer/piratepad_control/proc/stop_sending(custom_report) + if(!sending) + return + sending = FALSE + status_report = "Ready for delivery." + if(custom_report) + status_report = custom_report + var/obj/machinery/piratepad/pad = pad_ref?.resolve() + pad.icon_state = pad.idle_state + deltimer(sending_timer) + +//Attempts to find the thing on station +/datum/export/pirate/proc/find_loot() + return + +/datum/export/pirate/ransom + cost = 3000 + unit_name = "hostage" + export_types = list(/mob/living/carbon/human) + +/datum/export/pirate/ransom/find_loot() + var/list/head_minds = SSjob.get_living_heads() + var/list/head_mobs = list() + for(var/datum/mind/M as anything in head_minds) + head_mobs += M.current + if(head_mobs.len) + return pick(head_mobs) + +/datum/export/pirate/ransom/get_cost(atom/movable/AM) + var/mob/living/carbon/human/H = AM + if(H.stat != CONSCIOUS || !H.mind) //mint condition only + return 0 + else if("pirate" in H.faction) //can't ransom your fellow pirates to CentCom! + return 0 + else if(H.mind.assigned_role.departments_bitflags & DEPARTMENT_BITFLAG_COMMAND) + return 3000 + else + return 1000 + +/datum/export/pirate/parrot + cost = 2000 + unit_name = "alive parrot" + export_types = list(/mob/living/simple_animal/parrot) + +/datum/export/pirate/parrot/find_loot() + for(var/mob/living/simple_animal/parrot/P in GLOB.alive_mob_list) + var/turf/T = get_turf(P) + if(T && is_station_level(T.z)) + return P + +/datum/export/pirate/cash + cost = 1 + unit_name = "bills" + export_types = list(/obj/item/stack/spacecash) + +/datum/export/pirate/cash/get_amount(obj/O) + var/obj/item/stack/spacecash/C = O + return ..() * C.amount * C.value + +/datum/export/pirate/holochip + cost = 1 + unit_name = "holochip" + export_types = list(/obj/item/holochip) + +/datum/export/pirate/holochip/get_cost(atom/movable/AM) + var/obj/item/holochip/H = AM + return H.credits diff --git a/code/modules/events/_event.dm b/code/modules/events/_event.dm index a84a2e3d7d4..cd1e2f178ea 100644 --- a/code/modules/events/_event.dm +++ b/code/modules/events/_event.dm @@ -30,10 +30,16 @@ /// Whether or not dynamic should hijack this event var/dynamic_should_hijack = FALSE + /// Datum that will handle admin options for forcing the event. + /// If there are no options, just leave it null. + var/datum/event_admin_setup/admin_setup = null + /datum/round_event_control/New() if(config && !wizardevent) // Magic is unaffected by configs earliest_start = CEILING(earliest_start * CONFIG_GET(number/events_min_time_mul), 1) min_players = CEILING(min_players * CONFIG_GET(number/events_min_players_mul), 1) + if(admin_setup) + admin_setup = new admin_setup(src) /datum/round_event_control/wizard category = EVENT_CATEGORY_WIZARD @@ -122,22 +128,25 @@ Runs the event * * In the worst case scenario we can still recall a event which we cancelled by accident, which is much better then to have a unwanted event */ UnregisterSignal(SSdcs, COMSIG_GLOB_RANDOM_EVENT) - var/datum/round_event/E = new typepath(TRUE, src) - E.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) + var/datum/round_event/round_event = new typepath(TRUE, src) + if(admin_forced && admin_setup) + admin_setup.apply_to_event(round_event) + round_event.setup() + round_event.current_players = get_active_player_count(alive_check = 1, afk_check = 1, human_check = 1) occurrences++ SSevents.previously_run += src //SKYRAT EDIT ADDITION if(announce_chance_override != null) - E.announce_chance = announce_chance_override + round_event.announce_chance = announce_chance_override - testing("[time2text(world.time, "hh:mm:ss")] [E.type]") + testing("[time2text(world.time, "hh:mm:ss")] [round_event.type]") triggering = TRUE if(!triggering) RegisterSignal(SSdcs, COMSIG_GLOB_RANDOM_EVENT, PROC_REF(stop_random_event)) - E.cancel_event = TRUE - return E + round_event.cancel_event = TRUE + return round_event triggering = FALSE if(random) @@ -146,8 +155,8 @@ Runs the event if(alert_observers) announce_deadchat(random) - SSblackbox.record_feedback("tally", "event_ran", 1, "[E]") - return E + SSblackbox.record_feedback("tally", "event_ran", 1, "[round_event]") + return round_event ///Annouces the event name to deadchat, override this if what an event should show to deadchat is different to its event name. /datum/round_event_control/proc/announce_deadchat(random) @@ -158,12 +167,6 @@ Runs the event SIGNAL_HANDLER return CANCEL_RANDOM_EVENT -/// Any special things admins can do while triggering this event to "improve" it. -/// Return [ADMIN_CANCEL_EVENT] to stop the event from actually happening after all -/datum/round_event_control/proc/admin_setup(mob/admin) - SHOULD_CALL_PARENT(FALSE) - return - /datum/round_event //NOTE: Times are measured in master controller ticks! var/processing = TRUE var/datum/round_event_control/control @@ -194,12 +197,14 @@ Runs the event //It will only have been overridden by the time we get to announce() start() tick() or end() (anything but setup basically). //This is really only for setting defaults which can be overridden later when New() finishes. /datum/round_event/proc/setup() + SHOULD_CALL_PARENT(FALSE) return //Called when the tick is equal to the start_when variable. //Allows you to start before announcing or vice versa. //Only called once. /datum/round_event/proc/start() + SHOULD_CALL_PARENT(FALSE) return //Called after something followable has been spawned by an event @@ -285,7 +290,6 @@ Runs the event //Sets up the event then adds the event to the the list of running events /datum/round_event/New(my_processing = TRUE, datum/round_event_control/event_controller) control = event_controller - setup() processing = my_processing SSevents.running += src return ..() diff --git a/code/modules/events/_event_admin_setup.dm b/code/modules/events/_event_admin_setup.dm new file mode 100644 index 00000000000..1116eb05866 --- /dev/null +++ b/code/modules/events/_event_admin_setup.dm @@ -0,0 +1,83 @@ +/// Datum that holds a proc for additional options when running an event. +/// Prototypes are declared here, non-prototypes on the event files. +/datum/event_admin_setup + /// event control that owns this. + var/datum/round_event_control/event_control + +/datum/event_admin_setup/New(event_control) + src.event_control = event_control + +/datum/event_admin_setup/proc/prompt_admins() + SHOULD_CALL_PARENT(FALSE) + CRASH("Unimplemented prompt_admins() on [event_control]'s admin setup.") + +/datum/event_admin_setup/proc/apply_to_event(datum/round_event/event) + SHOULD_CALL_PARENT(FALSE) + CRASH("Unimplemented apply_to_event() on [event_control]'s admin setup.") + +/// A very common pattern is picking from a tgui list input, so this does that. +/// Supply a list in `get_list` and prompt admins will have the admin pick from it or cancel. +/datum/event_admin_setup/listed_options + /// Text to ask the user, for example "What deal would you like to offer the crew?" + var/input_text = "Unset Text" + /// If set, picking this will be the same as running the event without admin setup. + var/normal_run_option + /// Picked list option to be applied. + var/chosen + +/datum/event_admin_setup/listed_options/proc/get_list() + SHOULD_CALL_PARENT(FALSE) + CRASH("Unimplemented get_list() on [event_control]'s admin setup.") + +/datum/event_admin_setup/listed_options/prompt_admins() + var/list/options = get_list() + if(normal_run_option) + options.Insert(1, normal_run_option) + chosen = tgui_input_list(usr, input_text, event_control.name, options) + if(!chosen) + return ADMIN_CANCEL_EVENT + if(normal_run_option && chosen == normal_run_option) + chosen = null //no admin pick = runs as normal + +/// For admin setups that want a custom string. Suggests what the event would have picked normally. +/datum/event_admin_setup/text_input + /// Text to ask the user, for example "What horrifying truth will you reveal?" + var/input_text = "Unset Text" + /// Picked string to be applied. + var/chosen + +/// Returns a string to suggest to the admin, which would be what the event would have chosen. +/// No suggestion if an empty string, which is default behavior. +/datum/event_admin_setup/text_input/proc/get_text_suggestion() + return "" + +/datum/event_admin_setup/text_input/prompt_admins() + var/suggestion = get_text_suggestion() + chosen = tgui_input_text(usr, input_text, event_control.name, suggestion) + if(!chosen) + return ADMIN_CANCEL_EVENT + +/// Some events are not always a good idea when a game state is in a certain situation. +/// This runs a check and warns the admin. +/datum/event_admin_setup/warn_admin + /// Warning text shown to admin on the alert. + var/warning_text = "Unset warning text" + /// Message sent to other admins. Example: "has forced a shuttle catastrophe while a shuttle was already docked." + var/snitch_text = "Unset snitching text (be mad at coders AND the admin responsible)" + +/datum/event_admin_setup/warn_admin/prompt_admins() + if(!should_warn()) + return + var/mob/admin = usr + if(tgui_alert(usr, "WARNING: [warning_text]", event_control.name, list("Yes", "No")) == "Yes") + message_admins("[admin.ckey] [snitch_text]") + else + return ADMIN_CANCEL_EVENT + +/// Returns whether the admin should get an alert. +/datum/event_admin_setup/warn_admin/proc/should_warn() + SHOULD_CALL_PARENT(FALSE) + CRASH("Unimplemented should_warn() on [event_control]'s admin setup.") + +/datum/event_admin_setup/warn_admin/apply_to_event(datum/round_event/event) + return diff --git a/code/modules/events/anomaly/_anomaly.dm b/code/modules/events/anomaly/_anomaly.dm index 0e3cb80bcc9..4b15ac93c29 100644 --- a/code/modules/events/anomaly/_anomaly.dm +++ b/code/modules/events/anomaly/_anomaly.dm @@ -7,31 +7,20 @@ weight = 15 category = EVENT_CATEGORY_ANOMALIES description = "This anomaly shocks and explodes. This is the base type." - ///The admin-chosen spawn location. - var/turf/spawn_location - -/datum/round_event_control/anomaly/admin_setup(mob/admin) - . = ..() - - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - if(tgui_alert(usr, "Spawn anomaly at your current location?", "Anomaly Alert", list("Yes", "No")) == "Yes") - spawn_location = get_turf(usr) + admin_setup = /datum/event_admin_setup/anomaly /datum/round_event/anomaly + announce_when = 1 var/area/impact_area var/datum/anomaly_placer/placer = new() var/obj/effect/anomaly/anomaly_path = /obj/effect/anomaly/flux - announce_when = 1 + ///The admin-chosen spawn location. + var/turf/spawn_location /datum/round_event/anomaly/setup() - end_when = start_when + 1 //Admin vars are cleared on end(), so we make sure the anomaly spawns before then. - - var/datum/round_event_control/anomaly/anomaly_event = control - if(anomaly_event.spawn_location) - impact_area = get_area(anomaly_event.spawn_location) + if(spawn_location) + impact_area = get_area(spawn_location) else impact_area = placer.findValidArea() @@ -41,9 +30,8 @@ /datum/round_event/anomaly/start() var/turf/anomaly_turf - var/datum/round_event_control/anomaly/anomaly_event = control - if(anomaly_event.spawn_location) - anomaly_turf = anomaly_event.spawn_location + if(spawn_location) + anomaly_turf = spawn_location else anomaly_turf = placer.findValidTurf(impact_area) @@ -53,6 +41,13 @@ if (newAnomaly) announce_to_ghosts(newAnomaly) -/datum/round_event/anomaly/end() - var/datum/round_event_control/anomaly/anomaly_event = control - anomaly_event.spawn_location = null +/datum/event_admin_setup/anomaly + ///The admin-chosen spawn location. + var/turf/spawn_location + +/datum/event_admin_setup/anomaly/prompt_admins() + if(tgui_alert(usr, "Spawn anomaly at your current location?", "Anomaly Alert", list("Yes", "No")) == "Yes") + spawn_location = get_turf(usr) + +/datum/event_admin_setup/anomaly/apply_to_event(datum/round_event/anomaly/event) + event.spawn_location = spawn_location diff --git a/code/modules/events/brand_intelligence.dm b/code/modules/events/brand_intelligence.dm index 94cf816d3b5..1484ea3cad1 100644 --- a/code/modules/events/brand_intelligence.dm +++ b/code/modules/events/brand_intelligence.dm @@ -6,23 +6,20 @@ description = "Vending machines will attack people until the Patient Zero is disabled." min_players = 15 max_occurrences = 1 - ///Var used to determine vendor subtype if used for admin setup - var/chosen_vendor - -/datum/round_event_control/brand_intelligence/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - if(tgui_alert(usr, "Select a specific vendor path?", "Capitalism-ho!", list("Yes", "No")) == "Yes") - var/list/vendors = list() - vendors += subtypesof(/obj/machinery/vending) - chosen_vendor = tgui_input_list(usr, "Vendor type must have at least one instance on the station for this to work!","Vendor Selector", vendors) + admin_setup = /datum/event_admin_setup/listed_options/brand_intelligence /datum/round_event/brand_intelligence announce_when = 21 end_when = 1000 //Ends when all vending machines are subverted anyway. - var/list/obj/machinery/vending/vendingMachines = list() - var/list/obj/machinery/vending/infectedMachines = list() - var/obj/machinery/vending/originMachine + /// Admin picked subtype for what kind of vendor goes haywire. + var/chosen_vendor_type + /// All vending machines valid to get infected. + var/list/obj/machinery/vending/vending_machines = list() + /// All vending machines that have been infected. + var/list/obj/machinery/vending/infected_machines = list() + /// The original machine infected. Killing it ends the event. + var/obj/machinery/vending/origin_machine + /// Murderous sayings from the machines. var/list/rampant_speeches = list( "Try our aggressive new marketing strategies!", "You should buy products to feed your lifestyle obsession!", @@ -33,66 +30,62 @@ "You don't want to buy anything? Yeah, well, I didn't want to buy your mom either.", ) +/datum/round_event/brand_intelligence/setup() + //select our origin machine (which will also be the type of vending machine affected.) + for(var/obj/machinery/vending/vendor in GLOB.machines) + if(!is_station_level(vendor.z)) + continue + if(!vendor.density) + continue + if(chosen_vendor_type && !istype(vendor, chosen_vendor_type)) + continue + vending_machines.Add(vendor) + if(!length(vending_machines)) //If somehow there are still no elligible vendors, give up. + kill() + return + origin_machine = pick_n_take(vending_machines) /datum/round_event/brand_intelligence/announce(fake) - var/source = "unknown machine" - if(fake) - for(var/obj/machinery/vending/vendor in GLOB.machines) - if(!is_station_level(vendor.z)) - continue - vendingMachines.Add(vendor) - var/obj/machinery/vending/chosen_vendor = pick(vendingMachines) - source = chosen_vendor.name - else if(originMachine) - source = originMachine.name - priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please inspect any [source] brand vendors for aggressive marketing tactics, and reboot them if necessary.", "Machine Learning Alert") + priority_announce("Rampant brand intelligence has been detected aboard [station_name()]. Please inspect any [origin_machine] brand vendors for aggressive marketing tactics, and reboot them if necessary.", "Machine Learning Alert") /datum/round_event/brand_intelligence/start() - var/datum/round_event_control/brand_intelligence/brand_event = control - if(brand_event.chosen_vendor) //Attempt to search for vendors of the selected admin subtype - var/chosen_vendor = brand_event.chosen_vendor - for(var/obj/machinery/vending/vendor in GLOB.machines) - if(!is_station_level(vendor.z) || !istype(vendor, chosen_vendor) || !vendor.density) - continue - vendingMachines.Add(vendor) - brand_event.chosen_vendor = null //Event has a max_occurences of 1 but juuust in case - if(!length(vendingMachines)) //If no vendors are in vendingMachines, setup defaults back to randomly selecting one. - for(var/obj/machinery/vending/vendor in GLOB.machines) - if(!is_station_level(vendor.z) || !vendor.density) - continue - vendingMachines.Add(vendor) - if(!length(vendingMachines)) //If somehow there are still no elligible vendors, give up. - kill() - return - originMachine = pick(vendingMachines) - vendingMachines.Remove(originMachine) - originMachine.shut_up = FALSE - originMachine.shoot_inventory = TRUE - announce_to_ghosts(originMachine) + origin_machine.shut_up = FALSE + origin_machine.shoot_inventory = TRUE + announce_to_ghosts(origin_machine) /datum/round_event/brand_intelligence/tick() - if(!originMachine || QDELETED(originMachine) || originMachine.shut_up || originMachine.wires.is_all_cut()) //if the original vending machine is missing or has it's voice switch flipped - for(var/obj/machinery/vending/saved in infectedMachines) + if(!origin_machine || QDELETED(origin_machine) || origin_machine.shut_up || origin_machine.wires.is_all_cut()) //if the original vending machine is missing or has it's voice switch flipped + for(var/obj/machinery/vending/saved in infected_machines) saved.shoot_inventory = FALSE - if(originMachine) - originMachine.speak("I am... vanquished. My people will remem...ber...meeee.") - originMachine.visible_message(span_notice("[originMachine] beeps and seems lifeless.")) + if(origin_machine) + origin_machine.speak("I am... vanquished. My people will remem...ber...meeee.") + origin_machine.visible_message(span_notice("[origin_machine] beeps and seems lifeless.")) kill() return - list_clear_nulls(vendingMachines) - if(!vendingMachines.len) //if every machine is infected - for(var/obj/machinery/vending/upriser in infectedMachines) + list_clear_nulls(vending_machines) + if(!vending_machines.len) //if every machine is infected + for(var/obj/machinery/vending/upriser in infected_machines) if(!QDELETED(upriser)) upriser.ai_controller = new /datum/ai_controller/vending_machine(upriser) - infectedMachines.Remove(upriser) + infected_machines.Remove(upriser) kill() return if(ISMULTIPLE(activeFor, 2)) - var/obj/machinery/vending/rebel = pick(vendingMachines) - vendingMachines.Remove(rebel) - infectedMachines.Add(rebel) + var/obj/machinery/vending/rebel = pick(vending_machines) + vending_machines.Remove(rebel) + infected_machines.Add(rebel) rebel.shut_up = FALSE rebel.shoot_inventory = TRUE if(ISMULTIPLE(activeFor, 4)) - originMachine.speak(pick(rampant_speeches)) + origin_machine.speak(pick(rampant_speeches)) + +/datum/event_admin_setup/listed_options/brand_intelligence + input_text = "Select a specific vendor path?" + normal_run_option = "Random Vendor" + +/datum/event_admin_setup/listed_options/brand_intelligence/get_list() + return subtypesof(/obj/machinery/vending) + +/datum/event_admin_setup/listed_options/brand_intelligence/apply_to_event(datum/round_event/brand_intelligence/event) + event.chosen_vendor_type = chosen diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index d90a7f6453e..0f246a9248f 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -6,10 +6,9 @@ weight = 5 category = EVENT_CATEGORY_HEALTH description = "A 'classic' virus will infect some members of the crew." //These are the ones with PERSONALITY + admin_setup = /datum/event_admin_setup/disease_outbreak ///Disease recipient candidates var/list/disease_candidates = list() - ///Admin selected disease, to be passed down to the round_event - var/chosen_disease /datum/round_event_control/disease_outbreak/can_spawn_event(players_amt) . = ..() @@ -19,21 +18,6 @@ if(length(disease_candidates)) return TRUE -/datum/round_event_control/disease_outbreak/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - generate_candidates() - - if(!length(disease_candidates)) - message_admins("No disease candidates found!") - return ADMIN_CANCEL_EVENT - - message_admins("[length(disease_candidates)] candidates found!") - - if(tgui_alert(usr, "Select a specific disease?", "Sickening behavior", list("Yes", "No")) == "Yes") - chosen_disease = tgui_input_list(usr, "Warning: Some of these are EXTREMELY dangerous.","Bacteria Hysteria", subtypesof(/datum/disease)) - /** * Creates a list of people who are elligible to become disease carriers for the event * @@ -68,10 +52,6 @@ var/datum/round_event_control/disease_outbreak/disease_event = control afflicted += disease_event.disease_candidates disease_event.disease_candidates.Cut() //Clean the list after use - if(disease_event.chosen_disease) - virus_type = disease_event.chosen_disease - disease_event.chosen_disease = null - if(!virus_type) var/list/virus_candidates = list() @@ -104,26 +84,7 @@ typepath = /datum/round_event/disease_outbreak/advanced category = EVENT_CATEGORY_HEALTH description = "An 'advanced' disease will infect some members of the crew." //These are the ones that get viro lynched! - ///Admin selected custom severity rating for the event - var/chosen_severity - ///Admin selected custom value for the maximum symptoms this virus should have - var/chosen_max_symptoms - -/datum/round_event_control/disease_outbreak/advanced/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - generate_candidates() - - if(!length(disease_candidates)) - message_admins("No disease candidates found!") - return ADMIN_CANCEL_EVENT - - message_admins("[length(disease_candidates)] candidates found!") - - if(tgui_alert(usr,"Customize your virus?", "Glorified Debug Tool", list("Yes", "No")) == "Yes") - chosen_severity = tgui_input_number(usr, "Select a custom severity for your virus!", "Plague Incorporation!", 3, 8) - chosen_max_symptoms = tgui_input_number(usr, "How many symptoms do you want your virus to have?", "A pox upon ye!", 3, 15) + admin_setup = /datum/event_admin_setup/disease_outbreak/advanced /datum/round_event/disease_outbreak/advanced ///Number of symptoms for our virus @@ -136,17 +97,11 @@ afflicted += disease_event.disease_candidates disease_event.disease_candidates.Cut() //Clean the list after use - if(disease_event.chosen_max_symptoms) - max_symptoms = disease_event.chosen_max_symptoms - disease_event.chosen_max_symptoms = null - else + if(!max_symptoms) max_symptoms = 3 + max(FLOOR((world.time - control.earliest_start)/6000, 1),0) //3 symptoms at 20 minutes, plus 1 per 10 minutes. max_symptoms = clamp(max_symptoms, 3, 8) //Capping the virus symptoms prevents the event from becoming "smite one poor player with an -12 transmission hell virus" after a certain round length. - if(disease_event.chosen_severity) - max_severity = disease_event.chosen_severity - disease_event.chosen_severity = null - else + if(!max_severity) max_severity = 3 + max(FLOOR((world.time - control.earliest_start)/6000, 1),0) //Max severity doesn't need clamping var/datum/disease/advance/advanced_disease = new /datum/disease/advance/random(max_symptoms, max_severity) @@ -162,3 +117,47 @@ announce_to_ghosts(victim) else log_game("An event attempted to trigger a random advanced virus outbreak on [key_name(victim)], but failed.") + +/datum/event_admin_setup/disease_outbreak + ///Admin selected disease, to be passed down to the round_event + var/virus_type + +/// Checks for candidates. Returns false if there isn't enough +/datum/event_admin_setup/disease_outbreak/proc/candidate_check() + var/datum/round_event_control/disease_outbreak/disease_control = event_control + disease_control.generate_candidates() //can_spawn_event() is bypassed by admin_setup, so this makes sure that the candidates are still generated + return length(disease_control.disease_candidates) + +/datum/event_admin_setup/disease_outbreak/prompt_admins() + var/candidate_count = candidate_check() + if(!candidate_check()) + tgui_alert(usr, "There are no candidates eligible to recieve a disease!", "Error") + return ADMIN_CANCEL_EVENT + tgui_alert(usr, "[candidate_count] candidates found!", "Disease Outbreak") + + if(tgui_alert(usr, "Select a specific disease?", "Sickening behavior", list("Yes", "No")) == "Yes") + virus_type = tgui_input_list(usr, "Warning: Some of these are EXTREMELY dangerous.","Bacteria Hysteria", subtypesof(/datum/disease)) + +/datum/event_admin_setup/disease_outbreak/apply_to_event(datum/round_event/disease_outbreak/event) + event.virus_type = virus_type + +/datum/event_admin_setup/disease_outbreak/advanced + ///Admin selected custom severity rating for the event + var/max_severity + ///Admin selected custom value for the maximum symptoms this virus should have + var/max_symptoms + +/datum/event_admin_setup/disease_outbreak/advanced/prompt_admins() + var/candidate_count = candidate_check() + if(!candidate_check()) + tgui_alert(usr, "There are no candidates eligible to recieve a disease!", "Error") + return ADMIN_CANCEL_EVENT + tgui_alert(usr, "[candidate_count] candidates found!", "Disease Outbreak") + + if(tgui_alert(usr,"Customize your virus?", "Glorified Debug Tool", list("Yes", "No")) == "Yes") + max_severity = tgui_input_number(usr, "Select a custom severity for your virus!", "Plague Incorporation!", 3, 8) + max_symptoms = tgui_input_number(usr, "How many symptoms do you want your virus to have?", "A pox upon ye!", 3, 15) + +/datum/event_admin_setup/disease_outbreak/advanced/apply_to_event(datum/round_event/disease_outbreak/advanced/event) + event.max_severity = max_severity + event.max_symptoms = max_symptoms diff --git a/code/modules/events/false_alarm.dm b/code/modules/events/false_alarm.dm index 5a04b30a6ae..8ed8c065177 100644 --- a/code/modules/events/false_alarm.dm +++ b/code/modules/events/false_alarm.dm @@ -3,23 +3,9 @@ typepath = /datum/round_event/falsealarm weight = 20 max_occurrences = 5 - var/forced_type //Admin abuse category = EVENT_CATEGORY_BUREAUCRATIC description = "Fakes an event announcement." - -/datum/round_event_control/falsealarm/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return - - var/list/possible_types = list() - - for(var/datum/round_event_control/E in SSevents.control) - var/datum/round_event/event = E.typepath - if(!initial(event.fakeable)) - continue - possible_types += E - - forced_type = input(usr, "Select the scare.","False event") as null|anything in sort_names(possible_types) + admin_setup = /datum/event_admin_setup/listed_options/false_alarm /datum/round_event_control/falsealarm/can_spawn_event(players_amt) . = ..() @@ -34,6 +20,8 @@ announce_when = 0 end_when = 1 fakeable = FALSE + /// Admin's pick of fake event (wow! you picked blob!! you're so creative and smart!) + var/forced_type /datum/round_event/falsealarm/announce(fake) if(fake) //What are you doing @@ -42,10 +30,8 @@ var/events_list = gather_false_events(players_amt) var/datum/round_event_control/event_control - var/datum/round_event_control/falsealarm/C = control - if(C.forced_type) - event_control = C.forced_type - C.forced_type = null + if(forced_type) + event_control = forced_type else event_control = pick(events_list) if(event_control) @@ -66,3 +52,18 @@ if(!initial(event.fakeable)) continue . += E + +/datum/event_admin_setup/listed_options/false_alarm + normal_run_option = "Random Fake Event" + +/datum/event_admin_setup/listed_options/false_alarm/get_list() + var/list/possible_types = list() + for(var/datum/round_event_control/event_control in SSevents.control) + var/datum/round_event/event = event_control.typepath + if(!initial(event.fakeable)) + continue + possible_types += event_control + return possible_types + +/datum/event_admin_setup/listed_options/false_alarm/apply_to_event(datum/round_event/falsealarm/event) + event.forced_type = chosen diff --git a/code/modules/events/heart_attack.dm b/code/modules/events/heart_attack.dm index d913dbd6f08..e5ba47dd79a 100644 --- a/code/modules/events/heart_attack.dm +++ b/code/modules/events/heart_attack.dm @@ -6,10 +6,9 @@ min_players = 40 // To avoid shafting lowpop category = EVENT_CATEGORY_HEALTH description = "A random crewmember's heart gives out." + admin_setup = /datum/event_admin_setup/heart_attack ///Candidates for recieving a healthy dose of heart disease var/list/heart_attack_candidates = list() - ///Number of candidates to be smote - var/quantity = 1 /datum/round_event_control/heart_attack/can_spawn_event(players_amt) . = ..() @@ -19,17 +18,6 @@ if(length(heart_attack_candidates)) return TRUE -/datum/round_event_control/heart_attack/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - generate_candidates() //can_spawn_event() is bypassed by admin_setup, so this makes sure that the candidates are still generated - - if(!length(heart_attack_candidates)) - message_admins("There are no candidates eligible to recieve a heart attack!") - return ADMIN_CANCEL_EVENT - quantity = tgui_input_number(usr, "There are [length(heart_attack_candidates)] crewmembers eligible for a heart attack. Please select how many people's days you wish to ruin.", "Shia Hato Atakku!", 1, length(heart_attack_candidates)) - /** * Performs initial analysis of which living players are eligible to be selected for a heart attack. * @@ -52,19 +40,17 @@ ///A list of prime candidates for heart attacking var/list/victims = list() ///Number of heart attacks to distribute - var/attacks_left = 1 + var/quantity = 1 + /datum/round_event/heart_attack/start() - var/datum/round_event_control/heart_attack/heart_attack_event = control + var/datum/round_event_control/heart_attack/heart_control = control + victims += heart_control.heart_attack_candidates + heart_control.heart_attack_candidates.Cut() - attacks_left = heart_attack_event.quantity - victims += heart_attack_event.heart_attack_candidates - heart_attack_event.heart_attack_candidates.Cut() - heart_attack_event.quantity = 1 - - while(attacks_left > 0 && length(victims)) + while(quantity > 0 && length(victims)) if(attack_heart()) - attacks_left-- + quantity-- /** * Picks a victim from a list and attempts to give them a heart attack @@ -91,3 +77,19 @@ victims -= winner return TRUE return FALSE + +/datum/event_admin_setup/heart_attack + ///Number of candidates to be smote + var/quantity = 1 + +/datum/event_admin_setup/heart_attack/prompt_admins() + var/datum/round_event_control/heart_attack/heart_control = event_control + heart_control.generate_candidates() //can_spawn_event() is bypassed by admin_setup, so this makes sure that the candidates are still generated + + if(!length(heart_control.heart_attack_candidates)) + tgui_alert(usr, "There are no candidates eligible to recieve a heart attack!", "Error") + return ADMIN_CANCEL_EVENT + quantity = tgui_input_number(usr, "There are [length(heart_control.heart_attack_candidates)] crewmembers eligible for a heart attack. Please select how many people's days you wish to ruin.", "Shia Hato Atakku!", 1, length(heart_control.heart_attack_candidates)) + +/datum/event_admin_setup/heart_attack/apply_to_event(datum/round_event/heart_attack/event) + event.quantity = quantity diff --git a/code/modules/events/immovable_rod.dm b/code/modules/events/immovable_rod/immovable_rod.dm similarity index 82% rename from code/modules/events/immovable_rod.dm rename to code/modules/events/immovable_rod/immovable_rod.dm index 46500a6bc1b..08453f73837 100644 --- a/code/modules/events/immovable_rod.dm +++ b/code/modules/events/immovable_rod/immovable_rod.dm @@ -1,51 +1,4 @@ -/* -Immovable rod random event. -The rod will spawn at some location outside the station, and travel in a straight line to the opposite side of the station -Everything solid in the way will be ex_act()'d -In my current plan for it, 'solid' will be defined as anything with density == 1 - ---NEOFite -*/ - -/datum/round_event_control/immovable_rod - name = "Immovable Rod" - typepath = /datum/round_event/immovable_rod - min_players = 15 - max_occurrences = 5 - var/atom/special_target - var/force_looping = FALSE - category = EVENT_CATEGORY_SPACE - description = "The station passes through an immovable rod." - -/datum/round_event_control/immovable_rod/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return - - var/aimed = tgui_alert(usr,"Aimed at current location?", "Sniperod", list("Yes", "No")) - if(aimed == "Yes") - special_target = get_turf(usr) - var/looper = tgui_alert(usr,"Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", list("Yes", "No")) - if(looper == "Yes") - force_looping = TRUE - message_admins("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") - log_admin("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") - -/datum/round_event/immovable_rod - announce_when = 5 - -/datum/round_event/immovable_rod/announce(fake) - priority_announce("What the fuck was that?!", "General Alert") - -/datum/round_event/immovable_rod/start() - var/datum/round_event_control/immovable_rod/our_controller = control - var/startside = pick(GLOB.cardinals) - var/turf/end_turf = get_edge_target_turf(get_random_station_turf(), turn(startside, 180)) - var/turf/start_turf = spaceDebrisStartLoc(startside, end_turf.z) - var/atom/rod = new /obj/effect/immovablerod(start_turf, end_turf, our_controller.special_target, our_controller.force_looping) - our_controller.special_target = null //Cleanup for future event rolls. - our_controller.force_looping = FALSE - announce_to_ghosts(rod) - +/// "What the fuck was that?!" /obj/effect/immovablerod name = "immovable rod" desc = "What the fuck is that?" diff --git a/code/modules/events/immovable_rod/immovable_rod_event.dm b/code/modules/events/immovable_rod/immovable_rod_event.dm new file mode 100644 index 00000000000..a21c77d3e89 --- /dev/null +++ b/code/modules/events/immovable_rod/immovable_rod_event.dm @@ -0,0 +1,47 @@ +/// Immovable rod random event. +/// The rod will spawn at some location outside the station, and travel in a straight line to the opposite side of the station +/datum/round_event_control/immovable_rod + name = "Immovable Rod" + typepath = /datum/round_event/immovable_rod + min_players = 15 + max_occurrences = 5 + category = EVENT_CATEGORY_SPACE + description = "The station passes through an immovable rod." + admin_setup = /datum/event_admin_setup/immovable_rod + +/datum/round_event/immovable_rod + announce_when = 5 + /// Admins can pick a spot the rod will aim for. + var/atom/special_target + /// Admins can also force it to loop around forever, or at least until the RD gets their hands on it. + var/force_looping = FALSE + +/datum/round_event/immovable_rod/announce(fake) + priority_announce("What the fuck was that?!", "General Alert") + +/datum/round_event/immovable_rod/start() + var/startside = pick(GLOB.cardinals) + var/turf/end_turf = get_edge_target_turf(get_random_station_turf(), turn(startside, 180)) + var/turf/start_turf = spaceDebrisStartLoc(startside, end_turf.z) + var/atom/rod = new /obj/effect/immovablerod(start_turf, end_turf, special_target, force_looping) + announce_to_ghosts(rod) + +/datum/event_admin_setup/immovable_rod + /// Admins can pick a spot the rod will aim for. + var/atom/special_target + /// Admins can also force it to loop around forever, or at least until the RD gets their hands on it. + var/force_looping = FALSE + +/datum/event_admin_setup/immovable_rod/prompt_admins() + var/aimed = tgui_alert(usr,"Aimed at current location?", "Sniperod", list("Yes", "No")) + if(aimed == "Yes") + special_target = get_turf(usr) + var/looper = tgui_alert(usr,"Would you like this rod to force-loop across space z-levels?", "Loopy McLoopface", list("Yes", "No")) + if(looper == "Yes") + force_looping = TRUE + message_admins("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") + log_admin("[key_name_admin(usr)] has aimed an immovable rod [force_looping ? "(forced looping)" : ""] at [AREACOORD(special_target)].") + +/datum/event_admin_setup/immovable_rod/apply_to_event(datum/round_event/immovable_rod/event) + event.special_target = special_target + event.force_looping = force_looping diff --git a/code/modules/events/mass_hallucination.dm b/code/modules/events/mass_hallucination.dm index d2ccc2d49e1..188234efd3d 100644 --- a/code/modules/events/mass_hallucination.dm +++ b/code/modules/events/mass_hallucination.dm @@ -6,71 +6,36 @@ max_occurrences = 2 min_players = 1 category = EVENT_CATEGORY_HEALTH + admin_setup = /datum/event_admin_setup/mass_hallucination +/datum/round_event/mass_hallucination + fakeable = FALSE /// For admins, what hallucination did we pick var/admin_forced_hallucination /// For admins, what arguments are we passing to said hallucination var/list/admin_forced_args -/datum/round_event_control/mass_hallucination/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - var/force = tgui_alert(usr, "Do you want to force a hallucination?", name, list("Yes", "No", "Cancel")) - if(force == "Cancel") - return ADMIN_CANCEL_EVENT - if(force != "Yes") - return - - var/force_what = tgui_alert(usr, "Generic hallucination or Custom configured delusion? (Delusions are those which make people appear as other mobs)", name, list("Hallucination", "Custom Delusion", "Cancel")) - switch(force_what) - if("Cancel") - return ADMIN_CANCEL_EVENT - - if("Hallucination") - var/chosen = select_hallucination_type(admin, "What hallucination should be forced for [name]?", name) - if(!chosen || !check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - admin_forced_hallucination = chosen - - if("Custom Delusion") - var/list/chosen_args = create_delusion(admin) - if(!length(chosen_args) || !check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - admin_forced_hallucination = chosen_args[1] - admin_forced_args = chosen_args.Copy(3) - -/datum/round_event/mass_hallucination - fakeable = FALSE - /datum/round_event/mass_hallucination/start() - var/datum/round_event_control/mass_hallucination/our_controller = control - - var/picked_hallucination = our_controller?.admin_forced_hallucination - var/list/other_args = our_controller?.admin_forced_args - - if(!picked_hallucination) + if(!admin_forced_hallucination) var/category_to_pick_from = rand(1, 10) switch(category_to_pick_from) if(1) // Send the same sound to everyone - picked_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/fake_sound/normal) + admin_forced_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/fake_sound/normal) if(2) // Send the same sound to everyone, but weird - picked_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/fake_sound/weird) + admin_forced_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/fake_sound/weird) if(3) // Send the same message to everyone - picked_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/station_message) + admin_forced_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/station_message) if(4) // Send the same delusion to everyone, but... - picked_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/delusion/preset) + admin_forced_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/delusion/preset) // The delusion will affect everyone BUT the hallucinator. - other_args = list( + admin_forced_args = list( duration = 30 SECONDS, skip_nearby = FALSE, affects_us = FALSE, @@ -80,9 +45,9 @@ if(5) // Send the same delusion to everyone, but... - picked_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/delusion/preset) + admin_forced_hallucination = get_random_valid_hallucination_subtype(/datum/hallucination/delusion/preset) // The delusion will affect only the hallucinator. - other_args = list( + admin_forced_args = list( duration = 45 SECONDS, skip_nearby = FALSE, affects_us = TRUE, @@ -103,14 +68,14 @@ /datum/hallucination/xeno_attack, ) - picked_hallucination = pick(generic_hallucinations) + admin_forced_hallucination = pick(generic_hallucinations) - if(!picked_hallucination) - CRASH("[type] couldn't find a hallucination to play. (Got: [picked_hallucination], Picked category: [category_to_pick_from])") + if(!admin_forced_hallucination) + CRASH("[type] couldn't find a hallucination to play. (Got: [admin_forced_hallucination], Picked category: [category_to_pick_from])") - var/list/hallucination_args = list(picked_hallucination, "mass hallucination") - if(islist(other_args)) - hallucination_args += other_args + var/list/hallucination_args = list(admin_forced_hallucination, "mass hallucination") + if(islist(admin_forced_args)) + hallucination_args += admin_forced_args // We'll only hallucinate for carbons now, even though livings can hallucinate just fine in most cases. for(var/mob/living/carbon/hallucinating as anything in GLOB.carbon_list) @@ -129,7 +94,39 @@ // Not using the wrapper here because we already have a list / arglist hallucinating._cause_hallucination(hallucination_args) -/datum/round_event/mass_hallucination/end() - var/datum/round_event_control/mass_hallucination/our_controller = control - our_controller.admin_forced_hallucination = null - our_controller.admin_forced_args = null +/datum/event_admin_setup/mass_hallucination + /// For admins, what hallucination did we pick + var/admin_forced_hallucination + /// For admins, what arguments are we passing to said hallucination + var/list/admin_forced_args + +/datum/event_admin_setup/mass_hallucination/prompt_admins() + var/force = tgui_alert(usr, "Do you want to force a hallucination?", event_control.name, list("Yes", "No", "Cancel")) + if(force == "Cancel") + return ADMIN_CANCEL_EVENT + if(force != "Yes") + return + + var/force_what = tgui_alert(usr, "Generic hallucination or Custom configured delusion? (Delusions are those which make people appear as other mobs)", event_control.name, list("Hallucination", "Custom Delusion", "Cancel")) + switch(force_what) + if("Cancel") + return ADMIN_CANCEL_EVENT + + if("Hallucination") + var/chosen = select_hallucination_type(usr, "What hallucination should be forced for [event_control.name]?", event_control.name) + if(!chosen || !check_rights(R_FUN)) + return ADMIN_CANCEL_EVENT + + admin_forced_hallucination = chosen + + if("Custom Delusion") + var/list/chosen_args = create_delusion(usr) + if(!length(chosen_args) || !check_rights(R_FUN)) + return ADMIN_CANCEL_EVENT + + admin_forced_hallucination = chosen_args[HALLUCINATION_ARG_TYPE] + admin_forced_args = chosen_args.Copy(HALLUCINATION_ARGLIST) + +/datum/event_admin_setup/mass_hallucination/apply_to_event(datum/round_event/mass_hallucination/event) + event.admin_forced_hallucination = admin_forced_hallucination + event.admin_forced_args = admin_forced_args diff --git a/code/modules/events/sandstorm.dm b/code/modules/events/sandstorm.dm index d6a19b5d808..047fb0d5fc3 100644 --- a/code/modules/events/sandstorm.dm +++ b/code/modules/events/sandstorm.dm @@ -15,24 +15,7 @@ earliest_start = 35 MINUTES category = EVENT_CATEGORY_SPACE description = "A wave of space dust continually grinds down a side of the station." - ///Where will the sandstorm be coming from -- Established in admin_setup, passed down to round_event - var/start_side - -/datum/round_event_control/sandstorm/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - if(tgui_alert(usr, "Choose a side to powersand?", "I hate sand.", list("Yes", "No")) == "Yes") - var/chosen_direction = tgui_input_list(usr, "Pick one!","Rough, gets everywhere, coarse, etc.", list("Up", "Down", "Right", "Left")) - switch(chosen_direction) - if("Up") - start_side = NORTH - if("Down") - start_side = SOUTH - if("Right") - start_side = EAST - if("Left") - start_side = WEST + admin_setup = /datum/event_admin_setup/listed_options/sandstorm /datum/round_event/sandstorm start_when = 60 @@ -46,10 +29,7 @@ end_when = rand(110, 140) /datum/round_event/sandstorm/announce(fake) - var/datum/round_event_control/sandstorm/sandstorm_event = control - if(sandstorm_event.start_side) - start_side = sandstorm_event.start_side - else + if(!start_side) start_side = pick(GLOB.cardinals) var/start_side_text = "unknown" @@ -98,3 +78,21 @@ /datum/round_event/sandstorm_classic/tick() spawn_meteors(10, GLOB.meteors_dust) + +/datum/event_admin_setup/listed_options/sandstorm + input_text = "Choose a side to powersand?" + normal_run_option = "Random Sandstorm Direction" + +/datum/event_admin_setup/listed_options/sandstorm/get_list() + return list("Up", "Down", "Right", "Left") + +/datum/event_admin_setup/listed_options/sandstorm/apply_to_event(datum/round_event/sandstorm/event) + switch(chosen) + if("Up") + event.start_side = NORTH + if("Down") + event.start_side = SOUTH + if("Right") + event.start_side = EAST + if("Left") + event.start_side = WEST diff --git a/code/modules/events/scrubber_overflow.dm b/code/modules/events/scrubber_overflow.dm index 1fe0e07c588..153e10f23d8 100644 --- a/code/modules/events/scrubber_overflow.dm +++ b/code/modules/events/scrubber_overflow.dm @@ -6,6 +6,7 @@ min_players = 10 category = EVENT_CATEGORY_JANITORIAL description = "The scrubbers release a tide of mostly harmless froth." + admin_setup = /datum/event_admin_setup/listed_options/scrubber_overflow /datum/round_event/scrubber_overflow announce_when = 1 @@ -151,13 +152,6 @@ /datum/round_event_control/scrubber_overflow/custom/announce_deadchat(random) deadchat_broadcast(" has just been[random ? " randomly" : ""] triggered!", "Scrubber Overflow: [initial(custom_reagent.name)]", message_type=DEADCHAT_ANNOUNCEMENT) -/datum/round_event_control/scrubber_overflow/custom/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return - custom_reagent = tgui_input_list(usr, "Choose a reagent to flood.", "Choose a reagent.", sort_list(subtypesof(/datum/reagent), /proc/cmp_typepaths_asc)) - if (isnull(custom_reagent)) - return ADMIN_CANCEL_EVENT - /datum/round_event/scrubber_overflow/custom overflow_probability = 100 forced_reagent = /datum/reagent/consumable/ethanol/beer @@ -167,3 +161,12 @@ var/datum/round_event_control/scrubber_overflow/custom/event_controller = control forced_reagent = event_controller.custom_reagent return ..() + +/datum/event_admin_setup/listed_options/scrubber_overflow + normal_run_option = "Random Reagent" + +/datum/event_admin_setup/listed_options/scrubber_overflow/get_list() + return sort_list(subtypesof(/datum/reagent), /proc/cmp_typepaths_asc) + +/datum/event_admin_setup/listed_options/scrubber_overflow/apply_to_event(datum/round_event/scrubber_overflow/event) + event.forced_reagent = chosen diff --git a/code/modules/events/shuttle_catastrophe.dm b/code/modules/events/shuttle_catastrophe.dm index 79a230a2dff..ac79108c016 100644 --- a/code/modules/events/shuttle_catastrophe.dm +++ b/code/modules/events/shuttle_catastrophe.dm @@ -5,6 +5,7 @@ max_occurrences = 1 category = EVENT_CATEGORY_BUREAUCRATIC description = "Replaces the emergency shuttle with a random one." + admin_setup = /datum/event_admin_setup/warn_admin/shuttle_catastrophe /datum/round_event_control/shuttle_catastrophe/can_spawn_event(players) . = ..() @@ -19,13 +20,6 @@ return FALSE //don't remove all players when its already on station or going to centcom return TRUE -/datum/round_event_control/shuttle_catastrophe/admin_setup(mob/admin) - if(EMERGENCY_AT_LEAST_DOCKED || istype(SSshuttle.emergency, /obj/docking_port/mobile/emergency/shuttle_build)) - if(tgui_alert(usr, "WARNING: This will unload the currently docked emergency shuttle, and ERASE ANYTHING within it. Proceed anyways?", "How about a REAL catastrophe?", list("Yes", "No")) == "Yes") - message_admins("[admin.ckey] has forced a shuttle catastrophe while a shuttle was already docked.") //Just in case - else - return ADMIN_CANCEL_EVENT - /datum/round_event/shuttle_catastrophe var/datum/map_template/shuttle/new_shuttle @@ -63,3 +57,10 @@ SSshuttle.existing_shuttle = SSshuttle.emergency SSshuttle.action_load(new_shuttle, replace = TRUE) log_shuttle("Shuttle Catastrophe set a new shuttle, [new_shuttle.name].") + +/datum/event_admin_setup/warn_admin/shuttle_catastrophe + warning_text = "This will unload the currently docked emergency shuttle, and ERASE ANYTHING within it. Proceed anyways?" + snitch_text = "has forced a shuttle catastrophe while a shuttle was already docked." + +/datum/event_admin_setup/warn_admin/shuttle_catastrophe/should_warn() + return EMERGENCY_AT_LEAST_DOCKED || istype(SSshuttle.emergency, /obj/docking_port/mobile/emergency/shuttle_build) diff --git a/code/modules/events/shuttle_loan.dm b/code/modules/events/shuttle_loan.dm deleted file mode 100644 index 9f047863b50..00000000000 --- a/code/modules/events/shuttle_loan.dm +++ /dev/null @@ -1,345 +0,0 @@ -#define HIJACK_SYNDIE "syndies" -#define RUSKY_PARTY "ruskies" -#define SPIDER_GIFT "spiders" -#define DEPARTMENT_RESUPPLY "resupplies" -#define ANTIDOTE_NEEDED "disease" -#define PIZZA_DELIVERY "pizza" -#define ITS_HIP_TO "bees" -#define MY_GOD_JC "bomb" -#define PAPERS_PLEASE "paperwork" - -/datum/round_event_control/shuttle_loan - name = "Shuttle Loan" - typepath = /datum/round_event/shuttle_loan - max_occurrences = 3 - earliest_start = 7 MINUTES - category = EVENT_CATEGORY_BUREAUCRATIC - description = "If cargo accepts the offer, fills the shuttle with loot and/or enemies." - ///The types of loan offers that the crew can recieve. - var/list/shuttle_loan_offers = list( - ANTIDOTE_NEEDED, - DEPARTMENT_RESUPPLY, - HIJACK_SYNDIE, - ITS_HIP_TO, - MY_GOD_JC, - PIZZA_DELIVERY, - RUSKY_PARTY, - SPIDER_GIFT, - PAPERS_PLEASE, - ) - ///The types of loan events already run (and to be excluded if the event triggers). - var/list/run_events = list() - ///The admin-selected loan offer ID. - var/chosen_event - -/datum/round_event_control/shuttle_loan/can_spawn_event(players_amt) - . = ..() - - for(var/datum/round_event/running_event in SSevents.running) - if(istype(running_event, /datum/round_event/shuttle_loan)) //Make sure two of these don't happen at once. - return FALSE - -/datum/round_event_control/shuttle_loan/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - if(tgui_alert(usr, "Select a loan offer?", "Trade Offer:", list("Yes", "No")) == "Yes") - chosen_event = tgui_input_list(usr, "What deal would you like to offer the crew?", "Throw them a bone.", shuttle_loan_offers) - - for(var/datum/round_event/shuttle_loan/loan_event in SSevents.running) - loan_event.kill() //Force out the old event for a new one to take its place - -/datum/round_event/shuttle_loan - announce_when = 1 - end_when = 500 - var/dispatched = FALSE - var/dispatch_type = "none" - var/bonus_points = 10000 - var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble." - var/loan_type //for logging - -/datum/round_event/shuttle_loan/setup() - - for(var/datum/round_event_control/shuttle_loan/loan_event_control in SSevents.control) //We can't call control, because it hasn't been set yet - if(loan_event_control.chosen_event) //Pass down the admin selection and clean it for future use. - dispatch_type = loan_event_control.chosen_event - loan_event_control.chosen_event = null - else //Otherwise, generate and pick from the list of offerable offers. - var/list/loan_list = list() - loan_list += loan_event_control.shuttle_loan_offers - var/list/run_events = loan_event_control.run_events //Ask the round_event_control which loans have already been offered - loan_list -= run_events //Remove the already offered loans from the candidate list - if(!length(loan_list)) //If we somehow run out of loans, they all become available again - loan_list += loan_event_control.shuttle_loan_offers - run_events.Cut() - dispatch_type = pick(loan_list) //Pick a loan to offer - loan_event_control.run_events += dispatch_type //Regardless of admin selection, we add the event being run to the run_events list - -/datum/round_event/shuttle_loan/announce(fake) - SSshuttle.shuttle_loan = src - switch(dispatch_type) - if(HIJACK_SYNDIE) - priority_announce("Cargo: The syndicate are trying to infiltrate your station. If you let them hijack your cargo shuttle, you'll save us a headache.","CentCom Counterintelligence") - if(RUSKY_PARTY) - priority_announce("Cargo: A group of angry Russians want to have a party. Can you send them your cargo shuttle then make them disappear?","CentCom Russian Outreach Program") - if(SPIDER_GIFT) - priority_announce("Cargo: The Spider Clan has sent us a mysterious gift. Can we ship it to you to see what's inside?","CentCom Diplomatic Corps") - if(DEPARTMENT_RESUPPLY) - priority_announce("Cargo: Seems we've ordered doubles of our department resupply packages this month. Can we send them to you?","CentCom Supply Department") - thanks_msg = "The cargo shuttle should return in five minutes." - bonus_points = 0 - if(ANTIDOTE_NEEDED) - priority_announce("Cargo: Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples.", "CentCom Research Initiatives") - if(PIZZA_DELIVERY) - priority_announce("Cargo: It looks like a neighbouring station accidentally delivered their pizza to you instead.", "CentCom Spacepizza Division") - thanks_msg = "The cargo shuttle should return in five minutes." - bonus_points = 0 - if(ITS_HIP_TO) - priority_announce("Cargo: One of our freighters carrying a bee shipment has been attacked by eco-terrorists. Can you clean up the mess for us?", "CentCom Janitorial Division") - bonus_points = 20000 //Toxin bees can be unbeelievably lethal - if(MY_GOD_JC) - priority_announce("Cargo: We have discovered an active Syndicate bomb near our VIP shuttle's fuel lines. If you feel up to the task, we will pay you for defusing it.", "CentCom Security Division") - thanks_msg = "Live explosive ordnance incoming via supply shuttle. Evacuating cargo bay is recommended." - bonus_points = 45000 //If you mess up, people die and the shuttle gets turned into swiss cheese - if(PAPERS_PLEASE) - priority_announce("Cargo: A neighboring station needs some help handling some paperwork. Could you help process it for us?", "CentCom Paperwork Division") - thanks_msg = "The cargo shuttle should return in five minutes. Payment will be rendered when the paperwork is processed and returned." - bonus_points = 0 //Payout is made when the stamped papers are returned - else - log_game("Shuttle Loan event could not find [dispatch_type] event to offer.") - kill() - return - -/datum/round_event/shuttle_loan/proc/loan_shuttle() - priority_announce(thanks_msg, "Cargo shuttle commandeered by CentCom.") - - dispatched = TRUE - var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) - if(D) - D.adjust_money(bonus_points) - end_when = activeFor + 1 - - SSshuttle.supply.mode = SHUTTLE_CALL - SSshuttle.supply.destination = SSshuttle.getDock("cargo_home") - SSshuttle.supply.setTimer(3000) - - switch(dispatch_type) - if(HIJACK_SYNDIE) - SSshuttle.centcom_message += "Syndicate hijack team incoming." - loan_type = "Syndicate boarding party" - if(RUSKY_PARTY) - SSshuttle.centcom_message += "Partying Russians incoming." - loan_type = "Russian party squad" - if(SPIDER_GIFT) - SSshuttle.centcom_message += "Spider Clan gift incoming." - loan_type = "Shuttle full of spiders" - if(DEPARTMENT_RESUPPLY) - SSshuttle.centcom_message += "Department resupply incoming." - loan_type = "Resupply packages" - if(ANTIDOTE_NEEDED) - SSshuttle.centcom_message += "Virus samples incoming." - loan_type = "Virus shuttle" - if(PIZZA_DELIVERY) - SSshuttle.centcom_message += "Pizza delivery for [station_name()]" - loan_type = "Pizza delivery" - if(ITS_HIP_TO) - SSshuttle.centcom_message += "Biohazard cleanup incoming." - loan_type = "Shuttle full of bees" - if(MY_GOD_JC) - SSshuttle.centcom_message += "Live explosive ordnance incoming. Exercise extreme caution." - loan_type = "Shuttle with a ticking bomb" - if(PAPERS_PLEASE) - SSshuttle.centcom_message += "Paperwork incoming." - loan_type = "Paperwork shipment" - - log_game("Shuttle loan event firing with type '[loan_type]'.") - -/datum/round_event/shuttle_loan/tick() - if(dispatched) - if(SSshuttle.supply.mode != SHUTTLE_IDLE) - end_when = activeFor - else - end_when = activeFor + 1 - -/datum/round_event/shuttle_loan/end() - if(SSshuttle.shuttle_loan && SSshuttle.shuttle_loan.dispatched) - //make sure the shuttle was dispatched in time - SSshuttle.shuttle_loan = null - - var/list/empty_shuttle_turfs = list() - var/list/area/shuttle/shuttle_areas = SSshuttle.supply.shuttle_areas - for(var/place in shuttle_areas) - var/area/shuttle/shuttle_area = place - for(var/turf/open/floor/T in shuttle_area) - if(T.is_blocked_turf()) - continue - empty_shuttle_turfs += T - if(!empty_shuttle_turfs.len) - return - - var/list/shuttle_spawns = list() - switch(dispatch_type) - if(HIJACK_SYNDIE) - var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops] - pack.generate(pick_n_take(empty_shuttle_turfs)) - - shuttle_spawns.Add(/mob/living/basic/syndicate/ranged/infiltrator) - shuttle_spawns.Add(/mob/living/basic/syndicate/ranged/infiltrator) - if(prob(75)) - shuttle_spawns.Add(/mob/living/basic/syndicate/ranged/infiltrator) - if(prob(50)) - shuttle_spawns.Add(/mob/living/basic/syndicate/ranged/infiltrator) - - if(RUSKY_PARTY) - var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/service/party] - pack.generate(pick_n_take(empty_shuttle_turfs)) - - shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian/ranged) //drops a mateba - shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear/russian) - if(prob(75)) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/russian) - if(prob(50)) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/bear/russian) - - if(SPIDER_GIFT) - var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops] - pack.generate(pick_n_take(empty_shuttle_turfs)) - - shuttle_spawns.Add(/mob/living/simple_animal/hostile/giant_spider) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/giant_spider) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/giant_spider/nurse) - if(prob(50)) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/giant_spider/hunter) - - var/turf/T = pick_n_take(empty_shuttle_turfs) - - new /obj/effect/decal/remains/human(T) - new /obj/item/clothing/shoes/jackboots/fast(T) - new /obj/item/clothing/mask/balaclava(T) - - for(var/i in 1 to 5) - T = pick_n_take(empty_shuttle_turfs) - new /obj/structure/spider/stickyweb(T) - - if(ANTIDOTE_NEEDED) - var/obj/effect/mob_spawn/corpse/human/assistant/infected_assistant = pick(/obj/effect/mob_spawn/corpse/human/assistant/beesease_infection, /obj/effect/mob_spawn/corpse/human/assistant/brainrot_infection, /obj/effect/mob_spawn/corpse/human/assistant/spanishflu_infection) - var/turf/T - for(var/i in 1 to 10) - if(prob(15)) - shuttle_spawns.Add(/obj/item/reagent_containers/cup/bottle) - else if(prob(15)) - shuttle_spawns.Add(/obj/item/reagent_containers/syringe) - else if(prob(25)) - shuttle_spawns.Add(/obj/item/shard) - T = pick_n_take(empty_shuttle_turfs) - new infected_assistant(T) - shuttle_spawns.Add(/obj/structure/closet/crate) - shuttle_spawns.Add(/obj/item/reagent_containers/cup/bottle/pierrot_throat) - shuttle_spawns.Add(/obj/item/reagent_containers/cup/bottle/magnitis) - - if(DEPARTMENT_RESUPPLY) - var/list/crate_types = list( - /datum/supply_pack/emergency/equipment, - /datum/supply_pack/security/supplies, - /datum/supply_pack/organic/food, - /datum/supply_pack/emergency/weedcontrol, - /datum/supply_pack/engineering/tools, - /datum/supply_pack/engineering/engiequipment, - /datum/supply_pack/science/robotics, - /datum/supply_pack/science/plasma, - /datum/supply_pack/medical/supplies - ) - for(var/crate in crate_types) - var/datum/supply_pack/pack = SSshuttle.supply_packs[crate] - pack.generate(pick_n_take(empty_shuttle_turfs)) - - for(var/i in 1 to 5) - var/decal = pick(/obj/effect/decal/cleanable/food/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil) - new decal(pick_n_take(empty_shuttle_turfs)) - if(PIZZA_DELIVERY) - var/naughtypizza = list(/obj/item/pizzabox/bomb,/obj/item/pizzabox/margherita/robo) //oh look another blaklist, for pizza nonetheless! - var/nicepizza = list(/obj/item/pizzabox/margherita, /obj/item/pizzabox/meat, /obj/item/pizzabox/vegetable, /obj/item/pizzabox/mushroom) - for(var/i in 1 to 6) - shuttle_spawns.Add(pick(prob(5) ? naughtypizza : nicepizza)) - if(ITS_HIP_TO) - var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/hydroponics/beekeeping_fullkit] - pack.generate(pick_n_take(empty_shuttle_turfs)) - - shuttle_spawns.Add(/obj/effect/mob_spawn/corpse/human/bee_terrorist) - shuttle_spawns.Add(/obj/effect/mob_spawn/corpse/human/cargo_tech) - shuttle_spawns.Add(/obj/effect/mob_spawn/corpse/human/cargo_tech) - shuttle_spawns.Add(/obj/effect/mob_spawn/corpse/human/nanotrasensoldier) - shuttle_spawns.Add(/obj/item/gun/ballistic/automatic/pistol/no_mag) - shuttle_spawns.Add(/obj/item/gun/ballistic/automatic/pistol/m1911/no_mag) - shuttle_spawns.Add(/obj/item/honey_frame) - shuttle_spawns.Add(/obj/item/honey_frame) - shuttle_spawns.Add(/obj/item/honey_frame) - shuttle_spawns.Add(/obj/structure/beebox/unwrenched) - shuttle_spawns.Add(/obj/item/queen_bee/bought) - shuttle_spawns.Add(/obj/structure/closet/crate/hydroponics) - - for(var/i in 1 to 8) - shuttle_spawns.Add(/mob/living/simple_animal/hostile/bee/toxin) - - for(var/i in 1 to 5) - var/decal = pick(/obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/insectguts) - new decal(pick_n_take(empty_shuttle_turfs)) - - for(var/i in 1 to 10) - var/casing = /obj/item/ammo_casing/spent - new casing(pick_n_take(empty_shuttle_turfs)) - - if(MY_GOD_JC) - shuttle_spawns.Add(/obj/machinery/syndicatebomb/shuttle_loan) - if(prob(95)) - shuttle_spawns.Add(/obj/item/paper/fluff/cargo/bomb) - else - shuttle_spawns.Add(/obj/item/paper/fluff/cargo/bomb/allyourbase) - - if(PAPERS_PLEASE) - shuttle_spawns += subtypesof(/obj/item/paperwork) - typesof(/obj/item/paperwork/photocopy) - typesof(/obj/item/paperwork/ancient) - - var/false_positive = 0 - while(shuttle_spawns.len && empty_shuttle_turfs.len) - var/turf/T = pick_n_take(empty_shuttle_turfs) - if(T.contents.len && false_positive < 5) - false_positive++ - continue - - var/spawn_type = pick_n_take(shuttle_spawns) - new spawn_type(T) - -//items that appear only in shuttle loan events - -/obj/item/storage/belt/fannypack/yellow/bee_terrorist/PopulateContents() - new /obj/item/grenade/c4 (src) - new /obj/item/reagent_containers/pill/cyanide(src) - new /obj/item/grenade/chem_grenade/facid(src) - -/obj/item/paper/fluff/bee_objectives - name = "Objectives of a Bee Liberation Front Operative" - default_raw_text = "Objective #1. Liberate all bees on the NT transport vessel 2416/B. Success!
Objective #2. Escape alive. Failed." - -/obj/machinery/syndicatebomb/shuttle_loan/Initialize(mapload) - . = ..() - set_anchored(TRUE) - timer_set = rand(480, 600) //once the supply shuttle docks (after 5 minutes travel time), players have between 3-5 minutes to defuse the bomb - activate() - update_appearance() - -/obj/item/paper/fluff/cargo/bomb - name = "hastly scribbled note" - default_raw_text = "GOOD LUCK!" - -/obj/item/paper/fluff/cargo/bomb/allyourbase - default_raw_text = "Somebody set us up the bomb!" - -#undef HIJACK_SYNDIE -#undef RUSKY_PARTY -#undef SPIDER_GIFT -#undef DEPARTMENT_RESUPPLY -#undef ANTIDOTE_NEEDED -#undef PIZZA_DELIVERY -#undef ITS_HIP_TO -#undef MY_GOD_JC diff --git a/code/modules/events/shuttle_loan/shuttle_loan_datum.dm b/code/modules/events/shuttle_loan/shuttle_loan_datum.dm new file mode 100644 index 00000000000..ba85a41132a --- /dev/null +++ b/code/modules/events/shuttle_loan/shuttle_loan_datum.dm @@ -0,0 +1,213 @@ +/// One of the potential shuttle loans you might recieve. +/datum/shuttle_loan_situation + /// Who sent the shuttle + var/sender = "Centcom" + /// What they said about it. + var/announcement_text = "Unset announcement text" + /// What the shuttle says about it. + var/shuttle_transit_text = "Unset transit text" + /// Supply points earned for taking the deal. + var/bonus_points = 10000 + /// Response for taking the deal. + var/thanks_msg = "The cargo shuttle should return in five minutes. Have some supply points for your trouble." + /// Small description of the loan for easier log reading. + var/logging_desc + +/datum/shuttle_loan_situation/New() + . = ..() + if(!logging_desc) + stack_trace("No logging blurb set for [src.type]!") + +/// Spawns paths added to `spawn_list`, and passes empty shuttle turfs so you can spawn more complicated things like dead bodies. +/datum/shuttle_loan_situation/proc/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + SHOULD_CALL_PARENT(FALSE) + CRASH("Unimplemented get_spawned_items() on [src.type].") + +/datum/shuttle_loan_situation/antidote + sender = "CentCom Research Initiatives" + announcement_text = "Your station has been chosen for an epidemiological research project. Send us your cargo shuttle to receive your research samples." + shuttle_transit_text = "Virus samples incoming." + logging_desc = "Virus shuttle" + +/datum/shuttle_loan_situation/antidote/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/obj/effect/mob_spawn/corpse/human/assistant/infected_assistant = pick(list( + /obj/effect/mob_spawn/corpse/human/assistant/beesease_infection, + /obj/effect/mob_spawn/corpse/human/assistant/brainrot_infection, + /obj/effect/mob_spawn/corpse/human/assistant/spanishflu_infection, + )) + for(var/i in 1 to 10) + if(prob(15)) + spawn_list.Add(/obj/item/reagent_containers/cup/bottle) + else if(prob(15)) + spawn_list.Add(/obj/item/reagent_containers/syringe) + else if(prob(25)) + spawn_list.Add(/obj/item/shard) + var/turf/assistant_turf = pick_n_take(empty_shuttle_turfs) + new infected_assistant(assistant_turf) + spawn_list.Add(/obj/structure/closet/crate) + spawn_list.Add(/obj/item/reagent_containers/cup/bottle/pierrot_throat) + spawn_list.Add(/obj/item/reagent_containers/cup/bottle/magnitis) + +/datum/shuttle_loan_situation/department_resupply + sender = "CentCom Supply Department" + announcement_text = "Seems we've ordered doubles of our department resupply packages this month. Can we send them to you?" + shuttle_transit_text = "Department resupply incoming." + thanks_msg = "The cargo shuttle should return in five minutes." + bonus_points = 0 + logging_desc = "Resupply packages" + +/datum/shuttle_loan_situation/department_resupply/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/list/crate_types = list( + /datum/supply_pack/emergency/equipment, + /datum/supply_pack/security/supplies, + /datum/supply_pack/organic/food, + /datum/supply_pack/emergency/weedcontrol, + /datum/supply_pack/engineering/tools, + /datum/supply_pack/engineering/engiequipment, + /datum/supply_pack/science/robotics, + /datum/supply_pack/science/plasma, + /datum/supply_pack/medical/supplies + ) + for(var/crate in crate_types) + var/datum/supply_pack/pack = SSshuttle.supply_packs[crate] + pack.generate(pick_n_take(empty_shuttle_turfs)) + + for(var/i in 1 to 5) + var/decal = pick(/obj/effect/decal/cleanable/food/flour, /obj/effect/decal/cleanable/robot_debris, /obj/effect/decal/cleanable/oil) + new decal(pick_n_take(empty_shuttle_turfs)) + +/datum/shuttle_loan_situation/department_resupply + sender = "CentCom Counterintelligence" + announcement_text = "The syndicate are trying to infiltrate your station. If you let them hijack your cargo shuttle, you'll save us a headache." + shuttle_transit_text = "Syndicate hijack team incoming." + logging_desc = "Syndicate boarding party" + +/datum/shuttle_loan_situation/department_resupply/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops] + pack.generate(pick_n_take(empty_shuttle_turfs)) + + spawn_list.Add(/mob/living/basic/syndicate/ranged/infiltrator) + spawn_list.Add(/mob/living/basic/syndicate/ranged/infiltrator) + if(prob(75)) + spawn_list.Add(/mob/living/basic/syndicate/ranged/infiltrator) + if(prob(50)) + spawn_list.Add(/mob/living/basic/syndicate/ranged/infiltrator) + +/datum/shuttle_loan_situation/lots_of_bees + sender = "CentCom Janitorial Division" + announcement_text = "One of our freighters carrying a bee shipment has been attacked by eco-terrorists. Can you clean up the mess for us?" + shuttle_transit_text = "Biohazard cleanup incoming." + bonus_points = 20000 //Toxin bees can be unbeelievably lethal + logging_desc = "Shuttle full of bees" + +/datum/shuttle_loan_situation/lots_of_bees/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/organic/hydroponics/beekeeping_fullkit] + pack.generate(pick_n_take(empty_shuttle_turfs)) + + spawn_list.Add(/obj/effect/mob_spawn/corpse/human/bee_terrorist) + spawn_list.Add(/obj/effect/mob_spawn/corpse/human/cargo_tech) + spawn_list.Add(/obj/effect/mob_spawn/corpse/human/cargo_tech) + spawn_list.Add(/obj/effect/mob_spawn/corpse/human/nanotrasensoldier) + spawn_list.Add(/obj/item/gun/ballistic/automatic/pistol/no_mag) + spawn_list.Add(/obj/item/gun/ballistic/automatic/pistol/m1911/no_mag) + spawn_list.Add(/obj/item/honey_frame) + spawn_list.Add(/obj/item/honey_frame) + spawn_list.Add(/obj/item/honey_frame) + spawn_list.Add(/obj/structure/beebox/unwrenched) + spawn_list.Add(/obj/item/queen_bee/bought) + spawn_list.Add(/obj/structure/closet/crate/hydroponics) + + for(var/i in 1 to 8) + spawn_list.Add(/mob/living/simple_animal/hostile/bee/toxin) + + for(var/i in 1 to 5) + var/decal = pick(/obj/effect/decal/cleanable/blood, /obj/effect/decal/cleanable/insectguts) + new decal(pick_n_take(empty_shuttle_turfs)) + + for(var/i in 1 to 10) + var/casing = /obj/item/ammo_casing/spent + new casing(pick_n_take(empty_shuttle_turfs)) + +/datum/shuttle_loan_situation/jc_a_bomb + sender = "CentCom Security Division" + announcement_text = "We have discovered an active Syndicate bomb near our VIP shuttle's fuel lines. If you feel up to the task, we will pay you for defusing it." + shuttle_transit_text = "Live explosive ordnance incoming. Exercise extreme caution." + thanks_msg = "Live explosive ordnance incoming via supply shuttle. Evacuating cargo bay is recommended." + bonus_points = 45000 //If you mess up, people die and the shuttle gets turned into swiss cheese + logging_desc = "Shuttle with a ticking bomb" + +/datum/shuttle_loan_situation/jc_a_bomb/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + spawn_list.Add(/obj/machinery/syndicatebomb/shuttle_loan) + if(prob(95)) + spawn_list.Add(/obj/item/paper/fluff/cargo/bomb) + else + spawn_list.Add(/obj/item/paper/fluff/cargo/bomb/allyourbase) + +/datum/shuttle_loan_situation/papers_please + sender = "CentCom Paperwork Division" + announcement_text = "A neighboring station needs some help handling some paperwork. Could you help process it for us?" + shuttle_transit_text = "Paperwork incoming." + thanks_msg = "The cargo shuttle should return in five minutes. Payment will be rendered when the paperwork is processed and returned." + bonus_points = 0 //Payout is made when the stamped papers are returned + logging_desc = "Paperwork shipment" + +/datum/shuttle_loan_situation/papers_please/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + spawn_list += subtypesof(/obj/item/paperwork) - typesof(/obj/item/paperwork/photocopy) - typesof(/obj/item/paperwork/ancient) + +/datum/shuttle_loan_situation/pizza_delivery + sender = "CentCom Spacepizza Division" + announcement_text = "It looks like a neighbouring station accidentally delivered their pizza to you instead." + shuttle_transit_text = "Pizza delivery!" + thanks_msg = "The cargo shuttle should return in five minutes." + bonus_points = 0 + logging_desc = "Pizza delivery" + +/datum/shuttle_loan_situation/pizza_delivery/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/naughtypizza = list(/obj/item/pizzabox/bomb, /obj/item/pizzabox/margherita/robo) //oh look another blacklist, for pizza nonetheless! + var/nicepizza = list(/obj/item/pizzabox/margherita, /obj/item/pizzabox/meat, /obj/item/pizzabox/vegetable, /obj/item/pizzabox/mushroom) + for(var/i in 1 to 6) + spawn_list.Add(pick(prob(5) ? naughtypizza : nicepizza)) + +/datum/shuttle_loan_situation/russian_party + sender = "CentCom Russian Outreach Program" + announcement_text = "A group of angry Russians want to have a party. Can you send them your cargo shuttle then make them disappear?" + shuttle_transit_text = "Partying Russians incoming." + logging_desc = "Russian party squad" + +/datum/shuttle_loan_situation/russian_party/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/service/party] + pack.generate(pick_n_take(empty_shuttle_turfs)) + + spawn_list.Add(/mob/living/simple_animal/hostile/russian) + spawn_list.Add(/mob/living/simple_animal/hostile/russian/ranged) //drops a mateba + spawn_list.Add(/mob/living/simple_animal/hostile/bear/russian) + if(prob(75)) + spawn_list.Add(/mob/living/simple_animal/hostile/russian) + if(prob(50)) + spawn_list.Add(/mob/living/simple_animal/hostile/bear/russian) + +/datum/shuttle_loan_situation/spider_gift + sender = "CentCom Diplomatic Corps" + announcement_text = "The Spider Clan has sent us a mysterious gift. Can we ship it to you to see what's inside?" + shuttle_transit_text = "Spider Clan gift incoming." + logging_desc = "Shuttle full of spiders" + +/datum/shuttle_loan_situation/spider_gift/spawn_items(list/spawn_list, list/empty_shuttle_turfs) + var/datum/supply_pack/pack = SSshuttle.supply_packs[/datum/supply_pack/emergency/specialops] + pack.generate(pick_n_take(empty_shuttle_turfs)) + + spawn_list.Add(/mob/living/simple_animal/hostile/giant_spider) + spawn_list.Add(/mob/living/simple_animal/hostile/giant_spider) + spawn_list.Add(/mob/living/simple_animal/hostile/giant_spider/nurse) + if(prob(50)) + spawn_list.Add(/mob/living/simple_animal/hostile/giant_spider/hunter) + + var/turf/victim_turf = pick_n_take(empty_shuttle_turfs) + + new /obj/effect/decal/remains/human(victim_turf) + new /obj/item/clothing/shoes/jackboots/fast(victim_turf) + new /obj/item/clothing/mask/balaclava(victim_turf) + + for(var/i in 1 to 5) + var/turf/web_turf = pick_n_take(empty_shuttle_turfs) + new /obj/structure/spider/stickyweb(web_turf) diff --git a/code/modules/events/shuttle_loan/shuttle_loan_event.dm b/code/modules/events/shuttle_loan/shuttle_loan_event.dm new file mode 100644 index 00000000000..8dd08772166 --- /dev/null +++ b/code/modules/events/shuttle_loan/shuttle_loan_event.dm @@ -0,0 +1,106 @@ + +/datum/round_event_control/shuttle_loan + name = "Shuttle Loan" + typepath = /datum/round_event/shuttle_loan + max_occurrences = 3 + earliest_start = 7 MINUTES + category = EVENT_CATEGORY_BUREAUCRATIC + description = "If cargo accepts the offer, fills the shuttle with loot and/or enemies." + ///The types of loan events already run (and to be excluded if the event triggers). + admin_setup = /datum/event_admin_setup/listed_options/shuttle_loan + var/list/run_situations = list() + +/datum/round_event_control/shuttle_loan/can_spawn_event(players_amt) + . = ..() + for(var/datum/round_event/running_event in SSevents.running) + if(istype(running_event, /datum/round_event/shuttle_loan)) //Make sure two of these don't happen at once. + return FALSE + +/datum/round_event/shuttle_loan + announce_when = 1 + end_when = 500 + /// what type of shuttle loan situation the station faces. + var/datum/shuttle_loan_situation/situation + /// Whether the station has let Centcom commandeer the shuttle yet. + var/dispatched = FALSE + +/datum/round_event/shuttle_loan/setup() + var/datum/round_event_control/shuttle_loan/loan_control = control + //by this point if situation is admin picked, it is a type, not an instance. + if(!situation) + var/list/valid_situations = subtypesof(/datum/shuttle_loan_situation) - loan_control.run_situations + if(!valid_situations.len) + //If we somehow run out of loans (fking campbell), they all become available again + loan_control.run_situations.Cut() + valid_situations = subtypesof(/datum/shuttle_loan_situation) + situation = pick(valid_situations) + + loan_control.run_situations.Add(situation) + situation = new situation() + +/datum/round_event/shuttle_loan/announce(fake) + priority_announce("Cargo: [situation.announcement_text]", situation.sender) + SSshuttle.shuttle_loan = src + +/datum/round_event/shuttle_loan/proc/loan_shuttle() + priority_announce(situation.thanks_msg, "Cargo shuttle commandeered by CentCom.") + + dispatched = TRUE + var/datum/bank_account/dep_account = SSeconomy.get_dep_account(ACCOUNT_CAR) + dep_account?.adjust_money(situation.bonus_points) + end_when = activeFor + 1 + + SSshuttle.supply.mode = SHUTTLE_CALL + SSshuttle.supply.destination = SSshuttle.getDock("cargo_home") + SSshuttle.supply.setTimer(3000) + SSshuttle.centcom_message += situation.shuttle_transit_text + + log_game("Shuttle loan event firing with type '[situation.logging_desc]'.") + +/datum/round_event/shuttle_loan/tick() + if(dispatched) + if(SSshuttle.supply.mode != SHUTTLE_IDLE) + end_when = activeFor + else + end_when = activeFor + 1 + +/datum/round_event/shuttle_loan/end() + if(!SSshuttle.shuttle_loan || !SSshuttle.shuttle_loan.dispatched) + return + //make sure the shuttle was dispatched in time + SSshuttle.shuttle_loan = null + + //get empty turfs + var/list/empty_shuttle_turfs = list() + var/list/area/shuttle/shuttle_areas = SSshuttle.supply.shuttle_areas + for(var/area/shuttle/shuttle_area as anything in shuttle_areas) + for(var/turf/open/floor/shuttle_turf in shuttle_area) + if(shuttle_turf.is_blocked_turf()) + continue + empty_shuttle_turfs += shuttle_turf + if(!empty_shuttle_turfs.len) + return + + //let the situation spawn its items + var/list/spawn_list = list() + situation.spawn_items(spawn_list, empty_shuttle_turfs) + + var/false_positive = 0 + while(spawn_list.len && empty_shuttle_turfs.len) + var/turf/spawn_turf = pick_n_take(empty_shuttle_turfs) + if(spawn_turf.contents.len && false_positive < 5) + false_positive++ + continue + var/spawn_type = pick_n_take(spawn_list) + new spawn_type(spawn_turf) + +/datum/event_admin_setup/listed_options/shuttle_loan + input_text = "Select a loan offer?" + +/datum/event_admin_setup/listed_options/shuttle_loan/get_list() + var/datum/round_event_control/shuttle_loan/loan_event = event_control + var/list/valid_situations = subtypesof(/datum/shuttle_loan_situation) - loan_event.run_situations + return valid_situations + +/datum/event_admin_setup/listed_options/shuttle_loan/apply_to_event(datum/round_event/shuttle_loan/event) + event.situation = chosen diff --git a/code/modules/events/shuttle_loan/shuttle_loan_items.dm b/code/modules/events/shuttle_loan/shuttle_loan_items.dm new file mode 100644 index 00000000000..ded82c6e1a6 --- /dev/null +++ b/code/modules/events/shuttle_loan/shuttle_loan_items.dm @@ -0,0 +1,23 @@ + +/obj/item/storage/belt/fannypack/yellow/bee_terrorist/PopulateContents() + new /obj/item/grenade/c4 (src) + new /obj/item/reagent_containers/pill/cyanide(src) + new /obj/item/grenade/chem_grenade/facid(src) + +/obj/item/paper/fluff/bee_objectives + name = "Objectives of a Bee Liberation Front Operative" + default_raw_text = "Objective #1. Liberate all bees on the NT transport vessel 2416/B. Success!
Objective #2. Escape alive. Failed." + +/obj/machinery/syndicatebomb/shuttle_loan/Initialize(mapload) + . = ..() + set_anchored(TRUE) + timer_set = rand(480, 600) //once the supply shuttle docks (after 5 minutes travel time), players have between 3-5 minutes to defuse the bomb + activate() + update_appearance() + +/obj/item/paper/fluff/cargo/bomb + name = "hastly scribbled note" + default_raw_text = "GOOD LUCK!" + +/obj/item/paper/fluff/cargo/bomb/allyourbase + default_raw_text = "Somebody set us up the bomb!" diff --git a/code/modules/events/stray_meteor.dm b/code/modules/events/stray_meteor.dm index 89ae470fa5b..a526dba7cb6 100644 --- a/code/modules/events/stray_meteor.dm +++ b/code/modules/events/stray_meteor.dm @@ -7,30 +7,17 @@ earliest_start = 20 MINUTES category = EVENT_CATEGORY_SPACE description = "Throw a random meteor somewhere near the station." - ///The selected meteor type if chosen through admin setup. - var/chosen_meteor - -/datum/round_event_control/stray_meteor/admin_setup() - if(!check_rights(R_FUN)) - return ADMIN_CANCEL_EVENT - - if(tgui_alert(usr, "Select a meteor?", "Plasuable Deniability!", list("Yes", "No")) == "Yes") - var/list/meteor_list = list() - meteor_list += subtypesof(/obj/effect/meteor) - chosen_meteor = tgui_input_list(usr, "Too lazy for buildmode?","Throw meteor", meteor_list) + admin_setup = /datum/event_admin_setup/listed_options/stray_meteor /datum/round_event/stray_meteor announce_when = 1 fakeable = FALSE //Already faked by meteors that miss + ///The selected meteor type if chosen through admin setup. + var/chosen_meteor /datum/round_event/stray_meteor/start() - var/datum/round_event_control/stray_meteor/meteor_event = control - if(meteor_event.chosen_meteor) - var/chosen_meteor = meteor_event.chosen_meteor - meteor_event.chosen_meteor = null - var/list/passed_meteor = list() - passed_meteor[chosen_meteor] = 1 - spawn_meteor(passed_meteor) + if(chosen_meteor) + spawn_meteor(list(chosen_meteor = 1)) else spawn_meteor(GLOB.meteors_stray) @@ -39,3 +26,13 @@ var/obj/effect/meteor/detected_meteor = pick(GLOB.meteor_list) //If we accidentally pick a meteor not spawned by the event, we're still technically not wrong var/sensor_name = detected_meteor.signature priority_announce("Our [sensor_name] sensors have detected an incoming signature approaching [GLOB.station_name]. Please brace for impact.", "Meteor Alert") + +/datum/event_admin_setup/listed_options/stray_meteor + input_text = "Select a meteor type?" + normal_run_option = "Random Meteor" + +/datum/event_admin_setup/listed_options/stray_meteor/get_list() + return subtypesof(/obj/effect/meteor) + +/datum/event_admin_setup/listed_options/stray_meteor/apply_to_event(datum/round_event/stray_meteor/event) + event.chosen_meteor = chosen diff --git a/code/modules/events/wizard/departmentrevolt.dm b/code/modules/events/wizard/departmentrevolt.dm index 4fedb8e784e..48929a0cc3c 100644 --- a/code/modules/events/wizard/departmentrevolt.dm +++ b/code/modules/events/wizard/departmentrevolt.dm @@ -1,3 +1,6 @@ + +#define RANDOM_DEPARTMENT "Random Department" + /datum/round_event_control/wizard/deprevolt //stationwide! name = "Departmental Uprising" weight = 0 //An order that requires order in a round of chaos was maybe not the best idea. Requiescat in pace departmental uprising August 2014 - March 2015 //hello motherfucker i fixed your shit in 2021 @@ -5,25 +8,39 @@ max_occurrences = 1 earliest_start = 0 MINUTES description = "A department is turned into an independent state." + admin_setup = /datum/event_admin_setup/department_revolt - ///manual choice of what department to revolt for admins to pick +/datum/round_event/wizard/deprevolt + ///which department is revolting? var/datum/job_department/picked_department - ///admin choice on whether to announce the department + /// Announce the separatist nation to the round? var/announce = FALSE - ///admin choice on whether this nation will have objectives to attack other nations, default true for !fun! + /// Is it going to try fighting other nations? var/dangerous_nation = TRUE -/datum/round_event_control/wizard/deprevolt/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return +/datum/round_event/wizard/deprevolt/start() + // no setup needed, this proc handles empty values. God i'm good (i wrote all of this) + create_separatist_nation(picked_department, announce, dangerous_nation) - var/list/options = list() +/datum/event_admin_setup/department_revolt + ///which department is revolting? + var/datum/job_department/picked_department + /// Announce the separatist nation to the round? + var/announce = FALSE + /// Is it going to try fighting other nations? + var/dangerous_nation = TRUE + +/datum/event_admin_setup/department_revolt/prompt_admins() + var/list/options = list("Random" = RANDOM_DEPARTMENT) var/list/pickable_departments = subtypesof(/datum/job_department) for(var/datum/job_department/dep as anything in pickable_departments) options[initial(dep.department_name)] = dep - picked_department = options[(input(usr,"Which department should revolt? Select none for a random department.","Select a department") as null|anything in options)] + picked_department = options[(tgui_input_list(usr,"Which department should revolt? Select none for a random department.","Select a department", options))] if(!picked_department) - return //eh just random they dont care + return ADMIN_CANCEL_EVENT + if(picked_department == RANDOM_DEPARTMENT) + picked_department = null + return var/announce_question = tgui_alert(usr, "Announce This New Independent State?", "Secession", list("Announce", "No Announcement")) if(announce_question == "Announce") @@ -33,6 +50,9 @@ if(dangerous_question == "No") dangerous_nation = FALSE -/datum/round_event/wizard/deprevolt/start() - var/datum/round_event_control/wizard/deprevolt/event_control = control - create_separatist_nation(event_control.picked_department, event_control.announce, event_control.dangerous_nation) +/datum/event_admin_setup/department_revolt/apply_to_event(datum/round_event/wizard/deprevolt/event) + event.picked_department = picked_department + event.announce = announce + event.dangerous_nation = dangerous_nation + +#undef RANDOM_DEPARTMENT diff --git a/code/modules/events/wizard/madness.dm b/code/modules/events/wizard/madness.dm index bcf40be2883..07d374ee879 100644 --- a/code/modules/events/wizard/madness.dm +++ b/code/modules/events/wizard/madness.dm @@ -4,26 +4,23 @@ typepath = /datum/round_event/wizard/madness earliest_start = 0 MINUTES description = "Reveals a horrifying truth to everyone, giving them a trauma." + admin_setup = /datum/event_admin_setup/text_input/madness - var/forced_secret - -/datum/round_event_control/wizard/madness/admin_setup(mob/admin) - if(!check_rights(R_FUN)) - return - - var/suggested = pick(strings(REDPILL_FILE, "redpill_questions")) - - forced_secret = (input(usr, "What horrifying truth will you reveal?", "Curse of Madness", sort_list(suggested)) as text|null) || suggested - -/datum/round_event/wizard/madness/start() - var/datum/round_event_control/wizard/madness/C = control - +/datum/round_event/wizard/madness + /// the horrifying truth sent to the crew, can be picked by admins. var/horrifying_truth - if(C.forced_secret) - horrifying_truth = C.forced_secret - C.forced_secret = null - else +/datum/round_event/wizard/madness/start() + if(!horrifying_truth) horrifying_truth = pick(strings(REDPILL_FILE, "redpill_questions")) curse_of_madness(null, horrifying_truth) + +/datum/event_admin_setup/text_input/madness + input_text = "What horrifying truth will you reveal?" + +/datum/event_admin_setup/text_input/madness/get_text_suggestion() + return pick(strings(REDPILL_FILE, "redpill_questions")) + +/datum/event_admin_setup/text_input/madness/apply_to_event(datum/round_event/wizard/madness/event) + event.horrifying_truth = chosen diff --git a/modular_skyrat/master_files/code/modules/events/disease_outbreak.dm b/modular_skyrat/master_files/code/modules/events/disease_outbreak.dm deleted file mode 100644 index 14d73eb506a..00000000000 --- a/modular_skyrat/master_files/code/modules/events/disease_outbreak.dm +++ /dev/null @@ -1,31 +0,0 @@ -//We cap max disease symptoms at 3 at a preset severity, making them transmissible no matter our round length. -/datum/round_event/disease_outbreak/advanced/start() - var/datum/round_event_control/disease_outbreak/advanced/disease_event = control - afflicted += disease_event.disease_candidates - disease_event.disease_candidates.Cut() //Clean the list after use - - if(disease_event.chosen_max_symptoms) - max_symptoms = disease_event.chosen_max_symptoms - disease_event.chosen_max_symptoms = null - else - max_symptoms = 3 //Consistent symptoms taking into account severity - - if(disease_event.chosen_severity) - max_severity = disease_event.chosen_severity - disease_event.chosen_severity = null - else - max_severity = 4 //Don't make it too severe or it won't have transmissibility - - var/datum/disease/advance/advanced_disease = new /datum/disease/advance/random(max_symptoms, max_severity) - - var/list/name_symptoms = list() //for feedback - for(var/datum/symptom/new_symptom in advanced_disease.symptoms) - name_symptoms += new_symptom.name - - var/mob/living/carbon/human/victim = pick_n_take(afflicted) - if(victim.ForceContractDisease(advanced_disease, FALSE)) - message_admins("An event has triggered a random advanced virus outbreak on [ADMIN_LOOKUPFLW(victim)]! It has these symptoms: [english_list(name_symptoms)]") - log_game("An event has triggered a random advanced virus outbreak on [key_name(victim)]! It has these symptoms: [english_list(name_symptoms)].") - announce_to_ghosts(victim) - else - log_game("An event attempted to trigger a random advanced virus outbreak on [key_name(victim)], but failed.") diff --git a/tgstation.dme b/tgstation.dme index b197201c60b..e4c2cf3c6ae 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2615,6 +2615,7 @@ #include "code\modules\antagonists\pirate\pirate_gangs.dm" #include "code\modules\antagonists\pirate\pirate_outfits.dm" #include "code\modules\antagonists\pirate\pirate_roles.dm" +#include "code\modules\antagonists\pirate\pirate_shuttle_equipment.dm" #include "code\modules\antagonists\pirate\pirate_special_items.dm" #include "code\modules\antagonists\pyro_slime\pyro_slime.dm" #include "code\modules\antagonists\revenant\haunted_item.dm" @@ -3198,6 +3199,7 @@ #include "code\modules\escape_menu\subsystem.dm" #include "code\modules\escape_menu\title.dm" #include "code\modules\events\_event.dm" +#include "code\modules\events\_event_admin_setup.dm" #include "code\modules\events\aurora_caelus.dm" #include "code\modules\events\brain_trauma.dm" #include "code\modules\events\brand_intelligence.dm" @@ -3215,7 +3217,6 @@ #include "code\modules\events\grey_tide.dm" #include "code\modules\events\grid_check.dm" #include "code\modules\events\heart_attack.dm" -#include "code\modules\events\immovable_rod.dm" #include "code\modules\events\ion_storm.dm" #include "code\modules\events\market_crash.dm" #include "code\modules\events\mass_hallucination.dm" @@ -3229,7 +3230,6 @@ #include "code\modules\events\scrubber_overflow.dm" #include "code\modules\events\shuttle_catastrophe.dm" #include "code\modules\events\shuttle_insurance.dm" -#include "code\modules\events\shuttle_loan.dm" #include "code\modules\events\spacevine.dm" #include "code\modules\events\spider_infestation.dm" #include "code\modules\events\stray_cargo.dm" @@ -3265,6 +3265,11 @@ #include "code\modules\events\holiday\halloween.dm" #include "code\modules\events\holiday\vday.dm" #include "code\modules\events\holiday\xmas.dm" +#include "code\modules\events\immovable_rod\immovable_rod.dm" +#include "code\modules\events\immovable_rod\immovable_rod_event.dm" +#include "code\modules\events\shuttle_loan\shuttle_loan_datum.dm" +#include "code\modules\events\shuttle_loan\shuttle_loan_event.dm" +#include "code\modules\events\shuttle_loan\shuttle_loan_items.dm" #include "code\modules\events\wizard\aid.dm" #include "code\modules\events\wizard\blobies.dm" #include "code\modules\events\wizard\curseditems.dm" @@ -5265,7 +5270,6 @@ #include "modular_skyrat\master_files\code\modules\clothing\under\jobs\security.dm" #include "modular_skyrat\master_files\code\modules\clothing\under\jobs\civilian\civilian.dm" #include "modular_skyrat\master_files\code\modules\clothing\under\jobs\civilian\suits.dm" -#include "modular_skyrat\master_files\code\modules\events\disease_outbreak.dm" #include "modular_skyrat\master_files\code\modules\events\spacevine.dm" #include "modular_skyrat\master_files\code\modules\food_and_drinks\recipes\food_mixtures.dm" #include "modular_skyrat\master_files\code\modules\jobs\departments\departments.dm"