diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index e0b0aed75d2..5afacbd42c3 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1377,3 +1377,11 @@ proc/find_holder_of_type(var/atom/reference,var/typepath) //Returns the first ob
/world/Error(exception/e)
print_runtime(e)
..()
+
+//Checks if any of the atoms in the turf are dense
+//Returns 1 is anything is dense, 0 otherwise
+/turf/proc/has_dense_content()
+ for(var/atom/turf_contents in contents)
+ if(turf_contents.density)
+ return 1
+ return 0
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 7c5334d802e..838556ca79a 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -518,10 +518,7 @@
AM.change_area(old_area,src)
var/list/ignored_keys = list("loc", "locs", "parent_type", "vars", "verbs", "type", "x", "y", "z","group","contents","air","light","areaMaster","underlays","lighting_overlay")
-var/list/moved_landmarks = list(latejoin, wizardstart, meteor_materialkit,\
- meteor_bombkit, meteor_bombkitextra, meteor_tankkit, meteor_canisterkit,\
- meteor_buildkit, meteor_pizzakit, meteor_panickit, meteor_shieldkit,\
- meteor_genkit, meteor_breachkit) //Landmarks that are moved by move_area_to and move_contents_to
+var/list/moved_landmarks = list(latejoin, wizardstart) //Landmarks that are moved by move_area_to and move_contents_to
var/list/transparent_icons = list("diagonalWall3","swall_f5","swall_f6","swall_f9","swall_f10") //icon_states for which to prepare an underlay
/area/proc/move_contents_to(var/area/A, var/turftoleave=null, var/direction = null)
diff --git a/code/game/gamemodes/meteor/meteor.dm b/code/game/gamemodes/meteor/meteor.dm
index be95c466c63..44427449d6a 100644
--- a/code/game/gamemodes/meteor/meteor.dm
+++ b/code/game/gamemodes/meteor/meteor.dm
@@ -1,41 +1,43 @@
/datum/game_mode/meteor
name = "meteor"
config_tag = "meteor"
+
var/const/waittime_l = 600 //Lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //Upper bound on time before intercept arrives (in tenths of seconds)
- var/const/meteorannouncedelay_l = 6000 //Lower bound on announcement, here 10 minutes
- var/const/meteorannouncedelay_h = 9000 //Upper bound on announcement, here 15 minutes
- var/meteorannouncedelay = 7500 //Final announcement delay, this is a failsafe value
- var/const/supplydelay = 300 //Delay before meteor supplies are spawned in tenth of seconds
- var/const/meteordelay_l = 1800 //Lower bound to meteor arrival, here 3 minutes
- var/const/meteordelay_h = 3000 //Higher bound to meteor arrival, here 5 minutes
- var/const/meteorshuttlemultiplier = 4.5 //How much more will we need to hold out ? Here 45 minutes until the shuttle arrives. 1 is 10 minutes
- var/meteordelay = 2400 //Final meteor delay, failsafe as above
- var/nometeors = 1 //Can we send the meteors ?
- var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
- required_players = 20
+
+ var/const/meteorannouncedelay_l = 2100 //Lower bound on announcement, here 3 minutes and 30 seconds
+ var/const/meteorannouncedelay_h = 3000 //Upper bound on announcement, here 5 minutes
+ var/meteorannouncedelay = 2400 //Default final announcement delay
+ var/const/supplydelay = 100 //Delay before meteor supplies are spawned in tenth of seconds
+ var/const/meteordelay_l = 3000 //Lower bound to meteor wave arrival, here 5 minutes
+ var/const/meteordelay_h = 4500 //Higher bound to meteor wave arrival, here 7 and a half minutes
+ var/const/meteorshuttlemultiplier = 3 //How much more will we need to hold out ? Here 30 minutes until the shuttle arrives. Multiplies by 10
+ var/meteordelay = 7500 //Default final meteor delay
+ var/meteors_allowed = 0 //Can we send the meteors ?
+ required_players = 0
+ required_players_secret = 20
uplink_welcome = "EVIL METEOR Uplink Console:"
uplink_uses = 10
/datum/game_mode/meteor/announce()
world << "The current game mode is - Meteor!"
- world << "The space station has been stuck in a major meteor shower. You must escape from the station or at least live."
+ world << "The space station is about to be struck by a major meteor shower. You must hold out until the escape shuttle arrives."
/datum/universal_state/meteor_storm
name = "Meteor Storm"
- desc = "Meteors are currently running havoc around this sector. Better get out of here quickly."
+ desc = "A meteor storm is currently wrecking havoc around this sector. Duck and cover."
- decay_rate = 0 // Just to make sure
+ decay_rate = 0 //Just to make sure
/datum/universal_state/meteor_storm/OnShuttleCall(var/mob/user)
if(user)
- user << "You hear an automatic dispatch from Nanotrasen. It states that Centcomm is being shielded due to the incoming meteor storm and that regular shuttle service has been interrupted."
+ user << "You hear an automatic dispatch from Nanotrasen. It states that Centcomm is being shielded due to an incoming meteor storm and that regular shuttle service has been interrupted."
return 0
/datum/game_mode/meteor/post_setup()
- //Let's set up the announcement and meteor delay immediatly to send to admins and use later
+ //Let's set up the announcement and meteor delay immediatly to send to the admins and use later
meteorannouncedelay = rand((meteorannouncedelay_l/600), (meteorannouncedelay_h/600))*600 //Minute interval for simplicity
meteordelay = rand((meteordelay_l/600), (meteordelay_h/600))*600 //Ditto above
@@ -47,237 +49,34 @@
spawn(meteorannouncedelay)
if(prob(70)) //Slighty off-scale
- command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 600, meteordelay + 600))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds. Make good use of these supplies to build a safe zone and good luck.", "Space Weather Automated Announcements")
+ command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 600, meteordelay + 600))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \
+ "Space Weather Automated Announcements")
else //Oh boy
- command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 1200, meteordelay + 3000))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds. Make good use of these supplies to build a safe zone and good luck.", "Space Weather Automated Announcements")
- world << sound('sound/AI/meteorround.ogg')
+ command_alert("A meteor storm has been detected in proximity of [station_name()] and is expected to strike within [round((rand(meteordelay - 1800, meteordelay + 1800))/600)] minutes. A backup emergency shuttle is being dispatched and emergency gear should be teleported into your station's Bar area in [supplydelay/10] seconds.", \
+ "Space Weather Automated Announcements")
+ world << sound('sound/AI/meteorround.ogg')
+ /*
for(var/obj/item/mecha_parts/mecha_equipment/tool/rcd/rcd in world) //Borg RCDs are fairly cheap, so disabling those
rcd.disabled = 1
+ */
spawn(100) //Panic interval
emergency_shuttle.incall(meteorshuttlemultiplier)
- captain_announce("A backup emergency shuttle has been called. It will arrive in [round((emergency_shuttle.timeleft())/60)] minutes. Justification : 'Major meteor storm inbound in this sector. Evacuation procedures deferred to Space Weather Inc. THIS IS NOT A DRILL'")
+ captain_announce("A backup emergency shuttle has been called. It will arrive in [round((emergency_shuttle.timeleft())/60)] minutes. Justification : 'Major meteor storm inbound. Evacuation procedures deferred to Space Weather Inc. THIS IS NOT A DRILL'")
world << sound('sound/AI/shuttlecalled.ogg')
SetUniversalState(/datum/universal_state/meteor_storm)
spawn(supplydelay)
- //For barricades and materials
- for(var/turf/T in meteor_materialkit)
- meteor_materialkit -= T
- for(var/atom/A in T) //Cleaning loop borrowed from the shuttle
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib() //We told you to get the fuck out of here
- if(istype(A,/obj) || istype(A,/turf/simulated/wall)) //Remove anything in the way
- qdel(A) //Telegib
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/rack(T)
- new /obj/item/stack/sheet/wood(T, 50) //10 cade kits, or miscellaneous things
- var/obj/item/stack/sheet/metal/M = getFromPool(/obj/item/stack/sheet/metal,T)
- M.amount = 50
- //new /obj/item/stack/sheet/metal(T, 50)
- new /obj/item/stack/sheet/glass/glass(T, 50)
- new /obj/item/stack/sheet/glass/plasmarglass(T, 50) //Bomb-proof, so very useful
-
- //Discount EVA that also acts as explosion shielding
- for(var/turf/T in meteor_bombkit)
- meteor_bombkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) && !istype(A, /obj/machinery/atmospherics) || istype(A,/turf/simulated/wall)) //Snowflake code since some instances are over pipes
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/machinery/suit_storage_unit/meteor_eod(T)
-
- //Things that don't fit in the EVA kits
- for(var/turf/T in meteor_bombkitextra)
- meteor_bombkitextra -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/table(T) //Enough racks already
- new /obj/item/clothing/gloves/black(T) //Always dress with style
- new /obj/item/clothing/gloves/black(T)
- new /obj/item/clothing/gloves/black(T)
- new /obj/item/clothing/gloves/black(T)
- new /obj/item/clothing/gloves/black(T)
- new /obj/item/clothing/gloves/black(T)
- new /obj/item/clothing/glasses/sunglasses(T) //Wouldn't it be dumb if a meteor explosion blinded you
- new /obj/item/clothing/glasses/sunglasses(T)
- new /obj/item/clothing/glasses/sunglasses(T)
- new /obj/item/clothing/glasses/sunglasses(T)
- new /obj/item/clothing/glasses/sunglasses(T)
- new /obj/item/clothing/glasses/sunglasses(T)
-
- //Free oxygen tanks
- for(var/turf/T in meteor_tankkit)
- meteor_tankkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/dispenser/oxygen(T)
-
- //Oxygen canisters for internals, don't waste 'em
- for(var/turf/T in meteor_canisterkit)
- meteor_canisterkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/machinery/portable_atmospherics/canister/oxygen(T)
-
- //WE BUILD
- for(var/turf/T in meteor_buildkit)
- meteor_buildkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/rack(T)
- new /obj/item/weapon/storage/toolbox/electrical(T)
- new /obj/item/weapon/storage/toolbox/electrical(T)
- new /obj/item/weapon/storage/toolbox/mechanical(T)
- new /obj/item/weapon/storage/toolbox/mechanical(T)
- new /obj/item/clothing/head/welding(T)
- new /obj/item/clothing/head/welding(T)
- new /obj/item/device/multitool(T)
- new /obj/item/device/multitool(T)
-
- //Because eating is important
- for(var/turf/T in meteor_pizzakit)
- meteor_pizzakit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/rack(T)
- new /obj/item/pizzabox/margherita(T)
- new /obj/item/pizzabox/mushroom(T)
- new /obj/item/pizzabox/meat(T)
- new /obj/item/pizzabox/vegetable(T)
- new /obj/item/weapon/kitchen/utensil/knife/large(T)
-
- //Don't panic
- for(var/turf/T in meteor_panickit)
- meteor_panickit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/rack(T)
- new /obj/item/weapon/storage/toolbox/emergency(T)
- new /obj/item/weapon/storage/toolbox/emergency(T)
- new /obj/item/device/violin(T) //My tune will go on
- new /obj/item/weapon/paper_bin(T) //Any last wishes ?
- new /obj/item/weapon/pen/red(T)
-
- //Emergency Area Shielding. Uses a lot of power
- for(var/turf/T in meteor_shieldkit)
- meteor_shieldkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/machinery/shieldgen(T)
-
- //Power that should last for a bit. Pairs well with the shield generator when Engineering is dead
- for(var/turf/T in meteor_genkit)
- meteor_genkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/machinery/power/port_gen/pacman(T)
- new /obj/item/stack/sheet/mineral/plasma(T, 20)
-
- for(var/turf/T in meteor_breachkit)
- meteor_breachkit -= T
- for(var/atom/A in T)
- //if(istype(A,/mob/living))
- //var/mob/living/unlucky_person = A
- //unlucky_person.gib()
- if(istype(A,/obj) || istype(A,/turf/simulated/wall))
- qdel(A)
- spawn(1)
- spark_system.attach(T)
- spark_system.set_up(5, 0, T)
- spark_system.start()
- new /obj/structure/table(T)
- new /obj/item/taperoll/atmos(T) //Just for the hell of it
- new /obj/item/taperoll/atmos(T)
- new /obj/item/weapon/grenade/chem_grenade/metalfoam(T) //Could use a custom box
- new /obj/item/weapon/grenade/chem_grenade/metalfoam(T)
- new /obj/item/weapon/grenade/chem_grenade/metalfoam(T)
- new /obj/item/weapon/grenade/chem_grenade/metalfoam(T)
-
- //Use existing templates in landmarks.dm, global.dm and here to add more supplies
+ meteor_initial_supply() //Handled in meteor_supply.dm
spawn(meteordelay)
- nometeors = 0
+ meteors_allowed = 1
/datum/game_mode/meteor/process()
- if(!nometeors)
- meteors_in_wave = rand(100,200) //Between 100 and 200 meteors per wave
- meteor_wave(meteors_in_wave)
+ if(meteors_allowed)
+ var/meteors_in_wave = rand(50, 100) //Between 25 and 50 meteors per wave
+ meteor_wave(meteors_in_wave, 3)
return
/datum/game_mode/meteor/declare_completion()
@@ -286,7 +85,8 @@
for(var/mob/living/player in player_list)
if(player.stat != DEAD)
var/turf/location = get_turf(player.loc)
- if(!location) continue
+ if(!location)
+ continue
switch(location.loc.type)
if(/area/shuttle/escape/centcom)
text += "
[player.real_name] escaped on the emergency shuttle"
@@ -299,10 +99,10 @@
if(survivors)
world << "The following survived the meteor storm:[text]"
else
- world << "Nobody survived the meteor storm!"
+ world << "The meteors crashed this station with no survivors!"
- feedback_set_details("round_end_result","end - evacuation")
- feedback_set("round_end_result",survivors)
+ feedback_set_details("round_end_result", "end - evacuation")
+ feedback_set("round_end_result", survivors)
..()
return 1
diff --git a/code/game/gamemodes/meteor/meteor_supply.dm b/code/game/gamemodes/meteor/meteor_supply.dm
new file mode 100644
index 00000000000..050cc193d94
--- /dev/null
+++ b/code/game/gamemodes/meteor/meteor_supply.dm
@@ -0,0 +1,161 @@
+/datum/game_mode/meteor/proc/meteor_initial_supply()
+
+ var/list/meteor_initial_drop = list(/obj/structure/closet/crate/engi/meteor_materials, \
+ /obj/structure/closet/crate/meteor_assorted_protection, \
+ /obj/structure/closet/crate/engi/meteor_buildgear, \
+ /obj/structure/closet/crate/freezer/meteor_pizza, \
+ /obj/structure/closet/crate/meteor_panic, \
+ /obj/structure/closet/crate/secure/large/meteor_shieldwallgen, \
+ /obj/structure/closet/crate/secure/large/meteor_shieldgens, \
+ /obj/structure/closet/crate/secure/large/meteor_power, \
+ /obj/structure/closet/crate/engi/meteor_breach, \
+ /obj/machinery/computer/bhangmeter)
+
+ var/area/initial_supply_area = locate(/area/crew_quarters/bar)
+
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
+
+ //One loop for each crate
+ for(var/meteor_supplypaths in meteor_initial_drop)
+ var/list/turf/simulated/floor/valid = list()
+ //Loop through each floor in the supply drop area
+ for(var/turf/simulated/floor/F in initial_supply_area)
+ if(!F.has_dense_content())
+ valid.Add(F)
+
+ var/picked = pick(valid)
+ spark_system.attach(picked)
+ spark_system.set_up(5, 0, picked)
+ spark_system.start()
+ new meteor_supplypaths(picked)
+
+/*
+ * Below are all the supply crates that spawn on the initial drop
+ */
+
+//Barricades and physical fortifications
+/obj/structure/closet/crate/engi/meteor_materials
+ name = "\improper Space Weather Inc. materials crate"
+ desc = "For all your building and rebuilding needs."
+
+/obj/structure/closet/crate/engi/meteor_materials/New()
+
+ ..()
+ getFromPool(/obj/item/stack/sheet/metal, src, 50)
+ getFromPool(/obj/item/stack/sheet/metal, src, 50)
+ getFromPool(/obj/item/stack/sheet/wood, src, 50)
+ getFromPool(/obj/item/stack/sheet/wood, src, 50)
+ getFromPool(/obj/item/stack/sheet/glass/rglass, src, 50)
+ getFromPool(/obj/item/stack/sheet/glass/plasmarglass, src, 50)
+
+//Assorted protection items. Gloves, sunglasses
+/obj/structure/closet/crate/meteor_assorted_protection
+ name = "\improper Space Weather Inc. protective gear crate"
+ desc = "Cool crewmen don't look at meteor explosions, with the naked eye."
+
+/obj/structure/closet/crate/meteor_assorted_protection/New()
+
+ ..()
+ //Three boxes containing seven black gloves each
+ new /obj/item/weapon/storage/box/bgloves(src)
+ new /obj/item/weapon/storage/box/bgloves(src)
+ new /obj/item/weapon/storage/box/bgloves(src)
+ //Three boxes containing seven sunglasses each
+ new /obj/item/weapon/storage/box/sunglasses(src)
+ new /obj/item/weapon/storage/box/sunglasses(src)
+ new /obj/item/weapon/storage/box/sunglasses(src)
+
+//Building gear
+/obj/structure/closet/crate/engi/meteor_buildgear
+ name = "\improper Space Weather Inc. build gear"
+ desc = "Building gear, for all your building needs."
+
+/obj/structure/closet/crate/engi/meteor_buildgear/New()
+
+ ..()
+ new /obj/item/weapon/storage/belt/utility/complete(src)
+ new /obj/item/weapon/storage/belt/utility/complete(src)
+ new /obj/item/weapon/storage/belt/utility/complete(src)
+ new /obj/item/clothing/head/welding(src)
+ new /obj/item/clothing/head/welding(src)
+ new /obj/item/clothing/head/welding(src)
+
+//Pizza, just in case
+/obj/structure/closet/crate/freezer/meteor_pizza
+ name = "\improper Space Weather Inc. pizza stash"
+ desc = "Who can endure a 24/7 weather monitoring job without pizza ? Not us."
+
+/obj/structure/closet/crate/freezer/meteor_pizza/New()
+
+ ..()
+ new /obj/item/pizzabox/margherita(src)
+ new /obj/item/pizzabox/margherita(src)
+ new /obj/item/pizzabox/mushroom(src)
+ new /obj/item/pizzabox/meat(src)
+ new /obj/item/pizzabox/meat(src)
+ new /obj/item/pizzabox/vegetable(src)
+ new /obj/item/weapon/kitchen/utensil/knife/large(src)
+
+//Flavor and flares
+/obj/structure/closet/crate/meteor_panic
+ name = "\improper Space Weather Inc. panic kit"
+ desc = "Open only in case of absolute emergency, or severe boredom."
+
+/obj/structure/closet/crate/meteor_panic/New()
+
+ new /obj/item/device/violin(src) //My tune will go on
+ new /obj/item/weapon/phone(src)
+ new /obj/item/weapon/storage/fancy/flares(src)
+ new /obj/item/weapon/storage/fancy/flares(src)
+ new /obj/item/weapon/paper_bin(src) //Any last wishes ?
+ new /obj/item/weapon/pen/red(src)
+
+//Will create a large forcefield if given enough power
+/obj/structure/closet/crate/secure/large/meteor_shieldwallgen
+ name = "\improper Space Weather Inc. wall shield generator"
+ desc = "Ensure a proper power source is available for sustained operation."
+
+/obj/structure/closet/crate/secure/large/meteor_shieldwallgen/New()
+
+ ..()
+ new /obj/machinery/shieldwallgen(src)
+ new /obj/machinery/shieldwallgen(src)
+ new /obj/machinery/shieldwallgen(src)
+ new /obj/machinery/shieldwallgen(src)
+
+//Can protect window bays locally by putting forcefields in front of them, limited usefulness
+/obj/structure/closet/crate/secure/large/meteor_shieldgens
+ name = "\improper Space Weather Inc. point shield generators"
+ desc = "Four portable point shield generators that can hold up a window bay against small meteor pelting."
+
+/obj/structure/closet/crate/secure/large/meteor_shieldgens/New()
+
+ ..()
+ new /obj/machinery/shieldgen(src)
+ new /obj/machinery/shieldgen(src)
+ new /obj/machinery/shieldgen(src)
+ new /obj/machinery/shieldgen(src)
+
+//Power to run all that fancy shit. Partially at least, evacuating the AME isn't a bad idea
+/obj/structure/closet/crate/secure/large/meteor_power
+ name = "\improper Space Weather Inc. emergency generator"
+ desc = "Uranium-powered SUPERPACMAN emergency generator. Keep away from meteors."
+
+/obj/structure/closet/crate/secure/large/meteor_power/New()
+
+ ..()
+ new /obj/machinery/power/port_gen/pacman/super(src)
+ getFromPool(/obj/item/stack/sheet/mineral/uranium, src, 50)
+
+/obj/structure/closet/crate/engi/meteor_breach
+ name = "\improper Space Weather Inc. anti-breach kit"
+ desc = "Apply grenade to breached area, apply atmospherics taperoll to entrances to said area."
+
+/obj/structure/closet/crate/engi/meteor_breach/New()
+
+ ..()
+ new /obj/item/taperoll/atmos(src)
+ new /obj/item/taperoll/atmos(src)
+ new /obj/item/taperoll/atmos(src)
+ new /obj/item/weapon/storage/box/foam(src)
+ new /obj/item/weapon/storage/box/foam(src)
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 7f8eee2f0fd..4ac4bab9a59 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -1,29 +1,64 @@
#define METEOR_TEMPERATURE
-/var/meteor_wave_delay = 300 //Failsafe wait between waves in tenths of seconds
-//Set it above 100 (10s delay) if you want to minimize lag for some reason
-
-/var/meteors_in_wave = 10 //Failsafe in case a number isn't called
-/var/meteorwavecurrent = 0
+/var/meteor_wave_delay = 300 //Default wait between waves in tenths of seconds
+/var/meteors_in_wave = 10 //Default absolute size
+/var/meteor_wave_active = 0
/var/max_meteor_size = 0
/var/chosen_dir = 1
-/proc/meteor_wave(var/number = meteors_in_wave, var/max_size = 0, var/list/types=null) //Call above constants to change
+/proc/meteor_wave(var/number = meteors_in_wave, var/max_size = 0, var/list/types = null) //Call above constants to change
//writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/meteor_wave() called tick#: [world.time]")
- if(!ticker || meteorwavecurrent)
+ if(!ticker || meteor_wave_active)
return
- meteorwavecurrent = 1
- meteor_wave_delay = (rand(30,45)) * 10 //Between 30 and 45 seconds, makes everything more chaotic
+ meteor_wave_active = 1
+ meteor_wave_delay = (rand(25, 40)) * 10 //Between 30 and 45 seconds, engineers need time to shuffle in relative safety
chosen_dir = pick(cardinal) //Pick a direction
max_meteor_size = max_size
- for(var/i = 0 to number)
- spawn(rand(15,20)) //1.5 to 2 seconds between meteors
- var/meteor_type = null
- if(types != null)
- meteor_type = pick(types)
- spawn_meteor(chosen_dir, meteor_type)
+ //Generate a name for our wave
+ var/greek_alphabet = list("Alpha", "Beta", "Delta", "Epsilon", "Zeta", "Eta,", "Theta", "Iota", "Kappa", "Lambda", "Mu", \
+ "Nu", "Xi", "Omicron", "Pi", "Rho", "Sigma", "Tau", "Upsilon", "Phi", "Chi", "Psi", "Omega")
+ var/wave_final_name = "[number > 25 ? "Major":"Minor"] Meteor [pick("Wave", "Cluster", "Group")] [pick(greek_alphabet)]-[rand(1, 999)]"
+ output_information(meteor_wave_delay, chosen_dir, max_size, number, wave_final_name)
spawn(meteor_wave_delay)
- meteorwavecurrent = 0
+ for(var/i = 0 to number)
+ spawn(rand(15, 20)) //1.5 to 2 seconds between meteors
+ var/meteor_type = null
+ if(types != null)
+ meteor_type = pick(types)
+ spawn_meteor(chosen_dir, meteor_type)
+ sleep(50) //Five seconds for the chat to scroll
+ meteor_wave_active = 0
+
+//A bunch of information to be used by the bhangmeter (doubles as a meteor monitoring computer), and sent to the admins otherwise
+/proc/output_information(var/meteor_delay, var/wave_dir, var/meteor_size, var/wave_size, var/wave_name)
+
+ var/meteor_l_size = "normal"
+ switch(meteor_size)
+ if(1)
+ meteor_l_size = "small"
+ if(2)
+ meteor_l_size = "normal"
+ if(3)
+ meteor_l_size = "large"
+ else
+ meteor_l_size = "unknown"
+ var/wave_l_dir = "north"
+ switch(wave_dir)
+ if(1)
+ wave_l_dir = "north"
+ if(2)
+ wave_l_dir = "south"
+ if(4)
+ wave_l_dir = "east"
+ if(8)
+ wave_l_dir = "west"
+
+ message_admins("[wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.")
+
+ //Send to all Bhangmeters
+ for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays)
+ if(bhangmeter && !bhangmeter.stat)
+ bhangmeter.say("Detected: [wave_name], containing [wave_size] objects up to [meteor_l_size] size and incoming from the [wave_l_dir], will strike in [meteor_delay/10] seconds.")
/proc/spawn_meteor(var/chosen_dir, var/meteorpath = null)
@@ -112,11 +147,7 @@
/obj/effect/meteor/Bump(atom/A)
- for(var/mob/M in range(15, src)) //One screen length's from ex_act 3 reach
- if(!M.stat && !istype(M, /mob/living/silicon/ai)) //Bad idea to shake an ai's view
- shake_camera(M, 4, 2) //Medium hit
-
- explosion(src.loc, 2, 4, 6, 8, 0) //Medium meteor, medium boom
+ explosion(get_turf(src), 2, 4, 6, 8, 0, 0, 0) //Medium meteor, medium boom
qdel(src)
/obj/effect/meteor/Move()
@@ -130,11 +161,7 @@
/obj/effect/meteor/small/Bump(atom/A)
- for(var/mob/M in range(10, src)) //One screen length's from ex_act 3 reach
- if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
- shake_camera(M, 1, 1) //Poof
-
- explosion(src.loc, -1, 1, 3, 4, 0) //Tiny meteor doesn't cause too much damage
+ explosion(get_turf(src), -1, 1, 3, 4, 0, 0, 0) //Tiny meteor doesn't cause too much damage
qdel(src)
/obj/effect/meteor/big
@@ -143,15 +170,11 @@
/obj/effect/meteor/big/Bump(atom/A)
- for(var/mob/M in range(15, src)) //One screen length's from ex_act 3 reach
- if(!M.stat && !istype(M, /mob/living/silicon/ai)) //bad idea to shake an ai's view
- shake_camera(M, 6, 4) //Massive shellshock
-
- explosion(src.loc, 4, 6, 8, 8, 0) //You have been visited by the nuclear meteor
+ explosion(get_turf(src), 4, 6, 8, 8, 0, 0, 1) //You have been visited by the nuclear meteor
qdel(src)
/obj/effect/meteor/attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W, /obj/item/weapon/pickaxe))
+ if(istype(W, /obj/item/weapon/pickaxe)) //Yeah, you can totally do that
qdel(src)
..()
diff --git a/code/game/machinery/doppler_array.dm b/code/game/machinery/doppler_array.dm
index e79bcdab9a7..2db7c8a5936 100644
--- a/code/game/machinery/doppler_array.dm
+++ b/code/game/machinery/doppler_array.dm
@@ -2,7 +2,7 @@ var/list/doppler_arrays = list()
/obj/machinery/computer/bhangmeter
name = "bhangmeter"
- desc = "Ancient technology used to measure explosions of all shapes and sizes."
+ desc = "Ancient technology used to measure explosions of all shapes and sizes. Has been recently outfitted by meteor monitoring software by Space Weather Inc."
icon = 'icons/obj/computer.dmi'
icon_state = "forensic"
circuit = "/obj/item/weapon/circuitboard/bhangmeter"
@@ -35,9 +35,9 @@ var/list/doppler_arrays = list()
return
var/list/data[0]
- var/list/explosions=list()
- for(var/list/bangarangs in bangs) // removing sortAtom because nano updates it just enough for the lag to happen
- var/list/bang_data=list()
+ var/list/explosions = list()
+ for(var/list/bangarangs in bangs) //Removing sortAtom because nano updates it just enough for the lag to happen
+ var/list/bang_data = list()
bang_data["x"] = bangarangs["x"]
bang_data["y"] = bangarangs["y"]
bang_data["z"] = bangarangs["z"]
@@ -51,35 +51,35 @@ var/list/doppler_arrays = list()
bang_data["xoffset"] = bang_data["x"]-WORLD_X_OFFSET[z]
bang_data["yoffset"] = bang_data["y"]-WORLD_Y_OFFSET[z]
explosions += list(bang_data)
- data["explosions"]=explosions
+ data["explosions"] = explosions
data["explosion_cap"] = MAX_EXPLOSION_RANGE
- if (!ui) // no ui has been passed, so we'll search for one
+ if(!ui) //No ui has been passed, so we'll search for one
ui = nanomanager.get_open_ui(user, src, ui_key)
- if (!ui)
- // the ui does not exist, so we'll create a new one
+ if(!ui)
+ //The ui does not exist, so we'll create a new one
ui = new(user, src, ui_key, "bhangmeter.tmpl", name, 900, 800)
- // adding a template with the key "mapContent" enables the map ui functionality
+ //Adding a template with the key "mapContent" enables the map ui functionality
ui.add_template("mapContent", "bhangmeter_map_content.tmpl")
- // adding a template with the key "mapHeader" replaces the map header content
+ //Adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "bhangmeter_map_header.tmpl")
- // When the UI is first opened this is the data it will use
- // we want to show the map by default
+ //When the UI is first opened this is the data it will use
+ //We want to show the map by default
ui.set_show_map(1)
ui.set_initial_data(data)
ui.open()
- // Auto update every Master Controller tick
+ //Auto update every Master Controller tick
ui.set_auto_update(1)
else
- // The UI is already open so push the new data to it
+ //The UI is already open so push the new data to it
ui.push_data(data)
return
/obj/machinery/computer/bhangmeter/interact(mob/user as mob)
- var/listing={"
+ var/listing = {"