mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 02:09:41 +00:00
Merge pull request #6072 from Mechoid/Start_Conversion_To_Good_RNG
[RNG is the new RNG] Converts a bunch of events to the Game Master datum system.
This commit is contained in:
@@ -1,26 +1,33 @@
|
||||
/proc/wormhole_event()
|
||||
/proc/wormhole_event(var/set_duration = 5 MINUTES, var/wormhole_duration_modifier = 1)
|
||||
spawn()
|
||||
var/list/pick_turfs = list()
|
||||
var/list/Z_choices = list()
|
||||
Z_choices |= using_map.get_map_levels(1, FALSE)
|
||||
for(var/turf/simulated/floor/T in turfs)
|
||||
if(T.z in using_map.station_levels)
|
||||
pick_turfs += T
|
||||
if(T.z in Z_choices)
|
||||
if(!T.block_tele)
|
||||
pick_turfs += T
|
||||
|
||||
if(pick_turfs.len)
|
||||
|
||||
var/wormhole_max_duration = round((5 MINUTES) * wormhole_duration_modifier)
|
||||
var/wormhole_min_duration = round((30 SECONDS) * wormhole_duration_modifier)
|
||||
|
||||
//All ready. Announce that bad juju is afoot.
|
||||
command_announcement.Announce("Space-time anomalies detected on the station. There is no additional data.", "Anomaly Alert", new_sound = 'sound/AI/spanomalies.ogg')
|
||||
|
||||
//prob(20) can be approximated to 1 wormhole every 5 turfs!
|
||||
//admittedly less random but totally worth it >_<
|
||||
var/event_duration = 3000 //~5 minutes in ticks
|
||||
var/number_of_selections = (pick_turfs.len/5)+1 //+1 to avoid division by zero!
|
||||
var/sleep_duration = round( event_duration / number_of_selections )
|
||||
var/event_duration = set_duration
|
||||
var/number_of_selections = round(pick_turfs.len/(4 * (Z_choices.len + 1)))+1 //+1 to avoid division by zero!
|
||||
var/sleep_duration = 0.2 SECONDS
|
||||
var/end_time = world.time + event_duration //the time by which the event should have ended
|
||||
|
||||
var/increment = max(1,round(number_of_selections/50))
|
||||
// world << "DEBUG: number_of_selections: [number_of_selections] | sleep_duration: [sleep_duration]"
|
||||
|
||||
var/i = 1
|
||||
while( 1 )
|
||||
var/index = 1
|
||||
for(var/I = 1 to number_of_selections)
|
||||
|
||||
//we've run into overtime. End the event
|
||||
if( end_time < world.time )
|
||||
@@ -31,26 +38,27 @@
|
||||
return
|
||||
|
||||
//loop it round
|
||||
i += increment
|
||||
i %= pick_turfs.len
|
||||
i++
|
||||
index += increment
|
||||
index %= pick_turfs.len
|
||||
index++
|
||||
|
||||
//get our enter and exit locations
|
||||
var/turf/simulated/floor/enter = pick_turfs[i]
|
||||
var/turf/simulated/floor/enter = pick_turfs[index]
|
||||
pick_turfs -= enter //remove it from pickable turfs list
|
||||
if( !enter || !istype(enter) ) continue //sanity
|
||||
|
||||
var/turf/simulated/floor/exit = pick(pick_turfs)
|
||||
pick_turfs -= exit
|
||||
// pick_turfs -= exit
|
||||
if( !exit || !istype(exit) ) continue //sanity
|
||||
|
||||
create_wormhole(enter,exit)
|
||||
create_wormhole(enter,exit,wormhole_min_duration,wormhole_max_duration)
|
||||
|
||||
sleep(sleep_duration) //have a well deserved nap!
|
||||
|
||||
|
||||
//maybe this proc can even be used as an admin tool for teleporting players without ruining immulsions?
|
||||
/proc/create_wormhole(var/turf/enter as turf, var/turf/exit as turf)
|
||||
/proc/create_wormhole(var/turf/enter as turf, var/turf/exit as turf, var/min_duration = 30 SECONDS, var/max_duration = 60 SECONDS)
|
||||
set waitfor = FALSE
|
||||
var/obj/effect/portal/P = new /obj/effect/portal( enter )
|
||||
P.target = exit
|
||||
P.creator = null
|
||||
@@ -58,5 +66,5 @@
|
||||
P.failchance = 0
|
||||
P.icon_state = "anom"
|
||||
P.name = "wormhole"
|
||||
spawn(rand(300,600))
|
||||
qdel(P)
|
||||
spawn(rand(min_duration,max_duration))
|
||||
qdel(P)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/var/global/account_hack_attempted = 0
|
||||
//var/global/account_hack_attempted = 0
|
||||
|
||||
/datum/event/money_hacker
|
||||
var/datum/money_account/affected_account
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/var/global/list/event_viruses = list() // so that event viruses are kept around for admin logs, rather than being GCed
|
||||
//var/global/list/event_viruses = list() // so that event viruses are kept around for admin logs, rather than being GCed
|
||||
|
||||
datum/event/viral_infection
|
||||
var/list/viruses = list()
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
|
||||
datum/event/viral_outbreak
|
||||
/datum/event/viral_outbreak
|
||||
var/severity = 1
|
||||
|
||||
datum/event/viral_outbreak/setup()
|
||||
/datum/event/viral_outbreak/setup()
|
||||
announceWhen = rand(0, 3000)
|
||||
endWhen = announceWhen + 1
|
||||
severity = rand(2, 4)
|
||||
|
||||
datum/event/viral_outbreak/announce()
|
||||
/datum/event/viral_outbreak/announce()
|
||||
command_alert("Confirmed outbreak of level 7 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert")
|
||||
world << sound('sound/AI/outbreak7.ogg')
|
||||
|
||||
datum/event/viral_outbreak/start()
|
||||
/datum/event/viral_outbreak/start()
|
||||
var/list/candidates = list() //list of candidate keys
|
||||
for(var/mob/living/carbon/human/G in player_list)
|
||||
if(G.client && G.stat != DEAD)
|
||||
|
||||
76
code/modules/gamemaster/actions/atmos_leak.dm
Normal file
76
code/modules/gamemaster/actions/atmos_leak.dm
Normal file
@@ -0,0 +1,76 @@
|
||||
/datum/gm_action/atmos_leak
|
||||
name = "atmospherics leak"
|
||||
departments = list(ROLE_ENGINEERING, ROLE_SYNTHETIC)
|
||||
var/area/target_area // Chosen target area
|
||||
var/area/target_turf // Chosen target turf in target_area
|
||||
var/gas_type // Chosen gas to release
|
||||
// Exclude these types and sub-types from targeting eligibilty
|
||||
var/list/area/excluded = list(
|
||||
/area/shuttle,
|
||||
/area/crew_quarters,
|
||||
/area/holodeck,
|
||||
/area/engineering/engine_room
|
||||
)
|
||||
|
||||
var/severity
|
||||
|
||||
// Decide which area will be targeted!
|
||||
/datum/gm_action/atmos_leak/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 8,
|
||||
EVENT_LEVEL_MODERATE = 5,
|
||||
EVENT_LEVEL_MAJOR = 3
|
||||
)
|
||||
|
||||
var/gas_choices = list("carbon_dioxide", "sleeping_agent") // Annoying
|
||||
if(severity >= EVENT_LEVEL_MODERATE)
|
||||
gas_choices += "phoron" // Dangerous
|
||||
if(severity >= EVENT_LEVEL_MAJOR)
|
||||
gas_choices += "volatile_fuel" // Dangerous and no default atmos setup!
|
||||
gas_type = pick(gas_choices)
|
||||
|
||||
var/list/area/grand_list_of_areas = get_station_areas(excluded)
|
||||
|
||||
// Okay, now lets try and pick a target! Lets try 10 times, otherwise give up
|
||||
for(var/i in 1 to 10)
|
||||
var/area/A = pick(grand_list_of_areas)
|
||||
if(is_area_occupied(A))
|
||||
log_debug("atmos_leak event: Rejected [A] because it is occupied.")
|
||||
continue
|
||||
// A good area, great! Lets try and pick a turf
|
||||
var/list/turfs = list()
|
||||
for(var/turf/simulated/floor/F in A)
|
||||
if(turf_clear(F))
|
||||
turfs += F
|
||||
if(turfs.len == 0)
|
||||
log_debug("atmos_leak event: Rejected [A] because it has no clear turfs.")
|
||||
continue
|
||||
target_area = A
|
||||
target_turf = pick(turfs)
|
||||
|
||||
// If we can't find a good target, give up
|
||||
if(!target_area)
|
||||
log_debug("atmos_leak event: Giving up after too many failures to pick target area")
|
||||
return
|
||||
|
||||
/datum/gm_action/atmos_leak/announce()
|
||||
if(target_area)
|
||||
command_announcement.Announce("Warning, hazardous [gas_data.name[gas_type]] gas leak detected in \the [target_area], evacuate the area.", "Hazard Alert")
|
||||
|
||||
/datum/gm_action/atmos_leak/start()
|
||||
if(!target_turf)
|
||||
return
|
||||
..()
|
||||
spawn(rand(0, 600))
|
||||
// Okay, time to actually put the gas in the room!
|
||||
// TODO - Would be nice to break a waste pipe perhaps?
|
||||
// TODO - Maybe having it released from a single point and thus causing airflow to blow stuff around
|
||||
|
||||
// Fow now just add a bunch of it to the air
|
||||
var/datum/gas_mixture/air_contents = new
|
||||
air_contents.temperature = T20C + ((severity - 1) * rand(-50, 50))
|
||||
air_contents.gas[gas_type] = 10 * MOLES_CELLSTANDARD
|
||||
target_turf.assume_air(air_contents)
|
||||
playsound(target_turf, 'sound/effects/smoke.ogg', 50, 1)
|
||||
|
||||
/datum/gm_action/atmos_leak/get_weight()
|
||||
return 15 + (metric.count_people_in_department(ROLE_ENGINEERING) * 10 + metric.count_people_in_department(ROLE_SYNTHETIC) * 30) // Synthetics are counted in higher value because they can wirelessly connect to alarms.
|
||||
28
code/modules/gamemaster/actions/blob.dm
Normal file
28
code/modules/gamemaster/actions/blob.dm
Normal file
@@ -0,0 +1,28 @@
|
||||
/datum/gm_action/blob
|
||||
name = "blob infestation"
|
||||
departments = list(ROLE_ENGINEERING, ROLE_SECURITY, ROLE_MEDICAL)
|
||||
chaotic = 25
|
||||
|
||||
var/obj/structure/blob/core/Blob
|
||||
|
||||
/datum/gm_action/blob/start()
|
||||
..()
|
||||
var/turf/T = pick(blobstart)
|
||||
|
||||
Blob = new /obj/structure/blob/core/random_medium(T)
|
||||
|
||||
/datum/gm_action/blob/announce()
|
||||
spawn(rand(600, 3000)) // 1-5 minute leeway for the blob to go un-detected.
|
||||
command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
|
||||
|
||||
/datum/gm_action/blob/get_weight()
|
||||
var/engineers = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
var/security = metric.count_people_in_department(ROLE_SECURITY)
|
||||
var/medical = metric.count_people_in_department(ROLE_MEDICAL)
|
||||
|
||||
var/assigned_staff = engineers + security
|
||||
if(engineers || security) // Medical only counts if one of the other two exists, and even then they count as half.
|
||||
assigned_staff += round(medical / 2)
|
||||
|
||||
var/weight = (max(assigned_staff - 2, 0) * 20) // An assigned staff count of 2 must be had to spawn a blob.
|
||||
return weight
|
||||
69
code/modules/gamemaster/actions/brand_intelligence.dm
Normal file
69
code/modules/gamemaster/actions/brand_intelligence.dm
Normal file
@@ -0,0 +1,69 @@
|
||||
/datum/gm_action/brand_intelligence
|
||||
name = "rampant vending machines"
|
||||
length = 30 MINUTES
|
||||
departments = list(ROLE_ENGINEERING, ROLE_EVERYONE)
|
||||
|
||||
var/list/obj/machinery/vending/vendingMachines = list()
|
||||
var/list/obj/machinery/vending/infectedVendingMachines = list()
|
||||
var/obj/machinery/vending/originMachine
|
||||
var/start_time = 0
|
||||
|
||||
var/active = FALSE // Are we currently infecting?
|
||||
|
||||
/datum/gm_action/brand_intelligence/announce()
|
||||
if(prob(90))
|
||||
command_announcement.Announce("An ongoing mass upload of malware for vendors has been detected onboard [station_name()], which appears to transmit \
|
||||
to other nearby vendors. The original infected machine is believed to be \a [originMachine.name].", "Vendor Service Alert")
|
||||
|
||||
/datum/gm_action/brand_intelligence/set_up()
|
||||
vendingMachines.Cut()
|
||||
infectedVendingMachines.Cut()
|
||||
|
||||
for(var/obj/machinery/vending/V in machines)
|
||||
if(isNotStationLevel(V.z)) continue
|
||||
vendingMachines.Add(V)
|
||||
|
||||
if(!vendingMachines.len)
|
||||
length = 0
|
||||
return
|
||||
|
||||
originMachine = pick(vendingMachines)
|
||||
vendingMachines.Remove(originMachine)
|
||||
originMachine.shut_up = 0
|
||||
originMachine.shoot_inventory = 1
|
||||
|
||||
start_time = world.time
|
||||
active = TRUE
|
||||
|
||||
/datum/gm_action/brand_intelligence/start()
|
||||
..()
|
||||
while(originMachine || active)
|
||||
if(!vendingMachines.len || !originMachine || originMachine.shut_up) //if every machine is infected, or if the original vending machine is missing or has it's voice switch flipped
|
||||
end()
|
||||
return
|
||||
|
||||
if(ISMULTIPLE(world.time - start_time, 5))
|
||||
if(prob(15))
|
||||
var/obj/machinery/vending/infectedMachine = pick(vendingMachines)
|
||||
vendingMachines.Remove(infectedMachine)
|
||||
infectedVendingMachines.Add(infectedMachine)
|
||||
infectedMachine.shut_up = 0
|
||||
infectedMachine.shoot_inventory = 1
|
||||
|
||||
if(ISMULTIPLE(world.time - start_time, 12))
|
||||
originMachine.speak(pick("Try our aggressive new marketing strategies!", \
|
||||
"You should buy products to feed your lifestyle obsession!", \
|
||||
"Consume!", \
|
||||
"Your money can buy happiness!", \
|
||||
"Engage direct marketing!", \
|
||||
"Advertising is legalized lying! But don't let that put you off our great deals!", \
|
||||
"You don't want to buy anything? Yeah, well I didn't want to buy your mom either."))
|
||||
|
||||
/datum/gm_action/brand_intelligence/end()
|
||||
active = FALSE
|
||||
for(var/obj/machinery/vending/infectedMachine in infectedVendingMachines)
|
||||
infectedMachine.shut_up = 1
|
||||
infectedMachine.shoot_inventory = 0
|
||||
|
||||
/datum/gm_action/brand_intelligence/get_weight()
|
||||
return 60 + (metric.count_people_in_department(ROLE_ENGINEERING) * 20)
|
||||
52
code/modules/gamemaster/actions/camera_damage.dm
Normal file
52
code/modules/gamemaster/actions/camera_damage.dm
Normal file
@@ -0,0 +1,52 @@
|
||||
/datum/gm_action/camera_damage
|
||||
name = "random camera damage"
|
||||
reusable = TRUE
|
||||
departments = list(ROLE_SYNTHETIC, ROLE_ENGINEERING)
|
||||
|
||||
/datum/gm_action/camera_damage/start()
|
||||
var/obj/machinery/camera/C = acquire_random_camera()
|
||||
if(!C)
|
||||
return
|
||||
..()
|
||||
|
||||
var/severity_range = 0
|
||||
var/severity = pickweight(EVENT_LEVEL_MUNDANE = 10,
|
||||
EVENT_LEVEL_MODERATE = 5,
|
||||
EVENT_LEVEL_MAJOR = 1
|
||||
)
|
||||
|
||||
switch(severity)
|
||||
if(EVENT_LEVEL_MUNDANE)
|
||||
severity_range = 0
|
||||
if(EVENT_LEVEL_MODERATE)
|
||||
severity_range = 7
|
||||
if(EVENT_LEVEL_MAJOR)
|
||||
severity_range = 15
|
||||
|
||||
for(var/obj/machinery/camera/cam in range(severity_range,C))
|
||||
if(is_valid_camera(cam))
|
||||
if(prob(2*severity))
|
||||
cam.destroy()
|
||||
else
|
||||
cam.wires.UpdateCut(CAMERA_WIRE_POWER, 0)
|
||||
if(prob(5*severity))
|
||||
cam.wires.UpdateCut(CAMERA_WIRE_ALARM, 0)
|
||||
|
||||
/datum/gm_action/camera_damage/proc/acquire_random_camera(var/remaining_attempts = 5)
|
||||
if(!cameranet.cameras.len)
|
||||
return
|
||||
if(!remaining_attempts)
|
||||
return
|
||||
|
||||
var/obj/machinery/camera/C = pick(cameranet.cameras)
|
||||
if(is_valid_camera(C))
|
||||
return C
|
||||
return acquire_random_camera(remaining_attempts--)
|
||||
|
||||
/datum/gm_action/camera_damage/proc/is_valid_camera(var/obj/machinery/camera/C)
|
||||
// Only return a functional camera, not installed in a silicon, and that exists somewhere players have access
|
||||
var/turf/T = get_turf(C)
|
||||
return T && C.can_use() && !istype(C.loc, /mob/living/silicon) && (T.z in using_map.player_levels)
|
||||
|
||||
/datum/gm_action/camera_damage/get_weight()
|
||||
return 40 + (metric.count_people_in_department(ROLE_ENGINEERING) * 20) + (metric.count_people_in_department(ROLE_SYNTHETIC) * 40)
|
||||
33
code/modules/gamemaster/actions/electrical_storm.dm
Normal file
33
code/modules/gamemaster/actions/electrical_storm.dm
Normal file
@@ -0,0 +1,33 @@
|
||||
/datum/gm_action/electrical_storm
|
||||
name = "electrical storm"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
reusable = TRUE
|
||||
var/lightsoutAmount = 1
|
||||
var/lightsoutRange = 25
|
||||
|
||||
/datum/gm_action/electrical_storm/announce()
|
||||
command_announcement.Announce("An electrical issue has been detected in your area, please repair potential electronic overloads.", "Electrical Alert")
|
||||
|
||||
/datum/gm_action/electrical_storm/start()
|
||||
..()
|
||||
var/list/epicentreList = list()
|
||||
|
||||
for(var/i=1, i <= lightsoutAmount, i++)
|
||||
var/list/possibleEpicentres = list()
|
||||
for(var/obj/effect/landmark/newEpicentre in landmarks_list)
|
||||
if(newEpicentre.name == "lightsout" && !(newEpicentre in epicentreList))
|
||||
possibleEpicentres += newEpicentre
|
||||
if(possibleEpicentres.len)
|
||||
epicentreList += pick(possibleEpicentres)
|
||||
else
|
||||
break
|
||||
|
||||
if(!epicentreList.len)
|
||||
return
|
||||
|
||||
for(var/obj/effect/landmark/epicentre in epicentreList)
|
||||
for(var/obj/machinery/power/apc/apc in range(epicentre,lightsoutRange))
|
||||
apc.overload_lighting()
|
||||
|
||||
/datum/gm_action/electrical_storm/get_weight()
|
||||
return 30 + (metric.count_people_in_department(ROLE_ENGINEERING) * 15) + (metric.count_people_in_department(ROLE_EVERYONE) * 5)
|
||||
70
code/modules/gamemaster/actions/electrified_door.dm
Normal file
70
code/modules/gamemaster/actions/electrified_door.dm
Normal file
@@ -0,0 +1,70 @@
|
||||
/datum/gm_action/electrified_door
|
||||
name = "airlock short-circuit"
|
||||
departments = list(ROLE_ENGINEERING, ROLE_MEDICAL)
|
||||
chaotic = 10
|
||||
var/obj/machinery/door/airlock/chosen_door
|
||||
var/list/area/excluded = list(
|
||||
/area/shuttle,
|
||||
/area/crew_quarters
|
||||
)
|
||||
var/severity
|
||||
|
||||
/datum/gm_action/electrified_door/set_up()
|
||||
var/list/area/grand_list_of_areas = get_station_areas(excluded)
|
||||
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 10,
|
||||
EVENT_LEVEL_MODERATE = 5,
|
||||
EVENT_LEVEL_MAJOR = 1
|
||||
)
|
||||
|
||||
//try 10 times
|
||||
for(var/i in 1 to 10)
|
||||
var/area/A = pick(grand_list_of_areas)
|
||||
var/list/obj/machinery/door/airlock/target_doors = list()
|
||||
for(var/obj/machinery/door/airlock/target_door in A.contents)
|
||||
target_doors += target_door
|
||||
target_doors = shuffle(target_doors)
|
||||
|
||||
for(var/obj/machinery/door/airlock/target_door in target_doors)
|
||||
if(!target_door.isElectrified() && target_door.arePowerSystemsOn() && target_door.maxhealth == target_door.health)
|
||||
chosen_door = target_door
|
||||
return
|
||||
|
||||
/datum/gm_action/electrified_door/start()
|
||||
..()
|
||||
if(!chosen_door)
|
||||
return
|
||||
if(prob(33))
|
||||
chosen_door.visible_message("<span class='danger'>\The [chosen_door]'s panel sparks!</span>")
|
||||
chosen_door.set_safeties(0)
|
||||
if(severity >= EVENT_LEVEL_MODERATE)
|
||||
chosen_door.electrify(-1)
|
||||
|
||||
if(severity >= EVENT_LEVEL_MAJOR) // New Major effect. Hydraulic boom.
|
||||
spawn()
|
||||
chosen_door.visible_message("<span class='warning'>\The [chosen_door] buzzes.</span>")
|
||||
playsound(get_turf(chosen_door), 'sound/machines/buzz-sigh.ogg', 50, 1)
|
||||
sleep(rand(10 SECONDS, 3 MINUTES))
|
||||
if(!chosen_door || !chosen_door.arePowerSystemsOn())
|
||||
return
|
||||
chosen_door.visible_message("<span class='warning'>\The [chosen_door]'s hydraulics creak.</span>")
|
||||
playsound(get_turf(chosen_door), 'sound/machines/airlock_creaking.ogg', 50, 1)
|
||||
sleep(rand(30 SECONDS, 10 MINUTES))
|
||||
if(!chosen_door || !chosen_door.arePowerSystemsOn())
|
||||
return
|
||||
chosen_door.visible_message("<span class='danger'>\The [chosen_door] emits a hydraulic shriek!</span>")
|
||||
playsound(get_turf(chosen_door), 'sound/machines/airlock.ogg', 80, 1)
|
||||
spawn(rand(5 SECONDS, 30 SECONDS))
|
||||
if(!chosen_door || !chosen_door.arePowerSystemsOn())
|
||||
return
|
||||
chosen_door.visible_message("<span class='critical'>\The [chosen_door]'s hydraulics detonate!</span>")
|
||||
chosen_door.fragmentate(get_turf(chosen_door), rand(5, 10), rand(3, 5), list(/obj/item/projectile/bullet/pellet/fragment/tank/small))
|
||||
explosion(get_turf(chosen_door),-1,-1,2,3)
|
||||
|
||||
chosen_door.lock()
|
||||
chosen_door.health = chosen_door.maxhealth / 6
|
||||
chosen_door.aiControlDisabled = 1
|
||||
chosen_door.update_icon()
|
||||
|
||||
/datum/gm_action/electrified_door/get_weight()
|
||||
return 10 + (metric.count_people_in_department(ROLE_ENGINEERING) * 5 + metric.count_people_in_department(ROLE_MEDICAL) * 10)
|
||||
36
code/modules/gamemaster/actions/gravity.dm
Normal file
36
code/modules/gamemaster/actions/gravity.dm
Normal file
@@ -0,0 +1,36 @@
|
||||
/datum/gm_action/gravity
|
||||
name = "gravity failure"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
length = 600
|
||||
var/list/zLevels
|
||||
|
||||
/datum/gm_action/gravity/set_up()
|
||||
length = rand(length, length * 5)
|
||||
// Setup which levels we will disrupt gravit on.
|
||||
zLevels = using_map.station_levels.Copy()
|
||||
for(var/datum/planet/P in SSplanets.planets)
|
||||
zLevels -= P.expected_z_levels
|
||||
|
||||
/datum/gm_action/gravity/announce()
|
||||
command_announcement.Announce("Feedback surge detected in mass-distributions systems. Artificial gravity has been disabled whilst the system \
|
||||
reinitializes. Please stand by while the gravity system reinitializes.", "Gravity Failure")
|
||||
|
||||
/datum/gm_action/gravity/start()
|
||||
..()
|
||||
gravity_is_on = 0
|
||||
for(var/area/A in all_areas)
|
||||
if(A.z in zLevels)
|
||||
A.gravitychange(gravity_is_on, A)
|
||||
|
||||
/datum/gm_action/gravity/end()
|
||||
if(!gravity_is_on)
|
||||
gravity_is_on = 1
|
||||
|
||||
for(var/area/A in all_areas)
|
||||
if(A.z in zLevels)
|
||||
A.gravitychange(gravity_is_on, A)
|
||||
|
||||
command_announcement.Announce("Gravity generators are again functioning within normal parameters. Sorry for any inconvenience.", "Gravity Restored")
|
||||
|
||||
/datum/gm_action/gravity/get_weight()
|
||||
return 30 + (metric.count_people_in_department(ROLE_EVERYONE) * 20)
|
||||
43
code/modules/gamemaster/actions/ion_storm.dm
Normal file
43
code/modules/gamemaster/actions/ion_storm.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
/datum/gm_action/ionstorm
|
||||
var/botEmagChance = 0.5
|
||||
var/list/players = list()
|
||||
var/active = FALSE
|
||||
length = 1 MINUTE
|
||||
|
||||
/datum/gm_action/ionstorm/set_up()
|
||||
length = rand(length, length * 10)
|
||||
// command_alert("The station has entered an ion storm. Monitor all electronic equipment for malfunctions", "Anomaly Alert")
|
||||
for (var/mob/living/carbon/human/player in player_list)
|
||||
if( !player.mind || player_is_antag(player.mind, only_offstation_roles = 1) || player.client.inactivity > MinutesToTicks(10))
|
||||
continue
|
||||
players += player.real_name
|
||||
|
||||
for (var/mob/living/silicon/ai/target in silicon_mob_list)
|
||||
var/law = target.generate_ion_law()
|
||||
target << "<font color='red'><b>You have detected a change in your laws information:</b></font>"
|
||||
target << law
|
||||
target.add_ion_law(law)
|
||||
target.show_laws()
|
||||
|
||||
/datum/gm_action/ionstorm/announce()
|
||||
if(message_servers)
|
||||
for (var/obj/machinery/message_server/MS in message_servers)
|
||||
MS.spamfilter.Cut()
|
||||
var/i
|
||||
for (i = 1, i <= MS.spamfilter_limit, i++)
|
||||
MS.spamfilter += pick("kitty","HONK","rev","malf","liberty","freedom","drugs", "[using_map.station_short]", \
|
||||
"admin","ponies","heresy","meow","Pun Pun","monkey","Ian","moron","pizza","message","spam",\
|
||||
"director", "Hello", "Hi!"," ","nuke","crate","dwarf","xeno")
|
||||
|
||||
/datum/gm_action/ionstorm/start()
|
||||
while(active)
|
||||
sleep(1)
|
||||
if(botEmagChance)
|
||||
for(var/mob/living/bot/bot in mob_list)
|
||||
if(prob(botEmagChance))
|
||||
bot.emag_act(1)
|
||||
|
||||
/datum/gm_action/ionstorm/end()
|
||||
spawn(rand(5000,8000))
|
||||
if(prob(50))
|
||||
ion_storm_announcement()
|
||||
@@ -34,10 +34,10 @@
|
||||
/datum/gm_action/meteor_defense/start()
|
||||
..()
|
||||
spawn(0)
|
||||
// sleep(5 MINUTES)
|
||||
sleep(5 MINUTES)
|
||||
var/announcement = "The incoming debris are expected to approach from the [dir_text] side. ETA to arrival is approximately 5 minutes."
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
// sleep(5 MINUTES)
|
||||
sleep(5 MINUTES)
|
||||
announcement = "Incoming debris approaches from the [dir_text] side!"
|
||||
command_announcement.Announce(announcement, "Meteor Alert - Update")
|
||||
while(waves)
|
||||
|
||||
79
code/modules/gamemaster/actions/money_hacker.dm
Normal file
79
code/modules/gamemaster/actions/money_hacker.dm
Normal file
@@ -0,0 +1,79 @@
|
||||
/var/global/account_hack_attempted = 0
|
||||
|
||||
/datum/gm_action/money_hacker
|
||||
name = "bank account hacker"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
reusable = TRUE
|
||||
var/datum/money_account/affected_account
|
||||
var/active
|
||||
var/activeFor
|
||||
var/end_time
|
||||
|
||||
/datum/gm_action/money_hacker/set_up()
|
||||
active = TRUE
|
||||
end_time = world.time + 6000
|
||||
if(all_money_accounts.len)
|
||||
affected_account = pick(all_money_accounts)
|
||||
|
||||
account_hack_attempted = 1
|
||||
|
||||
/datum/gm_action/money_hacker/announce()
|
||||
var/message = "A brute force hack has been detected (in progress since [stationtime2text()]). The target of the attack is: Financial account #[affected_account.account_number], \
|
||||
without intervention this attack will succeed in approximately 10 minutes. Required intervention: temporary suspension of affected accounts until the attack has ceased. \
|
||||
Notifications will be sent as updates occur.<br>"
|
||||
var/my_department = "[station_name()] firewall subroutines"
|
||||
|
||||
for(var/obj/machinery/message_server/MS in machines)
|
||||
if(!MS.active) continue
|
||||
MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
|
||||
|
||||
|
||||
/datum/gm_action/money_hacker/start()
|
||||
..()
|
||||
spawn(0)
|
||||
while(active)
|
||||
sleep(1)
|
||||
activeFor++
|
||||
if(world.time >= end_time)
|
||||
length = activeFor
|
||||
else
|
||||
length = activeFor + 10
|
||||
|
||||
/datum/gm_action/money_hacker/end()
|
||||
active = FALSE
|
||||
var/message
|
||||
if(affected_account && !affected_account.suspended)
|
||||
//hacker wins
|
||||
message = "The hack attempt has succeeded."
|
||||
|
||||
//subtract the money
|
||||
var/lost = affected_account.money * 0.8 + (rand(2,4) - 2) / 10
|
||||
affected_account.money -= lost
|
||||
|
||||
//create a taunting log entry
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = pick("","yo brotha from anotha motha","el Presidente","chieF smackDowN","Nobody")
|
||||
T.purpose = pick("Ne$ ---ount fu%ds init*&lisat@*n","PAY BACK YOUR MUM","Funds withdrawal","pWnAgE","l33t hax","liberationez","Hit","Nothing")
|
||||
T.amount = pick("","([rand(0,99999)])","alla money","9001$","HOLLA HOLLA GET DOLLA","([lost])")
|
||||
var/date1 = "31 December, 1999"
|
||||
var/date2 = "[num2text(rand(1,31))] [pick("January","February","March","April","May","June","July","August","September","October","November","December")], [rand(1000,3000)]"
|
||||
T.date = pick("", current_date_string, date1, date2,"Nowhen")
|
||||
var/time1 = rand(0, 99999999)
|
||||
var/time2 = "[round(time1 / 36000)+12]:[(time1 / 600 % 60) < 10 ? add_zero(time1 / 600 % 60, 1) : time1 / 600 % 60]"
|
||||
T.time = pick("", stationtime2text(), time2, "Never")
|
||||
T.source_terminal = pick("","[pick("Biesel","New Gibson")] GalaxyNet Terminal #[rand(111,999)]","your mums place","nantrasen high CommanD","Angessa's Pearl","Nowhere")
|
||||
|
||||
affected_account.transaction_log.Add(T)
|
||||
|
||||
else
|
||||
//crew wins
|
||||
message = "The attack has ceased, the affected accounts can now be brought online."
|
||||
|
||||
var/my_department = "[station_name()] firewall subroutines"
|
||||
|
||||
for(var/obj/machinery/message_server/MS in machines)
|
||||
if(!MS.active) continue
|
||||
MS.send_rc_message("Head of Personnel's Desk", my_department, message, "", "", 2)
|
||||
|
||||
/datum/gm_action/money_hacker/get_weight()
|
||||
return 30 * all_money_accounts.len
|
||||
39
code/modules/gamemaster/actions/money_lotto.dm
Normal file
39
code/modules/gamemaster/actions/money_lotto.dm
Normal file
@@ -0,0 +1,39 @@
|
||||
/datum/gm_action/money_lotto
|
||||
name = "lottery win"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
var/winner_name = "John Smith"
|
||||
var/winner_sum = 0
|
||||
var/deposit_success = 0
|
||||
|
||||
/datum/gm_action/money_lotto/start()
|
||||
..()
|
||||
winner_sum = pick(5000, 10000, 50000, 100000, 500000, 1000000, 1500000)
|
||||
if(all_money_accounts.len)
|
||||
var/datum/money_account/D = pick(all_money_accounts)
|
||||
winner_name = D.owner_name
|
||||
if(!D.suspended)
|
||||
D.money += winner_sum
|
||||
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "The [using_map.starsys_name] Times Grand Slam -Stellar- Lottery"
|
||||
T.purpose = "Winner!"
|
||||
T.amount = winner_sum
|
||||
T.date = current_date_string
|
||||
T.time = stationtime2text()
|
||||
T.source_terminal = "Sif TCD Terminal #[rand(111,333)]"
|
||||
D.transaction_log.Add(T)
|
||||
|
||||
deposit_success = 1
|
||||
|
||||
/datum/gm_action/money_lotto/announce()
|
||||
var/author = "[using_map.company_name] Editor"
|
||||
var/channel = "The [using_map.starsys_name] Times"
|
||||
|
||||
var/body = "The [using_map.starsys_name] Times wishes to congratulate <b>[winner_name]</b> for recieving the [using_map.starsys_name] Stellar Slam Lottery, and receiving the out of this world sum of [winner_sum] credits!"
|
||||
if(!deposit_success)
|
||||
body += "<br>Unfortunately, we were unable to verify the account details provided, so we were unable to transfer the money. Send a cheque containing the sum of 5000 Thalers to ND 'Stellar Slam' office on the The [using_map.starsys_name] Times gateway containing updated details, and your winnings'll be re-sent within the month."
|
||||
|
||||
news_network.SubmitArticle(body, author, channel, null, 1)
|
||||
|
||||
/datum/gm_action/money_lotto/get_weight()
|
||||
return 25 * metric.count_people_in_department(ROLE_EVERYONE)
|
||||
129
code/modules/gamemaster/actions/money_spam.dm
Normal file
129
code/modules/gamemaster/actions/money_spam.dm
Normal file
@@ -0,0 +1,129 @@
|
||||
/datum/gm_action/pda_spam
|
||||
name = "PDA spam"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
reusable = TRUE
|
||||
var/last_spam_time = 0
|
||||
var/obj/machinery/message_server/useMS
|
||||
var/obj/machinery/exonet_node/node
|
||||
|
||||
/datum/gm_action/pda_spam/set_up()
|
||||
last_spam_time = world.time
|
||||
pick_message_server()
|
||||
|
||||
/datum/gm_action/pda_spam/proc/pick_message_server()
|
||||
if(message_servers)
|
||||
for (var/obj/machinery/message_server/MS in message_servers)
|
||||
if(MS.active)
|
||||
useMS = MS
|
||||
break
|
||||
|
||||
/datum/gm_action/pda_spam/start()
|
||||
..()
|
||||
while(world.time < last_spam_time + 3000)
|
||||
if(!node)
|
||||
node = get_exonet_node()
|
||||
|
||||
if(!node || !node.on || !node.allow_external_PDAs)
|
||||
return
|
||||
|
||||
if(!useMS || !useMS.active)
|
||||
useMS = null
|
||||
pick_message_server()
|
||||
|
||||
if(useMS)
|
||||
if(prob(5))
|
||||
// /obj/machinery/message_server/proc/send_pda_message(var/recipient = "",var/sender = "",var/message = "")
|
||||
var/obj/item/device/pda/P
|
||||
var/list/viables = list()
|
||||
for(var/obj/item/device/pda/check_pda in sortAtom(PDAs))
|
||||
if (!check_pda.owner||check_pda.toff||check_pda == src||check_pda.hidden)
|
||||
continue
|
||||
viables.Add(check_pda)
|
||||
|
||||
if(!viables.len)
|
||||
return
|
||||
P = pick(viables)
|
||||
|
||||
var/sender
|
||||
var/message
|
||||
switch(pick(1,2,3,4,5,6,7))
|
||||
if(1)
|
||||
sender = pick("MaxBet","MaxBet Online Casino","There is no better time to register","I'm excited for you to join us")
|
||||
message = pick("Triple deposits are waiting for you at MaxBet Online when you register to play with us.",\
|
||||
"You can qualify for a 200% Welcome Bonus at MaxBet Online when you sign up today.",\
|
||||
"Once you are a player with MaxBet, you will also receive lucrative weekly and monthly promotions.",\
|
||||
"You will be able to enjoy over 450 top-flight casino games at MaxBet.")
|
||||
if(2)
|
||||
sender = pick(300;"QuickDatingSystem",200;"Find your russian bride",50;"Tajaran beauties are waiting",50;"Find your secret skrell crush",50;"Beautiful unathi brides")
|
||||
message = pick("Your profile caught my attention and I wanted to write and say hello (QuickDating).",\
|
||||
"If you will write to me on my email [pick(first_names_female)]@[pick(last_names)].[pick("ru","ck","tj","ur","nt")] I shall necessarily send you a photo (QuickDating).",\
|
||||
"I want that we write each other and I hope, that you will like my profile and you will answer me (QuickDating).",\
|
||||
"You have (1) new message!",\
|
||||
"You have (2) new profile views!")
|
||||
if(3)
|
||||
sender = pick("Galactic Payments Association","Better Business Bureau","[using_map.starsys_name] E-Payments","NAnoTransen Finance Deparmtent","Luxury Replicas")
|
||||
message = pick("Luxury watches for Blowout sale prices!",\
|
||||
"Watches, Jewelry & Accessories, Bags & Wallets !",\
|
||||
"Deposit 100$ and get 300$ totally free!",\
|
||||
" 100K NT.|WOWGOLD <20>nly $89 <HOT>",\
|
||||
"We have been filed with a complaint from one of your customers in respect of their business relations with you.",\
|
||||
"We kindly ask you to open the COMPLAINT REPORT (attached) to reply on this complaint..")
|
||||
if(4)
|
||||
sender = pick("Buy Dr. Maxman","Having dysfuctional troubles?")
|
||||
message = pick("DR MAXMAN: REAL Doctors, REAL Science, REAL Results!",\
|
||||
"Dr. Maxman was created by George Acuilar, M.D, a [using_map.boss_short] Certified Urologist who has treated over 70,000 patients sector wide with 'male problems'.",\
|
||||
"After seven years of research, Dr Acuilar and his team came up with this simple breakthrough male enhancement formula.",\
|
||||
"Men of all species report AMAZING increases in length, width and stamina.")
|
||||
if(5)
|
||||
sender = pick("Dr","Crown prince","King Regent","Professor","Captain")
|
||||
sender += " " + pick("Robert","Alfred","Josephat","Kingsley","Sehi","Zbahi")
|
||||
sender += " " + pick("Mugawe","Nkem","Gbatokwia","Nchekwube","Ndim","Ndubisi")
|
||||
message = pick("YOUR FUND HAS BEEN MOVED TO [pick("Salusa","Segunda","Cepheus","Andromeda","Gruis","Corona","Aquila","ARES","Asellus")] DEVELOPMENTARY BANK FOR ONWARD REMITTANCE.",\
|
||||
"We are happy to inform you that due to the delay, we have been instructed to IMMEDIATELY deposit all funds into your account",\
|
||||
"Dear fund beneficiary, We have please to inform you that overdue funds payment has finally been approved and released for payment",\
|
||||
"Due to my lack of agents I require an off-world financial account to immediately deposit the sum of 1 POINT FIVE MILLION credits.",\
|
||||
"Greetings sir, I regretfully to inform you that as I lay dying here due to my lack ofheirs I have chosen you to recieve the full sum of my lifetime savings of 1.5 billion credits")
|
||||
if(6)
|
||||
sender = pick("[using_map.company_name] Morale Divison","Feeling Lonely?","Bored?","www.wetskrell.nt")
|
||||
message = pick("The [using_map.company_name] Morale Division wishes to provide you with quality entertainment sites.",\
|
||||
"WetSkrell.nt is a xenophillic website endorsed by NT for the use of male crewmembers among it's many stations and outposts.",\
|
||||
"Wetskrell.nt only provides the higest quality of male entertaiment to [using_map.company_name] Employees.",\
|
||||
"Simply enter your [using_map.company_name] Bank account system number and pin. With three easy steps this service could be yours!")
|
||||
if(7)
|
||||
sender = pick("You have won free tickets!","Click here to claim your prize!","You are the 1000th vistor!","You are our lucky grand prize winner!")
|
||||
message = pick("You have won tickets to the newest ACTION JAXSON MOVIE!",\
|
||||
"You have won tickets to the newest crime drama DETECTIVE MYSTERY IN THE CLAMITY CAPER!",\
|
||||
"You have won tickets to the newest romantic comedy 16 RULES OF LOVE!",\
|
||||
"You have won tickets to the newest thriller THE CULT OF THE SLEEPING ONE!")
|
||||
|
||||
if (useMS.send_pda_message("[P.owner]", sender, message)) //Message been filtered by spam filter.
|
||||
return
|
||||
|
||||
last_spam_time = world.time
|
||||
|
||||
if (prob(50)) //Give the AI an increased chance to intercept the message
|
||||
for(var/mob/living/silicon/ai/ai in mob_list)
|
||||
// Allows other AIs to intercept the message but the AI won't intercept their own message.
|
||||
if(ai.aiPDA != P && ai.aiPDA != src)
|
||||
ai.show_message("<i>Intercepted message from <b>[sender]</b></i> (Unknown / spam?) <i>to <b>[P:owner]</b>: [message]</i>")
|
||||
|
||||
//Commented out because we don't send messages like this anymore. Instead it will just popup in their chat window.
|
||||
//P.tnote += "<i><b>← From [sender] (Unknown / spam?):</b></i><br>[message]<br>"
|
||||
|
||||
if (!P.message_silent)
|
||||
playsound(P.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(3, P.loc))
|
||||
if(!P.message_silent) O.show_message(text("\icon[P] *[P.ttone]*"))
|
||||
//Search for holder of the PDA.
|
||||
var/mob/living/L = null
|
||||
if(P.loc && isliving(P.loc))
|
||||
L = P.loc
|
||||
//Maybe they are a pAI!
|
||||
else
|
||||
L = get(P, /mob/living/silicon)
|
||||
|
||||
if(L)
|
||||
L << "\icon[P] <b>Message from [sender] (Unknown / spam?), </b>\"[message]\" (Unable to Reply)"
|
||||
|
||||
/datum/gm_action/pda_spam/get_weight()
|
||||
return 25 * metric.count_people_in_department(ROLE_EVERYONE)
|
||||
93
code/modules/gamemaster/actions/prison_break.dm
Normal file
93
code/modules/gamemaster/actions/prison_break.dm
Normal file
@@ -0,0 +1,93 @@
|
||||
/datum/gm_action/prison_break
|
||||
name = "prison break"
|
||||
departments = list(ROLE_SECURITY, ROLE_SYNTHETIC)
|
||||
|
||||
var/start_time = 0
|
||||
var/active = FALSE // Are we doing stuff?
|
||||
var/releaseWhen = 60 // The delay for the breakout to occur.
|
||||
var/list/area/areas = list() // List of areas to affect. Filled by start()
|
||||
|
||||
var/eventDept = "Security" // Department name in announcement
|
||||
var/list/areaName = list("Brig") // Names of areas mentioned in AI and Engineering announcements
|
||||
var/list/areaType = list(/area/security/prison, /area/security/brig) // Area types to include.
|
||||
var/list/areaNotType = list() // Area types to specifically exclude.
|
||||
|
||||
/datum/gm_action/prison_break/get_weight()
|
||||
var/afflicted_staff = 0
|
||||
var/assigned_staff = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
for(var/department in departments)
|
||||
afflicted_staff += round(metric.count_people_in_department(department) / 2)
|
||||
|
||||
var/weight = 20 + (assigned_staff * 10)
|
||||
|
||||
if(assigned_staff)
|
||||
weight += afflicted_staff
|
||||
|
||||
return weight
|
||||
|
||||
/datum/gm_action/prison_break/virology
|
||||
name = "virology breakout"
|
||||
departments = list(ROLE_MEDICAL, ROLE_SYNTHETIC)
|
||||
eventDept = "Medical"
|
||||
areaName = list("Virology")
|
||||
areaType = list(/area/medical/virology, /area/medical/virologyaccess)
|
||||
|
||||
/datum/gm_action/prison_break/xenobiology
|
||||
name = "xenobiology breakout"
|
||||
departments = list(ROLE_RESEARCH, ROLE_SYNTHETIC)
|
||||
eventDept = "Science"
|
||||
areaName = list("Xenobiology")
|
||||
areaType = list(/area/rnd/xenobiology)
|
||||
areaNotType = list(/area/rnd/xenobiology/xenoflora, /area/rnd/xenobiology/xenoflora_storage)
|
||||
|
||||
/datum/gm_action/prison_break/station
|
||||
name = "station-wide breakout"
|
||||
departments = list(ROLE_SECURITY, ROLE_MEDICAL, ROLE_RESEARCH, ROLE_SYNTHETIC)
|
||||
eventDept = "Station"
|
||||
areaName = list("Brig","Virology","Xenobiology")
|
||||
areaType = list(/area/security/prison, /area/security/brig, /area/medical/virology, /area/medical/virologyaccess, /area/rnd/xenobiology)
|
||||
areaNotType = list(/area/rnd/xenobiology/xenoflora, /area/rnd/xenobiology/xenoflora_storage)
|
||||
|
||||
/datum/gm_action/prison_break/set_up()
|
||||
releaseWhen = rand(60, 90)
|
||||
start_time = world.time
|
||||
active = TRUE
|
||||
length = releaseWhen + 1 SECOND
|
||||
|
||||
/datum/gm_action/prison_break/announce()
|
||||
if(areas && areas.len > 0)
|
||||
command_announcement.Announce("[pick("Gr3y.T1d3 virus","Malignant trojan")] detected in [station_name()] [(eventDept == "Security")? "imprisonment":"containment"] subroutines. Secure any compromised areas immediately. Station AI involvement is recommended.", "[eventDept] Alert")
|
||||
|
||||
/datum/gm_action/prison_break/start()
|
||||
..()
|
||||
for(var/area/A in all_areas)
|
||||
if(is_type_in_list(A,areaType) && !is_type_in_list(A,areaNotType))
|
||||
areas += A
|
||||
|
||||
if(areas && areas.len > 0)
|
||||
var/my_department = "[station_name()] firewall subroutines"
|
||||
var/rc_message = "An unknown malicious program has been detected in the [english_list(areaName)] lighting and airlock control systems at [stationtime2text()]. Systems will be fully compromised within approximately three minutes. Direct intervention is required immediately.<br>"
|
||||
for(var/obj/machinery/message_server/MS in machines)
|
||||
MS.send_rc_message("Engineering", my_department, rc_message, "", "", 2)
|
||||
for(var/mob/living/silicon/ai/A in player_list)
|
||||
A << "<span class='danger'>Malicious program detected in the [english_list(areaName)] lighting and airlock control systems by [my_department].</span>"
|
||||
|
||||
else
|
||||
world.log << "ERROR: Could not initate grey-tide. Unable to find suitable containment area."
|
||||
|
||||
if(areas && areas.len > 0)
|
||||
spawn()
|
||||
while(active)
|
||||
sleep(1)
|
||||
if(world.time >= releaseWhen + start_time)
|
||||
var/obj/machinery/power/apc/theAPC = null
|
||||
for(var/area/A in areas)
|
||||
theAPC = A.get_apc()
|
||||
if(theAPC.operating) //If the apc's off, it's a little hard to overload the lights.
|
||||
for(var/obj/machinery/light/L in A)
|
||||
L.flicker(10)
|
||||
|
||||
/datum/gm_action/prison_break/end()
|
||||
active = FALSE
|
||||
for(var/area/A in shuffle(areas))
|
||||
A.prison_break()
|
||||
74
code/modules/gamemaster/actions/radiation_storm.dm
Normal file
74
code/modules/gamemaster/actions/radiation_storm.dm
Normal file
@@ -0,0 +1,74 @@
|
||||
/datum/gm_action/radiation_storm
|
||||
name = "radiation storm"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
reusable = TRUE
|
||||
|
||||
var/enterBelt = 30
|
||||
var/radIntervall = 5
|
||||
var/leaveBelt = 80
|
||||
var/revokeAccess = 165
|
||||
var/activeFor = 0
|
||||
var/postStartTicks = 0
|
||||
var/active = FALSE
|
||||
|
||||
/datum/gm_action/radiation_storm/announce()
|
||||
command_announcement.Announce("High levels of radiation detected near \the [station_name()]. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
|
||||
|
||||
/datum/gm_action/radiation_storm/set_up()
|
||||
active = TRUE
|
||||
|
||||
/datum/gm_action/radiation_storm/start()
|
||||
..()
|
||||
make_maint_all_access()
|
||||
|
||||
while(active)
|
||||
sleep(1 SECOND)
|
||||
activeFor ++
|
||||
if(activeFor == enterBelt)
|
||||
command_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert")
|
||||
radiate()
|
||||
|
||||
if(activeFor >= enterBelt && activeFor <= leaveBelt)
|
||||
postStartTicks++
|
||||
|
||||
if(postStartTicks == radIntervall)
|
||||
postStartTicks = 0
|
||||
radiate()
|
||||
|
||||
else if(activeFor == leaveBelt)
|
||||
command_announcement.Announce("The station has passed the radiation belt. Please allow for up to one minute while radiation levels dissipate, and report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
|
||||
|
||||
/datum/gm_action/radiation_storm/proc/radiate()
|
||||
var/radiation_level = rand(15, 35)
|
||||
for(var/z in using_map.station_levels)
|
||||
radiation_repository.z_radiate(locate(1, 1, z), radiation_level, 1)
|
||||
|
||||
for(var/mob/living/carbon/C in living_mob_list)
|
||||
var/area/A = get_area(C)
|
||||
if(!A)
|
||||
continue
|
||||
if(A.flags & RAD_SHIELDED)
|
||||
continue
|
||||
if(istype(C,/mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if(prob(5))
|
||||
if (prob(75))
|
||||
randmutb(H) // Applies bad mutation
|
||||
domutcheck(H,null,MUTCHK_FORCED)
|
||||
else
|
||||
randmutg(H) // Applies good mutation
|
||||
domutcheck(H,null,MUTCHK_FORCED)
|
||||
|
||||
/datum/gm_action/radiation_storm/end()
|
||||
spawn(revokeAccess SECONDS)
|
||||
revoke_maint_all_access()
|
||||
|
||||
/datum/gm_action/radiation_storm/get_weight()
|
||||
var/people_in_space = 0
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in using_map.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
people_in_space++
|
||||
return 20 + (metric.count_people_in_department(ROLE_MEDICAL) * 10) + (people_in_space * 40) + (metric.count_people_in_department(ROLE_EVERYONE) * 20)
|
||||
23
code/modules/gamemaster/actions/random_antagonist.dm
Normal file
23
code/modules/gamemaster/actions/random_antagonist.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
// The random spawn proc on the antag datum will handle announcing the spawn and whatnot.
|
||||
/datum/gm_action/random_antag
|
||||
name = "random antagonist"
|
||||
departments = list(ROLE_EVERYONE)
|
||||
chaotic = 30
|
||||
reusable = TRUE
|
||||
|
||||
/datum/gm_action/random_antag/start()
|
||||
..()
|
||||
var/list/valid_types = list()
|
||||
for(var/antag_type in all_antag_types)
|
||||
var/datum/antagonist/antag = all_antag_types[antag_type]
|
||||
if(antag.flags & ANTAG_RANDSPAWN)
|
||||
valid_types |= antag
|
||||
if(valid_types.len)
|
||||
var/datum/antagonist/antag = pick(valid_types)
|
||||
antag.attempt_random_spawn()
|
||||
|
||||
/datum/gm_action/random_antag/get_weight()
|
||||
. = ..()
|
||||
if(gm)
|
||||
var/weight = max(0, (metric.count_people_in_department(ROLE_SECURITY) * 20) + (metric.count_people_in_department(ROLE_EVERYONE) * 5) + gm.staleness)
|
||||
return weight
|
||||
70
code/modules/gamemaster/actions/rogue_drones.dm
Normal file
70
code/modules/gamemaster/actions/rogue_drones.dm
Normal file
@@ -0,0 +1,70 @@
|
||||
/datum/gm_action/rogue_drone
|
||||
name = "rogue drones"
|
||||
departments = list(ROLE_SECURITY)
|
||||
chaotic = 60
|
||||
length = 20 MINUTES
|
||||
var/list/drones_list = list()
|
||||
|
||||
/datum/gm_action/rogue_drone/start()
|
||||
..()
|
||||
//spawn them at the same place as carp
|
||||
var/list/possible_spawns = list()
|
||||
for(var/obj/effect/landmark/C in landmarks_list)
|
||||
if(C.name == "carpspawn")
|
||||
possible_spawns.Add(C)
|
||||
|
||||
//25% chance for this to be a false alarm
|
||||
var/num
|
||||
if(prob(25))
|
||||
num = 0
|
||||
else
|
||||
num = rand(2,6)
|
||||
for(var/i=0, i<num, i++)
|
||||
var/mob/living/simple_mob/mechanical/combat_drone/event/D = new(get_turf(pick(possible_spawns)))
|
||||
drones_list.Add(D)
|
||||
|
||||
/datum/gm_action/rogue_drone/announce()
|
||||
var/msg
|
||||
var/rng = rand(1,5)
|
||||
switch(rng)
|
||||
if(1)
|
||||
msg = "A combat drone wing operating in close orbit above Sif has failed to return from a anti-piracy sweep. If any are sighted, \
|
||||
approach with caution."
|
||||
if(2)
|
||||
msg = "Contact has been lost with a combat drone wing in Sif orbit. If any are sighted in the area, approach with \
|
||||
caution."
|
||||
if(3)
|
||||
msg = "Unidentified hackers have targeted a combat drone wing deployed around Sif. If any are sighted in the area, approach with caution."
|
||||
if(4)
|
||||
msg = "A passing derelict ship's drone defense systems have just activated. If any are sighted in the area, use caution."
|
||||
if(5)
|
||||
msg = "We're detecting a swarm of small objects approaching your station. Most likely a bunch of drones. Please exercise caution if you see any."
|
||||
|
||||
command_announcement.Announce(msg, "Rogue drone alert")
|
||||
|
||||
/datum/gm_action/rogue_drone/end()
|
||||
var/num_recovered = 0
|
||||
for(var/mob/living/simple_mob/mechanical/combat_drone/D in drones_list)
|
||||
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(3, 0, D.loc)
|
||||
sparks.start()
|
||||
D.z = using_map.admin_levels[1]
|
||||
D.loot_list = list()
|
||||
|
||||
qdel(D)
|
||||
num_recovered++
|
||||
|
||||
if(num_recovered > drones_list.len * 0.75)
|
||||
command_announcement.Announce("The drones that were malfunctioning have been recovered safely.", "Rogue drone alert")
|
||||
else
|
||||
command_announcement.Announce("We're disappointed at the loss of the drones, but the survivors have been recovered.", "Rogue drone alert")
|
||||
|
||||
/datum/gm_action/rogue_drone/get_weight()
|
||||
var/people_in_space = 0
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in using_map.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
people_in_space++
|
||||
return 20 + (metric.count_people_in_department(ROLE_SECURITY) * 10) + (people_in_space * 30)
|
||||
61
code/modules/gamemaster/actions/solar_storm.dm
Normal file
61
code/modules/gamemaster/actions/solar_storm.dm
Normal file
@@ -0,0 +1,61 @@
|
||||
/datum/gm_action/solar_storm
|
||||
name = "solar storm"
|
||||
var/const/rad_interval = 5 //Same interval period as radiation storms.
|
||||
var/base_solar_gen_rate
|
||||
length = 3 MINUTES
|
||||
var/duration // Duration for the storm
|
||||
var/start_time = 0
|
||||
|
||||
reusable = TRUE
|
||||
|
||||
/datum/gm_action/solar_storm/set_up()
|
||||
start_time = world.time
|
||||
duration = length
|
||||
duration += rand(-1 * 1 MINUTE, 1 MINUTE)
|
||||
|
||||
/datum/gm_action/solar_storm/announce()
|
||||
command_announcement.Announce("A solar storm has been detected approaching \the [station_name()]. Please halt all EVA activites immediately and return to the interior of the station.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
|
||||
adjust_solar_output(1.5)
|
||||
|
||||
/datum/gm_action/solar_storm/proc/adjust_solar_output(var/mult = 1)
|
||||
if(isnull(base_solar_gen_rate)) base_solar_gen_rate = GLOB.solar_gen_rate
|
||||
GLOB.solar_gen_rate = mult * base_solar_gen_rate
|
||||
|
||||
|
||||
/datum/gm_action/solar_storm/start()
|
||||
..()
|
||||
length = duration
|
||||
command_announcement.Announce("The solar storm has reached the station. Please refain from EVA and remain inside the station until it has passed.", "Anomaly Alert")
|
||||
adjust_solar_output(5)
|
||||
|
||||
while(world.time <= world.time + duration)
|
||||
if(duration % rad_interval == 0)
|
||||
radiate()
|
||||
|
||||
/datum/gm_action/solar_storm/get_weight()
|
||||
var/people_in_space = 0
|
||||
for(var/mob/living/L in player_list)
|
||||
if(!(L.z in using_map.station_levels))
|
||||
continue // Not on the right z-level.
|
||||
var/turf/T = get_turf(L)
|
||||
if(istype(T, /turf/space) && istype(T.loc,/area/space))
|
||||
people_in_space++
|
||||
return 20 + (metric.count_people_in_department(ROLE_ENGINEERING) * 10) + (people_in_space * 30)
|
||||
|
||||
/datum/gm_action/solar_storm/proc/radiate()
|
||||
// Note: Too complicated to be worth trying to use the radiation system for this. Its only in space anyway, so we make an exception in this case.
|
||||
for(var/mob/living/L in living_mob_list)
|
||||
var/turf/T = get_turf(L)
|
||||
if(!T)
|
||||
continue
|
||||
|
||||
if(!istype(T.loc,/area/space) && !istype(T,/turf/space)) //Make sure you're in a space area or on a space turf
|
||||
continue
|
||||
|
||||
//Todo: Apply some burn damage from the heat of the sun. Until then, enjoy some moderate radiation.
|
||||
L.rad_act(rand(15, 30))
|
||||
|
||||
/datum/gm_action/solar_storm/end()
|
||||
command_announcement.Announce("The solar storm has passed the station. It is now safe to resume EVA activities. Please report to medbay if you experience any unusual symptoms. ", "Anomaly Alert")
|
||||
adjust_solar_output()
|
||||
length = initial(length)
|
||||
14
code/modules/gamemaster/actions/spacevine.dm
Normal file
14
code/modules/gamemaster/actions/spacevine.dm
Normal file
@@ -0,0 +1,14 @@
|
||||
/datum/gm_action/spacevine
|
||||
name = "space-vine infestation"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
chaotic = 2
|
||||
|
||||
/datum/gm_action/spacevine/start()
|
||||
..()
|
||||
spacevine_infestation()
|
||||
|
||||
/datum/gm_action/spacevine/announce()
|
||||
level_seven_announcement()
|
||||
|
||||
/datum/gm_action/spacevine/get_weight()
|
||||
return 20 + (metric.count_people_in_department(ROLE_ENGINEERING) * 20) + (metric.count_people_in_department(ROLE_EVERYONE) * 10)
|
||||
49
code/modules/gamemaster/actions/spider_infestation.dm
Normal file
49
code/modules/gamemaster/actions/spider_infestation.dm
Normal file
@@ -0,0 +1,49 @@
|
||||
/datum/gm_action/spider_infestation
|
||||
name = "spider infestation"
|
||||
departments = list(ROLE_SECURITY, ROLE_MEDICAL, ROLE_EVERYONE)
|
||||
chaotic = 30
|
||||
|
||||
var/severity = 1
|
||||
|
||||
var/spawncount = 1
|
||||
|
||||
/datum/gm_action/spider_infestation/set_up()
|
||||
spawn(rand(600, 6000))
|
||||
announce()
|
||||
|
||||
if(prob(40))
|
||||
severity = rand(2,3)
|
||||
else
|
||||
severity = 1
|
||||
|
||||
spawncount = rand(4 * severity, 6 * severity)
|
||||
|
||||
/datum/gm_action/spider_infestation/announce()
|
||||
command_announcement.Announce("Unidentified lifesigns detected coming aboard [station_name()]. Secure any exterior access, including ducting and ventilation.", "Lifesign Alert", new_sound = 'sound/AI/aliens.ogg')
|
||||
|
||||
if(severity >= 3)
|
||||
spawn(rand(600, 3000))
|
||||
command_announcement.Announce("Unidentified lifesigns previously detected coming aboard [station_name()] have been classified as a swarm of arachnids. Extreme caution is advised.", "Arachnid Alert")
|
||||
|
||||
/datum/gm_action/spider_infestation/start()
|
||||
..()
|
||||
var/list/vents = list()
|
||||
for(var/obj/machinery/atmospherics/unary/vent_pump/temp_vent in machines)
|
||||
if(!temp_vent.welded && temp_vent.network && temp_vent.loc.z in using_map.station_levels)
|
||||
if(temp_vent.network.normal_members.len > 50)
|
||||
vents += temp_vent
|
||||
|
||||
while((spawncount >= 1) && vents.len)
|
||||
var/obj/vent = pick(vents)
|
||||
new /obj/effect/spider/spiderling(vent.loc)
|
||||
vents -= vent
|
||||
spawncount--
|
||||
|
||||
/datum/gm_action/spider_infestation/get_weight()
|
||||
var/security = metric.count_people_in_department(ROLE_SECURITY)
|
||||
var/medical = metric.count_people_in_department(ROLE_MEDICAL)
|
||||
var/engineering = metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
|
||||
var/assigned_staff = security + round(medical / 2) + round(engineering / 2)
|
||||
|
||||
return 10 + (assigned_staff * 15)
|
||||
13
code/modules/gamemaster/actions/spontaneous_appendicitis.dm
Normal file
13
code/modules/gamemaster/actions/spontaneous_appendicitis.dm
Normal file
@@ -0,0 +1,13 @@
|
||||
/datum/gm_action/spontaneous_appendicitis
|
||||
name = "appendicitis"
|
||||
departments = list(ROLE_MEDICAL, ROLE_EVERYONE)
|
||||
chaotic = 1
|
||||
|
||||
/datum/gm_action/spontaneous_appendicitis/start()
|
||||
..()
|
||||
for(var/mob/living/carbon/human/H in shuffle(living_mob_list))
|
||||
if(H.client && !player_is_antag(H.mind) && H.appendicitis())
|
||||
break
|
||||
|
||||
/datum/gm_action/spontaneous_appendicitis/get_weight()
|
||||
return 5 + (metric.count_people_in_department(ROLE_MEDICAL) * 10)
|
||||
83
code/modules/gamemaster/actions/viral_infection.dm
Normal file
83
code/modules/gamemaster/actions/viral_infection.dm
Normal file
@@ -0,0 +1,83 @@
|
||||
/var/global/list/event_viruses = list() // so that event viruses are kept around for admin logs, rather than being GCed
|
||||
|
||||
/datum/gm_action/viral_infection
|
||||
name = "viral infection"
|
||||
departments = list(ROLE_MEDICAL)
|
||||
chaotic = 5
|
||||
var/list/viruses = list()
|
||||
var/severity = 1
|
||||
|
||||
/datum/gm_action/viral_infection/set_up()
|
||||
severity = pickweight(EVENT_LEVEL_MUNDANE = 20,
|
||||
EVENT_LEVEL_MODERATE = 10,
|
||||
EVENT_LEVEL_MAJOR = 3
|
||||
)
|
||||
|
||||
//generate 1-3 viruses. This way there's an upper limit on how many individual diseases need to be cured if many people are initially infected
|
||||
var/num_diseases = rand(1,3)
|
||||
for (var/i=0, i < num_diseases, i++)
|
||||
var/datum/disease2/disease/D = new /datum/disease2/disease
|
||||
|
||||
var/strength = 1 //whether the disease is of the greater or lesser variety
|
||||
if (severity >= EVENT_LEVEL_MAJOR && prob(75))
|
||||
strength = 2
|
||||
D.makerandom(strength)
|
||||
viruses += D
|
||||
|
||||
/datum/gm_action/viral_infection/announce()
|
||||
var/level
|
||||
if (severity == EVENT_LEVEL_MUNDANE)
|
||||
return
|
||||
else if (severity == EVENT_LEVEL_MODERATE)
|
||||
level = pick("one", "two", "three", "four")
|
||||
else
|
||||
level = "five"
|
||||
|
||||
spawn(rand(0, 3000))
|
||||
if(severity == EVENT_LEVEL_MAJOR || prob(60))
|
||||
command_announcement.Announce("Confirmed outbreak of level [level] biohazard aboard \the [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak5.ogg')
|
||||
|
||||
/datum/gm_action/viral_infection/start()
|
||||
if(!viruses.len) return
|
||||
|
||||
..()
|
||||
|
||||
var/list/candidates = list() //list of candidate keys
|
||||
for(var/mob/living/carbon/human/G in player_list)
|
||||
if(G.mind && G.stat != DEAD && G.is_client_active(5) && !player_is_antag(G.mind))
|
||||
var/turf/T = get_turf(G)
|
||||
if(T.z in using_map.station_levels)
|
||||
candidates += G
|
||||
if(!candidates.len) return
|
||||
candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
|
||||
|
||||
var/list/used_viruses = list()
|
||||
var/list/used_candidates = list()
|
||||
severity = max(EVENT_LEVEL_MUNDANE, severity - 1)
|
||||
var/actual_severity = severity * rand(1, 3)
|
||||
while(actual_severity > 0 && candidates.len)
|
||||
var/datum/disease2/disease/D = pick(viruses)
|
||||
infect_mob(candidates[1], D.getcopy())
|
||||
used_candidates += candidates[1]
|
||||
candidates.Remove(candidates[1])
|
||||
actual_severity--
|
||||
used_viruses |= D
|
||||
|
||||
event_viruses |= used_viruses
|
||||
var/list/used_viruses_links = list()
|
||||
var/list/used_viruses_text = list()
|
||||
for(var/datum/disease2/disease/D in used_viruses)
|
||||
used_viruses_links += "<a href='?src=\ref[D];info=1'>[D.name()]</a>"
|
||||
used_viruses_text += D.name()
|
||||
|
||||
var/list/used_candidates_links = list()
|
||||
var/list/used_candidates_text = list()
|
||||
for(var/mob/M in used_candidates)
|
||||
used_candidates_links += key_name_admin(M)
|
||||
used_candidates_text += key_name(M)
|
||||
|
||||
log_admin("Virus event affecting [english_list(used_candidates_text)] started; Viruses: [english_list(used_viruses_text)]")
|
||||
message_admins("Virus event affecting [english_list(used_candidates_links)] started; Viruses: [english_list(used_viruses_links)]")
|
||||
|
||||
/datum/gm_action/viral_infection/get_weight()
|
||||
return (metric.count_people_in_department(ROLE_MEDICAL) * 20)
|
||||
44
code/modules/gamemaster/actions/viral_outbreak.dm
Normal file
44
code/modules/gamemaster/actions/viral_outbreak.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/datum/gm_action/viral_outbreak
|
||||
name = "viral outbreak"
|
||||
departments = list(ROLE_MEDICAL, ROLE_EVERYONE)
|
||||
chaotic = 30
|
||||
var/severity = 1
|
||||
var/list/candidates = list()
|
||||
|
||||
/datum/gm_action/viral_outbreak/set_up()
|
||||
candidates.Cut() // Incase we somehow get run twice.
|
||||
severity = rand(2, 4)
|
||||
for(var/mob/living/carbon/human/G in player_list)
|
||||
if(G.client && G.stat != DEAD)
|
||||
candidates += G
|
||||
if(!candidates.len) return
|
||||
candidates = shuffle(candidates)//Incorporating Donkie's list shuffle
|
||||
|
||||
/datum/gm_action/viral_outbreak/announce()
|
||||
command_announcement.Announce("Confirmed outbreak of level 7 biohazard aboard \the [station_name()]. All personnel must contain the outbreak.", "Biohazard Alert", new_sound = 'sound/AI/outbreak7.ogg')
|
||||
|
||||
/datum/gm_action/viral_outbreak/start()
|
||||
..()
|
||||
while(severity > 0 && candidates.len)
|
||||
if(prob(33))
|
||||
infect_mob_random_lesser(candidates[1])
|
||||
else
|
||||
infect_mob_random_greater(candidates[1])
|
||||
|
||||
candidates.Remove(candidates[1])
|
||||
severity--
|
||||
|
||||
/datum/gm_action/viral_outbreak/get_weight()
|
||||
var/medical = metric.count_people_in_department(ROLE_MEDICAL)
|
||||
var/security = metric.count_people_in_department(ROLE_SECURITY)
|
||||
var/everyone = metric.count_people_in_department(ROLE_EVERYONE)
|
||||
|
||||
var/assigned_staff = medical + round(security / 2)
|
||||
|
||||
if(!medical) // No docs, no staff.
|
||||
assigned_staff = 0
|
||||
|
||||
if(assigned_staff < round(everyone / 6) - assigned_staff) // A doc or half an officer per roughly six people. Any less, and assigned staff is halved.
|
||||
assigned_staff /= 2
|
||||
|
||||
return (assigned_staff * 10)
|
||||
43
code/modules/gamemaster/actions/wallrot.dm
Normal file
43
code/modules/gamemaster/actions/wallrot.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
/datum/gm_action/wallrot
|
||||
name = "wall rot"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
reusable = TRUE
|
||||
var/turf/simulated/wall/center
|
||||
var/severity = 1
|
||||
|
||||
/datum/gm_action/wallrot/set_up()
|
||||
severity = rand(1,3)
|
||||
center = null
|
||||
// 100 attempts
|
||||
for(var/i=0, i<100, i++)
|
||||
var/turf/candidate = locate(rand(1, world.maxx), rand(1, world.maxy), 1)
|
||||
if(istype(candidate, /turf/simulated/wall))
|
||||
center = candidate
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/gm_action/wallrot/announce()
|
||||
if(center && prob(min(90,40 * severity)))
|
||||
command_announcement.Announce("Harmful fungi detected on \the [station_name()] nearby [center.loc.name]. Station structures may be contaminated.", "Biohazard Alert")
|
||||
|
||||
/datum/gm_action/wallrot/start()
|
||||
..()
|
||||
spawn()
|
||||
if(center)
|
||||
// Make sure at least one piece of wall rots!
|
||||
center.rot()
|
||||
|
||||
// Have a chance to rot lots of other walls.
|
||||
var/rotcount = 0
|
||||
var/actual_severity = severity * rand(5, 10)
|
||||
for(var/turf/simulated/wall/W in range(5, center))
|
||||
if(prob(50))
|
||||
W.rot()
|
||||
rotcount++
|
||||
|
||||
// Only rot up to severity walls
|
||||
if(rotcount >= actual_severity)
|
||||
break
|
||||
|
||||
/datum/gm_action/wallrot/get_weight()
|
||||
return 60 + (metric.count_people_in_department(ROLE_ENGINEERING) * 35)
|
||||
78
code/modules/gamemaster/actions/window_break.dm
Normal file
78
code/modules/gamemaster/actions/window_break.dm
Normal file
@@ -0,0 +1,78 @@
|
||||
/datum/gm_action/window_break
|
||||
name = "window breach"
|
||||
departments = list(ROLE_ENGINEERING)
|
||||
chaotic = 5
|
||||
var/obj/structure/window/chosen_window
|
||||
var/list/obj/structure/window/collateral_windows
|
||||
var/turf/chosen_location
|
||||
var/list/area/excluded = list(
|
||||
/area/shuttle,
|
||||
/area/crew_quarters
|
||||
)
|
||||
|
||||
/datum/gm_action/window_break/set_up()
|
||||
var/list/area/grand_list_of_areas = get_station_areas(excluded)
|
||||
//try 10 times
|
||||
for(var/i in 1 to 10)
|
||||
var/area/A = pick(grand_list_of_areas)
|
||||
var/list/obj/structure/window/possible_target_windows = list()
|
||||
for(var/obj/structure/window/target_window in A.contents)
|
||||
possible_target_windows += target_window
|
||||
possible_target_windows = shuffle(possible_target_windows)
|
||||
|
||||
for(var/obj/structure/window/target_window in possible_target_windows)
|
||||
//if() don't have any conditions, for isn't strictly necessary
|
||||
chosen_window = target_window
|
||||
chosen_location = chosen_window.loc
|
||||
collateral_windows = gather_collateral_windows(chosen_window)
|
||||
return
|
||||
|
||||
//TL;DR: breadth first search for all connected turfs with windows
|
||||
/datum/gm_action/window_break/proc/gather_collateral_windows(var/obj/structure/window/target_window)
|
||||
var/list/turf/frontier_set = list(target_window.loc)
|
||||
var/list/obj/structure/window/result_set = list()
|
||||
var/list/turf/explored_set = list()
|
||||
|
||||
while(frontier_set.len > 0)
|
||||
var/turf/current = frontier_set[1]
|
||||
frontier_set -= current
|
||||
explored_set += current
|
||||
|
||||
var/contains_windows = 0
|
||||
for(var/obj/structure/window/to_add in current.contents)
|
||||
contains_windows = 1
|
||||
result_set += to_add
|
||||
|
||||
if(contains_windows)
|
||||
//add adjacent turfs to be checked for windows as well
|
||||
var/turf/neighbor = locate(current.x + 1, current.y, current.z)
|
||||
if(!(neighbor in frontier_set) && !(neighbor in explored_set))
|
||||
frontier_set += neighbor
|
||||
neighbor = locate(current.x - 1, current.y, current.z)
|
||||
if(!(neighbor in frontier_set) && !(neighbor in explored_set))
|
||||
frontier_set += neighbor
|
||||
neighbor = locate(current.x, current.y + 1, current.z)
|
||||
if(!(neighbor in frontier_set) && !(neighbor in explored_set))
|
||||
frontier_set += neighbor
|
||||
neighbor = locate(current.x, current.y - 1, current.z)
|
||||
if(!(neighbor in frontier_set) && !(neighbor in explored_set))
|
||||
frontier_set += neighbor
|
||||
return result_set
|
||||
|
||||
/datum/gm_action/window_break/start()
|
||||
if(!chosen_window)
|
||||
return
|
||||
..()
|
||||
chosen_window.shatter(0)
|
||||
|
||||
spawn()
|
||||
for(var/obj/structure/window/current_collateral in collateral_windows)
|
||||
sleep(rand(1,20))
|
||||
current_collateral.take_damage(current_collateral.health - (current_collateral.maxhealth / 5)) //set to 1/5th health
|
||||
|
||||
/datum/gm_action/window_break/announce()
|
||||
if(chosen_window)
|
||||
command_announcement.Announce("Structural integrity of windows at [chosen_location.loc.name] is failing. Immediate repair or replacement is advised.", "Structural Alert")
|
||||
|
||||
/datum/gm_action/window_break/get_weight()
|
||||
return 20 * metric.count_people_in_department(ROLE_ENGINEERING)
|
||||
23
code/modules/gamemaster/actions/wormholes.dm
Normal file
23
code/modules/gamemaster/actions/wormholes.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
/datum/gm_action/wormholes
|
||||
name = "space-time anomalies"
|
||||
chaotic = 70
|
||||
length = 12 MINUTES
|
||||
departments = list(ROLE_EVERYONE)
|
||||
var/severity = 1
|
||||
|
||||
/datum/gm_action/wormholes/set_up() // 1 out of 5 will be full-duration wormholes, meaning up to a minute long.
|
||||
severity = pickweight(list(
|
||||
3 = 5,
|
||||
2 = 7,
|
||||
1 = 13
|
||||
))
|
||||
|
||||
/datum/gm_action/wormholes/start()
|
||||
..()
|
||||
wormhole_event(length / 2, (severity / 3))
|
||||
|
||||
/datum/gm_action/wormholes/get_weight()
|
||||
return 10 + max(0, -30 + (metric.count_people_in_department(ROLE_EVERYONE) * 5) + (metric.count_people_in_department(ROLE_ENGINEERING) + 10) + (metric.count_people_in_department(ROLE_MEDICAL) * 20))
|
||||
|
||||
/datum/gm_action/wormholes/end()
|
||||
command_announcement.Announce("There are no more space-time anomalies detected on the station.", "Anomaly Alert")
|
||||
@@ -39,6 +39,9 @@
|
||||
spreadtype = prob(70) ? "Airborne" : "Contact"
|
||||
resistance = rand(15,70)
|
||||
|
||||
if(severity >= 2 && prob(33))
|
||||
resistance += 10
|
||||
|
||||
if(all_species.len)
|
||||
affected_species = get_infectable_species()
|
||||
|
||||
|
||||
@@ -1845,17 +1845,41 @@
|
||||
#include "code\modules\gamemaster\game_master.dm"
|
||||
#include "code\modules\gamemaster\helpers.dm"
|
||||
#include "code\modules\gamemaster\actions\action.dm"
|
||||
#include "code\modules\gamemaster\actions\atmos_leak.dm"
|
||||
#include "code\modules\gamemaster\actions\blob.dm"
|
||||
#include "code\modules\gamemaster\actions\brand_intelligence.dm"
|
||||
#include "code\modules\gamemaster\actions\camera_damage.dm"
|
||||
#include "code\modules\gamemaster\actions\canister_leak.dm"
|
||||
#include "code\modules\gamemaster\actions\carp_migration.dm"
|
||||
#include "code\modules\gamemaster\actions\carp_migration_vr.dm"
|
||||
#include "code\modules\gamemaster\actions\comms_blackout.dm"
|
||||
#include "code\modules\gamemaster\actions\dust.dm"
|
||||
#include "code\modules\gamemaster\actions\electrical_storm.dm"
|
||||
#include "code\modules\gamemaster\actions\electrified_door.dm"
|
||||
#include "code\modules\gamemaster\actions\gravity.dm"
|
||||
#include "code\modules\gamemaster\actions\grid_check.dm"
|
||||
#include "code\modules\gamemaster\actions\ion_storm.dm"
|
||||
#include "code\modules\gamemaster\actions\meteor_defense.dm"
|
||||
#include "code\modules\gamemaster\actions\money_hacker.dm"
|
||||
#include "code\modules\gamemaster\actions\money_lotto.dm"
|
||||
#include "code\modules\gamemaster\actions\money_spam.dm"
|
||||
#include "code\modules\gamemaster\actions\prison_break.dm"
|
||||
#include "code\modules\gamemaster\actions\radiation_storm.dm"
|
||||
#include "code\modules\gamemaster\actions\random_antagonist.dm"
|
||||
#include "code\modules\gamemaster\actions\rogue_drones.dm"
|
||||
#include "code\modules\gamemaster\actions\shipping_error.dm"
|
||||
#include "code\modules\gamemaster\actions\solar_storm.dm"
|
||||
#include "code\modules\gamemaster\actions\spacevine.dm"
|
||||
#include "code\modules\gamemaster\actions\spider_infestation.dm"
|
||||
#include "code\modules\gamemaster\actions\spontaneous_appendicitis.dm"
|
||||
#include "code\modules\gamemaster\actions\surprise_carp_attack.dm"
|
||||
#include "code\modules\gamemaster\actions\surprise_meteor.dm"
|
||||
#include "code\modules\gamemaster\actions\viral_infection.dm"
|
||||
#include "code\modules\gamemaster\actions\viral_outbreak.dm"
|
||||
#include "code\modules\gamemaster\actions\wallrot.dm"
|
||||
#include "code\modules\gamemaster\actions\waste_disposal.dm"
|
||||
#include "code\modules\gamemaster\actions\window_break.dm"
|
||||
#include "code\modules\gamemaster\actions\wormholes.dm"
|
||||
#include "code\modules\games\cah.dm"
|
||||
#include "code\modules\games\cah_black_cards.dm"
|
||||
#include "code\modules\games\cah_white_cards.dm"
|
||||
|
||||
Reference in New Issue
Block a user