Refactors Admin Setups on Forced Events + Refactors Vending Sentience + Refactors Shuttle Loans (#72998)

## About The Pull Request

- [x] TEST EVERYTHING
tested:
- Pirates
- Vending Machines
- Shuttle Catastrophe
- Anomalies
- Immovable Rod
- Sandstorms
- Scrubber Overflow
- Stray Meteor
- Madness
- Department Revolt (Well obviously, it is my super robust code after
all)
- Shuttle Loan
- Mass Hallucination
- Heart Attack
- False Alarm

Disease Outbreak is probably fine aha... It correctly reports that there
are no candidates before aborting.

#### The biggest change you'll notice is that some admin setup questions
allow you to let the game decide where previously you had to choose!

### Refactors Admin Setups on Forced Events

I need to refactor and datumize how admins set up special conditions on
forced events, so I did! Now `/datum/event_admin_setup` handles admin
settings, with a few prototypes to make it easier to give events admin
options in the future. This was exhausting and what 90% of the pr is.

### Refactors Vending Sentience

The code was so bad I could not datumize the admin part of it so I
cleaned it up, making a lot of things in the event get decided in
`setup()` where they should.

### Refactors Shuttle Loans

The code was so bad I could not datumize the admin part of it so I
cleaned it up AS WELL, by datumizing the shuttle loans. Should be easier
to add more types in the future, actually kinda stoked.

## Why It's Good For The Game

This is preparation for a tgui change to ForceEvent.ts an admin has
requested. Phew!

## Changelog
🆑
refactor: Refactored a bunch of admin-related event code, hopefully you
won't notice much
admin: ... But you specifically may notice some minor differences. Raw
inputs changed into tgui ones, minor soul removal, etc.
/🆑
This commit is contained in:
tralezab
2023-01-30 17:57:12 +00:00
committed by GitHub
parent eae6a343e3
commit bdf5e7b60a
25 changed files with 1255 additions and 1146 deletions
+13 -5
View File
@@ -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
+1 -1
View File
@@ -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
+21 -421
View File
@@ -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
@@ -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
+19 -15
View File
@@ -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 ..()
+83
View File
@@ -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
+18 -23
View File
@@ -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
+51 -58
View File
@@ -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
+48 -49
View File
@@ -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
+20 -19
View File
@@ -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
+24 -22
View File
@@ -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
@@ -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?"
@@ -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
+53 -56
View File
@@ -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
+20 -22
View File
@@ -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
+10 -7
View File
@@ -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!", "<b>Scrubber Overflow: [initial(custom_reagent.name)]</b>", 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
+8 -7
View File
@@ -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)
-344
View File
@@ -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 = "<b>Objective #1</b>. Liberate all bees on the NT transport vessel 2416/B. <b>Success!</b> <br><b>Objective #2</b>. Escape alive. <b>Failed.</b>"
/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
@@ -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)
@@ -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
@@ -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 = "<b>Objective #1</b>. Liberate all bees on the NT transport vessel 2416/B. <b>Success!</b> <br><b>Objective #2</b>. Escape alive. <b>Failed.</b>"
/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!"
+15 -18
View File
@@ -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
+32 -12
View File
@@ -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
+14 -17
View File
@@ -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
+7 -2
View File
@@ -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"