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"