diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 9ceff97eafe..41da55fa265 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -1274,11 +1274,11 @@ /area/security/prison) "afD" = ( /obj/structure/table, -/obj/item/electropack, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 8 }, +/obj/item/electropack, /turf/open/floor/iron, /area/security/prison) "afF" = ( @@ -30983,8 +30983,6 @@ /area/hallway/secondary/exit) "iVY" = ( /obj/structure/table, -/obj/item/assembly/signaler, -/obj/item/clothing/suit/straight_jacket, /obj/effect/turf_decal/tile/red, /obj/effect/turf_decal/tile/red{ dir = 8 @@ -30995,6 +30993,8 @@ network = list("ss13","prison") }, /obj/machinery/light/directional/south, +/obj/item/assembly/signaler, +/obj/item/clothing/suit/straight_jacket, /turf/open/floor/iron, /area/security/prison) "iWe" = ( diff --git a/_maps/map_files/generic/CentCom.dmm b/_maps/map_files/generic/CentCom.dmm index 38b1cf19125..ed4a1418458 100644 --- a/_maps/map_files/generic/CentCom.dmm +++ b/_maps/map_files/generic/CentCom.dmm @@ -8370,10 +8370,23 @@ /area/centcom/ferry) "Ak" = ( /obj/structure/table/reinforced, -/obj/item/storage/firstaid/regular, +/obj/item/storage/firstaid/regular{ + pixel_x = -7 + }, /obj/effect/turf_decal/stripes/line{ dir = 5 }, +/obj/item/bodybag/environmental/nanotrasen{ + pixel_x = 7; + pixel_y = 12 + }, +/obj/item/bodybag/environmental/nanotrasen{ + pixel_x = 7; + pixel_y = 6 + }, +/obj/item/bodybag/environmental/nanotrasen{ + pixel_x = 7 + }, /turf/open/floor/iron, /area/centcom/ferry) "Al" = ( diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index a8c59583256..bd1f3ff31ca 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -42,6 +42,16 @@ /// Involved in checking the likelyhood of applying a wound to a mob. #define WOUND "wound" +// Weather immunities // +#define WEATHER_STORM "storm" +#define WEATHER_ACID "acid" +#define WEATHER_ASH "ash" +#define WEATHER_LAVA "lava" +#define WEATHER_RAD "rad" +#define WEATHER_SNOW "snow" +#define WEATHER_VOID "void" +#define WEATHER_ALL "all" + //bitflag damage defines used for suicide_act #define BRUTELOSS (1<<0) #define FIRELOSS (1<<1) diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm index 95cf6c96b9b..cccac59fdfc 100644 --- a/code/datums/weather/weather.dm +++ b/code/datums/weather/weather.dm @@ -63,7 +63,7 @@ /// If the weather has no purpose other than looks var/aesthetic = FALSE /// Used by mobs to prevent them from being affected by the weather - var/immunity_type = "storm" + var/immunity_type = WEATHER_STORM /// The stage of the weather, from 1-4 var/stage = END_STAGE @@ -189,14 +189,28 @@ * Returns TRUE if the living mob can be affected by the weather * */ -/datum/weather/proc/can_weather_act(mob/living/act_on) - var/turf/mob_turf = get_turf(act_on) - if(mob_turf && !(mob_turf.z in impacted_z_levels)) +/datum/weather/proc/can_weather_act(mob/living/mob_to_check) + var/turf/mob_turf = get_turf(mob_to_check) + + if(!(mob_turf.z in impacted_z_levels)) + if(mob_turf) + return + + if(!(mob_to_check.loc.z in impacted_z_levels)) // in this case, get_turf(mob_to_check) =/= mob_to_check.loc, so we have to proceed with checking the location's type + return + + if(istype(mob_to_check.loc, /obj/structure/closet)) + var/obj/structure/closet/current_locker = mob_to_check.loc + if(current_locker.weather_protection) + if((immunity_type in current_locker.weather_protection) || (WEATHER_ALL in current_locker.weather_protection)) + return + + if((immunity_type in mob_to_check.weather_immunities) || (WEATHER_ALL in mob_to_check.weather_immunities)) return - if(immunity_type in act_on.weather_immunities) - return - if(!(get_area(act_on) in impacted_areas)) + + if(!(get_area(mob_to_check) in impacted_areas)) return + return TRUE /** diff --git a/code/datums/weather/weather_types/acid_rain.dm b/code/datums/weather/weather_types/acid_rain.dm index 36e6b117128..5c5809bae81 100644 --- a/code/datums/weather/weather_types/acid_rain.dm +++ b/code/datums/weather/weather_types/acid_rain.dm @@ -21,7 +21,7 @@ protect_indoors = TRUE target_trait = ZTRAIT_ACIDRAIN - immunity_type = ACID // temp + immunity_type = WEATHER_ACID // temp barometer_predictable = TRUE diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm index 1a16e91889c..90565d4138e 100644 --- a/code/datums/weather/weather_types/ash_storm.dm +++ b/code/datums/weather/weather_types/ash_storm.dm @@ -20,7 +20,7 @@ protect_indoors = TRUE target_trait = ZTRAIT_ASHSTORM - immunity_type = "ash" + immunity_type = WEATHER_ASH probability = 90 @@ -72,7 +72,7 @@ return TRUE if(isliving(L))// if we're a non immune mob inside an immune mob we have to reconsider if that mob is immune to protect ourselves var/mob/living/the_mob = L - if("ash" in the_mob.weather_immunities) + if(WEATHER_ASH in the_mob.weather_immunities) return TRUE L = L.loc //Check parent items immunities (recurses up to the turf) return FALSE //RIP you diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm index ad7d9c8ff36..bff7e0b825c 100644 --- a/code/datums/weather/weather_types/floor_is_lava.dm +++ b/code/datums/weather/weather_types/floor_is_lava.dm @@ -20,7 +20,7 @@ overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only overlay_plane = FLOOR_PLANE - immunity_type = "lava" + immunity_type = WEATHER_LAVA /datum/weather/floor_is_lava/weather_act(mob/living/L) diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm index 2db50521132..ca014a99874 100644 --- a/code/datums/weather/weather_types/radiation_storm.dm +++ b/code/datums/weather/weather_types/radiation_storm.dm @@ -21,7 +21,7 @@ /area/ai_monitored/turret_protected/ai, /area/commons/storage/emergency/starboard, /area/commons/storage/emergency/port, /area/shuttle, /area/security/prison/safe, /area/security/prison/toilet) target_trait = ZTRAIT_STATION - immunity_type = RAD + immunity_type = WEATHER_RAD /datum/weather/rad_storm/telegraph() ..() diff --git a/code/datums/weather/weather_types/snow_storm.dm b/code/datums/weather/weather_types/snow_storm.dm index 8ab4839cdbd..fab359df18b 100644 --- a/code/datums/weather/weather_types/snow_storm.dm +++ b/code/datums/weather/weather_types/snow_storm.dm @@ -19,7 +19,7 @@ protect_indoors = TRUE target_trait = ZTRAIT_SNOWSTORM - immunity_type = "snow" + immunity_type = WEATHER_SNOW barometer_predictable = TRUE diff --git a/code/datums/weather/weather_types/void_storm.dm b/code/datums/weather/weather_types/void_storm.dm index 58c9e7be632..9091ecb63f6 100644 --- a/code/datums/weather/weather_types/void_storm.dm +++ b/code/datums/weather/weather_types/void_storm.dm @@ -17,7 +17,7 @@ protect_indoors = FALSE target_trait = ZTRAIT_VOIDSTORM - immunity_type = "void" + immunity_type = WEATHER_VOID barometer_predictable = FALSE perpetual = TRUE diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ec62865bb5b..dccba1b5b56 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -75,6 +75,11 @@ /// Whether this atom should have its dir automatically changed when it moves. Setting this to FALSE allows for things such as directional windows to retain dir on moving without snowflake code all of the place. var/set_dir_on_move = TRUE + /// The degree of thermal insulation that mobs in list/contents have from the external environment, between 0 and 1 + var/contents_thermal_insulation = 0 + /// The degree of pressure protection that mobs in list/contents have from the external environment, between 0 and 1 + var/contents_pressure_protection = 0 + /atom/movable/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/bodybag.dm b/code/game/objects/items/bodybag.dm index e48c5eb023e..db784a5297c 100644 --- a/code/game/objects/items/bodybag.dm +++ b/code/game/objects/items/bodybag.dm @@ -89,3 +89,34 @@ return loc.visible_message(span_warning("[user] suddenly appears in front of [loc]!"), span_userdanger("[user] breaks free of [src]!")) qdel(src) + +/obj/item/bodybag/environmental + name = "environmental protection bag" + desc = "A folded, reinforced bag designed to protect against exoplanetary environmental storms." + icon = 'icons/obj/bodybag.dmi' + icon_state = "envirobag_folded" + unfoldedbag_path = /obj/structure/closet/body_bag/environmental + w_class = WEIGHT_CLASS_NORMAL //It's reinforced and insulated, like a beefed-up sleeping bag, so it has a higher bulkiness than regular bodybag + resistance_flags = ACID_PROOF | FIRE_PROOF | FREEZE_PROOF + +/obj/item/bodybag/environmental/nanotrasen + name = "elite environmental protection bag" + desc = "A folded, heavily reinforced, and insulated bag, capable of fully isolating its contents from external factors." + icon_state = "ntenvirobag_folded" + unfoldedbag_path = /obj/structure/closet/body_bag/environmental/nanotrasen + resistance_flags = ACID_PROOF | FIRE_PROOF | FREEZE_PROOF | LAVA_PROOF + +/obj/item/bodybag/environmental/prisoner + name = "prisoner transport bag" + desc = "Intended for transport of prisoners through hazardous environments, this folded environmental protection bag comes with straps to keep an occupant secure." + icon = 'icons/obj/bodybag.dmi' + icon_state = "prisonerenvirobag_folded" + unfoldedbag_path = /obj/structure/closet/body_bag/environmental/prisoner + +/obj/item/bodybag/environmental/prisoner/syndicate + name = "syndicate prisoner transport bag" + desc = "An alteration of Nanotrasen's environmental protection bag which has been used in several high-profile kidnappings. Designed to keep a victim unconscious, alive, and secured until they are transported to a required location." + icon = 'icons/obj/bodybag.dmi' + icon_state = "syndieenvirobag_folded" + unfoldedbag_path = /obj/structure/closet/body_bag/environmental/prisoner/syndicate + resistance_flags = ACID_PROOF | FIRE_PROOF | FREEZE_PROOF | LAVA_PROOF diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm index d422fb166a5..aa05d1fe326 100644 --- a/code/game/objects/items/robot/robot_upgrades.dm +++ b/code/game/objects/items/robot/robot_upgrades.dm @@ -296,12 +296,12 @@ /obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr) . = ..() if(.) - LAZYADD(R.weather_immunities, "lava") + LAZYADD(R.weather_immunities, WEATHER_LAVA) /obj/item/borg/upgrade/lavaproof/deactivate(mob/living/silicon/robot/R, user = usr) . = ..() if (.) - LAZYREMOVE(R.weather_immunities, "lava") + LAZYREMOVE(R.weather_immunities, WEATHER_LAVA) /obj/item/borg/upgrade/selfrepair name = "self-repair module" diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 822e4e5b374..27b872efbe3 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -44,6 +44,12 @@ var/delivery_icon = "deliverycloset" //which icon to use when packagewrapped. null to be unwrappable. var/anchorable = TRUE var/icon_welded = "welded" + /// Protection against weather that being inside of it provides. + var/list/weather_protection = null + /// How close being inside of the thing provides complete pressure safety. Must be between 0 and 1! + contents_pressure_protection = 0 + /// How insulated the thing is, for the purposes of calculating body temperature. Must be between 0 and 1! + contents_thermal_insulation = 0 /// Whether a skittish person can dive inside this closet. Disable if opening the closet causes "bad things" to happen or that it leads to a logical inconsistency. var/divable = TRUE /// true whenever someone with the strong pull component is dragging this, preventing opening diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index 37ec4c71682..b2db4a716f0 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -27,13 +27,13 @@ QDEL_NULL(foldedbag_instance) return ..() -/obj/structure/closet/body_bag/attackby(obj/item/I, mob/user, params) - if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon)) +/obj/structure/closet/body_bag/attackby(obj/item/interact_tool, mob/user, params) + if (istype(interact_tool, /obj/item/pen) || istype(interact_tool, /obj/item/toy/crayon)) if(!user.is_literate()) to_chat(user, span_notice("You scribble illegibly on [src]!")) return var/t = stripped_input(user, "What would you like the label to be?", name, null, 53) - if(user.get_active_held_item() != I) + if(user.get_active_held_item() != interact_tool) return if(!user.canUseTopic(src, BE_CLOSE)) return @@ -44,7 +44,7 @@ else name = initial(name) return - else if(I.tool_behaviour == TOOL_WIRECUTTER) + else if((interact_tool.tool_behaviour == TOOL_WIRECUTTER) && tagged) to_chat(user, span_notice("You cut the tag off [src].")) name = "body bag" tagged = FALSE @@ -87,9 +87,10 @@ if(opened) to_chat(the_folder, span_warning("You wrestle with [src], but it won't fold while unzipped.")) return - if(contents.len) - to_chat(the_folder, span_warning("There are too many things inside of [src] to fold it up!")) - return + for(var/content_thing in contents) + if(istype(content_thing, /mob) || istype(content_thing, /obj)) + to_chat(the_folder, span_warning("There are too many things inside of [src] to fold it up!")) + return // toto we made it! return TRUE @@ -148,3 +149,198 @@ max_weight_of_contents = A_is_item.w_class B.w_class = max_weight_of_contents usr.put_in_hands(B) + +/// Environmental bags + +/obj/structure/closet/body_bag/environmental + name = "environmental protection bag" + desc = "An insulated, reinforced bag designed to protect against exoplanetary storms and other environmental factors." + icon = 'icons/obj/bodybag.dmi' + icon_state = "envirobag" + mob_storage_capacity = 1 + contents_pressure_protection = 0.8 + contents_thermal_insulation = 0.5 + foldedbag_path = /obj/item/bodybag/environmental/ + weather_protection = list(WEATHER_ACID, WEATHER_ASH, WEATHER_RAD, WEATHER_SNOW, WEATHER_VOID) // Does not protect against lava or the The Floor Is Lava spell. + +/obj/structure/closet/body_bag/environmental/nanotrasen + name = "elite environmental protection bag" + desc = "A heavily reinforced and insulated bag, capable of fully isolating its contents from external factors." + icon = 'icons/obj/bodybag.dmi' + icon_state = "ntenvirobag" + contents_pressure_protection = 1 + contents_thermal_insulation = 1 + foldedbag_path = /obj/item/bodybag/environmental/nanotrasen/ + weather_protection = list(WEATHER_ALL) + +/// Securable enviro. bags + +/obj/structure/closet/body_bag/environmental/prisoner + name = "prisoner transport bag" + desc = "Intended for transport of prisoners through hazardous environments, this environmental protection bag comes with straps to keep an occupant secure." + icon = 'icons/obj/bodybag.dmi' + icon_state = "prisonerenvirobag" + foldedbag_path = /obj/item/bodybag/environmental/prisoner/ + breakout_time = 4 MINUTES // because it's probably about as hard to get out of this as it is to get out of a straightjacket. + /// How long it takes to sinch the bag. + var/sinch_time = 10 SECONDS + /// Whether or not the bag is sinched. Starts unsinched. + var/sinched = FALSE + /// The sound that plays when the bag is done sinching. + var/sinch_sound = 'sound/items/equip/toolbelt_equip.ogg' + +/obj/structure/closet/body_bag/environmental/prisoner/attempt_fold(mob/living/carbon/human/the_folder) + if(sinched) + to_chat(the_folder, span_warning("You wrestle with [src], but it won't fold while its straps are fastened.")) + return ..() + +/obj/structure/closet/body_bag/environmental/prisoner/update_icon() + . = ..() + if(sinched) + icon_state = initial(icon_state) + "_sinched" + else + icon_state = initial(icon_state) + +/obj/structure/closet/body_bag/environmental/prisoner/can_open(mob/living/user, force = FALSE) + if(force) + return TRUE + if(sinched) + to_chat(user, span_danger("The buckles on [src] are sinched down, preventing it from opening.")) + return FALSE + . = ..() + +/obj/structure/closet/body_bag/environmental/prisoner/open(mob/living/user, force = FALSE) + if(!can_open(user, force)) + return + if(opened) + return + sinched = FALSE + playsound(loc, open_sound, open_sound_volume, TRUE, -3) + opened = TRUE + if(!dense_when_open) + set_density(FALSE) + dump_contents() + update_appearance() + after_open(user, force) + return TRUE + +/obj/structure/closet/body_bag/environmental/prisoner/container_resist_act(mob/living/user) + /// copy-pasted with changes because flavor text as well as some other misc stuff + if(opened) + return + if(ismovable(loc)) + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + var/atom/movable/location = loc + location.relay_container_resist_act(user, src) + return + if(!sinched) + open() + return + + user.changeNext_move(CLICK_CD_BREAKOUT) + user.last_special = world.time + CLICK_CD_BREAKOUT + user.visible_message(span_warning("Someone in [src] begins to wriggle!"), \ + span_notice("You start wriggling, attempting to loosen [src]'s buckles... (this will take about [DisplayTimeText(breakout_time)].)"), \ + span_hear("You hear straining cloth from [src].")) + if(do_after(user,(breakout_time), target = src)) + if(!user || user.stat != CONSCIOUS || user.loc != src || opened || !sinched ) + return + //we check after a while whether there is a point of resisting anymore and whether the user is capable of resisting + user.visible_message(span_danger("[user] successfully broke out of [src]!"), + span_notice("You successfully break out of [src]!")) + bust_open() + else + if(user.loc == src) //so we don't get the message if we resisted multiple times and succeeded. + to_chat(user, span_warning("You fail to break out of [src]!")) + + +/obj/structure/closet/body_bag/environmental/prisoner/bust_open() + sinched = FALSE + // We don't break the bag, because the buckles were backed out as opposed to fully broken. + open() + +/obj/structure/closet/body_bag/environmental/prisoner/attack_hand_secondary(mob/user, modifiers) + if(!user.canUseTopic(src, BE_CLOSE) || !isturf(loc)) + return + if(!opened) + togglelock(user) + return TRUE + +/obj/structure/closet/body_bag/environmental/prisoner/togglelock(mob/living/user, silent) + if(user in contents) + to_chat(user, span_warning("You can't reach the buckles from here!")) + return + if(iscarbon(user)) + add_fingerprint(user) + if(!sinched) + for(var/mob/living/target in contents) + to_chat(target, span_userdanger("You feel the lining of [src] tighten around you! Soon, you won't be able to escape!")) + user.visible_message(span_notice("You begin sinching down the buckles on [src].")) + if(!(do_after(user,(sinch_time),target = src))) + return + sinched = !sinched + if(sinched) + playsound(loc, sinch_sound, 15, TRUE, -2) + user.visible_message(span_notice("[user] [sinched ? null : "un"]sinches [src]."), + span_notice("You [sinched ? null : "un"]sinch [src]."), + span_hear("You hear stretching followed by metal clicking from [src].")) + log_game("[key_name(user)] [sinched ? "sinched":"unsinched"] secure environmental bag [src] at [AREACOORD(src)]") + update_appearance() + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate + name = "syndicate prisoner transport bag" + desc = "An alteration of Nanotrasen's environmental protection bag which has been used in several high-profile kidnappings. Designed to keep a victim unconscious, alive, and secured during transport." + icon = 'icons/obj/bodybag.dmi' + icon_state = "syndieenvirobag" + contents_pressure_protection = 1 + contents_thermal_insulation = 1 + foldedbag_path = /obj/item/bodybag/environmental/prisoner/syndicate + weather_protection = list(WEATHER_ALL) + breakout_time = 8 MINUTES + sinch_time = 20 SECONDS + // The contents of the gas to be distributed to an occupant once sinched down. Set in Initialize() + var/datum/gas_mixture/air_contents = null + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/Initialize() + . = ..() + refresh_air() + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/proc/refresh_air() + air_contents = null + air_contents = new(50) //liters + air_contents.temperature = T20C + + air_contents.assert_gases(/datum/gas/oxygen, /datum/gas/nitrous_oxide) + air_contents.gases[/datum/gas/oxygen][MOLES] = (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD + air_contents.gases[/datum/gas/nitrous_oxide][MOLES] = (ONE_ATMOSPHERE*50)/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/Destroy() + if(air_contents) + QDEL_NULL(air_contents) + + return ..() + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/return_air() + if(sinched) + refresh_air() + return air_contents + return ..() + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/remove_air(amount) + if(sinched) + refresh_air() + return air_contents // The internals for this bag are bottomless. Syndicate bluespace trickery. + return ..(amount) + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/return_analyzable_air() + if(sinched) + refresh_air() + return air_contents + return ..() + +/obj/structure/closet/body_bag/environmental/prisoner/syndicate/togglelock(mob/living/user, silent) + . = ..() + if(sinched) + for(var/mob/living/target in contents) + to_chat(target, span_warning("You hear a faint hiss, and a white mist fills your vision...")) diff --git a/code/game/objects/structures/crates_lockers/crates/critter.dm b/code/game/objects/structures/crates_lockers/crates/critter.dm index 39c2a726557..6c8fbae3845 100644 --- a/code/game/objects/structures/crates_lockers/crates/critter.dm +++ b/code/game/objects/structures/crates_lockers/crates/critter.dm @@ -12,6 +12,7 @@ close_sound = 'sound/machines/wooden_closet_close.ogg' open_sound_volume = 25 close_sound_volume = 50 + contents_pressure_protection = 0.8 var/obj/item/tank/internals/emergency_oxygen/tank /obj/structure/closet/crate/critter/Initialize() diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm index 4f4ef944eaf..be0859d6944 100644 --- a/code/game/turfs/open/lava.dm +++ b/code/game/turfs/open/lava.dm @@ -156,7 +156,7 @@ continue else if(isliving(buckle_check)) var/mob/living/live = buckle_check - if("lava" in live.weather_immunities) + if(WEATHER_LAVA in live.weather_immunities) continue if(iscarbon(L)) @@ -167,7 +167,7 @@ if(S && H && S.clothing_flags & LAVAPROTECT && H.clothing_flags & LAVAPROTECT) return - if("lava" in L.weather_immunities) + if(WEATHER_LAVA in L.weather_immunities) continue ADD_TRAIT(L, TRAIT_PERMANENTLY_ONFIRE,TURF_TRAIT) diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm index a26bc7c835c..f9aa22f913e 100644 --- a/code/modules/awaymissions/mission_code/snowdin.dm +++ b/code/modules/awaymissions/mission_code/snowdin.dm @@ -194,7 +194,7 @@ var/mob/living/L = thing if(L.movement_type & FLYING) continue //YOU'RE FLYING OVER IT - if("snow" in L.weather_immunities) + if(WEATHER_SNOW in L.weather_immunities) continue var/buckle_check = L.buckled @@ -205,7 +205,7 @@ else if(isliving(buckle_check)) var/mob/living/live = buckle_check - if("snow" in live.weather_immunities) + if(WEATHER_SNOW in live.weather_immunities) continue L.adjustFireLoss(2) diff --git a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm index 2cf4a2ba4b1..41114cad514 100644 --- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm +++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm @@ -48,7 +48,7 @@ //Because the leaping sprite is bigger than the normal one body_position_pixel_x_offset = -32 body_position_pixel_y_offset = -32 - LAZYADD(weather_immunities,"lava") + LAZYADD(weather_immunities, WEATHER_LAVA) update_icons() throw_at(A, MAX_ALIEN_LEAP_DIST, 1, src, FALSE, TRUE, callback = CALLBACK(src, .proc/leap_end)) @@ -56,7 +56,7 @@ leaping = FALSE body_position_pixel_x_offset = 0 body_position_pixel_y_offset = 0 - LAZYREMOVE(weather_immunities, "lava") + LAZYREMOVE(weather_immunities, WEATHER_LAVA) update_icons() /mob/living/carbon/alien/humanoid/hunter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index ae873d7f315..ab547ea4825 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -64,6 +64,10 @@ if(chest_covered && head_covered) return ONE_ATMOSPHERE + if(ismovable(loc)) + /// If we're in a space with 0.5 content pressure protection, it averages the values, for example. + var/atom/movable/occupied_space = loc + return (occupied_space.contents_pressure_protection * ONE_ATMOSPHERE + (1 - occupied_space.contents_pressure_protection) * pressure) return pressure diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index fcd4e22deee..52b7d4c93d2 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -251,11 +251,11 @@ /datum/species/golem/titanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() - LAZYOR(C.weather_immunities, "ash") + LAZYOR(C.weather_immunities, WEATHER_ASH) /datum/species/golem/titanium/on_species_loss(mob/living/carbon/C) . = ..() - LAZYREMOVE(C.weather_immunities, "ash") + LAZYREMOVE(C.weather_immunities, WEATHER_ASH) //Immune to ash storms and lava /datum/species/golem/plastitanium @@ -270,13 +270,13 @@ /datum/species/golem/plastitanium/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() - LAZYOR(C.weather_immunities, "lava") - LAZYOR(C.weather_immunities, "ash") + LAZYOR(C.weather_immunities, WEATHER_LAVA) + LAZYOR(C.weather_immunities, WEATHER_ASH) /datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C) . = ..() - LAZYREMOVE(C.weather_immunities, "ash") - LAZYREMOVE(C.weather_immunities, "lava") + LAZYREMOVE(C.weather_immunities, WEATHER_ASH) + LAZYREMOVE(C.weather_immunities, WEATHER_LAVA) //Fast and regenerates... but can only speak like an abductor /datum/species/golem/alloy @@ -1225,7 +1225,7 @@ /datum/species/golem/snow/on_species_gain(mob/living/carbon/C, datum/species/old_species) . = ..() - LAZYOR(C.weather_immunities, "snow") + LAZYOR(C.weather_immunities, WEATHER_SNOW) ball = new ball.charge_counter = 0 C.AddSpell(ball) @@ -1235,7 +1235,7 @@ /datum/species/golem/snow/on_species_loss(mob/living/carbon/C) . = ..() - LAZYREMOVE(C.weather_immunities, "snow") + LAZYREMOVE(C.weather_immunities, WEATHER_SNOW) if(ball) C.RemoveSpell(ball) if(cryo) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 970031ea0e4..2b8cbdaff36 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -98,6 +98,10 @@ var/loc_temp = get_temperature(environment) var/temp_delta = loc_temp - bodytemperature + if(ismovable(loc)) + var/atom/movable/occupied_space = loc + temp_delta *= (1 - occupied_space.contents_thermal_insulation) + if(temp_delta < 0) // it is cold here if(!on_fire) // do not reduce body temp when on fire adjust_bodytemperature(max(max(temp_delta / BODYTEMP_DIVISOR, BODYTEMP_COOLING_MAX) * delta_time, temp_delta)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 52c00e5da3f..e8dd2123864 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1086,6 +1086,9 @@ else if(isspaceturf(get_turf(src))) var/turf/heat_turf = get_turf(src) loc_temp = heat_turf.temperature + if(ismovable(loc)) + var/atom/movable/occupied_space = loc + loc_temp = ((1 - occupied_space.contents_thermal_insulation) * loc_temp) + (occupied_space.contents_thermal_insulation * bodytemperature) return loc_temp /mob/living/cancel_camera() diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm index d2bd0adfd02..f7f94eaba54 100644 --- a/code/modules/mob/living/silicon/pai/pai.dm +++ b/code/modules/mob/living/silicon/pai/pai.dm @@ -8,7 +8,7 @@ pass_flags = PASSTABLE | PASSMOB mob_size = MOB_SIZE_TINY desc = "A generic pAI mobile hard-light holographics emitter. It seems to be deactivated." - weather_immunities = list("ash") + weather_immunities = list(WEATHER_ASH) health = 500 maxHealth = 500 layer = BELOW_MOB_LAYER diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index 034fc713d46..9cc86253842 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -8,7 +8,7 @@ initial_language_holder = /datum/language_holder/synthetic see_in_dark = 8 bubble_icon = "machine" - weather_immunities = list("ash") + weather_immunities = list(WEATHER_ASH) mob_biotypes = MOB_ROBOTIC deathsound = 'sound/voice/borg_deathsound.ogg' speech_span = SPAN_ROBOT diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index 984c973dedf..d2ba20a91a2 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -82,7 +82,7 @@ icon_living = "snowbear" icon_dead = "snowbear_dead" desc = "It's a polar bear, in space, but not actually in space." - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) /mob/living/simple_animal/hostile/bear/russian name = "combat bear" diff --git a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm index 920622f3e7c..64efbcb06d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/dark_wizard.dm @@ -26,7 +26,7 @@ sentience_type = SENTIENCE_HUMANOID faction = list(ROLE_WIZARD) footstep_type = FOOTSTEP_MOB_SHOE - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA, WEATHER_ASH) minbodytemp = 0 maxbodytemp = INFINITY atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm index e7a9b874522..11979e7f0ce 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/_jungle_mobs.dm @@ -2,7 +2,7 @@ vision_range = 5 atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) faction = list("jungle") - weather_immunities = list(ACID) + weather_immunities = list(WEATHER_ACID) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm index 81f13033624..137855ff07f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/clockwork_knight.dm @@ -18,7 +18,7 @@ I'd rather there be something than the clockwork ruin be entirely empty though s attack_verb_simple = "slash" attack_sound = 'sound/weapons/bladeslice.ogg' attack_vis_effect = ATTACK_EFFECT_SLASH - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) speak_emote = list("roars") armour_penetration = 40 melee_damage_lower = 20 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm index 8fd2c8d7553..79a25687aef 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner.dm @@ -20,7 +20,7 @@ Difficulty: Extremely Hard mob_biotypes = MOB_ORGANIC|MOB_HUMANOID light_color = COLOR_LIGHT_GRAYISH_RED movement_type = GROUND - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) speak_emote = list("roars") armour_penetration = 100 melee_damage_lower = 10 diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm index 0ff91d98d06..7a3549dd3e5 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/megafauna.dm @@ -10,7 +10,7 @@ obj_damage = 400 light_range = 3 faction = list("mining", "boss") - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA,WEATHER_ASH) robust_searching = TRUE ranged_ignores_vision = TRUE stat_attack = DEAD diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm index a206ce0f857..128b2f3687f 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/swarmer.dm @@ -53,7 +53,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa crusher_achievement_type = /datum/award/achievement/boss/swarmer_beacon_crusher score_achievement_type = /datum/award/score/swarmer_beacon_score faction = list("mining", "boss", "swarmer") - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA, WEATHER_ASH) stop_automated_movement = TRUE wander = FALSE layer = BELOW_MOB_LAYER @@ -97,7 +97,7 @@ GLOBAL_LIST_INIT(AISwarmerCapsByType, list(/mob/living/simple_animal/hostile/swa /mob/living/simple_animal/hostile/swarmer/ai wander = 1 faction = list("swarmer", "mining") - weather_immunities = list("ash") //wouldn't be fun otherwise + weather_immunities = list(WEATHER_ASH) //wouldn't be fun otherwise AIStatus = AI_ON /mob/living/simple_animal/hostile/swarmer/ai/Initialize() diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm index dc58644c5d9..7255eb5cb11 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/wendigo.dm @@ -25,7 +25,7 @@ Difficulty: Hard attack_verb_simple = "claw" attack_sound = 'sound/magic/demon_attack1.ogg' attack_vis_effect = ATTACK_EFFECT_CLAW - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) speak_emote = list("roars") armour_penetration = 40 melee_damage_lower = 40 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm index fe59484cc1a..8095d654767 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/goliath_broodmother.dm @@ -257,13 +257,13 @@ if(use_time > world.time) to_chat(living_user, "The tongue looks dried out. You'll need to wait longer to use it again.") return - else if("lava" in living_user.weather_immunities) + else if(WEATHER_LAVA in living_user.weather_immunities) to_chat(living_user, "You stare at the tongue. You don't think this is any use to you.") return - LAZYOR(living_user.weather_immunities, "lava") + LAZYOR(living_user.weather_immunities, WEATHER_LAVA) to_chat(living_user, "You squeeze the tongue, and some transluscent liquid shoots out all over you.") addtimer(CALLBACK(src, .proc/remove_lavaproofing, living_user), 10 SECONDS) use_time = world.time + 60 SECONDS /obj/item/crusher_trophy/broodmother_tongue/proc/remove_lavaproofing(mob/living/user) - LAZYREMOVE(user.weather_immunities, "lava") + LAZYREMOVE(user.weather_immunities, WEATHER_LAVA) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm index 909f63790bc..444c8820aa7 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/gutlunch.dm @@ -10,7 +10,7 @@ speak_emote = list("warbles", "quavers") emote_hear = list("trills.") emote_see = list("sniffs.", "burps.") - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA, WEATHER_ASH) faction = list("mining", "ashwalker") density = FALSE speak_chance = 1 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm index 33288aef981..669bcef76d3 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/hivelord.dm @@ -264,7 +264,7 @@ aggro_vision_range = 9 speed = 3 faction = list("mining") - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA, WEATHER_ASH) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_STRUCTURES see_in_dark = 8 diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobstrosity.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobstrosity.dm index 7a25e3f6df3..3de8dbb6a06 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobstrosity.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/lobstrosity.dm @@ -25,7 +25,7 @@ attack_verb_simple = "snip" attack_sound = 'sound/weapons/bite.ogg' attack_vis_effect = ATTACK_EFFECT_BITE //the closest we have to a crustacean pinching attack effect rn. - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) vision_range = 5 aggro_vision_range = 7 charger = TRUE diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm index 59f1553ac03..eb2b1f1ed08 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/mining_mobs.dm @@ -3,7 +3,7 @@ vision_range = 2 atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) faction = list("mining") - weather_immunities = list("lava","ash") + weather_immunities = list(WEATHER_LAVA,WEATHER_ASH) obj_damage = 30 environment_smash = ENVIRONMENT_SMASH_WALLS minbodytemp = 0 diff --git a/code/modules/mob/living/simple_animal/hostile/skeleton.dm b/code/modules/mob/living/simple_animal/hostile/skeleton.dm index b58a0832344..b65dfd3eaab 100644 --- a/code/modules/mob/living/simple_animal/hostile/skeleton.dm +++ b/code/modules/mob/living/simple_animal/hostile/skeleton.dm @@ -45,7 +45,7 @@ icon_dead = "eskimo_dead" maxHealth = 55 health = 55 - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) melee_damage_lower = 17 melee_damage_upper = 20 deathmessage = "collapses into a pile of bones, its gear falling to the floor!" @@ -63,7 +63,7 @@ icon_dead = "templar_dead" maxHealth = 150 health = 150 - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) speed = 2 speak_chance = 1 speak = list("THE GODS WILL IT!","DEUS VULT!","REMOVE KABAB!") @@ -83,7 +83,7 @@ speed = 5 maxHealth = 75 health = 75 - weather_immunities = list("snow") + weather_immunities = list(WEATHER_SNOW) color = rgb(114,228,250) loot = list(/obj/effect/decal/remains/human{color = rgb(114,228,250)}) diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index b3430040483..34416d6f737 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -694,6 +694,8 @@ new /obj/item/pickaxe/emergency(src) new /obj/item/survivalcapsule(src) new /obj/item/storage/toolbox/emergency(src) + new /obj/item/bodybag/environmental(src) + new /obj/item/bodybag/environmental(src) /obj/item/storage/pod/attackby(obj/item/W, mob/user, params) if (can_interact(user)) diff --git a/icons/obj/bodybag.dmi b/icons/obj/bodybag.dmi index 7fcc193ad69..f3af89a5af8 100644 Binary files a/icons/obj/bodybag.dmi and b/icons/obj/bodybag.dmi differ