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/antagonists/pirate/pirate_event.dm b/code/modules/antagonists/pirate/pirate_event.dm index afbabec1a78..63e6c26f548 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,411 +80,22 @@ 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() + var/list/gang_choices = list("Random") -/obj/machinery/shuttle_scrambler/Initialize(mapload) - . = ..() - update_appearance() + for(var/datum/pirate_gang/possible_gang as anything in GLOB.pirate_gangs) + gang_choices[possible_gang.name] = possible_gang -/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) + 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] -/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 +/datum/event_admin_setup/pirates/apply_to_event(datum/round_event/pirates/event) + event.chosen_gang = chosen_gang 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 bcdd2d9b2f9..d1a68a554d5 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 @@ -112,20 +118,23 @@ 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++ 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) @@ -134,8 +143,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) @@ -146,12 +155,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 @@ -185,12 +188,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 @@ -276,7 +281,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 bea38262ab9..00000000000 --- a/code/modules/events/shuttle_loan.dm +++ /dev/null @@ -1,344 +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) - 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 - SSshuttle.shuttle_loan = src - -/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/tgstation.dme b/tgstation.dme index 4dbee8d90f1..0d90180660a 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2546,6 +2546,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" @@ -3129,6 +3130,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" @@ -3146,7 +3148,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" @@ -3161,7 +3162,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" @@ -3197,6 +3197,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"