diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm
index 111aba254f6..786f29cbf14 100644
--- a/code/__DEFINES/combat.dm
+++ b/code/__DEFINES/combat.dm
@@ -42,16 +42,6 @@
/// 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/__DEFINES/maps.dm b/code/__DEFINES/maps.dm
index 300133badba..5aa38a6efbb 100644
--- a/code/__DEFINES/maps.dm
+++ b/code/__DEFINES/maps.dm
@@ -43,7 +43,6 @@ require only minor tweaks.
// boolean - weather types that occur on the level
#define ZTRAIT_SNOWSTORM "Weather_Snowstorm"
#define ZTRAIT_ASHSTORM "Weather_Ashstorm"
-#define ZTRAIT_ACIDRAIN "Weather_Acidrain"
#define ZTRAIT_VOIDSTORM "Weather_Voidstorm"
// number - bombcap is multiplied by this before being applied to bombs
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 3b13dc83399..e41c5a998d4 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -401,6 +401,14 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Disables the floating animation. See above.
#define TRAIT_NO_FLOATING_ANIM "no-floating-animation"
+/// Weather immunities, also protect mobs inside them.
+#define TRAIT_LAVA_IMMUNE "lava_immune" //Used by lava turfs and The Floor Is Lava.
+#define TRAIT_ASHSTORM_IMMUNE "ashstorm_immune"
+#define TRAIT_SNOWSTORM_IMMUNE "snowstorm_immune"
+#define TRAIT_RADSTORM_IMMUNE "radstorm_immune"
+#define TRAIT_VOIDSTORM_IMMUNE "voidstorm_immune"
+#define TRAIT_WEATHER_IMMUNE "weather_immune" //Immune to ALL weather effects.
+
//non-mob traits
/// Used for limb-based paralysis, where replacing the limb will fix it.
#define TRAIT_PARALYSIS "paralysis"
@@ -637,6 +645,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define SPECIES_FLIGHT_TRAIT "species-flight"
#define FROSTMINER_ENRAGE_TRAIT "frostminer-enrage"
#define NO_GRAVITY_TRAIT "no-gravity"
+#define LEAPING_TRAIT "leaping"
#define LEAPER_BUBBLE_TRAIT "leaper-bubble"
/// sticky nodrop sounds like a bad soundcloud rapper's name
#define STICKY_NODROP "sticky-nodrop"
diff --git a/code/_globalvars/traits.dm b/code/_globalvars/traits.dm
index c842effb3f9..e4cc39823d9 100644
--- a/code/_globalvars/traits.dm
+++ b/code/_globalvars/traits.dm
@@ -185,7 +185,12 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_MOVE_FLYING" = TRAIT_MOVE_FLYING,
"TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING,
"TRAIT_MOVE_FLOATING" = TRAIT_MOVE_FLOATING,
- "TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING
+ "TRAIT_MOVE_PHASING" = TRAIT_MOVE_PHASING,
+ "TRAIT_LAVA_IMMUNE" = TRAIT_LAVA_IMMUNE,
+ "TRAIT_ASHSTORM_IMMUNE" = TRAIT_ASHSTORM_IMMUNE,
+ "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE,
+ "TRAIT_VOIDSTORM_IMMUNE" = TRAIT_VOIDSTORM_IMMUNE,
+ "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE,
),
/obj/item/card/id = list(
"TRAIT_MAGNETIC_ID_CARD" = TRAIT_MAGNETIC_ID_CARD,
diff --git a/code/datums/weather/weather.dm b/code/datums/weather/weather.dm
index 4562ef12b43..cda2c81a789 100644
--- a/code/datums/weather/weather.dm
+++ b/code/datums/weather/weather.dm
@@ -62,8 +62,8 @@
var/overlay_plane = BLACKNESS_PLANE
/// 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 = WEATHER_STORM
+ /// Used by mobs (or movables containing mobs, such as enviro bags) to prevent them from being affected by the weather.
+ var/immunity_type
/// The stage of the weather, from 1-4
var/stage = END_STAGE
@@ -198,15 +198,15 @@
if(!(mob_turf.z in impacted_z_levels))
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))
+ if((immunity_type && HAS_TRAIT(mob_to_check, immunity_type)) || HAS_TRAIT(mob_to_check, TRAIT_WEATHER_IMMUNE))
return
+ var/atom/loc_to_check = mob_to_check.loc
+ while(loc_to_check != mob_turf)
+ if((immunity_type && HAS_TRAIT(loc_to_check, immunity_type)) || HAS_TRAIT(loc_to_check, TRAIT_WEATHER_IMMUNE))
+ return
+ loc_to_check = loc_to_check.loc
+
if(!(get_area(mob_to_check) in impacted_areas))
return
diff --git a/code/datums/weather/weather_types/ash_storm.dm b/code/datums/weather/weather_types/ash_storm.dm
index cc70b0ed6c3..0350ed5ab29 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 = WEATHER_ASH
+ immunity_type = TRAIT_ASHSTORM_IMMUNE
probability = 90
@@ -61,32 +61,16 @@
GLOB.ash_storm_sounds -= weak_sounds
return ..()
-/datum/weather/ash_storm/proc/is_ash_immune(atom/L)
- while (L && !isturf(L))
- if(ismecha(L)) //Mechs are immune
- return TRUE
- if(ishuman(L)) //Are you immune?
- var/mob/living/carbon/human/H = L
- var/thermal_protection = H.get_thermal_protection()
- if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
- 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((WEATHER_ASH in the_mob.weather_immunities) || (WEATHER_ALL in the_mob.weather_immunities))
- return TRUE
- if(istype(L, /obj/structure/closet))
- var/obj/structure/closet/the_locker = L
- if(the_locker.weather_protection)
- if((WEATHER_ASH in the_locker.weather_protection) || (WEATHER_ALL in the_locker.weather_protection))
- return TRUE
- L = L.loc //Check parent items immunities (recurses up to the turf)
- return FALSE //RIP you
-
-/datum/weather/ash_storm/weather_act(mob/living/L)
- if(is_ash_immune(L))
+/datum/weather/ash_storm/can_weather_act(mob/living/mob_to_check)
+ . = ..()
+ if(!. || !ishuman(mob_to_check))
return
- L.adjustFireLoss(4)
+ var/mob/living/carbon/human/human_to_check = mob_to_check
+ if(human_to_check.get_thermal_protection() >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
+ return FALSE
+/datum/weather/ash_storm/weather_act(mob/living/victim)
+ victim.adjustFireLoss(4)
//Emberfalls are the result of an ash storm passing by close to the playable area of lavaland. They have a 10% chance to trigger in place of an ash storm.
/datum/weather/ash_storm/emberfall
diff --git a/code/datums/weather/weather_types/floor_is_lava.dm b/code/datums/weather/weather_types/floor_is_lava.dm
index bff7e0b825c..1ee58c68fa6 100644
--- a/code/datums/weather/weather_types/floor_is_lava.dm
+++ b/code/datums/weather/weather_types/floor_is_lava.dm
@@ -20,21 +20,23 @@
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
overlay_plane = FLOOR_PLANE
- immunity_type = WEATHER_LAVA
+ immunity_type = TRAIT_LAVA_IMMUNE
-/datum/weather/floor_is_lava/weather_act(mob/living/L)
- if(issilicon(L))
- return
- if(istype(L.buckled, /obj/structure/bed))
- return
- 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
- if(L.movement_type & FLYING)
- return
- L.adjustFireLoss(3)
+/datum/weather/floor_is_lava/can_weather_act(mob/living/mob_to_check)
+ if(!mob_to_check.client) //Only sentient people are going along with it!
+ return FALSE
+ . = ..()
+ if(!. || issilicon(mob_to_check) || istype(mob_to_check.buckled, /obj/structure/bed))
+ return FALSE
+ var/turf/mob_turf = get_turf(mob_to_check)
+ if(mob_turf.density) //Walls are not floors.
+ return FALSE
+ for(var/obj/structure/structure_to_check in mob_turf)
+ if(structure_to_check.density)
+ return FALSE
+ if(mob_to_check.movement_type & FLYING)
+ return FALSE
+
+/datum/weather/floor_is_lava/weather_act(mob/living/victim)
+ victim.adjustFireLoss(3)
diff --git a/code/datums/weather/weather_types/radiation_storm.dm b/code/datums/weather/weather_types/radiation_storm.dm
index bdb2f068012..544bb00fcb1 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 = WEATHER_RAD
+ immunity_type = TRAIT_RADSTORM_IMMUNE
/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 fab359df18b..db18fc5c9e2 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 = WEATHER_SNOW
+ immunity_type = TRAIT_SNOWSTORM_IMMUNE
barometer_predictable = TRUE
diff --git a/code/datums/weather/weather_types/void_storm.dm b/code/datums/weather/weather_types/void_storm.dm
index a502d992054..c990619ed43 100644
--- a/code/datums/weather/weather_types/void_storm.dm
+++ b/code/datums/weather/weather_types/void_storm.dm
@@ -18,16 +18,20 @@
protect_indoors = FALSE
target_trait = ZTRAIT_VOIDSTORM
- immunity_type = WEATHER_VOID
+ immunity_type = TRAIT_VOIDSTORM_IMMUNE
barometer_predictable = FALSE
perpetual = TRUE
-/datum/weather/void_storm/weather_act(mob/living/L)
- if(IS_HERETIC(L) || IS_HERETIC_MONSTER(L))
- return
- L.adjustOxyLoss(rand(1,3))
- L.adjustFireLoss(rand(1,3))
- L.adjust_blurriness(rand(0,1))
- L.adjust_bodytemperature(-rand(5,15))
+
+/datum/weather/void_storm/can_weather_act(mob/living/mob_to_check)
+ . = ..()
+ if(IS_HERETIC(mob_to_check) || IS_HERETIC_MONSTER(mob_to_check))
+ return FALSE
+
+/datum/weather/void_storm/weather_act(mob/living/victim)
+ victim.adjustOxyLoss(rand(1,3))
+ victim.adjustFireLoss(rand(1,3))
+ victim.adjust_blurriness(rand(0,1))
+ victim.adjust_bodytemperature(-rand(5,15))
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index aa1472d7d75..da086bf2bc4 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -297,12 +297,12 @@
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr)
. = ..()
if(.)
- LAZYADD(R.weather_immunities, WEATHER_LAVA)
+ ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, type)
/obj/item/borg/upgrade/lavaproof/deactivate(mob/living/silicon/robot/R, user = usr)
. = ..()
if (.)
- LAZYREMOVE(R.weather_immunities, WEATHER_LAVA)
+ REMOVE_TRAIT(src, TRAIT_LAVA_IMMUNE, type)
/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 c7e55981e69..8852dce4866 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -44,8 +44,6 @@
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!
diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
index f865ef46886..5275d2b8d3a 100644
--- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm
+++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm
@@ -150,7 +150,7 @@
B.w_class = max_weight_of_contents
usr.put_in_hands(B)
-/// Environmental bags
+/// Environmental bags. They protect against bad weather.
/obj/structure/closet/body_bag/environmental
name = "environmental protection bag"
@@ -161,7 +161,12 @@
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.
+ var/list/weather_protection = list(TRAIT_ASHSTORM_IMMUNE, TRAIT_RADSTORM_IMMUNE, TRAIT_SNOWSTORM_IMMUNE, TRAIT_VOIDSTORM_IMMUNE) // Does not protect against lava or the The Floor Is Lava spell.
+
+/obj/structure/closet/body_bag/environmental/Initialize()
+ . = ..()
+ for(var/trait in weather_protection)
+ ADD_TRAIT(src, trait, ROUNDSTART_TRAIT)
/obj/structure/closet/body_bag/environmental/nanotrasen
name = "elite environmental protection bag"
@@ -171,7 +176,7 @@
contents_pressure_protection = 1
contents_thermal_insulation = 1
foldedbag_path = /obj/item/bodybag/environmental/nanotrasen/
- weather_protection = list(WEATHER_ALL)
+ weather_protection = list(TRAIT_WEATHER_IMMUNE)
/// Securable enviro. bags
@@ -298,7 +303,7 @@
contents_pressure_protection = 1
contents_thermal_insulation = 1
foldedbag_path = /obj/item/bodybag/environmental/prisoner/syndicate
- weather_protection = list(WEATHER_ALL)
+ weather_protection = list(TRAIT_WEATHER_IMMUNE)
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()
diff --git a/code/game/turfs/open/lava.dm b/code/game/turfs/open/lava.dm
index 5ab11d40bbb..b5c8e04a5d4 100644
--- a/code/game/turfs/open/lava.dm
+++ b/code/game/turfs/open/lava.dm
@@ -22,6 +22,10 @@
var/lava_firestacks = 20
/// How much temperature we expose objects with
var/temperature_damage = 10000
+ /// mobs with this trait won't burn.
+ var/immunity_trait = TRAIT_LAVA_IMMUNE
+ /// objects with these flags won't burn.
+ var/immunity_resistance_flags = LAVA_PROOF
/turf/open/lava/ex_act(severity, target)
contents_explosion(severity, target)
@@ -121,68 +125,99 @@
LAZYREMOVE(found_safeties, S)
return LAZYLEN(found_safeties)
+///Generic return value of the can_burn_stuff() proc. Does nothing.
+#define LAVA_BE_IGNORING 0
+/// Another. Won't burn the target but will make the turf start processing.
+#define LAVA_BE_PROCESSING 1
+/// Burns the target and makes the turf process (depending on the return value of do_burn()).
+#define LAVA_BE_BURNING 2
-/turf/open/lava/proc/burn_stuff(AM, delta_time = 1)
- . = 0
-
+///Proc that sets on fire something or everything on the turf that's not immune to lava. Returns TRUE to make the turf start processing.
+/turf/open/lava/proc/burn_stuff(atom/movable/to_burn, delta_time = 1)
if(is_safe())
return FALSE
var/thing_to_check = src
- if (AM)
- thing_to_check = list(AM)
- for(var/thing in thing_to_check)
- if(isobj(thing))
- var/obj/O = thing
- if((O.resistance_flags & (LAVA_PROOF|INDESTRUCTIBLE)) || O.throwing)
+ if (to_burn)
+ thing_to_check = list(to_burn)
+ for(var/atom/movable/burn_target as anything in thing_to_check)
+ switch(can_burn_stuff(burn_target))
+ if(LAVA_BE_IGNORING)
continue
- . = 1
- if((O.resistance_flags & (ON_FIRE)))
- continue
- if(!(O.resistance_flags & FLAMMABLE))
- O.resistance_flags |= FLAMMABLE //Even fireproof things burn up in lava
- if(O.resistance_flags & FIRE_PROOF)
- O.resistance_flags &= ~FIRE_PROOF
- if(O.armor.fire > 50) //obj with 100% fire armor still get slowly burned away.
- O.armor = O.armor.setRating(fire = 50)
- O.fire_act(temperature_damage, 1000 * delta_time)
- if(istype(O, /obj/structure/closet))
- var/obj/structure/closet/C = O
- for(var/I in C.contents)
- burn_stuff(I)
- else if (isliving(thing))
- . = 1
- var/mob/living/L = thing
- if(L.movement_type & FLYING)
- continue //YOU'RE FLYING OVER IT
- var/buckle_check = L.buckled
- if(isobj(buckle_check))
- var/obj/O = buckle_check
- if(O.resistance_flags & LAVA_PROOF)
- continue
- else if(isliving(buckle_check))
- var/mob/living/live = buckle_check
- if(WEATHER_LAVA in live.weather_immunities)
+ if(LAVA_BE_BURNING)
+ if(!do_burn(burn_target, delta_time))
continue
+ . = TRUE
- if(iscarbon(L))
- var/mob/living/carbon/C = L
- var/obj/item/clothing/S = C.get_item_by_slot(ITEM_SLOT_OCLOTHING)
- var/obj/item/clothing/H = C.get_item_by_slot(ITEM_SLOT_HEAD)
+/turf/open/lava/proc/can_burn_stuff(atom/movable/burn_target)
+ if(burn_target.movement_type & (FLYING|FLOATING)) //you're flying over it.
+ return isliving(burn_target) ? LAVA_BE_PROCESSING : LAVA_BE_IGNORING
- if(S && H && S.clothing_flags & LAVAPROTECT && H.clothing_flags & LAVAPROTECT)
- return
+ if(isobj(burn_target))
+ if(burn_target.throwing) // to avoid gulag prisoners easily escaping, throwing only works for objects.
+ return LAVA_BE_IGNORING
+ var/obj/burn_obj = burn_target
+ if((burn_obj.resistance_flags & immunity_resistance_flags))
+ return LAVA_BE_PROCESSING
+ return LAVA_BE_BURNING
- if(WEATHER_LAVA in L.weather_immunities)
- continue
+ if (!isliving(burn_target))
+ return LAVA_BE_IGNORING
- ADD_TRAIT(L, TRAIT_PERMANENTLY_ONFIRE,TURF_TRAIT)
- L.update_fire()
+ if(HAS_TRAIT(burn_target, immunity_trait))
+ return LAVA_BE_PROCESSING
+ var/mob/living/burn_living = burn_target
+ var/atom/movable/burn_buckled = burn_living.buckled
+ if(burn_buckled)
+ if(burn_buckled.movement_type & (FLYING|FLOATING))
+ return LAVA_BE_PROCESSING
+ if(isobj(burn_buckled))
+ var/obj/burn_buckled_obj = burn_buckled
+ if(burn_buckled_obj.resistance_flags & immunity_resistance_flags)
+ return LAVA_BE_PROCESSING
+ else if(HAS_TRAIT(burn_buckled, immunity_trait))
+ return LAVA_BE_PROCESSING
- L.adjustFireLoss(lava_damage * delta_time)
- if(L) //mobs turning into object corpses could get deleted here.
- L.adjust_fire_stacks(lava_firestacks * delta_time)
- L.IgniteMob()
+ if(iscarbon(burn_living))
+ var/mob/living/carbon/burn_carbon = burn_living
+ var/obj/item/clothing/burn_suit = burn_carbon.get_item_by_slot(ITEM_SLOT_OCLOTHING)
+ var/obj/item/clothing/burn_helmet = burn_carbon.get_item_by_slot(ITEM_SLOT_HEAD)
+ if(burn_suit?.clothing_flags & LAVAPROTECT && burn_helmet?.clothing_flags & LAVAPROTECT)
+ return LAVA_BE_PROCESSING
+
+ return LAVA_BE_BURNING
+
+#undef LAVA_BE_IGNORING
+#undef LAVA_BE_PROCESSING
+#undef LAVA_BE_BURNING
+
+/turf/open/lava/proc/do_burn(atom/movable/burn_target, delta_time = 1)
+ . = TRUE
+ if(isobj(burn_target))
+ var/obj/burn_obj = burn_target
+ if(burn_obj.resistance_flags & ON_FIRE) // already on fire; skip it.
+ return
+ if(!(burn_obj.resistance_flags & FLAMMABLE))
+ burn_obj.resistance_flags |= FLAMMABLE //Even fireproof things burn up in lava
+ if(burn_obj.resistance_flags & FIRE_PROOF)
+ burn_obj.resistance_flags &= ~FIRE_PROOF
+ if(burn_obj.armor.fire > 50) //obj with 100% fire armor still get slowly burned away.
+ burn_obj.armor = burn_obj.armor.setRating(fire = 50)
+ burn_obj.fire_act(temperature_damage, 1000 * delta_time)
+ if(istype(burn_obj, /obj/structure/closet))
+ var/obj/structure/closet/burn_closet = burn_obj
+ for(var/burn_content in burn_closet.contents)
+ burn_stuff(burn_content)
+ return
+
+ var/mob/living/burn_living = burn_target
+ ADD_TRAIT(burn_living, TRAIT_PERMANENTLY_ONFIRE, TURF_TRAIT)
+ burn_living.update_fire()
+
+ burn_living.adjustFireLoss(lava_damage * delta_time)
+ if(!QDELETED(burn_living)) //mobs turning into object corpses could get deleted here.
+ burn_living.adjust_fire_stacks(lava_firestacks * delta_time)
+ burn_living.IgniteMob()
/turf/open/lava/smooth
name = "lava"
diff --git a/code/modules/awaymissions/mission_code/snowdin.dm b/code/modules/awaymissions/mission_code/snowdin.dm
index d6b2d9fb163..5050a833f00 100644
--- a/code/modules/awaymissions/mission_code/snowdin.dm
+++ b/code/modules/awaymissions/mission_code/snowdin.dm
@@ -164,11 +164,12 @@
icon_state = "liquidplasma"
initial_gas_mix = "n2=82;plasma=24;TEMP=120"
baseturfs = /turf/open/lava/plasma
- slowdown = 2
light_range = 3
light_power = 0.75
light_color = LIGHT_COLOR_PURPLE
+ immunity_trait = TRAIT_SNOWSTORM_IMMUNE
+ immunity_resistance_flags = FREEZE_PROOF
/turf/open/lava/plasma/attackby(obj/item/I, mob/user, params)
var/obj/item/reagent_containers/glass/C = I
@@ -178,74 +179,46 @@
C.reagents.add_reagent(/datum/reagent/toxin/plasma, rand(5, 10))
user.visible_message(span_notice("[user] scoops some plasma from the [src] with \the [C]."), span_notice("You scoop out some plasma from the [src] using \the [C]."))
-/turf/open/lava/plasma/burn_stuff(AM)
- . = 0
+/turf/open/lava/plasma/do_burn(atom/movable/burn_target, delta_time = 1)
+ . = TRUE
+ if(isobj(burn_target))
+ return FALSE // Does nothing against objects. Old code.
- if(is_safe())
- return FALSE
+ var/mob/living/burn_living = burn_target
+ burn_living.adjustFireLoss(2)
+ if(QDELETED(burn_living))
+ return
+ burn_living.adjust_fire_stacks(20) //dipping into a stream of plasma would probably make you more flammable than usual
+ burn_living.adjust_bodytemperature(-rand(50,65)) //its cold, man
+ if(!ishuman(burn_living) || DT_PROB(65, delta_time))
+ return
+ var/mob/living/carbon/human/burn_human = burn_living
+ var/datum/species/burn_species = burn_human.dna.species
+ if(istype(burn_species, /datum/species/plasmaman) || istype(burn_species, /datum/species/android) || istype(burn_species, /datum/species/synth)) //ignore plasmamen/robotic species
+ return
- var/thing_to_check = src
- if (AM)
- thing_to_check = list(AM)
- for(var/thing in thing_to_check)
- if(isobj(thing))
- var/obj/O = thing
- if((O.resistance_flags & (FREEZE_PROOF)) || O.throwing)
- continue
+ var/list/plasma_parts = list()//a list of the organic parts to be turned into plasma limbs
+ var/list/robo_parts = list()//keep a reference of robotic parts so we know if we can turn them into a plasmaman
+ for(var/obj/item/bodypart/burn_limb as anything in burn_human.bodyparts)
+ if(burn_limb.status == BODYPART_ORGANIC && burn_limb.species_id != SPECIES_PLASMAMAN) //getting every organic, non-plasmaman limb (augments/androids are immune to this)
+ plasma_parts += burn_limb
+ if(burn_limb.status == BODYPART_ROBOTIC)
+ robo_parts += burn_limb
- else if (isliving(thing))
- . = 1
- var/mob/living/L = thing
- if(L.movement_type & FLYING)
- continue //YOU'RE FLYING OVER IT
- if(WEATHER_SNOW in L.weather_immunities)
- continue
-
- var/buckle_check = L.buckled
- if(isobj(buckle_check))
- var/obj/O = buckle_check
- if(O.resistance_flags & FREEZE_PROOF)
- continue
-
- else if(isliving(buckle_check))
- var/mob/living/live = buckle_check
- if(WEATHER_SNOW in live.weather_immunities)
- continue
-
- L.adjustFireLoss(2)
- if(L)
- L.adjust_fire_stacks(20) //dipping into a stream of plasma would probably make you more flammable than usual
- L.adjust_bodytemperature(-rand(50,65)) //its cold, man
- if(ishuman(L))//are they a carbon?
- var/list/plasma_parts = list()//a list of the organic parts to be turned into plasma limbs
- var/list/robo_parts = list()//keep a reference of robotic parts so we know if we can turn them into a plasmaman
- var/mob/living/carbon/human/PP = L
- var/S = PP.dna.species
- if(istype(S, /datum/species/plasmaman) || istype(S, /datum/species/android) || istype(S, /datum/species/synth)) //ignore plasmamen/robotic species
- continue
-
- for(var/BP in PP.bodyparts)
- var/obj/item/bodypart/NN = BP
- if(NN.status == BODYPART_ORGANIC && NN.species_id != SPECIES_PLASMAMAN) //getting every organic, non-plasmaman limb (augments/androids are immune to this)
- plasma_parts += NN
- if(NN.status == BODYPART_ROBOTIC)
- robo_parts += NN
-
- if(prob(35)) //checking if the delay is over & if the victim actually has any parts to nom
- PP.adjustToxLoss(15)
- PP.adjustFireLoss(25)
- if(plasma_parts.len)
- var/obj/item/bodypart/NB = pick(plasma_parts) //using the above-mentioned list to get a choice of limbs
- PP.emote("scream")
- ADD_TRAIT(NB, TRAIT_PLASMABURNT, src)
- PP.update_body_parts()
- PP.visible_message(span_warning("[L] screams in pain as [L.p_their()] [NB] melts down to the bone!"), \
- span_userdanger("You scream out in pain as your [NB] melts down to the bone, leaving an eerie plasma-like glow where flesh used to be!"))
- if(!plasma_parts.len && !robo_parts.len) //a person with no potential organic limbs left AND no robotic limbs, time to turn them into a plasmaman
- PP.IgniteMob()
- PP.set_species(/datum/species/plasmaman)
- PP.visible_message(span_warning("[L] bursts into a brilliant purple flame as [L.p_their()] entire body is that of a skeleton!"), \
- span_userdanger("Your senses numb as all of your remaining flesh is turned into a purple slurry, sloshing off your body and leaving only your bones to show in a vibrant purple!"))
+ burn_human.adjustToxLoss(15)
+ burn_human.adjustFireLoss(25)
+ if(plasma_parts.len)
+ var/obj/item/bodypart/burn_limb = pick(plasma_parts) //using the above-mentioned list to get a choice of limbs
+ burn_human.emote("scream")
+ ADD_TRAIT(burn_limb, TRAIT_PLASMABURNT, src)
+ burn_human.update_body_parts()
+ burn_human.visible_message(span_warning("[burn_human] screams in pain as [burn_human.p_their()] [burn_limb] melts down to the bone!"), \
+ span_userdanger("You scream out in pain as your [burn_limb] melts down to the bone, leaving an eerie plasma-like glow where flesh used to be!"))
+ if(!plasma_parts.len && !robo_parts.len) //a person with no potential organic limbs left AND no robotic limbs, time to turn them into a plasmaman
+ burn_human.IgniteMob()
+ burn_human.set_species(/datum/species/plasmaman)
+ burn_human.visible_message(span_warning("[burn_human] bursts into a brilliant purple flame as [burn_human.p_their()] entire body is that of a skeleton!"), \
+ span_userdanger("Your senses numb as all of your remaining flesh is turned into a purple slurry, sloshing off your body and leaving only your bones to show in a vibrant purple!"))
//mafia specific tame happy plasma (normal atmos, no slowdown)
/turf/open/lava/plasma/mafia
diff --git a/code/modules/clothing/shoes/jumpboots.dm b/code/modules/clothing/shoes/jumpboots.dm
index 2b8036be4e9..8c4180b7a68 100644
--- a/code/modules/clothing/shoes/jumpboots.dm
+++ b/code/modules/clothing/shoes/jumpboots.dm
@@ -23,7 +23,8 @@
var/atom/target = get_edge_target_turf(user, user.dir) //gets the user's direction
- if (user.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE))
+ ADD_TRAIT(user, TRAIT_MOVE_FLOATING, LEAPING_TRAIT) //Throwing itself doesn't protect mobs against lava (because gulag).
+ if (user.throw_at(target, jumpdistance, jumpspeed, spin = FALSE, diagonals_first = TRUE, callback = TRAIT_CALLBACK_REMOVE(user, TRAIT_MOVE_FLOATING, LEAPING_TRAIT)))
playsound(src, 'sound/effects/stealthoff.ogg', 50, TRUE, TRUE)
user.visible_message(span_warning("[usr] dashes forward into the air!"))
recharging_time = world.time + recharging_rate
diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm
index 33b5f73df04..0599b31d412 100644
--- a/code/modules/mining/lavaland/megafauna_loot.dm
+++ b/code/modules/mining/lavaland/megafauna_loot.dm
@@ -723,7 +723,7 @@
user.mind.AddSpell(dragon_shapeshift)
if(4)
to_chat(user, span_danger("You feel like you could walk straight through lava now."))
- LAZYOR(consumer.weather_immunities, WEATHER_LAVA)
+ ADD_TRAIT(user, TRAIT_LAVA_IMMUNE, type)
playsound(user,'sound/items/drink.ogg', 30, TRUE)
qdel(src)
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 41114cad514..df117dd7b56 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/caste/hunter.dm
@@ -48,15 +48,15 @@
//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, WEATHER_LAVA)
update_icons()
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, LEAPING_TRAIT) //Throwing itself doesn't protect mobs against lava (because gulag).
throw_at(A, MAX_ALIEN_LEAP_DIST, 1, src, FALSE, TRUE, callback = CALLBACK(src, .proc/leap_end))
/mob/living/carbon/alien/humanoid/hunter/proc/leap_end()
leaping = FALSE
body_position_pixel_x_offset = 0
body_position_pixel_y_offset = 0
- LAZYREMOVE(weather_immunities, WEATHER_LAVA)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, LEAPING_TRAIT)
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/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm
index 427d076b2a5..def3a390503 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, WEATHER_ASH)
+ ADD_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
/datum/species/golem/titanium/on_species_loss(mob/living/carbon/C)
. = ..()
- LAZYREMOVE(C.weather_immunities, WEATHER_ASH)
+ REMOVE_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
//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, WEATHER_LAVA)
- LAZYOR(C.weather_immunities, WEATHER_ASH)
+ ADD_TRAIT(C, TRAIT_LAVA_IMMUNE, SPECIES_TRAIT)
+ ADD_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
/datum/species/golem/plastitanium/on_species_loss(mob/living/carbon/C)
. = ..()
- LAZYREMOVE(C.weather_immunities, WEATHER_ASH)
- LAZYREMOVE(C.weather_immunities, WEATHER_LAVA)
+ REMOVE_TRAIT(C, TRAIT_LAVA_IMMUNE, SPECIES_TRAIT)
+ REMOVE_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
//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, WEATHER_SNOW)
+ ADD_TRAIT(C, TRAIT_SNOWSTORM_IMMUNE, SPECIES_TRAIT)
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, WEATHER_SNOW)
+ REMOVE_TRAIT(C, TRAIT_SNOWSTORM_IMMUNE, SPECIES_TRAIT)
if(ball)
C.RemoveSpell(ball)
if(cryo)
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 3e3a8282d25..09dd56ea7f8 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -114,8 +114,6 @@
var/list/guaranteed_butcher_results = null ///these will always be yielded from butchering
var/butcher_difficulty = 0 ///effectiveness prob. is modified negatively by this amount; positive numbers make it more difficult, negative ones make it easier
- var/list/weather_immunities
-
var/stun_absorption = null ///converted to a list of stun absorption sources this mob has when one is added
var/blood_volume = 0 ///how much blood the mob has
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index f7f94eaba54..7fcb85d1f13 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -8,7 +8,6 @@
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(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 d8b3a1c3369..1e779abb539 100644
--- a/code/modules/mob/living/silicon/silicon.dm
+++ b/code/modules/mob/living/silicon/silicon.dm
@@ -8,7 +8,6 @@
initial_language_holder = /datum/language_holder/synthetic
see_in_dark = 8
bubble_icon = "machine"
- weather_immunities = list(WEATHER_ASH)
mob_biotypes = MOB_ROBOTIC
deathsound = 'sound/voice/borg_deathsound.ogg'
speech_span = SPAN_ROBOT
@@ -59,7 +58,8 @@
add_sensors()
ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
ADD_TRAIT(src, TRAIT_MARTIAL_ARTS_IMMUNE, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, SPECIES_TRAIT)
+ ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, ROUNDSTART_TRAIT)
+ ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT)
/mob/living/silicon/Destroy()
QDEL_NULL(radio)
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index e75721e3d5b..77c55e9d805 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
/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 8807b9474c1..0a4146bc7e0 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(WEATHER_LAVA, WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE)
minbodytemp = 0
maxbodytemp = INFINITY
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 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 8e2873ba7a5..1d62fd3128f 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,6 @@
vision_range = 5
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("jungle")
- 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/_megafauna.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/_megafauna.dm
index 79d0a1723ab..5be6b430719 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(WEATHER_LAVA,WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE,TRAIT_ASHSTORM_IMMUNE)
robust_searching = TRUE
ranged_ignores_vision = TRUE
stat_attack = DEAD
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 137855ff07f..daefcdfe338 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
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 2781c932cad..47ebe24b878 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
speak_emote = list("roars")
armour_penetration = 100
melee_damage_lower = 10
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 bf7d46a7789..ee78d5a7fb9 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(WEATHER_LAVA, WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE)
stop_automated_movement = TRUE
wander = FALSE
layer = BELOW_MOB_LAYER
@@ -107,7 +107,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(WEATHER_ASH) //wouldn't be fun otherwise
+ weather_immunities = list(TRAIT_ASHSTORM_IMMUNE) //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 0377ded69c9..0ba6398698c 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
speak_emote = list("roars")
armour_penetration = 40
melee_damage_lower = 40
@@ -142,7 +142,7 @@ Difficulty: Hard
/// Slams the ground around the source throwing back enemies caught nearby, delay is for the radius increase
/proc/wendigo_slam(atom/source, range, delay, throw_range)
var/turf/orgin = get_turf(source)
- if(!orgin)
+ if(!orgin)
return
var/list/all_turfs = RANGE_TURFS(range, orgin)
for(var/i = 0 to range)
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 8095d654767..1317cff6804 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,10 @@
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(WEATHER_LAVA in living_user.weather_immunities)
+ else if(HAS_TRAIT(living_user, TRAIT_LAVA_IMMUNE))
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, WEATHER_LAVA)
+ ADD_TRAIT(living_user, TRAIT_LAVA_IMMUNE, type)
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)
+ addtimer(TRAIT_CALLBACK_REMOVE(user, TRAIT_LAVA_IMMUNE, type), 10 SECONDS)
use_time = world.time + 60 SECONDS
-
-/obj/item/crusher_trophy/broodmother_tongue/proc/remove_lavaproofing(mob/living/user)
- 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 444c8820aa7..7fa05c1fc5b 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(WEATHER_LAVA, WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE)
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 dba7c3636e4..912cadbaf0c 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(WEATHER_LAVA, WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE)
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 3de8dbb6a06..c0ddea59c12 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
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 381ca9d32ac..8cb3cea04ff 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_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
faction = list("mining")
- weather_immunities = list(WEATHER_LAVA,WEATHER_ASH)
+ weather_immunities = list(TRAIT_LAVA_IMMUNE,TRAIT_ASHSTORM_IMMUNE)
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 3bbfb56dd08..b358b2925e6 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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
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(WEATHER_SNOW)
+ weather_immunities = list(TRAIT_SNOWSTORM_IMMUNE)
color = rgb(114,228,250)
loot = list(/obj/effect/decal/remains/human{color = rgb(114,228,250)})
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 87135d98293..3ed026e448b 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -64,6 +64,9 @@
///This damage is taken when the body temp is too hot.
var/unsuitable_heat_damage
+ /// List of weather immunity traits that are then added on Initialize(), see traits.dm.
+ var/list/weather_immunities
+
///Healable by medical stacks? Defaults to yes.
var/healable = 1
@@ -178,7 +181,9 @@
AddComponent(/datum/component/personal_crafting)
ADD_TRAIT(src, TRAIT_ADVANCEDTOOLUSER, ROUNDSTART_TRAIT)
ADD_TRAIT(src, TRAIT_CAN_STRIP, ROUNDSTART_TRAIT)
- ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, SPECIES_TRAIT)
+ ADD_TRAIT(src, TRAIT_NOFIRE_SPREAD, ROUNDSTART_TRAIT)
+ for(var/trait in weather_immunities)
+ ADD_TRAIT(src, trait, ROUNDSTART_TRAIT)
if(speak)
speak = string_list(speak)
diff --git a/code/modules/vehicles/mecha/_mecha.dm b/code/modules/vehicles/mecha/_mecha.dm
index 6111f000ca9..94ff9dd9559 100644
--- a/code/modules/vehicles/mecha/_mecha.dm
+++ b/code/modules/vehicles/mecha/_mecha.dm
@@ -213,6 +213,7 @@
AddElement(/datum/element/atmos_sensitive, mapload)
become_hearing_sensitive(trait_source = ROUNDSTART_TRAIT)
+ ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, ROUNDSTART_TRAIT) //protects pilots from ashstorms.
/obj/vehicle/sealed/mecha/Destroy()
for(var/ejectee in occupants)
diff --git a/modular_skyrat/modules/ashwalkers/Ashwalker/Ashwalkers.dm b/modular_skyrat/modules/ashwalkers/Ashwalker/Ashwalkers.dm
index f36129f5d23..0d28dd2d80b 100644
--- a/modular_skyrat/modules/ashwalkers/Ashwalker/Ashwalkers.dm
+++ b/modular_skyrat/modules/ashwalkers/Ashwalker/Ashwalkers.dm
@@ -5,8 +5,8 @@
/datum/species/lizard/ashwalker/on_species_gain(mob/living/carbon/C, datum/species/old_species)
. = ..()
- LAZYOR(C.weather_immunities, "ash")
+ ADD_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)
/datum/species/lizard/ashwalker/on_species_loss(mob/living/carbon/C)
. = ..()
- LAZYREMOVE(C.weather_immunities, "ash")
+ REMOVE_TRAIT(C, TRAIT_ASHSTORM_IMMUNE, SPECIES_TRAIT)