diff --git a/code/controllers/subsystem/weather.dm b/code/controllers/subsystem/weather.dm
new file mode 100644
index 0000000000..56341b7b55
--- /dev/null
+++ b/code/controllers/subsystem/weather.dm
@@ -0,0 +1,49 @@
+//Used for all kinds of weather, ex. lavaland ash storms.
+
+var/datum/subsystem/weather/SSweather
+/datum/subsystem/weather
+ name = "Weather"
+ flags = SS_BACKGROUND
+ wait = 10
+ var/list/processing = list()
+ var/list/existing_weather = list()
+ var/list/eligible_zlevels = list(ZLEVEL_LAVALAND)
+
+/datum/subsystem/weather/New()
+ NEW_SS_GLOBAL(SSweather)
+
+/datum/subsystem/weather/fire()
+ for(var/V in processing)
+ var/datum/weather/W = V
+ if(W.aesthetic)
+ continue
+ for(var/mob/living/L in mob_list)
+ if(W.can_impact(L))
+ W.impact(L)
+ for(var/Z in eligible_zlevels)
+ var/list/possible_weather_for_this_z = list()
+ for(var/V in existing_weather)
+ var/datum/weather/WE = V
+ if(WE.target_z == Z && WE.probability) //Another check so that it doesn't run extra weather
+ possible_weather_for_this_z[WE] = WE.probability
+ var/datum/weather/W = pickweight(possible_weather_for_this_z)
+ run_weather(W.name, Z)
+ eligible_zlevels -= Z
+ addtimer(src, "make_z_eligible", rand(3000, 6000) + W.weather_duration_upper, TRUE, Z) //Around 5-10 minutes between weathers
+
+/datum/subsystem/weather/Initialize(start_timeofday)
+ ..()
+ for(var/V in subtypesof(/datum/weather))
+ var/datum/weather/W = V
+ existing_weather |= new W
+
+/datum/subsystem/weather/proc/run_weather(weather_name, Z)
+ if(!weather_name)
+ return
+ for(var/V in existing_weather)
+ var/datum/weather/W = V
+ if(W.name == weather_name && W.target_z == Z)
+ W.telegraph()
+
+/datum/subsystem/weather/proc/make_z_eligible(zlevel)
+ eligible_zlevels |= zlevel
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
new file mode 100644
index 0000000000..c1afdea4ca
--- /dev/null
+++ b/code/datums/weather/weather.dm
@@ -0,0 +1,143 @@
+//The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures.
+
+#define STARTUP_STAGE 1
+#define MAIN_STAGE 2
+#define WIND_DOWN_STAGE 3
+#define END_STAGE 4
+
+/datum/weather
+ var/name = "space wind"
+ var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open."
+
+ var/telegraph_message = "The wind begins to pick up." //The message displayed in chat to foreshadow the weather's beginning
+ var/telegraph_duration = 300 //In deciseconds, how long from the beginning of the telegraph until the weather begins
+ var/telegraph_sound //The sound file played to everyone on an affected z-level
+ var/telegraph_overlay //The overlay applied to all tiles on the z-level
+
+ var/weather_message = "The wind begins to blow ferociously!" //Displayed in chat once the weather begins in earnest
+ var/weather_duration = 1200 //In deciseconds, how long the weather lasts once it begins
+ var/weather_duration_lower = 1200 //See above - this is the lowest possible duration
+ var/weather_duration_upper = 1500 //See above - this is the highest possible duration
+ var/weather_sound
+ var/weather_overlay
+ var/weather_color = null
+
+ var/end_message = "The wind relents its assault." //Displayed once the wather is over
+ var/end_duration = 300 //In deciseconds, how long the "wind-down" graphic will appear before vanishing entirely
+ var/end_sound
+ var/end_overlay
+
+ var/area_type = /area/space //Types of area to affect
+ var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
+ var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
+ var/target_z = ZLEVEL_STATION //The z-level to affect
+
+ var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that.
+ var/aesthetic = FALSE //If the weather has no purpose other than looks
+ var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
+
+ var/stage = END_STAGE //The stage of the weather, from 1-4
+
+ var/probability = FALSE //Percent chance to happen if there are other possible weathers on the z-level
+
+/datum/weather/New()
+ ..()
+ SSweather.existing_weather |= src
+
+/datum/weather/Destroy()
+ SSweather.existing_weather -= src
+ ..()
+
+/datum/weather/proc/telegraph()
+ if(stage == STARTUP_STAGE)
+ return
+ stage = STARTUP_STAGE
+ var/list/affectareas = list()
+ for(var/V in get_areas(area_type))
+ affectareas += V
+ for(var/V in protected_areas)
+ affectareas -= get_areas(V)
+ for(var/V in affectareas)
+ var/area/A = V
+ if(A.z == target_z)
+ impacted_areas |= A
+ weather_duration = rand(weather_duration_lower, weather_duration_upper)
+ update_areas()
+ for(var/V in player_list)
+ var/mob/M = V
+ if(M.z == target_z)
+ if(telegraph_message)
+ M << telegraph_message
+ if(telegraph_sound)
+ M << sound(telegraph_sound)
+ addtimer(src, "start", telegraph_duration)
+
+/datum/weather/proc/start()
+ if(stage >= MAIN_STAGE)
+ return
+ stage = MAIN_STAGE
+ update_areas()
+ for(var/V in player_list)
+ var/mob/M = V
+ if(M.z == target_z)
+ if(weather_message)
+ M << weather_message
+ if(weather_sound)
+ M << sound(weather_sound)
+ START_PROCESSING(SSweather, src)
+ addtimer(src, "wind_down", weather_duration)
+
+/datum/weather/proc/wind_down()
+ if(stage >= WIND_DOWN_STAGE)
+ return
+ stage = WIND_DOWN_STAGE
+ update_areas()
+ for(var/V in player_list)
+ var/mob/M = V
+ if(M.z == target_z)
+ if(end_message)
+ M << end_message
+ if(end_sound)
+ M << sound(end_sound)
+ STOP_PROCESSING(SSweather, src)
+ addtimer(src, "end", end_duration)
+
+/datum/weather/proc/end()
+ if(stage == END_STAGE)
+ return 1
+ stage = END_STAGE
+ update_areas()
+
+/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob?
+ if(L.z != target_z)
+ return
+ if(immunity_type in L.weather_immunities)
+ return
+ if(!(get_area(L) in impacted_areas))
+ return
+ return 1
+
+/datum/weather/proc/impact(mob/living/L) //What effect does this weather have on the hapless mob?
+ return
+
+/datum/weather/proc/update_areas()
+ for(var/V in impacted_areas)
+ var/area/N = V
+ N.layer = overlay_layer
+ N.icon = 'icons/effects/weather_effects.dmi'
+ N.invisibility = 0
+ N.color = weather_color
+ switch(stage)
+ if(STARTUP_STAGE)
+ N.icon_state = telegraph_overlay
+ if(MAIN_STAGE)
+ N.icon_state = weather_overlay
+ if(WIND_DOWN_STAGE)
+ N.icon_state = end_overlay
+ if(END_STAGE)
+ N.color = null
+ N.icon_state = initial(N.icon_state)
+ N.icon = 'icons/turf/areas.dmi'
+ N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial
+ N.invisibility = INVISIBILITY_MAXIMUM
+ N.opacity = 0
diff --git a/code/datums/weather/weather_types.dm b/code/datums/weather/weather_types.dm
new file mode 100644
index 0000000000..6bae9f3d4e
--- /dev/null
+++ b/code/datums/weather/weather_types.dm
@@ -0,0 +1,164 @@
+//Different types of weather.
+
+/datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object.
+ name = "the floor is lava"
+ desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
+
+ telegraph_message = "Waves of heat emanate from the ground..."
+ telegraph_duration = 150
+
+ weather_message = "The floor is lava! Get on top of something!"
+ weather_duration_lower = 300
+ weather_duration_upper = 600
+ weather_overlay = "lava"
+
+ end_message = "The ground cools and returns to its usual form."
+ end_duration = 0
+
+ area_type = /area
+ target_z = ZLEVEL_STATION
+
+ overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
+ immunity_type = "lava"
+
+/datum/weather/floor_is_lava/impact(mob/living/L)
+ for(var/obj/structure/O in L.loc)
+ if(O.density)
+ return
+ if(L.loc.density)
+ return
+ if(!L.client) //Only sentient people are going along with it!
+ return
+ L.adjustFireLoss(3)
+
+
+/datum/weather/advanced_darkness //Advanced Darkness: Restricts the vision of all affected mobs to a single tile in the cardinal directions.
+ name = "advanced darkness"
+ desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself."
+
+ telegraph_message = "The lights begin to dim... is the power going out?"
+ telegraph_duration = 150
+
+ weather_message = "This isn't your average everday darkness... this is advanced darkness!"
+ weather_duration_lower = 300
+ weather_duration_upper = 300
+
+ end_message = "At last, the darkness recedes."
+ end_duration = 0
+
+ area_type = /area
+ target_z = ZLEVEL_STATION
+
+/datum/weather/advanced_darkness/update_areas()
+ for(var/V in impacted_areas)
+ var/area/A = V
+ if(stage == MAIN_STAGE)
+ A.invisibility = 0
+ A.opacity = 1
+ A.layer = overlay_layer
+ A.icon = 'icons/effects/weather_effects.dmi'
+ A.icon_state = "darkness"
+ else
+ A.invisibility = INVISIBILITY_MAXIMUM
+ A.opacity = 0
+
+
+/datum/weather/ash_storm //Ash Storms: Common happenings on lavaland. Heavily obscures vision and deals heavy fire damage to anyone caught outside.
+ name = "ash storm"
+ desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected."
+
+ telegraph_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter."
+ telegraph_duration = 300
+ telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg'
+ telegraph_overlay = "light_ash"
+
+ weather_message = "Smoldering clouds of scorching ash billow down around you! Get inside!"
+ weather_duration_lower = 600
+ weather_duration_upper = 1500
+ weather_sound = 'sound/lavaland/ash_storm_start.ogg'
+ weather_overlay = "ash_storm"
+
+ end_message = "The shrieking wind whips away the last of the ash falls to its usual murmur. It should be safe to go outside now."
+ end_duration = 300
+ end_sound = 'sound/lavaland/ash_storm_end.ogg'
+ end_overlay = "light_ash"
+
+ area_type = /area/lavaland/surface/outdoors
+ target_z = ZLEVEL_LAVALAND
+
+ immunity_type = "ash"
+
+ probability = 90
+
+/datum/weather/ash_storm/impact(mob/living/L)
+ if(istype(L.loc, /obj/mecha))
+ return
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ var/thermal_protection = H.get_thermal_protection()
+ if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
+ return
+ L.adjustFireLoss(4)
+
+/datum/weather/ash_storm/emberfall //Emberfall: An ash storm passes by, resulting in harmless embers falling like snow. 10% to happen in place of an ash storm.
+ name = "emberfall"
+ desc = "A passing ash storm blankets the area in harmless embers."
+
+ weather_message = "Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by..."
+ weather_sound = 'sound/lavaland/ash_storm_windup.ogg'
+ weather_overlay = "light_ash"
+
+ end_message = "The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet."
+
+ aesthetic = TRUE
+
+ probability = 10
+
+/datum/weather/rad_storm
+ name = "radiation storm"
+ desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected."
+
+ telegraph_duration = 600
+ telegraph_message = "The air begins to grow warm."
+
+ weather_message = "You feel waves of heat wash over you! Find shelter!"
+ weather_overlay = "radiation"
+ weather_duration_lower = 600
+ weather_duration_upper = 1500
+ weather_color = "green"
+ weather_sound = 'sound/misc/bloblarm.ogg'
+
+ end_duration = 100
+ end_message = "The air seems to be cooling off again."
+
+ area_type = /area
+ protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai)
+ target_z = ZLEVEL_STATION
+
+ immunity_type = "rad"
+
+/datum/weather/rad_storm/impact(mob/living/L)
+ if(prob(20))
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ if(H.dna && H.dna.species)
+ if(!(RADIMMUNE in H.dna.species.specflags))
+ if(prob(50))
+ randmuti(H)
+ if(prob(90))
+ randmutb(H)
+ else
+ randmutg(H)
+ H.domutcheck()
+ L.rad_act(20,1)
+
+ L.adjustToxLoss(4)
+
+
+
+
+
+/datum/weather/rad_storm/end()
+ if(..())
+ return
+ priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
\ No newline at end of file
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index af673ce9bb..32bd100fba 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -32,8 +32,7 @@
mask_type = /obj/item/clothing/mask/breath
/obj/machinery/suit_storage_unit/captain
- suit_type = /obj/item/clothing/suit/space/captain
- helmet_type = /obj/item/clothing/head/helmet/space/captain
+ suit_type = /obj/item/clothing/suit/space/hardsuit/captain
mask_type = /obj/item/clothing/mask/gas
storage_type = /obj/item/weapon/tank/jetpack/oxygen/captain
diff --git a/code/game/objects/effects/overlays.dm b/code/game/objects/effects/overlays.dm
index 5a4fab9fa0..e2be069458 100644
--- a/code/game/objects/effects/overlays.dm
+++ b/code/game/objects/effects/overlays.dm
@@ -95,6 +95,13 @@
if(colour)
color = colour
+/obj/effect/overlay/temp/kinetic_blast
+ name = "kinetic explosion"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "kinetic_blast"
+ layer = ABOVE_ALL_MOB_LAYER
+ duration = 4
+
/obj/effect/overlay/temp/explosion
name = "explosion"
icon = 'icons/effects/96x96.dmi'
diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm
index 3e10d6715a..12ecd43495 100644
--- a/code/game/objects/items/crayons.dm
+++ b/code/game/objects/items/crayons.dm
@@ -38,7 +38,7 @@
var/list/runes = list("rune1","rune2","rune3","rune4","rune5","rune6")
var/list/randoms = list(RANDOM_ANY, RANDOM_RUNE, RANDOM_ORIENTED,
RANDOM_NUMBER, RANDOM_GRAFFITI, RANDOM_LETTER)
- var/list/graffiti_large_h = list("yiffhell", "secborg", "paint")
+ var/list/graffiti_large_h = list("yiffhell", "secborg", "paint", "madworld1", "madworld2")
var/list/all_drawables
diff --git a/code/game/objects/items/devices/boobytrap.dm b/code/game/objects/items/devices/boobytrap.dm
new file mode 100644
index 0000000000..fcce7b1aa9
--- /dev/null
+++ b/code/game/objects/items/devices/boobytrap.dm
@@ -0,0 +1,25 @@
+/obj/item/device/boobytrap
+ name = "booby trap"
+ desc = null //Different examine for traitors
+ item_state = "electronic"
+ icon_state = "boobytrap"
+ w_class = 1
+ throw_range = 4
+ throw_speed = 1
+ flags = NOBLUDGEON
+ force = 3
+ attack_verb = list("trapped", "rused", "tricked")
+ materials = list(MAT_METAL=50, MAT_GLASS=30)
+ origin_tech = "syndicate=1;combat=3;engineering=3"
+
+/obj/item/device/boobytrap/proc/blow()
+ explosion(src.loc,0,0,2,4,flame_range = 4)
+ qdel(src)
+
+/obj/item/device/boobytrap/examine(mob/user)
+ ..()
+ if(user.mind in ticker.mode.traitors) //No nuke ops because the device is excluded from nuclear
+ user << "A small device used to rig lockers and boxes with an explosive surprise. \
+ To use, simply attach it to a box or a locker."
+ else
+ user << "A suspicious array of delicate wires and parts."
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 8165c4d396..37cc14173f 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -187,6 +187,22 @@
else
return ..()
+/obj/item/weapon/twohanded/attackby(obj/item/weapon/W, mob/living/user, params)
+ if(istype(W, /obj/item/weapon/melee/energy/sword/saber))
+ switch(alert(user, "You feel like the sword might be a bit more dangerous to yourself than to others if you do this.", "Combine?", "Proceed", "Abort"))
+ if("Abort" || !in_range(src, user) || !src || !W || user.incapacitated())
+ return
+ user << "You attach the energy sword to the double \
+ bladed energy sword, making a single triple-bladed weapon! \
+ You're a genius!"
+ var/obj/item/weapon/trisword/newSaber = new(user.loc)
+ user.unEquip(W)
+ user.unEquip(src)
+ qdel(W)
+ qdel(src)
+ user.put_in_hands(newSaber)
+ return
+
/obj/item/weapon/melee/energy/sword/pirate
name = "energy cutlass"
desc = "Arrrr matey."
@@ -221,3 +237,67 @@
/obj/item/weapon/melee/energy/blade/attack_self(mob/user)
return
+
+/* Triple Esword! [joke weapon] */
+/obj/item/weapon/trisword
+ name = "triple-bladed energy sword"
+ desc = "Wow, an energy sword with THREE blades! This must be a REALLY good weapon."
+ force = 3
+ throwforce = 5
+ w_class = 2
+ icon_state = "trisaber_off"
+ item_state = "sword0"
+ var/progress = 0
+ var/on = 0
+
+/obj/item/weapon/trisword/attack_self(mob/living/carbon/user)
+ if(on || progress > 5)
+ return
+ if(progress == 0)
+ user << "You extend the... Hey, wait a second, how do you turn this thing on?"
+ progress = 1
+ return
+ if(progress == 1)
+ user << "No, seriously, what the fuck? Does this thing even have a button on it?"
+ progress = 2
+ return
+ if(progress == 2)
+ user << "Okay, you're getting sick of this. You mash random panels on [src], trying to find a way to activate it."
+ progress = 3
+ return
+ if(progress == 3)
+ user << "God dammit, how the fuck do you turn this shit on?"
+ progress = 4
+ return
+ if(progress == 4)
+ user << "You find what feels like a button on [src]! Now you just need to press it."
+ progress = 5
+ return
+ if(progress == 5)
+ user << "The third blade on [src] extends straight into your gut! God fucking dammit."
+ playsound(user, 'sound/weapons/saberon.ogg', 35, 1)
+ playsound(user, 'sound/weapons/blade1.ogg', 35, 1)
+ on = 1
+ icon_state = "trisaber"
+ if(!remove_item_from_storage(user))
+ user.unEquip(src)
+ user.adjustBruteLoss(110)
+
+/obj/item/weapon/trisword/dropped()
+ ..()
+ if(!on)
+ progress = 0
+
+/obj/item/weapon/trisword/attack_hand(mob/living/carbon/user)
+ if(on)
+ user << "You try to pick up [src], but accidentally grab one of the blades, and quickly drop the whole thing out of pain."
+ user.adjustBruteLoss(15)
+ playsound(user, 'sound/weapons/blade1.ogg', 35, 1)
+ else
+ ..()
+
+/obj/item/weapon/trisword/attack_tk(mob/living/carbon/user)
+ user << "You try to comprehend \the [src]."
+ user << "Your head hurts."
+ user.adjustBrainLoss(50)
+ user.confused += 15
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm
index 3a5f540e48..0834f4cc99 100644
--- a/code/game/objects/items/weapons/storage/belt.dm
+++ b/code/game/objects/items/weapons/storage/belt.dm
@@ -182,7 +182,10 @@
/obj/item/weapon/reagent_containers/pill,
/obj/item/weapon/storage/pill_bottle,
/obj/item/weapon/ore,
- /obj/item/weapon/reagent_containers/food/drinks
+ /obj/item/weapon/reagent_containers/food/drinks,
+ /obj/item/organ/hivelord_core,
+ /obj/item/device/wormhole_jaunter
+
)
diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm
index ea0d1a761e..fe8d35aca0 100644
--- a/code/game/objects/items/weapons/storage/boxes.dm
+++ b/code/game/objects/items/weapons/storage/boxes.dm
@@ -27,7 +27,100 @@
item_state = "syringe_kit"
burn_state = FLAMMABLE
var/foldable = /obj/item/stack/sheet/cardboard
+ var/obj/item/device/boobytrap/trap = null
+/obj/item/weapon/storage/box/examine(mob/user)
+ ..()
+
+ if(trap && in_range(user, src))
+ user << "Something seems to be wired to the inside of the box!"
+ return
+
+
+/obj/item/weapon/storage/box/attackby(obj/item/C, mob/user, params)
+
+ if(!istype(C, /obj/item/device/boobytrap) && trap && !istype(C, /obj/item/weapon/wirecutters))
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+
+ if(istype(C, /obj/item/device/boobytrap))
+ if(trap)
+ user << "There's already a booby trap hooked up to this box!"
+ return
+ user << "You apply [C]. Next time someone opens the box, it will explode."
+ C.loc = src
+ trap = C
+ qdel(C)
+ user.drop_item()
+
+ if(istype(C, /obj/item/weapon/wirecutters) && trap)
+ user << "You begin attempting to disarm the booby trap..."
+ visible_message("[user] begins attempting to disarm the booby trap.")
+ if(do_after(user, 80, target = src))
+ if(prob(75))
+ user << "You disarm the booby trap, destroying it in the process."
+ visible_message("[user] disarms the booby trap!")
+ trap = null
+
+ else
+ user << "You accidentally bump the sensor and set off the booby trap!"
+ visible_message("[user] fails to disarm the booby trap!")
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+ else
+ ..()
+
+/obj/item/weapon/storage/box/MouseDrop(atom/over_object)
+ if(iscarbon(usr) || isdrone(usr))
+ var/mob/M = usr
+
+ if(!over_object)
+ return
+
+ if (istype(usr.loc,/obj/mecha)) // stops inventory actions in a mech
+ return
+
+ if(over_object == M && Adjacent(M))
+ if(trap)
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+ ..()
+
+/obj/item/weapon/storage/box/attack_hand(mob/user)
+ ..()
+
+ if(trap)
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+ return ..()
/obj/item/weapon/storage/box/attack_self(mob/user)
..()
diff --git a/code/game/objects/items/weapons/storage/storage.dm b/code/game/objects/items/weapons/storage/storage.dm
index 9c3bb80609..5d4cfcd489 100644
--- a/code/game/objects/items/weapons/storage/storage.dm
+++ b/code/game/objects/items/weapons/storage/storage.dm
@@ -374,8 +374,8 @@
if(!can_be_inserted(W, 0 , user))
return
-
- handle_item_insertion(W, 0 , user)
+ if(!istype(W, /obj/item/device/boobytrap))
+ handle_item_insertion(W, 0 , user)
/obj/item/weapon/storage/attack_hand(mob/user)
diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm
index 06e2def119..3938cd9bc6 100644
--- a/code/game/objects/items/weapons/storage/uplink_kits.dm
+++ b/code/game/objects/items/weapons/storage/uplink_kits.dm
@@ -283,3 +283,8 @@
for(var/i in 1 to 3)
new/obj/item/cardboard_cutout/adaptive(src)
new/obj/item/toy/crayon/rainbow(src)
+
+/obj/item/weapon/storage/box/syndie_kit/thermite/New()
+ ..()
+ new /obj/item/weapon/reagent_containers/spray/thermite(src)
+ new /obj/item/weapon/lighter(src)
diff --git a/code/game/objects/items/weapons/twohanded.dm b/code/game/objects/items/weapons/twohanded.dm
index 7d8fcc93fb..93f7b1fea2 100644
--- a/code/game/objects/items/weapons/twohanded.dm
+++ b/code/game/objects/items/weapons/twohanded.dm
@@ -83,13 +83,6 @@
user.put_in_inactive_hand(O)
return
-/obj/item/weapon/twohanded/mob_can_equip(mob/M, slot)
- //Cannot equip wielded items.
- if(wielded)
- M << "Unwield the [name] first!"
- return 0
- return ..()
-
/obj/item/weapon/twohanded/dropped(mob/user)
..()
//handles unwielding a twohanded weapon when dropped as well as clearing up the offhand
@@ -109,6 +102,11 @@
else //Trying to wield it
wield(user)
+/obj/item/weapon/twohanded/equip_to_best_slot(mob/M)
+ if(..())
+ unwield(M)
+ return
+
///////////OFFHAND///////////////
/obj/item/weapon/twohanded/offhand
name = "offhand"
@@ -131,7 +129,7 @@
return
/obj/item/weapon/twohanded/required/mob_can_equip(mob/M, slot)
- if(wielded)
+ if(wielded && !slot_flags)
M << "\The [src] is too cumbersome to carry with anything but your hands!"
return 0
return ..()
@@ -143,9 +141,17 @@
if(H != null)
user << "\The [src] is too cumbersome to carry in one hand!"
return
- wield(user)
+ if(src.loc != user)
+ wield(user)
..()
+/obj/item/weapon/twohanded/required/equipped(mob/user, slot)
+ ..()
+ if(slot == slot_l_hand || slot == slot_r_hand)
+ wield(user)
+ else
+ unwield(user)
+
/obj/item/weapon/twohanded/
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index 51a943a5b6..5df150acc6 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -29,6 +29,7 @@
var/close_sound = 'sound/machines/click.ogg'
var/cutting_sound = 'sound/items/Welder.ogg'
var/material_drop = /obj/item/stack/sheet/metal
+ var/obj/item/device/boobytrap/trap = null
/obj/structure/closet/New()
..()
@@ -73,6 +74,8 @@
user << "It appears to be broken."
else if(secure && !opened)
user << "Alt-click to [locked ? "unlock" : "lock"]."
+ if(trap && in_range(user, src))
+ user << "Something seems to be wired to the inside of the closet!"
/obj/structure/closet/alter_health()
return get_turf(src)
@@ -130,6 +133,17 @@
climb_time *= 0.5 //it's faster to climb onto an open thing
dump_contents()
update_icon()
+ if(trap)
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+ return ..()
return 1
/obj/structure/closet/proc/insert(atom/movable/AM)
@@ -213,9 +227,20 @@
qdel(src)
/obj/structure/closet/attackby(obj/item/weapon/W, mob/user, params)
+
if(user in src)
return
if(opened)
+ if(istype(W, /obj/item/device/boobytrap))
+ if(trap)
+ user << "There's already a booby trap hooked up to this closet!"
+ ..()
+ user << "You apply [W]. Next time someone opens the closet, it will explode."
+ W.loc = src
+ trap = W
+ qdel(W)
+ ..()
+
if(istype(W, cutting_tool))
if(istype(W, /obj/item/weapon/weldingtool))
var/obj/item/weapon/weldingtool/WT = W
@@ -237,6 +262,10 @@
else if(user.drop_item())
W.forceMove(loc)
return 1
+ if(!opened && istype(W, /obj/item/device/boobytrap))
+ user << "You must open the closet first!"
+ ..()
+
else if(istype(W, /obj/item/weapon/weldingtool) && can_weld_shut)
var/obj/item/weapon/weldingtool/WT = W
if(!WT.remove_fuel(0, user))
@@ -252,10 +281,33 @@
"You [welded ? "weld" : "unwelded"] \the [src] with \the [WT].",
"You hear welding.")
update_icon()
+ else if(istype(W, /obj/item/weapon/wirecutters) && !opened && trap)
+ user << "You begin attempting to disarm the booby trap..."
+ visible_message("[user] begins attempting to disarm the booby trap.")
+ if(do_after(user, 80, target = src))
+ if(prob(75))
+ user << "You disarm the booby trap, destroying it in the process."
+ visible_message("[user] disarms the booby trap!")
+ trap = null
+
+ else
+ user << "You accidentally bump the sensor and set off the booby trap!"
+ visible_message("[user] fails to disarm the booby trap!")
+ visible_message("[src] blows up in a spray of deadly shrapnel!")
+ trap.loc = get_turf(src)
+ trap.blow()
+ trap = null
+ for(var/mob/living/carbon/human/H in orange(2,src))
+ H.Paralyse(8)
+ H.adjust_fire_stacks(1)
+ H.IgniteMob()
+ qdel(src)
+
else if(user.a_intent != "harm" && !(W.flags & NOBLUDGEON))
if(W.GetID() || !toggle(user))
togglelock(user)
return 1
+
else
return ..()
diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm
index 847fbb70c2..a405c85096 100644
--- a/code/game/objects/structures/watercloset.dm
+++ b/code/game/objects/structures/watercloset.dm
@@ -103,16 +103,19 @@
else
return ..()
-
-
/obj/structure/urinal
name = "urinal"
- desc = "The HU-452, an experimental urinal."
+ desc = "The HU-452, an experimental urinal. Comes complete with experimental urinal cake."
icon = 'icons/obj/watercloset.dmi'
icon_state = "urinal"
density = 0
anchored = 1
+ var/exposed = 0 // can you currently put an item inside
+ var/obj/item/hiddenitem = null // what's in the urinal
+/obj/structure/urinal/New()
+ ..()
+ hiddenitem = new /obj/item/weapon/reagent_containers/food/urinalcake
/obj/structure/urinal/attack_hand(mob/user)
if(user.pulling && user.a_intent == "grab" && isliving(user.pulling))
@@ -126,9 +129,50 @@
GM.adjustBruteLoss(8)
else
user << "You need a tighter grip!"
+
+ else if(exposed)
+ if(!hiddenitem)
+ user << "There is nothing in the drain holder."
+ else
+ if(ishuman(user))
+ user.put_in_hands(hiddenitem)
+ else
+ hiddenitem.forceMove(get_turf(src))
+ user << "You fish [hiddenitem] out of the drain enclosure."
+ src.hiddenitem = null
else
..()
+/obj/structure/urinal/attackby(obj/item/I, mob/living/user, params)
+ if(istype(I, /obj/item/weapon/screwdriver))
+ user << "You start to [exposed ? "screw the cap back into place" : "unscrew the cap to the drain protector"]..."
+ playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1)
+ if(do_after(user, 20/I.toolspeed, target = src))
+ user.visible_message("[user] [exposed ? "screws the cap back into place" : "unscrew the cap to the drain protector"]!", "You [exposed ? "screw the cap back into place" : "unscrew the cap on the drain"]!", "You hear metal and squishing noises.")
+ exposed = !exposed
+ else if(exposed)
+ if (hiddenitem)
+ user << "There is already something in the drain enclosure."
+ return
+ if(I.w_class > 1)
+ user << "[I] is too large for the drain enclosure."
+ return
+ if(!user.drop_item())
+ user << "\[I] is stuck to your hand, you cannot put it in the drain enclosure!"
+ return
+ I.forceMove(src)
+ hiddenitem = I
+ user << "You place [I] into the drain enclosure."
+
+
+/obj/item/weapon/reagent_containers/food/urinalcake
+ name = "urinal cake"
+ desc = "The noble urinal cake, protecting the station's pipes from the station's pee. Do not eat."
+ icon = 'icons/obj/items.dmi'
+ icon_state = "urinalcake"
+ w_class = 1
+ list_reagents = list("chlorine" = 3, "ammonia" = 1)
+
/obj/machinery/shower
name = "shower"
desc = "The HS-451. Installed in the 2550s by the Nanotrasen Hygiene Division."
@@ -376,7 +420,7 @@
var/washing_face = 0
if(selected_area in list("head", "mouth", "eyes"))
washing_face = 1
- user.visible_message("[user] start washing their [washing_face ? "face" : "hands"]...", \
+ user.visible_message("[user] starts washing their [washing_face ? "face" : "hands"]...", \
"You start washing your [washing_face ? "face" : "hands"]...")
busy = 1
@@ -478,3 +522,44 @@
icon_state = "puddle-splash"
. = ..()
icon_state = "puddle"
+
+
+//Shower Curtains//
+//Defines used are pre-existing in layers.dm//
+
+
+/obj/structure/curtain
+ name = "curtain"
+ desc = "Contains less than 1% mercury."
+ icon = 'icons/obj/watercloset.dmi'
+ icon_state = "open"
+ color = "#ACD1E9" //Default color, didn't bother hardcoding other colors, mappers can and should easily change it.
+ alpha = 200 //Mappers can also just set this to 255 if they want curtains that can't be seen through
+ layer = WALL_OBJ_LAYER
+ anchored = 1
+ opacity = 0
+ density = 0
+ var/open = TRUE
+
+
+/obj/structure/curtain/proc/toggle()
+ open = !open
+ update_icon()
+
+/obj/structure/curtain/update_icon()
+ if(!open)
+ icon_state = "closed"
+ layer = WALL_OBJ_LAYER
+ density = 1
+ open = FALSE
+
+ else
+ icon_state = "open"
+ layer = SIGN_LAYER
+ density = 0
+ open = TRUE
+
+/obj/structure/curtain/attack_hand(mob/user)
+ playsound(loc, 'sound/effects/curtain.ogg', 50, 1)
+ toggle()
+ ..()
diff --git a/code/game/turfs/space/space.dm b/code/game/turfs/space/space.dm
index cc5b4d1cc8..69db4ab9f1 100644
--- a/code/game/turfs/space/space.dm
+++ b/code/game/turfs/space/space.dm
@@ -2,6 +2,7 @@
icon = 'icons/turf/space.dmi'
icon_state = "0"
name = "\proper space"
+ desc = "A vast, cold, and lonely place."
intact = 0
temperature = TCMB
diff --git a/code/modules/admin/secrets.dm b/code/modules/admin/secrets.dm
index 26a284fa0c..cce111cdbf 100644
--- a/code/modules/admin/secrets.dm
+++ b/code/modules/admin/secrets.dm
@@ -427,8 +427,7 @@
L.fix()
if("floorlava")
- var/datum/weather/floor_is_lava/storm = new /datum/weather/floor_is_lava
- storm.weather_start_up()
+ SSweather.run_weather("the floor is lava")
if("virus")
if(!check_rights(R_FUN))
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index edd9177579..920620dbc5 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -99,6 +99,14 @@
dog_fashion = /datum/dog_fashion/head/ushanka
+/obj/item/clothing/head/hardhat/headlamp
+ name = "headlamp"
+ desc = "For giving people another reason to look away from you."
+ icon_state = "hardhat0_headlamp"
+ item_state = "hardhat0_headlamp"
+ item_color = "headlamp"
+ armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
+
/obj/item/clothing/head/ushanka/attack_self(mob/user)
if(earflaps)
src.icon_state = "ushankaup"
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index f3c478ce9e..4503c214dc 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -383,6 +383,25 @@
armor = list(melee = 30, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 50)
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/medical
+ //Captain hardsuit
+/obj/item/clothing/head/helmet/space/hardsuit/captain
+ name = "captain's hardsuit helmet"
+ desc = "An advanced, armoured helmet for travel and combat in a hazardous, low pressure environment. Feels extra cozy."
+ icon_state = "hardsuit0-captain"
+ item_state = "captain_helm"
+ item_color = "captain"
+ armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
+ flash_protect = 1
+
+/obj/item/clothing/suit/space/hardsuit/captain
+ name = "captain's hardsuit"
+ desc = "An advanced, Nanotrasen exclusive, heavily armoured hardsuit that protects against hazardous, low pressure environments. Warm, sexy, and stylish."
+ icon_state = "hardsuit-captain"
+ item_state = "captain_hardsuit"
+ allowed = list(/obj/item/weapon/tank/internals, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs)
+ armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
+ helmettype = /obj/item/clothing/head/helmet/space/hardsuit/captain
+
//Research Director hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/rd
name = "prototype hardsuit helmet"
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 601fe5f7fd..6f8a5b1266 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -14,26 +14,6 @@ Contains:
- Carp hardsuit
*/
- //Captain's space suit, not hardsuits because no flashlight!
-/obj/item/clothing/head/helmet/space/captain
- name = "captain's space helmet"
- icon_state = "capspace"
- item_state = "capspacehelmet"
- desc = "A special helmet designed for only the most fashionable of military figureheads."
- flags_inv = HIDEFACE|HIDEEARS|HIDEHAIR
- permeability_coefficient = 0.01
- armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
-
-/obj/item/clothing/suit/space/captain
- name = "captain's space suit"
- desc = "A bulky, heavy-duty piece of exclusive Nanotrasen armor. YOU are in charge!"
- icon_state = "caparmor"
- item_state = "capspacesuit"
- w_class = 4
- allowed = list(/obj/item/weapon/tank/internals, /obj/item/device/flashlight,/obj/item/weapon/gun/energy, /obj/item/weapon/gun/projectile, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/weapon/melee/baton,/obj/item/weapon/restraints/handcuffs)
- armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
-
-
//Death squad armored space suits, not hardsuits!
/obj/item/clothing/head/helmet/space/hardsuit/deathsquad
name = "deathsquad helmet"
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 1559706e34..5089e31ee3 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -319,6 +319,14 @@
reqs = list(/obj/item/weapon/paper = 5)
category = CAT_MISC
+/datum/crafting_recipe/headlamp
+ name = "Headlamp"
+ result = /obj/item/clothing/head/hardhat/headlamp
+ time = 30
+ reqs = list(/obj/item/stack/cable_coil = 15,
+ /obj/item/device/flashlight = 1)
+ category = CAT_MISC
+
/datum/crafting_recipe/chemical_payload
name = "Chemical Payload (C4)"
diff --git a/code/modules/events/radiation_storm.dm b/code/modules/events/radiation_storm.dm
index e41914b91b..7ab509e963 100644
--- a/code/modules/events/radiation_storm.dm
+++ b/code/modules/events/radiation_storm.dm
@@ -4,56 +4,16 @@
max_occurrences = 1
/datum/round_event/radiation_storm
- var/list/protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer, /area/turret_protected/ai)
/datum/round_event/radiation_storm/setup()
- startWhen = rand(10, 20)
- endWhen = startWhen + 5
+ startWhen = 3
+ endWhen = startWhen + 1
announceWhen = 1
/datum/round_event/radiation_storm/announce()
priority_announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/AI/radiation.ogg')
//sound not longer matches the text, but an audible warning is probably good
-
/datum/round_event/radiation_storm/start()
- for(var/mob/living/carbon/C in living_mob_list)
- var/turf/T = get_turf(C)
- if(!T)
- continue
- if(T.z != 1)
- continue
-
- var/skip = 0
- for(var/a in protected_areas)
- if(istype(T.loc, a))
- skip = 1
- continue
-
- if(skip)
- continue
-
- if(locate(/obj/machinery/power/apc) in T) //damn you maint APCs!!
- continue
-
- if(istype(C, /mob/living/carbon/human))
- var/mob/living/carbon/human/H = C
- if(prob(5))
- H.rad_act(rand(100, 160))
- else
- H.rad_act(rand(15, 75))
- if(prob(25))
- if(prob(75))
- randmutb(H)
- else
- randmutg(H)
- H.domutcheck()
-
- else if(istype(C, /mob/living/carbon/monkey))
- var/mob/living/carbon/monkey/M = C
- M.rad_act(rand(15, 75))
-
-
-/datum/round_event/radiation_storm/end()
- priority_announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
\ No newline at end of file
+ SSweather.run_weather("radiation storm",1)
\ No newline at end of file
diff --git a/code/modules/events/wizard/advanced_darkness.dm b/code/modules/events/wizard/advanced_darkness.dm
index 62603dd9a8..16e8042fb0 100644
--- a/code/modules/events/wizard/advanced_darkness.dm
+++ b/code/modules/events/wizard/advanced_darkness.dm
@@ -13,5 +13,4 @@
/datum/round_event/wizard/darkness/start()
if(!started)
started = TRUE
- var/datum/weather/advanced_darkness/darkness = new
- darkness.weather_start_up()
+ SSweather.run_weather("advanced darkness")
diff --git a/code/modules/events/wizard/lava.dm b/code/modules/events/wizard/lava.dm
index 231fab230d..42cae888fc 100644
--- a/code/modules/events/wizard/lava.dm
+++ b/code/modules/events/wizard/lava.dm
@@ -12,5 +12,4 @@
/datum/round_event/wizard/lava/start()
if(!started)
started = TRUE
- var/datum/weather/floor_is_lava/LAVA = new /datum/weather/floor_is_lava
- LAVA.weather_start_up()
+ SSweather.run_weather("the floor is lava")
\ No newline at end of file
diff --git a/code/modules/mining/equipment.dm b/code/modules/mining/equipment.dm
index fdb6380e26..609940bc36 100644
--- a/code/modules/mining/equipment.dm
+++ b/code/modules/mining/equipment.dm
@@ -482,3 +482,110 @@
C.preserved()
user << "You inject the [M] with the stabilizer. It will no longer go inert."
qdel(src)
+
+/*********************Mining Hammer****************/
+/obj/item/weapon/twohanded/required/mining_hammer
+ icon = 'icons/obj/mining.dmi'
+ icon_state = "mining_hammer1"
+ item_state = "mining_hammer1"
+ name = "proto-kinetic crusher"
+ desc = "An early design of the proto-kinetic accelerator, it is little more than an combination of various mining tools cobbled together, forming a high-tech club.\
+ While it is an effective mining tool, it did little to aid any but the most skilled and/or suicidal miners against local fauna. \
+ \nMark a mob with the destabilizing force, then hit them in melee to activate it for extra damage. Extra damage if backstabbed in this fashion. \
+ This weapon is only particularly effective against large creatures."
+ force = 20 //As much as a bone spear, but this is significantly more annoying to carry around due to requiring the use of both hands at all times
+ w_class = 4
+ slot_flags = SLOT_BACK
+ force_unwielded = 20 //It's never not wielded so these are the same
+ force_wielded = 20
+ throwforce = 5
+ throw_speed = 4
+ luminosity = 4
+ armour_penetration = 10
+ materials = list(MAT_METAL=1150, MAT_GLASS=2075)
+ hitsound = 'sound/weapons/bladeslice.ogg'
+ attack_verb = list("smashes", "crushes", "cleaves", "chops", "pulps")
+ sharpness = IS_SHARP
+ var/charged = 1
+ var/charge_time = 16
+ var/atom/mark = null
+ var/marked_image = null
+
+/obj/item/projectile/destabilizer
+ name = "destabilizing force"
+ icon_state = "pulse1"
+ damage = 0 //We're just here to mark people. This is still a melee weapon.
+ damage_type = BRUTE
+ flag = "bomb"
+ range = 6
+ var/obj/item/weapon/twohanded/required/mining_hammer/hammer_synced = null
+
+/obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0, hit_zone)
+ if(hammer_synced)
+ if(hammer_synced.mark == target)
+ return ..()
+ if(isliving(target))
+ if(hammer_synced.mark && hammer_synced.marked_image)
+ hammer_synced.mark.underlays -= hammer_synced.marked_image
+ hammer_synced.marked_image = null
+ var/mob/living/L = target
+ if(L.mob_size >= MOB_SIZE_LARGE)
+ hammer_synced.mark = L
+ var/image/I = image('icons/effects/effects.dmi', loc = L, icon_state = "shield2",pixel_y = (-L.pixel_y),pixel_x = (-L.pixel_x))
+ L.underlays += I
+ hammer_synced.marked_image = I
+ var/target_turf = get_turf(target)
+ if(istype(target_turf, /turf/closed/mineral))
+ var/turf/closed/mineral/M = target_turf
+ PoolOrNew(/obj/effect/overlay/temp/kinetic_blast, M)
+ M.gets_drilled(firer)
+ ..()
+
+/obj/item/weapon/twohanded/required/mining_hammer/afterattack(atom/target, mob/user, proximity_flag)
+ if(!proximity_flag && charged)//Mark a target, or mine a tile.
+ var/turf/proj_turf = get_turf(src)
+ if(!istype(proj_turf, /turf))
+ return
+ var/datum/gas_mixture/environment = proj_turf.return_air()
+ var/pressure = environment.return_pressure()
+ if(pressure > 50)
+ playsound(user, 'sound/weapons/empty.ogg', 100, 1)
+ return
+ var/obj/item/projectile/destabilizer/D = new /obj/item/projectile/destabilizer(user.loc)
+ D.preparePixelProjectile(target,get_turf(target), user)
+ D.hammer_synced = src
+ playsound(user, 'sound/weapons/plasma_cutter.ogg', 100, 1)
+ D.fire()
+ charged = 0
+ icon_state = "mining_hammer1_uncharged"
+ addtimer(src, "Recharge", charge_time)
+ return
+ if(proximity_flag && target == mark && isliving(target))
+ var/mob/living/L = target
+ PoolOrNew(/obj/effect/overlay/temp/kinetic_blast, get_turf(L))
+ mark = 0
+ if(L.mob_size >= MOB_SIZE_LARGE)
+ L.underlays -= marked_image
+ qdel(marked_image)
+ marked_image = null
+ var/backstab = check_target_facings(user, L)
+ var/def_check = L.getarmor(type = "bomb")
+ if(backstab == FACING_INIT_FACING_TARGET_TARGET_FACING_PERPENDICULAR || backstab == FACING_SAME_DIR)
+ L.apply_damage(80, BRUTE, blocked = def_check)
+ playsound(user, 'sound/weapons/Kenetic_accel.ogg', 100, 1) //Seriously who spelled it wrong
+ else
+ L.apply_damage(50, BRUTE, blocked = def_check)
+
+/obj/item/weapon/twohanded/required/mining_hammer/proc/Recharge()
+ if(!charged)
+ charged = 1
+ icon_state = "mining_hammer1"
+ playsound(src.loc, 'sound/weapons/kenetic_reload.ogg', 60, 1)
+
+/obj/item/weapon/twohanded/required/mining_hammer/pickup(mob/user)
+ ..()
+ user.AddLuminosity(luminosity)
+
+/obj/item/weapon/twohanded/required/mining_hammer/dropped(mob/user)
+ ..()
+ user.AddLuminosity(-luminosity)
\ No newline at end of file
diff --git a/code/modules/mining/lavaland/weather.dm b/code/modules/mining/lavaland/weather.dm
deleted file mode 100644
index 33eb1e4e6b..0000000000
--- a/code/modules/mining/lavaland/weather.dm
+++ /dev/null
@@ -1,110 +0,0 @@
-#define STARTUP_STAGE 1
-#define MAIN_STAGE 2
-#define WIND_DOWN_STAGE 3
-#define END_STAGE 4
-
-/datum/weather
- var/name = "storm"
- var/start_up_time = 300 //30 seconds
- var/start_up_message = "The wind begins to pick up."
- var/start_up_sound
- var/duration = 120 //2 minutes
- var/duration_lower = 120
- var/duration_upper = 120
- var/duration_sound
- var/duration_message = "A storm has started!"
- var/wind_down = 300 // 30 seconds
- var/wind_down_message = "The storm is passing."
- var/wind_down_sound
-
- var/target_z = 1
- var/exclude_walls = TRUE
- var/area_type = /area/space
- var/stage = STARTUP_STAGE
-
-
- var/start_up_overlay = "lava"
- var/duration_overlay = "lava"
- var/overlay_layer = AREA_LAYER //This is the default area layer, and above everything else. TURF_LAYER is floors/below walls and mobs.
- var/purely_aesthetic = FALSE //If we just want gentle rain that doesn't hurt people
- var/list/impacted_areas = list()
- var/immunity_type = "storm"
-
-/datum/weather/proc/weather_start_up()
- for(var/area/N in get_areas(area_type))
- if(N.z == target_z)
- impacted_areas += N
- duration = rand(duration_lower,duration_upper)
- update_areas()
- for(var/mob/M in player_list)
- if(M.z == target_z)
- M << "[start_up_message]"
- if(start_up_sound)
- M << start_up_sound
- sleep(start_up_time)
- if(src && stage != MAIN_STAGE)
- stage = MAIN_STAGE
- weather_main()
-
-
-/datum/weather/proc/weather_main()
- update_areas()
- for(var/mob/M in player_list)
- if(M.z == target_z)
- M << "[duration_message]"
- if(duration_sound)
- M << duration_sound
- if(purely_aesthetic)
- sleep(duration*10)
- else //Storm effects
- for(var/i in 1 to duration-1)
- for(var/mob/living/L in living_mob_list)
- var/area/storm_area = get_area(L)
- if(storm_area in impacted_areas)
- storm_act(L)
- sleep(10)
-
- if(src && stage != WIND_DOWN_STAGE)
- stage = WIND_DOWN_STAGE
- weather_wind_down()
-
-
-/datum/weather/proc/weather_wind_down()
- update_areas()
- for(var/mob/M in player_list)
- if(M.z == target_z)
- M << "[wind_down_message]"
- if(wind_down_sound)
- M << wind_down_sound
- sleep(wind_down)
-
- if(src && stage != END_STAGE)
- stage = END_STAGE
- update_areas()
-
-
-/datum/weather/proc/storm_act(mob/living/L)
- if(immunity_type in L.weather_immunities)
- return
-
-/datum/weather/proc/update_areas()
- for(var/area/N in impacted_areas)
- N.layer = overlay_layer
- N.icon = 'icons/effects/weather_effects.dmi'
- N.invisibility = 0
- switch(stage)
- if(STARTUP_STAGE)
- N.icon_state = start_up_overlay
-
- if(MAIN_STAGE)
- N.icon_state = duration_overlay
-
- if(WIND_DOWN_STAGE)
- N.icon_state = start_up_overlay
-
- if(END_STAGE)
- N.icon_state = initial(N.icon_state)
- N.icon = 'icons/turf/areas.dmi'
- N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial
- N.invisibility = INVISIBILITY_MAXIMUM
- N.opacity = 0
\ No newline at end of file
diff --git a/code/modules/mining/lavaland/weather_types.dm b/code/modules/mining/lavaland/weather_types.dm
deleted file mode 100644
index bc205602cc..0000000000
--- a/code/modules/mining/lavaland/weather_types.dm
+++ /dev/null
@@ -1,108 +0,0 @@
-///The floor is lava
-
-/datum/weather/floor_is_lava
- name = "floor is lava"
- start_up_time = 30 //3 seconds
- start_up_message = "The ground begins to bubble."
- duration_lower = 45
- duration_upper = 60 //1 minute
- duration_message = "The floor is lava!"
- wind_down = 30// 3 seconds
- wind_down_message = "The ground begins to cool."
-
- target_z = 1
- exclude_walls = TRUE
- area_type = /area
-
- start_up_overlay = "lava"
- duration_overlay = "lava"
- overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
-
- immunity_type = "lava"
-
-
-/datum/weather/floor_is_lava/storm_act(mob/living/L)
- if(immunity_type in L.weather_immunities)
- return
-
- var/turf/F = get_turf(L)
- for(var/obj/structure/O in F.contents)
- if(O.level > F.level && !istype(O, /obj/structure/window)) // Something to stand on and it isn't under the floor!
- return
- L.adjustFireLoss(3)
-
-
-
-/datum/weather/advanced_darkness
- name = "advanced darkness"
- start_up_time = 100 //10 seconds
- start_up_message = "The lights begin to dim... is power going out?"
- duration_lower = 45
- duration_upper = 60 //1 minute
- duration_message = "This isn't average everyday darkness... this is advanced darkness!"
- wind_down = 100 // 10 seconds
- wind_down_message = "The darkness recedes."
- purely_aesthetic = TRUE
-
- target_z = 1
- exclude_walls = TRUE
- area_type = /area
-
- start_up_overlay = ""
- duration_overlay = ""
- overlay_layer = AREA_LAYER
-
-/datum/weather/advanced_darkness/update_areas()
- for(var/area/A in impacted_areas)
- if(stage == MAIN_STAGE)
- A.invisibility = 0
- A.opacity = 1
- A.layer = overlay_layer
- A.icon = 'icons/effects/weather_effects.dmi'
- A.icon_state = start_up_overlay
- else
- A.invisibility = INVISIBILITY_MAXIMUM
- A.opacity = 0
-//Ash storms
-
-/datum/weather/ash_storm
- name = "ash storm"
- start_up_time = 300 //30 seconds
- start_up_message = "An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter."
- start_up_sound = 'sound/lavaland/ash_storm_windup.ogg'
- duration_lower = 60 //1 minute
- duration_upper = 150 //2.5 minutes
- duration_message = "Smoldering clouds of scorching ash billow down around you! Get inside!"
- duration_sound = 'sound/lavaland/ash_storm_start.ogg'
- wind_down = 300 // 30 seconds
- wind_down_message = "The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now."
- wind_down_sound = 'sound/lavaland/ash_storm_end.ogg'
-
- target_z = ZLEVEL_LAVALAND
- area_type = /area/lavaland/surface/outdoors
-
- start_up_overlay = "light_ash"
- duration_overlay = "ash_storm"
- overlay_layer = AREA_LAYER
-
- immunity_type = "ash"
-
-
-/datum/weather/ash_storm/false_alarm //No storm, just light ember fall
- purely_aesthetic = TRUE
- duration_overlay = "light_ash"
- duration_message = "Gentle ashfall surrounds you like grotesque snow. The storm seems to have passed you by."
- wind_down_message = "The ashfall quietly slows, then stops. Another layer of hardened soot to the volcanic rock beneath you."
-
-/datum/weather/ash_storm/storm_act(mob/living/L)
- if(immunity_type in L.weather_immunities)
- return
-
- if(istype(L.loc, /obj/mecha))
- return
- if(ishuman(L))
- var/mob/living/carbon/human/H = L
- var/thermal_protection = H.get_thermal_protection()
- if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
- return
- L.adjustFireLoss(4)
diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm
index 3452702bc3..e6f5372c7a 100644
--- a/code/modules/mining/machine_vending.dm
+++ b/code/modules/mining/machine_vending.dm
@@ -27,6 +27,7 @@
new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600),
new /datum/data/mining_equipment("Tracking Implant Kit",/obj/item/weapon/storage/box/minertracker, 600),
new /datum/data/mining_equipment("Jaunter", /obj/item/device/wormhole_jaunter, 750),
+ new /datum/data/mining_equipment("Kinetic Crusher", /obj/item/weapon/twohanded/required/mining_hammer, 750),
new /datum/data/mining_equipment("Kinetic Accelerator", /obj/item/weapon/gun/energy/kinetic_accelerator, 750),
new /datum/data/mining_equipment("Resonator", /obj/item/weapon/resonator, 800),
new /datum/data/mining_equipment("Medivac Balloon", /obj/item/weapon/extraction_pack/medivac, 800),
@@ -158,7 +159,7 @@
return ..()
/obj/machinery/mineral/equipment_vendor/proc/RedeemVoucher(obj/item/weapon/mining_voucher/voucher, mob/redeemer)
- var/items = list("Survival Capsule and Explorer's Webbing", "Resonator and Advanced Scanner", "Mining Drone", "Medivac Kit", "Extraction Kit")
+ var/items = list("Survival Capsule and Explorer's Webbing", "Resonator and Advanced Scanner", "Mining Drone", "Medivac Kit", "Extraction Kit", "Crusher Kit")
var/selection = input(redeemer, "Pick your equipment", "Mining Voucher Redemption") as null|anything in items
if(!selection || !Adjacent(redeemer) || qdeleted(voucher) || voucher.loc != redeemer)
@@ -181,6 +182,10 @@
new /obj/item/stack/sheet/metal/five(loc)
new /obj/item/weapon/extraction_pack(loc)
new /obj/item/fulton_core(loc)
+ if("Crusher Kit")
+ new /obj/item/weapon/twohanded/required/mining_hammer(loc)
+ new /obj/item/weapon/storage/belt/mining/alt(loc)
+ new /obj/item/weapon/extinguisher/mini(loc)
feedback_add_details("mining_voucher_redeemed", selection)
qdel(voucher)
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index c4ae6eefec..7ed125a038 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -118,37 +118,38 @@
force = 25
damtype = BURN
hitsound = 'sound/weapons/sear.ogg'
- var/obj/machinery/lavaland_controller/linked_machine
var/storm_cooldown = 0
/obj/item/weapon/staff_of_storms/attack_self(mob/user)
if(storm_cooldown > world.time)
user << "The staff is still recharging!"
return
+ if(user.z != ZLEVEL_LAVALAND)
+ user << "You can't seem to control the weather here!"
+ return
- if(!linked_machine || linked_machine.z != user.z)
- for(var/obj/machinery/lavaland_controller/controller in machines)
- if(controller.z == user.z)
- linked_machine = controller
- break
+ var/datum/weather/ash_storm/A
+ for(var/V in SSweather.existing_weather)
+ var/datum/weather/W = V
+ if(W.name == "ash storm")
+ A = W
+ break
+ if(!A)
+ user << "How odd! The planet seems to have lost its atmosphere!"
+ return
- if(linked_machine && linked_machine.ongoing_weather)
- if(linked_machine.ongoing_weather.stage == WIND_DOWN_STAGE || linked_machine.ongoing_weather.stage == END_STAGE)
- user << "The storm is already ending. It would be a waste to use the staff now."
+ if(A.stage != END_STAGE)
+ if(A.stage == WIND_DOWN_STAGE)
+ user << "The storm is already ending! It would be a waste to use the staff now."
return
- user.visible_message("[user] holds [src] skywards, causing its orb to flare!", \
- "With an appropriately dramatic flourish, you dispel the storm!")
- playsound(get_turf(src),'sound/magic/Staff_Change.ogg', 200, 0)
- storm_cooldown = world.time + 600
- linked_machine.ongoing_weather.stage = WIND_DOWN_STAGE
- linked_machine.ongoing_weather.weather_wind_down()
-
- else if (linked_machine && !linked_machine.ongoing_weather)
- user.visible_message("[user] holds [src] skywards, causing its orb to flare!", \
- "You lift your staff skywards, calling down a terrible storm!")
- playsound(get_turf(src),'sound/magic/Staff_Chaos.ogg', 200, 0)
- storm_cooldown = world.time + 600
- linked_machine.weather_cooldown = 0
-
+ user.visible_message("[user] holds [src] skywards as an orange beam travels into the sky!", \
+ "You hold [src] skyward, dispelling the ash storm!")
+ playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
+ A.wind_down()
else
- user << "You can't seem to control the weather here."
+ user.visible_message("[user] holds [src] skywards as red lightning crackles into the sky!", \
+ "You hold [src] skyward, calling down a terrible storm!")
+ playsound(user, 'sound/magic/Staff_Chaos.ogg', 200, 0)
+ A.telegraph()
+
+ storm_cooldown = world.time + 600
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index ac2f797396..095f76b3a6 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -15,6 +15,7 @@
var/icon_aggro = null // for swapping to when we get aggressive
see_in_dark = 8
see_invisible = SEE_INVISIBLE_MINIMUM
+ mob_size = MOB_SIZE_LARGE
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
@@ -264,7 +265,7 @@
else
feedback_add_details("hivelord_core", "[type]|stabilizer")
-
+
/obj/item/organ/hivelord_core/proc/go_inert()
inert = TRUE
desc = "The remains of a hivelord that have become useless, having been left alone too long after being harvested."
@@ -660,7 +661,6 @@
move_to_delay = 6
transform *= 2
environment_smash = 2
- mob_size = MOB_SIZE_LARGE
speed = 1
addtimer(src, "Deflate", 100)
diff --git a/code/modules/projectiles/pins.dm b/code/modules/projectiles/pins.dm
index b1a42f2db9..e72404e3c1 100644
--- a/code/modules/projectiles/pins.dm
+++ b/code/modules/projectiles/pins.dm
@@ -111,7 +111,14 @@
icon_state = "firing_pin_pindi"
req_implant = /obj/item/weapon/implant/weapons_auth
+/obj/item/device/firing_pin/trick
+ name = "self-destruct firing pin"
+ desc = "This pin will detonate the weapon it is put into upon trying to use it"
+ selfdestruct = 1
+ force_replace = 1
+/obj/item/device/firing_pin/trick/pin_auth(mob/living/user)
+ return 0
// Honk pin, clown's joke item.
// Can replace other pins. Replace a pin in cap's laser for extra fun!
diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm
index 6abff31602..582bf75748 100644
--- a/code/modules/reagents/reagent_containers/spray.dm
+++ b/code/modules/reagents/reagent_containers/spray.dm
@@ -211,3 +211,23 @@
item_state = "plantbgone"
volume = 100
list_reagents = list("plantbgone" = 100)
+
+/obj/item/weapon/reagent_containers/spray/thermite
+ name = "Thermite Spray"
+ desc = "A 50u spray bottle loaded with thermite, for melting walls. "
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "thermitespray"
+ item_state = "thermitespray"
+ volume = 50
+ list_reagents = list("thermite" = 50)
+
+/obj/item/weapon/reagent_containers/spray/thermite/afterattack(atom/A as mob|obj, mob/user)
+ if(istype(A, /turf/closed/wall))
+ if(reagents.get_reagent_amount("thermite") >= 10)
+ user.visible_message("You spray the thermite on [A].")
+ reagents.reaction(A, TOUCH)
+ reagents.remove_reagent("thermite", 10)
+ else
+ user.visible_message("You don't have enough thermite left!")
+ return
+ else return ..()
\ No newline at end of file
diff --git a/code/modules/ruins/lavaland_ruin_code.dm b/code/modules/ruins/lavaland_ruin_code.dm
index ac45476b53..f47ccb727e 100644
--- a/code/modules/ruins/lavaland_ruin_code.dm
+++ b/code/modules/ruins/lavaland_ruin_code.dm
@@ -1,32 +1,10 @@
//If you're looking for spawners like ash walker eggs, check ghost_role_spawners.dm
/obj/machinery/lavaland_controller
- name = "weather control machine"
- desc = "Controls the weather."
+ name = "weather machine"
+ desc = "Controls the weather... when it's on, at any rate. A sticky note on the side proclaims \"DISABLED IN FAVOR OF AN ACTUAL ATMOSPHERE\"."
icon = 'icons/obj/machines/telecomms.dmi'
- icon_state = "processor"
- var/datum/weather/ongoing_weather = FALSE
- var/weather_cooldown = 0
-
-/obj/machinery/lavaland_controller/process()
- if(ongoing_weather || weather_cooldown > world.time)
- return
- weather_cooldown = world.time + rand(3500, 6500)
- var/datum/weather/ash_storm/LAVA
- if(prob(10)) //10% chance for the ash storm to miss the area entirely
- LAVA = new /datum/weather/ash_storm/false_alarm
- else
- LAVA = new /datum/weather/ash_storm
- ongoing_weather = LAVA
- LAVA.weather_start_up()
- ongoing_weather = null
-
-/obj/machinery/lavaland_controller/Destroy(force)
- if(force)
- . = ..()
- else
- return QDEL_HINT_LETMELIVE
-
+ icon_state = "processor_off"
/obj/structure/fans/tiny/invisible //For blocking air in ruin doorways
invisibility = INVISIBILITY_ABSTRACT
@@ -105,4 +83,4 @@
else
user << "You need at least ten sheets to finish a golem."
else
- user << "You can't build a golem out of this kind of material."
+ user << "You can't build a golem out of this kind of material."
\ No newline at end of file
diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm
index 343eab844d..86bd6d64a9 100644
--- a/code/modules/uplink/uplink_item.dm
+++ b/code/modules/uplink/uplink_item.dm
@@ -624,6 +624,16 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
surplus = 10
exclude_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/stealthy_weapons/boobytrap
+ name = "Booby Trap"
+ desc = "A small explosive device that can be attached to boxes or closets. \
+ The next person to open the box or closet will trigger an explosion \
+ that knocks them down and destroys the boobytrapped object."
+ item = /obj/item/device/boobytrap
+ cost = 4
+ surplus = 10
+ exclude_modes = list(/datum/game_mode/nuclear)
+
// Stealth Items
/datum/uplink_item/stealthy_tools
category = "Stealth and Camouflage Items"
@@ -797,7 +807,7 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
name = "Military Belt"
desc = "A robust seven-slot red belt that is capable of holding all manner of tatical equipment."
item = /obj/item/weapon/storage/belt/military
- cost = 3
+ cost = 1
exclude_modes = list(/datum/game_mode/nuclear)
/datum/uplink_item/device_tools/medkit
@@ -835,6 +845,12 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
cost = 2
surplus = 75
+/datum/uplink_item/device_tools/selfdestruct_firingpin
+ name = "Trick Firing Pin"
+ desc = "This pin will detonate the weapon it is put into upon trying to use it"
+ item = /obj/item/device/firing_pin/trick
+ cost = 4
+
/datum/uplink_item/device_tools/ai_detector
name = "Artificial Intelligence Detector"
desc = "A functional multitool that turns red when it detects an artificial intelligence watching it or its \
@@ -858,6 +874,13 @@ var/list/uplink_items = list() // Global list so we only initialize this once.
cost = 2
include_modes = list(/datum/game_mode/nuclear)
+/datum/uplink_item/device_tools/thermitespray
+ name = "Thermite Kit"
+ desc = "A boxed zippo and 50u spray bottle filled with thermite, specially designed for spraying walls. \
+ 50u is enough thermite to spray 5 walls."
+ item = /obj/item/weapon/storage/box/syndie_kit/thermite
+ cost = 3
+
/datum/uplink_item/device_tools/c4
name = "Composition C-4"
desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, sabotage equipment, or connect \
diff --git a/icons/effects/96x32.dmi b/icons/effects/96x32.dmi
index 937b2e8d42..05b60c5f8b 100644
Binary files a/icons/effects/96x32.dmi and b/icons/effects/96x32.dmi differ
diff --git a/icons/effects/weather_effects.dmi b/icons/effects/weather_effects.dmi
index 215cf53556..a24565da63 100644
Binary files a/icons/effects/weather_effects.dmi and b/icons/effects/weather_effects.dmi differ
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index 078af3b172..02b63743a0 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/icons/mob/head.dmi b/icons/mob/head.dmi
index 10497b1c08..428fbb3dc7 100644
Binary files a/icons/mob/head.dmi and b/icons/mob/head.dmi differ
diff --git a/icons/mob/inhands/clothing_lefthand.dmi b/icons/mob/inhands/clothing_lefthand.dmi
index aa11f4e527..e6c1319d31 100644
Binary files a/icons/mob/inhands/clothing_lefthand.dmi and b/icons/mob/inhands/clothing_lefthand.dmi differ
diff --git a/icons/mob/inhands/clothing_righthand.dmi b/icons/mob/inhands/clothing_righthand.dmi
index edd47e107f..3aaea5ef11 100644
Binary files a/icons/mob/inhands/clothing_righthand.dmi and b/icons/mob/inhands/clothing_righthand.dmi differ
diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi
index 7328ffcbf3..41449fa3df 100644
Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ
diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi
index 9f249c233f..bccfd577fc 100644
Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ
diff --git a/icons/mob/suit.dmi b/icons/mob/suit.dmi
index 655b841f09..5ff2389364 100644
Binary files a/icons/mob/suit.dmi and b/icons/mob/suit.dmi differ
diff --git a/icons/obj/clothing/hats.dmi b/icons/obj/clothing/hats.dmi
index 9fd11036bc..f3fb62969c 100644
Binary files a/icons/obj/clothing/hats.dmi and b/icons/obj/clothing/hats.dmi differ
diff --git a/icons/obj/clothing/suits.dmi b/icons/obj/clothing/suits.dmi
index 528df2cd9e..b20401225a 100644
Binary files a/icons/obj/clothing/suits.dmi and b/icons/obj/clothing/suits.dmi differ
diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi
index 64825e13ed..63892f0070 100644
Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ
diff --git a/icons/obj/grenade.dmi b/icons/obj/grenade.dmi
index 4e38271e7e..c27e612e5f 100644
Binary files a/icons/obj/grenade.dmi and b/icons/obj/grenade.dmi differ
diff --git a/icons/obj/items.dmi b/icons/obj/items.dmi
index 130c276c27..21e4db6679 100644
Binary files a/icons/obj/items.dmi and b/icons/obj/items.dmi differ
diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi
index b23e91679d..036fc797d1 100644
Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ
diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi
index 32956b60a0..a3b0fa11c9 100644
Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ
diff --git a/sound/effects/curtain.ogg b/sound/effects/curtain.ogg
new file mode 100644
index 0000000000..b3be91aaa2
Binary files /dev/null and b/sound/effects/curtain.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index e22b7368ee..80c9b6b439 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -172,6 +172,7 @@
#include "code\controllers\subsystem\ticker.dm"
#include "code\controllers\subsystem\timer.dm"
#include "code\controllers\subsystem\voting.dm"
+#include "code\controllers\subsystem\weather.dm"
#include "code\datums\action.dm"
#include "code\datums\ai_laws.dm"
#include "code\datums\beam.dm"
@@ -254,6 +255,8 @@
#include "code\datums\martial\wrestling.dm"
#include "code\datums\ruins\lavaland.dm"
#include "code\datums\ruins\space.dm"
+#include "code\datums\weather\weather.dm"
+#include "code\datums\weather\weather_types.dm"
#include "code\datums\wires\airalarm.dm"
#include "code\datums\wires\airlock.dm"
#include "code\datums\wires\apc.dm"
@@ -606,6 +609,7 @@
#include "code\game\objects\items\toys.dm"
#include "code\game\objects\items\trash.dm"
#include "code\game\objects\items\devices\aicard.dm"
+#include "code\game\objects\items\devices\boobytrap.dm"
#include "code\game\objects\items\devices\camera_bug.dm"
#include "code\game\objects\items\devices\chameleonproj.dm"
#include "code\game\objects\items\devices\doorCharge.dm"
@@ -1272,8 +1276,6 @@
#include "code\modules\mining\laborcamp\laborstacker.dm"
#include "code\modules\mining\lavaland\lavaland_areas.dm"
#include "code\modules\mining\lavaland\necropolis_chests.dm"
-#include "code\modules\mining\lavaland\weather.dm"
-#include "code\modules\mining\lavaland\weather_types.dm"
#include "code\modules\mining\lavaland\ruins\gym.dm"
#include "code\modules\mob\death.dm"
#include "code\modules\mob\interactive.dm"
@@ -1391,6 +1393,7 @@
#include "code\modules\mob\living\carbon\monkey\punpun.dm"
#include "code\modules\mob\living\carbon\monkey\update_icons.dm"
#include "code\modules\mob\living\silicon\death.dm"
+#include "code\modules\mob\living\silicon\examine.dm"
#include "code\modules\mob\living\silicon\laws.dm"
#include "code\modules\mob\living\silicon\login.dm"
#include "code\modules\mob\living\silicon\say.dm"