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 = {" Nanotrasen Bhangmeter Mk. V @@ -102,10 +102,12 @@ var/list/doppler_arrays = list() user << browse(listing, "window=bhangmeter") onclose(user, "bhangmeter") return -/obj/machinery/computer/bhangmeter/proc/sense_explosion(var/x0,var/y0,var/z0,var/devastation_range,var/heavy_impact_range,var/light_impact_range,var/took, cap = 0) +/obj/machinery/computer/bhangmeter/proc/sense_explosion(var/x0, var/y0, var/z0, var/devastation_range, var/heavy_impact_range, var/light_impact_range, var/took, cap = 0, var/verbose = 1) //writepanic("[__FILE__].[__LINE__] ([src.type])([usr ? usr.ckey : ""]) \\/obj/machinery/computer/bhangmeter/proc/sense_explosion() called tick#: [world.time]") - if(stat & NOPOWER) return - if(z != z0) return + if(stat & NOPOWER) + return + if(z != z0) + return /* var/dx = abs(x0-x) @@ -127,7 +129,8 @@ var/list/doppler_arrays = list() */ var/message = "Explosive disturbance detected - Epicenter at: grid ([x0-WORLD_X_OFFSET[z0]],[y0-WORLD_Y_OFFSET[z0]], [z0]). [cap ? "\[Theoretical Results\] " : ""]Epicenter radius: [devastation_range]. Outer radius: [heavy_impact_range]. Shockwave radius: [light_impact_range]. Temporal displacement of tachyons: [took] second\s. Data logged." - say(message) + if(verbose) + say(message) //var/list/bang = params2list("x=[x0]&y=[y0]&z=[z0]&text=([worldtime2text()]) - ([x0-WORLD_X_OFFSET(z0)],[y0-WORLD_Y_OFFSET(z0)], [z0])([cap ? "\[Theoretical Results\] " : ""][devastation_range],[heavy_impact_range],[light_impact_range])[took]s") var/list/bang = list() bang["x"] = x0 @@ -140,8 +143,8 @@ var/list/doppler_arrays = list() bang["light"] = light_impact_range bang["took"] = took bang["area"] = get_area(locate(x0,y0,z0)) - bangs+=list(bang) + bangs += list(bang) nanomanager.update_uis(src) /obj/machinery/doppler_array/say_quote(text) - return "states coldly, \"[text]\"" \ No newline at end of file + return "states coldly, \"[text]\"" diff --git a/code/game/objects/effects/landmarks.dm b/code/game/objects/effects/landmarks.dm index a15c3d43aa9..0968f0fb398 100644 --- a/code/game/objects/effects/landmarks.dm +++ b/code/game/objects/effects/landmarks.dm @@ -79,41 +79,6 @@ endgame_exits += loc del(src) - //Meteor stuff - if("meteormaterialkit") - meteor_materialkit += loc - del(src) - if("meteorbombkit") - meteor_bombkit += loc - del(src) - if("meteorbombkitextra") - meteor_bombkitextra += loc - del(src) - if("meteortankkit") - meteor_tankkit += loc - del(src) - if("meteorcanisterkit") - meteor_canisterkit += loc - del(src) - if("meteorbuildkit") - meteor_buildkit += loc - del(src) - if("meteorpizzakit") - meteor_pizzakit += loc - del(src) - if("meteorpanickit") - meteor_panickit += loc - del(src) - if("meteorshieldkit") - meteor_shieldkit += loc - del(src) - if("meteorgenkit") - meteor_genkit += loc - del(src) - if("meteorbreachkit") - meteor_breachkit += loc - del(src) - landmarks_list += src return 1 diff --git a/code/game/objects/explosion.dm b/code/game/objects/explosion.dm index 4f0710abae6..a60e176d435 100644 --- a/code/game/objects/explosion.dm +++ b/code/game/objects/explosion.dm @@ -23,9 +23,10 @@ * @param light_impact_range * @param flash_range Unused * @param adminlog Log to admins - * @param squelch Do not notify explosion listeners + * @param ignored Do not notify explosion listeners + * @param verbose Explosion listeners will treat as an important explosion worth reporting on radio */ -/proc/explosion(turf/epicenter, const/devastation_range, const/heavy_impact_range, const/light_impact_range, const/flash_range, adminlog = 1, squelch = 0) +/proc/explosion(turf/epicenter, const/devastation_range, const/heavy_impact_range, const/light_impact_range, const/flash_range, adminlog = 1, ignored = 0, verbose = 1) //writepanic("[__FILE__].[__LINE__] (no type)([usr ? usr.ckey : ""]) \\/proc/explosion() called tick#: [world.time]") src = null //so we don't abort once src is deleted @@ -139,10 +140,10 @@ world.log << "## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds." //Machines which report explosions. - if(!squelch) + if(!ignored) for(var/obj/machinery/computer/bhangmeter/bhangmeter in doppler_arrays) if(bhangmeter && !bhangmeter.stat) - bhangmeter.sense_explosion(x0,y0,z0,devastation_range,heavy_impact_range,light_impact_range,took) + bhangmeter.sense_explosion(x0, y0, z0, devastation_range, heavy_impact_range, light_impact_range, took, 0, verbose) sleep(8) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index e739eaee4c9..9c14e67cb7f 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -96,6 +96,26 @@ for(var/i=0,i<7,i++) new /obj/item/clothing/gloves/latex(src) +/obj/item/weapon/storage/box/bgloves + name = "box of black gloves" + desc = "Contains black gloves." + icon_state = "bgloves" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/clothing/gloves/black(src) + +/obj/item/weapon/storage/box/sunglasses + name = "box of sunglasses" + desc = "Contains sunglasses." + icon_state = "sunglass" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/clothing/glasses/sunglasses(src) + /obj/item/weapon/storage/box/masks name = "sterile masks" desc = "This box contains masks of sterility." @@ -187,6 +207,15 @@ for(var/i=0,i<5,i++) new /obj/item/weapon/grenade/empgrenade(src) +/obj/item/weapon/storage/box/foam + name = "metal foam grenades" + desc = "A box containing 7 metal foam grenades" + icon_state = "metalfoam" + + New() + ..() + for(var/i = 0, i < 7, i++) + new /obj/item/weapon/grenade/chem_grenade/metalfoam(src) /obj/item/weapon/storage/box/trackimp name = "tracking implant kit" diff --git a/code/global.dm b/code/global.dm index 832df011cae..48def182054 100644 --- a/code/global.dm +++ b/code/global.dm @@ -185,17 +185,6 @@ var/list/holdingfacility = list() //captured people go here var/list/xeno_spawn = list()//Aliens spawn at these. var/list/endgame_safespawns = list() var/list/endgame_exits = list() -var/list/meteor_materialkit = list() -var/list/meteor_bombkit = list() -var/list/meteor_bombkitextra = list() -var/list/meteor_tankkit = list() -var/list/meteor_canisterkit = list() -var/list/meteor_buildkit = list() -var/list/meteor_pizzakit = list() -var/list/meteor_panickit = list() -var/list/meteor_shieldkit = list() -var/list/meteor_genkit = list() -var/list/meteor_breachkit = list() var/list/tdome1 = list() var/list/tdome2 = list() var/list/tdomeobserve = list() diff --git a/code/modules/events/meteors.dm b/code/modules/events/meteors.dm index 8843170e06b..aade928491e 100644 --- a/code/modules/events/meteors.dm +++ b/code/modules/events/meteors.dm @@ -5,30 +5,30 @@ //Meteor storms are much heavier /datum/event/meteor_wave - startWhen = 10 + startWhen = 0 //Note : Meteor waves have a delay before striking now endWhen = 30 /datum/event/meteor_wave/setup() - endWhen = rand(45, 90) + 10 //More drawn out than the shower, but not too powerful. Supposed to be a devastating event + endWhen = rand(45, 90) //More drawn out than the shower, but not too powerful. Supposed to be a devastating event /datum/event/meteor_wave/announce() command_alert("A meteor storm has been detected on collision course with the station. Seek shelter within the core of the station immediately.", "Meteor Alert") world << sound('sound/AI/meteors.ogg') -//Two to four waves. So 10 to 60. Note that it used to be (20, 50) per wave with two to three waves +//One to three waves. So 10 to 60. Note that it used to be (20, 50) per wave with two to three waves /datum/event/meteor_wave/tick() meteor_wave(rand(10, 15), max_size = 2) //Large waves, panic is mandatory /datum/event/meteor_wave/end() command_alert("The station has cleared the meteor storm.", "Meteor Alert") -// +//One to two vawes /datum/event/meteor_shower - startWhen = 10 + startWhen = 0 endWhen = 30 /datum/event/meteor_shower/setup() - endWhen = rand(30, 60) + 10 //From 30 seconds to one minute + endWhen = rand(30, 60) //From thirty seconds to one minute /datum/event/meteor_shower/announce() command_alert("The station is about to be hit by a small-intensity meteor storm. Seek shelter within the core of the station immediately", "Meteor Alert") diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi index 69dcf7d51a2..ac2bb9bbe32 100644 Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ diff --git a/vgstation13.dme b/vgstation13.dme index ce71d3d496a..996f1baa7d1 100644 --- a/vgstation13.dme +++ b/vgstation13.dme @@ -323,6 +323,7 @@ #include "code\game\gamemodes\malfunction\Malf_Modules.dm" #include "code\game\gamemodes\malfunction\malfunction.dm" #include "code\game\gamemodes\meteor\meteor.dm" +#include "code\game\gamemodes\meteor\meteor_supply.dm" #include "code\game\gamemodes\meteor\meteors.dm" #include "code\game\gamemodes\mixed\mixed.dm" #include "code\game\gamemodes\nuclear\nuclear.dm"