diff --git a/baystation12.dme b/baystation12.dme
index b3252985c5a..79bb1ebed88 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -5,6 +5,78 @@
// END_INTERNALS
// BEGIN_FILE_DIR
#define FILE_DIR .
+#define FILE_DIR "code"
+#define FILE_DIR "code/libs"
+#define FILE_DIR "code/libs/Get Flat Icon"
+#define FILE_DIR "code/libs/Get Flat Icon/demo"
+#define FILE_DIR "code/TriDimension"
+#define FILE_DIR "code/unused"
+#define FILE_DIR "code/unused/goonheist"
+#define FILE_DIR "code/WorkInProgress"
+#define FILE_DIR "code/WorkInProgress/Cael_Aislinn"
+#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Rust"
+#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/ShieldGen"
+#define FILE_DIR "code/WorkInProgress/Cael_Aislinn/Supermatter"
+#define FILE_DIR "code/WorkInProgress/Susan"
+#define FILE_DIR "html"
+#define FILE_DIR "icons"
+#define FILE_DIR "icons/48x48"
+#define FILE_DIR "icons/adminbus"
+#define FILE_DIR "icons/ass"
+#define FILE_DIR "icons/effects"
+#define FILE_DIR "icons/mecha"
+#define FILE_DIR "icons/misc"
+#define FILE_DIR "icons/mob"
+#define FILE_DIR "icons/mob/custom"
+#define FILE_DIR "icons/mob/custom/N3X15"
+#define FILE_DIR "icons/mob/human_races"
+#define FILE_DIR "icons/mob/in-hand"
+#define FILE_DIR "icons/mob/in-hand/left"
+#define FILE_DIR "icons/mob/in-hand/right"
+#define FILE_DIR "icons/mob/species"
+#define FILE_DIR "icons/mob/species/vox"
+#define FILE_DIR "icons/obj"
+#define FILE_DIR "icons/obj/assemblies"
+#define FILE_DIR "icons/obj/atmospherics"
+#define FILE_DIR "icons/obj/clothing"
+#define FILE_DIR "icons/obj/doors"
+#define FILE_DIR "icons/obj/flora"
+#define FILE_DIR "icons/obj/machines"
+#define FILE_DIR "icons/obj/map"
+#define FILE_DIR "icons/obj/pipes"
+#define FILE_DIR "icons/pda_icons"
+#define FILE_DIR "icons/pods"
+#define FILE_DIR "icons/spideros_icons"
+#define FILE_DIR "icons/splashworks"
+#define FILE_DIR "icons/Testing"
+#define FILE_DIR "icons/turf"
+#define FILE_DIR "icons/vending_icons"
+#define FILE_DIR "icons/xenoarch_icons"
+#define FILE_DIR "nano"
+#define FILE_DIR "nano/images"
+#define FILE_DIR "sound"
+#define FILE_DIR "sound/AI"
+#define FILE_DIR "sound/ambience"
+#define FILE_DIR "sound/effects"
+#define FILE_DIR "sound/effects/turret"
+#define FILE_DIR "sound/effects/wind"
+#define FILE_DIR "sound/hallucinations"
+#define FILE_DIR "sound/items"
+#define FILE_DIR "sound/machines"
+#define FILE_DIR "sound/mecha"
+#define FILE_DIR "sound/misc"
+#define FILE_DIR "sound/music"
+#define FILE_DIR "sound/piano"
+#define FILE_DIR "sound/scp"
+#define FILE_DIR "sound/violin"
+#define FILE_DIR "sound/voice"
+#define FILE_DIR "sound/voice/Serithi"
+#define FILE_DIR "sound/vox"
+#define FILE_DIR "sound/vox_fem"
+#define FILE_DIR "sound/weapons"
+#define FILE_DIR "tools"
+#define FILE_DIR "tools/AddToChangelog"
+#define FILE_DIR "tools/AddToChangelog/AddToChangelog"
// END_FILE_DIR
// BEGIN_PREFERENCES
#define DEBUG
@@ -276,6 +348,7 @@
#include "code\game\gamemodes\events\biomass.dm"
#include "code\game\gamemodes\events\black_hole.dm"
#include "code\game\gamemodes\events\clang.dm"
+#include "code\game\gamemodes\events\cosmic_freeze.dm"
#include "code\game\gamemodes\events\dust.dm"
#include "code\game\gamemodes\events\miniblob.dm"
#include "code\game\gamemodes\events\ninja_abilities.dm"
@@ -708,6 +781,7 @@
#include "code\game\objects\structures\noticeboard.dm"
#include "code\game\objects\structures\safe.dm"
#include "code\game\objects\structures\signs.dm"
+#include "code\game\objects\structures\snow.dm"
#include "code\game\objects\structures\support_rail.dm"
#include "code\game\objects\structures\tables_racks.dm"
#include "code\game\objects\structures\tank_dispenser.dm"
@@ -1244,6 +1318,7 @@
#include "code\modules\mob\living\simple_animal\hostile\retaliate\cluwne.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\drone.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
+#include "code\modules\mob\living\simple_animal\hostile\retaliate\snowman.dm"
#include "code\modules\mob\new_player\login.dm"
#include "code\modules\mob\new_player\logout.dm"
#include "code\modules\mob\new_player\new_player.dm"
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index f01c0e79cb8..c0ce277540b 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -136,6 +136,9 @@
/atom/proc/singuloCanEat()
return 1
+/atom/proc/freeze()
+ return
+
/atom/proc/bullet_act(var/obj/item/projectile/Proj)
return 0
diff --git a/code/game/gamemodes/events/cosmic_freeze.dm b/code/game/gamemodes/events/cosmic_freeze.dm
new file mode 100644
index 00000000000..c3bc1119a09
--- /dev/null
+++ b/code/game/gamemodes/events/cosmic_freeze.dm
@@ -0,0 +1,15 @@
+/proc/cosmic_freeze_event()
+
+ spawn() //to stop the secrets panel hanging
+ var/list/turf/simulated/floor/turfs = list()
+ for(var/areapath in typesof(/area/hallway,/area/crew_quarters,/area/maintenance))
+ var/area/A = locate(areapath)
+ for(var/area/B in A.related)
+ for(var/turf/simulated/floor/F in B.contents)
+ if(!F.contents.len)
+ turfs += F
+
+ if(turfs.len) //Pick a turf to spawn at if we can
+ var/turf/simulated/floor/T = pick(turfs)
+ new/obj/structure/snow/cosmic(T)
+ message_admins("\blue Event: Cosmic snow spawned at [T.loc] ([T.x],[T.y],[T.z])")
diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm
index 54e474d961c..42e6298a859 100644
--- a/code/game/machinery/alarm.dm
+++ b/code/game/machinery/alarm.dm
@@ -181,15 +181,21 @@
/obj/machinery/alarm/process()
+ var/turf/simulated/location = loc
+ if(!istype(location)) return//returns if loc is not simulated
+ var/datum/gas_mixture/environment = location.return_air()
+
+ if(stat & (FROZEN))
+ if(environment.temperature >= 300)
+ visible_message("The ice on \the [src] melts away. it should be operational once again.")
+ stat &= ~FROZEN
+ update_icon()
+ return
+
if((stat & (NOPOWER|BROKEN)) || shorted || buildstage != 2)
use_power = 0
return
- var/turf/simulated/location = loc
- if(!istype(location)) return//returns if loc is not simulated
-
- var/datum/gas_mixture/environment = location.return_air()
-
// Handle temperature adjustment here.
if(environment.temperature < target_temperature - 2 || environment.temperature > target_temperature + 2 || regulating_temperature)
//If it goes too far, we should adjust ourselves back before stopping.
@@ -313,9 +319,14 @@
return 0
/obj/machinery/alarm/update_icon()
+ overlays = 0
+ if(stat & FROZEN)
+ overlays += image(icon,"alarmf")
+
if(wiresexposed)
icon_state = "alarmx"
return
+
if((stat & (NOPOWER|BROKEN)) || shorted)
icon_state = "alarmp"
return
@@ -644,6 +655,10 @@
/obj/machinery/alarm/interact(mob/user)
+ if(stat & FROZEN)
+ user << "If only you could somehow melt the ice covering the alarm's interface..."
+ return
+
user.set_machine(src)
if(buildstage!=2)
@@ -830,6 +845,24 @@
*/
src.add_fingerprint(user)
+ if(stat & FROZEN)
+ if(istype(W, /obj/item/weapon/weldingtool))
+ var/obj/item/weapon/weldingtool/WT = W
+ if(!WT.isOn()) return
+ if (WT.get_fuel() < 5) // uses up 5 fuel.
+ user << "You need more fuel to complete this task."
+ return
+
+ user << "You begin melting the ice on \the [src]."
+ playsound(get_turf(src), pick('sound/items/Welder.ogg', 'sound/items/Welder2.ogg'), 50, 1)
+ if(do_after(user, 50))
+ if(!src || !WT.remove_fuel(5, user)) return
+ user << "You melt the ice. \the [src] should be operational once again."
+ stat &= ~FROZEN
+ update_icon()
+
+ return ..()
+
switch(buildstage)
if(2)
if(istype(W, /obj/item/weapon/screwdriver)) // Opening that Air Alarm up.
diff --git a/code/game/objects/items/weapons/gift_wrappaper.dm b/code/game/objects/items/weapons/gift_wrappaper.dm
index ad48b930b75..cd115e0dd9b 100644
--- a/code/game/objects/items/weapons/gift_wrappaper.dm
+++ b/code/game/objects/items/weapons/gift_wrappaper.dm
@@ -133,6 +133,7 @@
/obj/item/clothing/tie/horrible,
/obj/item/device/maracas,
/obj/item/weapon/gun/energy/temperature,
+ /obj/item/weapon/shovel/spade,
)
var/obj/item/I = new gift_type(M)
@@ -143,6 +144,7 @@
qdel(src)
return
+//christmas and festive food
/obj/item/weapon/winter_gift/food/attack_self(mob/M as mob)
var/gift_type = pick(
/obj/item/weapon/reagent_containers/food/snacks/sliceable/birthdaycake,
@@ -158,10 +160,18 @@
qdel(src)
return
+//warm clothes
/obj/item/weapon/winter_gift/cloth/attack_self(mob/M as mob)
+ if(prob(30))
+ cloth_bundle()
+ M << "You unwrapped a bundle of clothes! Looks comfy!"
+ qdel(src)
+ return
+
var/gift_type = pick(
/obj/item/clothing/gloves/black,
/obj/item/clothing/head/ushanka,
+ /obj/item/clothing/head/bearpelt,
)
var/obj/item/I = new gift_type(M)
@@ -172,6 +182,40 @@
qdel(src)
return
+/obj/item/weapon/winter_gift/cloth/proc/cloth_bundle()
+ var/bundle = pick(
+ 3;"batman",
+ 10;"russian fur",
+ 10;"chicken",
+ 8;"pirate captain",
+ 2;"cuban pete"
+ )
+
+ switch(bundle)
+ if("batman")
+ new /obj/item/weapon/storage/belt/security/batmanbelt(get_turf(loc))
+ new /obj/item/clothing/head/batman(get_turf(loc))
+ new /obj/item/clothing/gloves/batmangloves(get_turf(loc))
+ new /obj/item/clothing/shoes/jackboots/batmanboots(get_turf(loc))
+ new /obj/item/clothing/under/batmansuit(get_turf(loc))
+ if("russian fur")
+ new /obj/item/clothing/suit/russofurcoat(get_turf(loc))
+ new /obj/item/clothing/head/russofurhat(get_turf(loc))
+ if("chicken")
+ new /obj/item/clothing/head/chicken(get_turf(loc))
+ new /obj/item/clothing/suit/chickensuit(get_turf(loc))
+ if("pirate captain")
+ new /obj/item/clothing/glasses/eyepatch(get_turf(loc))
+ new /obj/item/clothing/head/hgpiratecap(get_turf(loc))
+ new /obj/item/clothing/suit/hgpirate(get_turf(loc))
+ new /obj/item/clothing/under/captain_fly(get_turf(loc))
+ new /obj/item/clothing/shoes/jackboots(get_turf(loc))
+ if("cuban pete")
+ new /obj/item/clothing/head/collectable/petehat(get_turf(loc))
+ new /obj/item/device/maracas(get_turf(loc))
+ new /obj/item/device/maracas(get_turf(loc))
+
+//dangerous items
/obj/item/weapon/winter_gift/special/attack_self(mob/M as mob)
var/gift_type = pick(
/obj/item/device/fuse_bomb,
@@ -205,6 +249,16 @@
qdel(src)
return
+//black gifts have 2% chance to spawn by default.
+/obj/item/weapon/winter_gift/proc/pick_a_gift(var/turf/T,var/special_chance = 2)
+ var/gift_type = pick(
+ 50;/obj/item/weapon/winter_gift/regular,
+ 25;/obj/item/weapon/winter_gift/food,
+ 25;/obj/item/weapon/winter_gift/cloth,
+ special_chance;/obj/item/weapon/winter_gift/special,
+ )
+ new gift_type(T)
+
////STRANGE PRESENTS(wrapped people)////
/obj/effect/spresent
diff --git a/code/game/objects/structures/snow.dm b/code/game/objects/structures/snow.dm
new file mode 100644
index 00000000000..b702fc58654
--- /dev/null
+++ b/code/game/objects/structures/snow.dm
@@ -0,0 +1,535 @@
+//////SNOW//////(winter 2014, by Deity Link)
+
+/obj/structure/snow
+ name = "snow"
+ layer = 2.5//above the plating and the vents, bellow most items and structures
+ icon = 'icons/turf/snow.dmi'
+ icon_state = "snow"
+ alpha = 230
+ anchored = 1
+ density = 0
+ mouse_opacity = 1
+
+ var/dug = 0
+
+ var/list/foliage = list(
+ "snowgrass1bb",
+ "snowgrass2bb",
+ "snowgrass3bb",
+ "snowgrass1gb",
+ "snowgrass2gb",
+ "snowgrass3gb",
+ "snowgrassall1",
+ "snowgrassall2",
+ "snowgrassall3",
+ )
+
+/obj/structure/snow/New()
+ ..()
+ if(prob(17))
+ overlays += image('icons/obj/flora/snowflora.dmi',pick(foliage))
+
+/obj/structure/snow/attackby(obj/item/W,mob/user)
+ if(istype(W,/obj/item/weapon/shovel))//using a shovel or spade harvests some snow and let's you click on the lower layers
+ if(dug < 2)
+ dug = 2
+ icon_state = "snow_dug"
+ mouse_opacity = 0
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ sleep(400)
+ icon_state = "snow_grabbed"
+ dug = 1
+ mouse_opacity = 1
+ sleep(400)
+ if(dug != 2)
+ icon_state = "snow"
+ dug = 0
+ else
+ user << "There isn't much snow left to dig. It might come back later."
+
+/obj/structure/snow/attack_hand(mob/user)
+ if(dug > 0) return
+ playsound(get_turf(src), "rustle", 50, 1)
+ user << "You start digging the snow with your hands."
+ if(do_after(user,30))
+ dug = 1
+ user << "You form a snowball in your hands."
+ user.put_in_hands(new /obj/item/stack/sheet/snow())
+ icon_state = "snow_grabbed"
+ sleep(400)
+ if(dug != 2)
+ icon_state = "snow"
+ dug = 0
+ return
+
+//////COSMIC SNOW(the one that spreads everywhere)//////
+
+/obj/structure/snow/cosmic
+ desc = "Winter is coming."
+
+ var/list/block_spread_turf = list(
+ /turf/space,
+ /turf/unsimulated,
+ )
+
+ var/list/block_spread_obj = list( //these objects always block the spread of the snow
+ /obj/structure/plasticflaps/mining,
+ /obj/structure/snow,
+ /obj/effect/forcefield,
+ )
+
+ var/list/block_spread_density = list( //these objects only block the spread of the snow if they are dense
+ /obj/machinery/door/firedoor,
+ /obj/machinery/door/airlock,
+ /obj/machinery/door/morgue,
+ /obj/machinery/door/poddoor,
+ )
+
+ var/datum/gas_mixture/env = null
+
+/obj/structure/snow/cosmic/New()
+ ..()
+ snow_tiles++
+
+ var/blocked = 0
+ for(var/atom/A in get_turf(src))
+ if(A.density)
+ blocked = 1
+
+ if((snow_tiles >= 200) && !blocked && prob(15))
+ if(prob(30))
+ new/obj/structure/snow_flora/sappling/pine(get_turf(src))
+ else
+ new/obj/structure/snow_flora/sappling(get_turf(src))
+
+ if((snow_tiles >= 400) && !blocked && prob(2))
+ new/mob/living/simple_animal/hostile/retaliate/snowman(get_turf(src))
+
+ if(!bear_invasion && (snow_tiles >= 800))
+ bear_invasion = 1
+ for(var/obj/effect/landmark/C in landmarks_list)
+ if(C.name == "carpspawn")
+ if(prob(50))
+ new /mob/living/simple_animal/hostile/bear(C.loc)
+
+ var/turf/simulated/TS = get_turf(src)
+ if(!istype(TS)) return
+ env = TS.return_air()
+
+ chill()
+
+ spawn(5)//so the parent snow doesn't have to wait for its children's spread to finish, to prevent some sort of gigantic recursion that only lets snow duplicate toward North.
+ if(src)
+ spread()
+
+ for(var/obj/machinery/alarm/A in get_turf(src))
+ A.stat |= FROZEN
+ A.rcon_setting = RCON_NO
+ A.update_icon()
+
+/obj/structure/snow/cosmic/proc/update_env_air()
+ var/turf/simulated/TS = get_turf(src)
+ if(!istype(TS)) return
+ env = TS.return_air()
+
+/obj/structure/snow/cosmic/proc/spread()
+ update_env_air()
+
+ if(!env) return
+
+ if(env.temperature > MELTPOINT_SNOW)//above 30°C, the snow melts away)
+ var/turf/simulated/TS = get_turf(src)
+ if(!istype(TS)) return
+ TS.wet(800)
+ snow_tiles--
+ qdel(src)
+ return
+
+ if(env.temperature < 296.15)//the cosmic snow only spreads when the temperature is bellow 23°C
+
+ for(var/i in cardinal)
+ var/turf/T = get_step(src,i)
+
+ if(is_type_in_list(T,block_spread_turf))
+ continue
+
+ if(T.density)
+ continue //walls, duh
+
+ var/can_spread = 1
+ for(var/blockingA in block_spread_obj)
+ if(locate(blockingA) in T)
+ can_spread = 0
+ break
+
+ for(var/blockingB in block_spread_density)
+ var/obj/BB = (locate(blockingB) in T)
+ if(BB && BB.density)
+ can_spread = 0
+ break
+
+ //checking for windows and windoors on the source tile
+ for(var/obj/structure/window/WA in get_turf(src))
+ if(WA.dir & get_dir(get_turf(src),T))
+ can_spread = 0
+ break
+
+ for(var/obj/machinery/door/window/WB in get_turf(src))
+ if((WB.dir & get_dir(get_turf(src),T)) && WB.density)
+ can_spread = 0
+ break
+
+ //checking for windows and windoors on the destination tile
+ for(var/obj/structure/window/WA in T)
+ if(WA.is_fulltile())
+ can_spread = 0
+ break
+ if(WA.dir & get_dir(T,get_turf(src)))
+ can_spread = 0
+ break
+
+ for(var/obj/machinery/door/window/WB in T)
+ if((WB.dir & get_dir(T,get_turf(src))) && WB.density)
+ can_spread = 0
+ break
+
+ var/datum/gas_mixture/env2 = T.return_air()
+
+ if(can_spread && (env2.temperature < MELTPOINT_SNOW))
+ new/obj/structure/snow/cosmic(T)
+
+ spawn(5)
+ if(src)
+ spread()
+
+/obj/structure/snow/cosmic/proc/chill()
+ if(env.temperature > 233)//the snow will slowly lower the temperature until -40°C.
+ env.temperature -= 0.02
+
+ spawn(20)
+ if(src)
+ chill()
+
+
+
+//////SNOWBALLS//////
+
+/obj/item/stack/sheet/snow
+ name = "snow"
+ desc = "Technically water."
+ singular_name = "snow ball"
+ icon_state = "snow"
+ melt_temperature = MELTPOINT_SNOW
+ force = 0
+ throwforce = 1
+ throw_speed = 3
+ throw_range = 6
+
+/obj/item/stack/sheet/snow/New(var/loc, var/amount=null)
+ recipes = snow_recipes
+ pixel_x = rand(-13,13)
+ pixel_y = rand(-13,13)
+ return ..()
+
+/obj/item/stack/sheet/snow/melt()
+ var/turf/T = get_turf(src)
+ if(istype(T,/turf/simulated))
+ var/turf/simulated/TS = T
+ TS.wet(800)
+ qdel(src)
+
+/obj/item/stack/sheet/snow/throw_at(atom/target, range, speed)
+ playsound(src.loc, 'sound/weapons/punchmiss.ogg', 50, 1)
+ ..()
+
+/obj/item/stack/sheet/snow/throw_impact(atom/hit_atom)
+ if(istype(hit_atom,/mob/living/carbon/))
+ var/mob/living/carbon/C = hit_atom
+ if(C.stuttering < 1 && (!(M_HULK in C.mutations)))
+ C.stuttering = 1
+ C.Weaken(1)
+ C.Stun(1)
+ playsound(C.loc, "swing_hit", 50, 1)
+ if(C.bodytemperature >= 265)
+ C.bodytemperature -= 5
+ else if(istype(hit_atom,/mob/living/simple_animal/hostile/retaliate/snowman))
+ var/mob/living/simple_animal/hostile/retaliate/snowman/S = hit_atom
+ playsound(S.loc, "swing_hit", 50, 1)
+ if(S.enemies.len)
+ if(prob(10))
+ S.enemies = list()
+ S.LoseTarget()
+ S.say("Ah, I give up, you've got a pretty good swing.")
+ call(/obj/item/weapon/winter_gift/proc/pick_a_gift)(S.loc)
+ else
+ S.say(pick("Didn't feel anything","You call that snowballing?"))
+ else
+ S.say(pick("A fight? With pleasure.","Don't forget that you're the one who started it all."))
+ S.Retaliate()
+ if(S.bodytemperature >= 232)
+ S.bodytemperature -= 5
+ else ..()
+
+var/global/list/datum/stack_recipe/snow_recipes = list (
+ new/datum/stack_recipe("snowman", /mob/living/simple_animal/hostile/retaliate/snowman, 10, time = 50, one_per_turf = 0, on_floor = 1),
+ new/datum/stack_recipe("snow barricade", /obj/structure/barricade/snow, 20, time = 50, one_per_turf = 1, on_floor = 1),
+ )
+
+
+
+//////BARRICADE//////
+
+/obj/structure/barricade/snow
+ name = "snow barricade"
+ desc = "This space is blocked off by a snow barricade."
+ icon = 'icons/obj/structures.dmi'
+ icon_state = "snowbarricade"
+ anchored = 1.0
+ density = 1.0
+ var/health = 50.0
+ var/maxhealth = 50.0
+
+/obj/structure/barricade/snow/attackby(obj/item/W as obj, mob/user as mob)
+ if (istype(W, /obj/item/stack/sheet/snow))
+ if (src.health < src.maxhealth)
+ visible_message("[user] begins to repair the [src]!")
+ if(do_after(user,20))
+ src.health = src.maxhealth
+ W:use(1)
+ visible_message("[user] repairs the [src]")
+ return
+ else
+ return
+ return
+ else
+ switch(W.damtype)
+ if("fire")
+ src.health -= W.force * 1
+ if("brute")
+ src.health -= W.force * 0.75
+ else
+ if (src.health <= 0)
+ visible_message("\the [src] is smashed apart!")
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ del(src)
+ ..()
+
+/obj/structure/barricade/snow/ex_act(severity)
+ switch(severity)
+ if(1.0)
+ visible_message("\the [src] is blown apart!")
+ qdel(src)
+ return
+ if(2.0)
+ src.health -= 25
+ if (src.health <= 0)
+ visible_message("\the [src] is blown apart!")
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ qdel(src)
+ return
+
+/obj/structure/barricade/snow/meteorhit()
+ visible_message("\the [src] is blown apart!")
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ new /obj/item/stack/sheet/snow(get_turf(src), 1)
+ del(src)
+ return
+
+/obj/structure/barricade/snow/blob_act()
+ src.health -= 25
+ if (src.health <= 0)
+ visible_message("The blob eats through \the [src]!")
+ del(src)
+ return
+
+/obj/structure/barricade/snow/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)//So bullets will fly over and stuff.
+ if(air_group || (height==0))
+ return 1
+ if(istype(mover) && mover.checkpass(PASSTABLE))
+ return 1
+ else
+ return 0
+
+
+
+//////TREES//////
+
+
+/obj/structure/snow_flora/sappling
+ name = "sappling"
+ desc = "Shh, it's growing..."
+ density = 0
+ anchored = 1
+ icon = 'icons/obj/flora/snowflora.dmi'
+ icon_state = "snowbush1"
+
+ var/growth = 0
+
+/obj/structure/snow_flora/sappling/New()
+ ..()
+ icon_state = pick(
+ "snowbush1",
+ "snowbush2",
+ "snowbush3",
+ "snowbush4",
+ "snowbush5",
+ "snowbush6",
+ )
+
+ growing()
+
+/obj/structure/snow_flora/sappling/proc/growing()
+ if(growth > 20)
+ new/obj/structure/snow_flora/tree(get_turf(src))
+ qdel(src)
+
+ if(locate(/obj/structure/snow) in get_turf(src))
+ growth++
+ spawn(40)
+ growing()
+ else
+ qdel(src)
+
+/obj/structure/snow_flora/sappling/attackby(obj/item/W,mob/user)
+ var/list/cutting = list(
+ /obj/item/weapon/minihoe,
+ /obj/item/weapon/scythe,
+ )
+ if(is_type_in_list(W,cutting))
+ qdel(src)
+
+/obj/structure/snow_flora/sappling/pine/growing()
+ if(growth > 30)
+ if(prob(20))
+ new/obj/structure/snow_flora/tree/pine/xmas(get_turf(src))
+ else
+ new/obj/structure/snow_flora/tree/pine(get_turf(src))
+ qdel(src)
+
+ if(locate(/obj/structure/snow) in get_turf(src))
+ growth++
+ spawn(40)
+ growing()
+ else
+ qdel(src)
+
+/obj/structure/snow_flora/tree
+ name = "tree"
+ desc = "Where's my axe when I need it?"
+ density = 0
+ anchored = 1
+ layer = FLY_LAYER
+ icon = 'icons/obj/flora/deadtrees.dmi'
+ icon_state = "tree_1"
+
+ var/axe_hits = 0
+
+/obj/structure/snow_flora/tree/New()
+ ..()
+ icon_state = pick(
+ "tree_1",
+ "tree_2",
+ "tree_3",
+ "tree_4",
+ "tree_5",
+ "tree_6",
+ )
+
+ idle()
+
+/obj/structure/snow_flora/tree/proc/idle()
+ if(!(locate(/obj/structure/snow) in get_turf(src)))
+ axe_hits++
+ if(axe_hits >= 3)
+ new/obj/item/weapon/grown/log(get_turf(src))
+ qdel(src)
+ return
+ spawn(50)
+ if(src)
+ idle()
+
+/obj/structure/snow_flora/tree/attackby(obj/item/W,mob/user)
+ var/list/cutting = list(
+ /obj/item/weapon/hatchet,
+ /obj/item/weapon/twohanded/fireaxe,
+ )
+ if(is_type_in_list(W,cutting))
+ axe_hits++
+ user.visible_message("[user] hits \the [src] with \the [W].")
+ if(axe_hits >= 3)
+ new/obj/item/weapon/grown/log(get_turf(src))
+ qdel(src)
+
+/obj/structure/snow_flora/tree/pine
+ name = "pine tree"
+ desc = "O Tannenbaum..."
+ icon = 'icons/obj/flora/pinetrees.dmi'
+ icon_state = "pine_1"
+ density = 1
+
+ pixel_x = -16
+
+/obj/structure/snow_flora/tree/pine/New()
+ ..()
+ icon_state = pick(
+ "pine_1",
+ "pine_2",
+ "pine_3",
+ )
+
+ if((snow_tiles >= 600) && prob(20))
+ new /mob/living/simple_animal/hostile/giant_spider/spiderling(get_turf(src))
+
+ if((snow_tiles >= 1000) && prob(20))
+ new /mob/living/simple_animal/hostile/bear(get_turf(src))
+
+/obj/structure/snow_flora/tree/pine/attackby(obj/item/W,mob/user)
+ var/list/cutting = list(
+ /obj/item/weapon/hatchet,
+ /obj/item/weapon/twohanded/fireaxe,
+ )
+ if(is_type_in_list(W,cutting))
+ axe_hits++
+ user.visible_message("[user] hits \the [src] with \the [W].")
+ if(axe_hits >= 5)
+ new/obj/item/weapon/grown/log(get_turf(src))
+ new/obj/item/weapon/grown/log(get_turf(src))
+ new/obj/item/weapon/grown/log(get_turf(src))
+ qdel(src)
+
+/obj/structure/snow_flora/tree/pine/idle()
+ if(!(locate(/obj/structure/snow) in get_turf(src)))
+ axe_hits++
+ if(axe_hits >= 5)
+ new/obj/item/weapon/grown/log(get_turf(src))
+ new/obj/item/weapon/grown/log(get_turf(src))
+ new/obj/item/weapon/grown/log(get_turf(src))
+ qdel(src)
+ return
+ spawn(50)
+ if(src)
+ idle()
+
+/obj/structure/snow_flora/tree/pine/xmas
+ name = "christmas tree"
+ desc = "Heck yeah!"
+ icon = 'icons/obj/flora/pinetrees.dmi'
+ icon_state = "pine_c"
+
+/obj/structure/snow_flora/tree/pine/xmas/New()
+ for(var/turf/simulated/floor/T in orange(1,src))
+ var/blocked = 0
+ for(var/atom/A in T)
+ if(A.density)
+ blocked = 1
+ if(blocked) continue
+
+ for(var/i=1,i<=rand(1,3),i++)
+ call(/obj/item/weapon/winter_gift/proc/pick_a_gift)(T,5)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index b3d865e075f..33cadbfa57b 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -706,6 +706,7 @@ var/global/floorIsLava = 0
Spawn Space-Vines
Trigger a communication blackout
Trigger a wave of PDA spams
+ Spawn a cosmic snow storm
Fun Secrets
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index b1ea872b6e6..0bccbba860d 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -2370,6 +2370,11 @@
feedback_add_details("admin_secrets_fun_used","PDA")
new /datum/event/pda_spam
+ if("freeze")
+ feedback_inc("admin_secrets_fun_used",1)
+ feedback_add_details("admin_secrets_fun_used","CF")
+ new /datum/event/cosmic_freeze
+
if("spaceninja")
feedback_inc("admin_secrets_fun_used",1)
feedback_add_details("admin_secrets_fun_used","SN")
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index efb0c464140..79f6769e5f7 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -3,6 +3,12 @@
var/list/species_restricted = null //Only these species can wear this kit.
var/wizard_garb = 0 // Wearing this empowers a wizard.
+ //temperatures in Kelvin. These default values won't affect protections in any way.
+ var/cold_breath_protection = 300 //that cloth protects its wearer's breath from cold air down to that temperature
+ var/hot_breath_protection = 300 //that cloth protects its wearer's breath from hot air up to that temperature
+
+ var/cold_speed_protection = 300 //that cloth allows its wearer to keep walking at normal speed at lower temperatures
+
//BS12: Species-restricted clothing check.
/obj/item/clothing/mob_can_equip(M as mob, slot)
@@ -221,6 +227,8 @@ BLIND // can't see anything
siemens_coefficient = 0.9
species_restricted = list("exclude","Diona","Muton")
+ cold_breath_protection = 230
+
/obj/item/clothing/suit/space
name = "Space suit"
desc = "A suit that protects against low pressure environments. Has a big 13 on the back."
diff --git a/code/modules/clothing/head/misc.dm b/code/modules/clothing/head/misc.dm
index add4b9eef06..29a5256fec4 100644
--- a/code/modules/clothing/head/misc.dm
+++ b/code/modules/clothing/head/misc.dm
@@ -235,6 +235,8 @@
flags = FPRINT | TABLEPASS | BLOCKHAIR
siemens_coefficient = 2.0
+ cold_breath_protection = 230
+
/obj/item/clothing/head/bearpelt
name = "bear pelt hat"
desc = "Fuzzy."
@@ -243,6 +245,8 @@
flags = FPRINT | TABLEPASS | BLOCKHEADHAIR
siemens_coefficient = 2.0
+ cold_breath_protection = 230
+
/obj/item/clothing/head/xenos
name = "xenos helmet"
icon_state = "xenos"
@@ -296,4 +300,6 @@
icon_state = "russofurhat"
item_state = "russofurhat"
flags = FPRINT | TABLEPASS | BLOCKHEADHAIR
- flags_inv = HIDEEARS
\ No newline at end of file
+ flags_inv = HIDEEARS
+
+ cold_breath_protection = 230
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index d97a41737b8..c2f967c9497 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -104,6 +104,8 @@
item_state = "ushankadown"
flags_inv = HIDEEARS
+ cold_breath_protection = 230
+
/obj/item/clothing/head/ushanka/attack_self(mob/user as mob)
if(src.icon_state == "ushankadown")
src.icon_state = "ushankaup"
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index 7f6816f4bd3..5b4c9f80bf3 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -8,6 +8,8 @@
w_class = 2
species_fit = list("Vox")
+ cold_breath_protection = 230
+
/obj/item/clothing/mask/luchador
name = "Luchador Mask"
desc = "Worn by robust fighters, flying high to defeat their foes!"
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index 0b39e7017ea..f432745a54b 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -38,7 +38,12 @@
//scarves (fit in in mask slot)
-/obj/item/clothing/mask/bluescarf
+/obj/item/clothing/mask/scarf
+ name = "scarf"
+
+ cold_breath_protection = 230
+
+/obj/item/clothing/mask/scarf/blue
name = "blue neck scarf"
desc = "A blue neck scarf."
icon_state = "blueneckscarf"
@@ -47,7 +52,7 @@
w_class = 2
gas_transfer_coefficient = 0.90
-/obj/item/clothing/mask/redscarf
+/obj/item/clothing/mask/scarf/redwhite
name = "red scarf"
desc = "A red and white checkered neck scarf."
icon_state = "redwhite_scarf"
@@ -56,7 +61,7 @@
w_class = 2
gas_transfer_coefficient = 0.90
-/obj/item/clothing/mask/greenscarf
+/obj/item/clothing/mask/scarf/green
name = "green scarf"
desc = "A green neck scarf."
icon_state = "green_scarf"
@@ -65,7 +70,7 @@
w_class = 2
gas_transfer_coefficient = 0.90
-/obj/item/clothing/mask/ninjascarf
+/obj/item/clothing/mask/scarf/ninja
name = "ninja scarf"
desc = "A stealthy, dark scarf."
icon_state = "ninja_scarf"
@@ -114,6 +119,8 @@
w_class = 1
can_flip = 1
+ cold_breath_protection = 230
+
obj/item/clothing/mask/bandana/red
name = "red bandana"
icon_state = "bandred"
\ No newline at end of file
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 4bc445c769e..7de3731239f 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -91,6 +91,8 @@
siemens_coefficient = 0.7
species_fit = list("Vox")
+ cold_speed_protection = 230
+
/obj/item/clothing/shoes/jackboots/batmanboots
name = "batboots"
desc = "Criminal stomping boots for fighting crime and looking good."
diff --git a/code/modules/clothing/suits/miscellaneous.dm b/code/modules/clothing/suits/miscellaneous.dm
index ced5374121e..a62f57de65d 100644
--- a/code/modules/clothing/suits/miscellaneous.dm
+++ b/code/modules/clothing/suits/miscellaneous.dm
@@ -49,6 +49,7 @@
flags_inv = HIDEJUMPSUIT
species_fit = list("Vox")
+ cold_speed_protection = 230
/obj/item/clothing/suit/cyborg_suit
name = "cyborg suit"
@@ -151,6 +152,8 @@
flags_inv = HIDESHOES|HIDEJUMPSUIT
siemens_coefficient = 2.0
+ cold_speed_protection = 230
+
/obj/item/clothing/suit/monkeysuit
name = "Monkey Suit"
@@ -380,15 +383,21 @@
icon_state = "officersuit"
item_state = "officersuit"
+ cold_speed_protection = 230
+
/obj/item/clothing/suit/soldiercoat
name = "Soldier's Coat"
desc = "Ein Mantel gemacht, um die Verbündeten zu zerstören."
icon_state = "soldiersuit"
item_state = "soldiersuit"
+ cold_speed_protection = 230
+
/obj/item/clothing/suit/russofurcoat
name = "russian fur coat"
desc = "Let the land do the fighting for you."
icon_state = "russofurcoat"
item_state = "russofurcoat"
- allowed = list(/obj/item/weapon/gun)
\ No newline at end of file
+ allowed = list(/obj/item/weapon/gun)
+
+ cold_speed_protection = 230
diff --git a/code/modules/events/cosmic_freeze.dm b/code/modules/events/cosmic_freeze.dm
index c2ac3496fb1..c1b511ec5de 100644
--- a/code/modules/events/cosmic_freeze.dm
+++ b/code/modules/events/cosmic_freeze.dm
@@ -1,183 +1,25 @@
-/obj/structure/snow
- name = "snow"
- layer = 2.5//above the plating and the vents, bellow most items and structures
- icon = 'icons/turf/snow.dmi'
- icon_state = "snow"
- alpha = 230
- anchored = 1
- density = 0
- mouse_opacity = 1
+/var/global/snow_tiles = 0
+/var/global/bear_invasion = 0
- var/has_sappling = 0
- var/dug = 0
- var/caught = 0
+/datum/event/cosmic_freeze
- var/list/foliage = list(
- "snowgrass1bb",
- "snowgrass2bb",
- "snowgrass3bb",
- "snowgrass1gb",
- "snowgrass2gb",
- "snowgrass3gb",
- "snowgrassall1",
- "snowgrassall2",
- "snowgrassall3",
- )
+/datum/event/cosmic_freeze/start()
+ cosmic_freeze_event()
- var/list/sappling = list(
- "snowbush1",
- "snowbush2",
- "snowbush3",
- "snowbush4",
- "snowbush5",
- "snowbush6",
- )
+/datum/event/cosmic_freeze/announce()
+ command_alert("Thermal scans suggest that the close approach of a comet has somehow manifested a snow storm aboard the station. Allowing that storm to propagate through the station might have unforeseen consequences.", "Cosmic freeze")
- var/list/trees = list(
- "tree_1",
- "tree_2",
- "tree_3",
- "tree_4",
- "tree_5",
- "tree_6",
- )
- var/list/pinetrees = list(
- "pine_1",
- "pine_2",
- "pine_3",
- )
-/obj/structure/snow/New()
- ..()
- if(prob(17))
- overlays += image('icons/obj/flora/snowflora.dmi',pick(foliage))
+/*
+/obj/structure/snowreader
+ name = "snowreader"
-/obj/structure/snow/attackby(obj/item/W,mob/user)
- if(istype(W,/obj/item/weapon/minihoe))
- if(has_sappling)
- has_sappling = 0
- overlays = 0
+/obj/structure/snowreader/New()
+ read_snow()
- if(istype(W,/obj/item/weapon/shovel))//using a shovel or spade harvests some snow and let's you click on the lower layers
- icon_state = "snow_dug"
- mouse_opacity = 0
-
-/obj/structure/snow/attack_hand(mob/user)
- if(dug || caught) return
- playsound(get_turf(src), "rustle", 50, 1)
- user << "You start digging the snow with your hands."
- if(do_after(user,30))
- caught = 1
- user << "You pick."
- user.put_in_hands(new /obj/item/stack/sheet/snow())
- icon_state = "snow_grabbed"
- sleep(400)
- if(!dug)
- icon_state = "snow"
- caught = 0
- return
-
-/obj/item/stack/sheet/snow
- name = "snow"
- desc = "Technically water."
- singular_name = "snow ball"
- icon_state = "snow"
- melt_temperature = MELTPOINT_SNOW
-
-/obj/item/stack/sheet/snow/New(var/loc, var/amount=null)
- recipes = snow_recipes
- pixel_x = rand(-13,13)
- pixel_y = rand(-13,13)
- return ..()
-
-/obj/item/stack/sheet/snow/melt()
- var/turf/T = get_turf(src)
- T.wet(800)
- qdel(src)
-
-var/global/list/datum/stack_recipe/snow_recipes = list (
- new/datum/stack_recipe("snowman", /mob/living/simple_animal, 10, time = 50, one_per_turf = 0, on_floor = 1),
- )
-
-/obj/structure/barricade/snow
- name = "snow barricade"
- desc = "This space is blocked off by a snow barricade."
- icon = 'icons/obj/structures.dmi'
- icon_state = "snowbarricade"
- anchored = 1.0
- density = 1.0
- var/health = 50.0
- var/maxhealth = 50.0
-
-/obj/structure/barricade/snow/attackby(obj/item/W as obj, mob/user as mob)
- if (istype(W, /obj/item/stack/sheet/snow))
- if (src.health < src.maxhealth)
- visible_message("[user] begins to repair the [src]!")
- if(do_after(user,20))
- src.health = src.maxhealth
- W:use(1)
- visible_message("[user] repairs the [src]")
- return
- else
- return
- return
- else
- switch(W.damtype)
- if("fire")
- src.health -= W.force * 1
- if("brute")
- src.health -= W.force * 0.75
- else
- if (src.health <= 0)
- visible_message("The barricade is smashed apart!")
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- del(src)
- ..()
-
-/obj/structure/barricade/snow/ex_act(severity)
- switch(severity)
- if(1.0)
- visible_message("\the [src] is blown apart!")
- qdel(src)
- return
- if(2.0)
- src.health -= 25
- if (src.health <= 0)
- visible_message("\the [src] is blown apart!")
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- qdel(src)
- return
-
-/obj/structure/barricade/snow/meteorhit()
- visible_message("\the [src] is blown apart!")
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- new /obj/item/stack/sheet/snow(get_turf(src, 1))
- del(src)
- return
-
-/obj/structure/barricade/snow/blob_act()
- src.health -= 25
- if (src.health <= 0)
- visible_message("The blob eats through \the [src]!")
- del(src)
- return
-
-/obj/structure/barricade/snow/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)//So bullets will fly over and stuff.
- if(air_group || (height==0))
- return 1
- if(istype(mover) && mover.checkpass(PASSTABLE))
- return 1
- else
- return 0
-
-/obj/structure/tree
- name = "tree"
- layer = FLY_LAYER
- icon = 'icons/obj/flora/deadtrees.dmi'
- icon_state = "tree_1"
+/obj/structure/snowreader/proc/read_snow()
+ world << "there are [snow_tiles] tiles covered in snow"
+ sleep(30)
+ read_snow()
+*/
\ No newline at end of file
diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm
index 094de2fff15..e30fa91bccd 100644
--- a/code/modules/events/event_dynamic.dm
+++ b/code/modules/events/event_dynamic.dm
@@ -47,6 +47,15 @@ var/list/event_last_fired = list()
possibleEvents[/datum/event/electrical_storm] = 10
possibleEvents[/datum/event/wallrot] = 30
+ var/current_month = text2num(time2text(world.timeofday, "MM"))
+ switch(current_month)
+ if(12,1,2)
+ if(snow_tiles <= 10)
+ possibleEvents[/datum/event/cosmic_freeze] = 30
+ if(3 to 11)
+ if(snow_tiles == 0)
+ possibleEvents[/datum/event/cosmic_freeze] = 15
+
if(!spacevines_spawned)
possibleEvents[/datum/event/spacevine] = 15
if(minutes_passed >= 30 && active_with_role["Engineer"] > 1) // Give engineers time to not set up the engine
diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm
index 00ddea9033e..eded1639623 100644
--- a/code/modules/mob/living/carbon/human/human_movement.dm
+++ b/code/modules/mob/living/carbon/human/human_movement.dm
@@ -53,7 +53,7 @@
return -1 // slimes become supercharged at high temperatures
if (bodytemperature < 183.222)
tally += (283.222 - bodytemperature) / 10 * 1.75
- else if (bodytemperature < 283.222)
+ else if ((bodytemperature < 283.222) && !check_speed_protections())
tally += (283.222 - bodytemperature) / 10 * 1.75
@@ -62,6 +62,15 @@
return (tally+config.human_delay)
+/mob/living/carbon/human/proc/check_speed_protections()
+ var/list/human_slots = get_cloth_slots()
+
+ for(var/obj/item/clothing/C in human_slots)
+ if(C.cold_speed_protection < bodytemperature)
+ return 1
+
+ return 0
+
/mob/living/carbon/human/Process_Spacemove(var/check_drift = 0)
//Can we act
if(restrained()) return 0
diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm
index 75b9845a2d5..0fff6ea6956 100644
--- a/code/modules/mob/living/carbon/human/inventory.dm
+++ b/code/modules/mob/living/carbon/human/inventory.dm
@@ -37,6 +37,21 @@
r_store,
s_store)
+/mob/living/carbon/human/proc/get_cloth_slots()
+ return list(
+ back,
+ wear_mask,
+ belt,
+ wear_id,
+ ears,
+ glasses,
+ gloves,
+ head,
+ shoes,
+ wear_suit,
+ w_uniform,
+ )
+
/mob/living/carbon/human/proc/equip_in_one_of_slots(obj/item/W, list/slots, act_on_fail = 1)
for (var/slot in slots)
if (equip_to_slot_if_possible(W, slots[slot], 0))
diff --git a/code/modules/mob/living/carbon/species.dm b/code/modules/mob/living/carbon/species.dm
index edfb1a2d8e3..92006670fd6 100644
--- a/code/modules/mob/living/carbon/species.dm
+++ b/code/modules/mob/living/carbon/species.dm
@@ -256,14 +256,14 @@ var/global/list/whitelisted_species = list("Human")
if( (abs(310.15 - breath.temperature) > 50) && !(M_RESIST_HEAT in H.mutations)) // Hot air hurts :(
if(H.status_flags & GODMODE) return 1 //godmode
if(breath.temperature < cold_level_1)
- if(prob(20))
- H << "\red You feel your face freezing and an icicle forming in your lungs!"
+ if(prob(20) && !check_breath_protections(H,breath.temperature))
+ H << "You feel your face freezing and an icicle forming in your lungs!"
else if(breath.temperature > heat_level_1)
if(prob(20))
if(H.dna.mutantrace == "slime")
- H << "\red You feel supercharged by the extreme heat!"
+ H << "You feel supercharged by the extreme heat!"
else
- H << "\red You feel your face burning and a searing heat in your lungs!"
+ H << "You feel your face burning and a searing heat in your lungs!"
if(H.dna.mutantrace == "slime")
if(breath.temperature < cold_level_1)
@@ -271,32 +271,42 @@ var/global/list/whitelisted_species = list("Human")
H.fire_alert = max(H.fire_alert, 1)
if(H.dna.mutantrace != "slime")
- switch(breath.temperature)
- if(-INFINITY to cold_level_3)
- H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold")
- H.fire_alert = max(H.fire_alert, 1)
+ if(!check_breath_protections(H,breath.temperature))
+ switch(breath.temperature)
+ if(-INFINITY to cold_level_3)
+ H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Cold")
+ H.fire_alert = max(H.fire_alert, 1)
- if(cold_level_3 to cold_level_2)
- H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold")
- H.fire_alert = max(H.fire_alert, 1)
+ if(cold_level_3 to cold_level_2)
+ H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Cold")
+ H.fire_alert = max(H.fire_alert, 1)
- if(cold_level_2 to cold_level_1)
- H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold")
- H.fire_alert = max(H.fire_alert, 1)
+ if(cold_level_2 to cold_level_1)
+ H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Cold")
+ H.fire_alert = max(H.fire_alert, 1)
- if(heat_level_1 to heat_level_2)
- H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Heat")
- H.fire_alert = max(H.fire_alert, 2)
+ if(heat_level_1 to heat_level_2)
+ H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, "head", used_weapon = "Excessive Heat")
+ H.fire_alert = max(H.fire_alert, 2)
- if(heat_level_2 to heat_level_3)
- H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat")
- H.fire_alert = max(H.fire_alert, 2)
+ if(heat_level_2 to heat_level_3)
+ H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, "head", used_weapon = "Excessive Heat")
+ H.fire_alert = max(H.fire_alert, 2)
- if(heat_level_3 to INFINITY)
- H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
- H.fire_alert = max(H.fire_alert, 2)
+ if(heat_level_3 to INFINITY)
+ H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, "head", used_weapon = "Excessive Heat")
+ H.fire_alert = max(H.fire_alert, 2)
return 1
+/datum/species/proc/check_breath_protections(var/mob/living/carbon/human/H,var/temperature)
+ var/list/human_slots = H.get_cloth_slots()
+
+ for(var/obj/item/clothing/C in human_slots)
+ if((C.cold_breath_protection < temperature) || (C.hot_breath_protection > temperature))
+ return 1
+
+ return 0
+
// Used for species-specific names (Vox, etc)
/datum/species/proc/makeName(var/gender,var/mob/living/carbon/C=null)
if(gender==FEMALE) return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
diff --git a/code/modules/mob/living/simple_animal/friendly/snowman.dm b/code/modules/mob/living/simple_animal/friendly/snowman.dm
deleted file mode 100644
index cdd4c0d1fb8..00000000000
--- a/code/modules/mob/living/simple_animal/friendly/snowman.dm
+++ /dev/null
@@ -1,31 +0,0 @@
-/mob/living/simple_animal/snowman
- name = "snowman"
- desc = "Good day sir."
- icon_state = "crab"
- icon_living = "crab"
- icon_dead = "crab_dead"
- small = 1
- speak_emote = list("clicks")
- emote_hear = list("clicks")
- emote_see = list("clacks")
- speak_chance = 1
- turns_per_move = 5
- meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
- response_help = "pets"
- response_disarm = "gently pushes aside"
- response_harm = "stomps"
- stop_automated_movement = 1
- friendly = "pinches"
- var/obj/item/inventory_head
- var/obj/item/inventory_mask
-
-/mob/living/simple_animal/snowman/Life()
- ..()
- //CRAB movement
- if(!ckey && !stat)
- if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc.
- turns_since_move++
- if(turns_since_move >= turns_per_move)
- Move(get_step(src,pick(4,8)))
- turns_since_move = 0
- regenerate_icons()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/snowman.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/snowman.dm
new file mode 100644
index 00000000000..fc4f246dd69
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/snowman.dm
@@ -0,0 +1,116 @@
+/mob/living/simple_animal/hostile/retaliate/snowman
+ name = "snowman"
+ desc = "Good day sir."
+ icon_state = "snowman"
+ icon_living = "snowman"
+ icon_dead = ""
+ speak = list("Good day sir.","Would you happen to have a carrot for my nose?","Cold day, isn't it?","What a pleasant weather.")
+ speak_emote = list("says")
+ emote_hear = list("says")
+ emote_see = list("hums")
+ speak_chance = 2.5
+ turns_per_move = 3
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
+ response_help = "hugs"
+ response_disarm = "gently pushes aside"
+ response_harm = "stomps"
+ friendly = "hugs"
+ faction = "snow"
+ health = 40
+ ranged = 1
+ retreat_distance = 5
+ minimum_distance = 3
+ projectilesound = 'sound/weapons/punchmiss.ogg'
+ projectiletype = /obj/item/projectile/snowball
+ environment_smash = 0
+
+ minbodytemp = 0
+ maxbodytemp = MELTPOINT_SNOW
+ heat_damage_per_tick = 5
+ bodytemperature = 270
+
+ var/obj/item/hat = null
+ var/obj/item/carrot = null
+
+/mob/living/simple_animal/hostile/retaliate/snowman/Life()
+ ..()
+ if(!ckey && !stat)
+ if(isturf(src.loc) && !resting && !buckled) //This is so it only moves if it's not inside a closet, gentics machine, etc.
+ turns_since_move++
+ if(turns_since_move >= turns_per_move)
+ Move(get_step(src,pick(4,8)))
+ turns_since_move = 0
+
+ if(enemies.len && prob(5))
+ enemies = list()
+ LoseTarget()
+ src.say("Whatever.")
+
+ if(stat)
+ visible_message("[src.name] murmurs, [pick("Oh my snowballs...","I will...be back...")]")
+ visible_message("\the [src] collapses in a pile of snow.")
+ var/turf/T = get_turf(src)
+ new /obj/item/stack/sheet/snow(T, 1)
+ new /obj/item/stack/sheet/snow(T, 1)
+ new /obj/item/stack/sheet/snow(T, 1)
+ if(hat)
+ hat.loc = T
+ if(carrot)
+ carrot.loc = T
+ del(src)
+
+ else if(fire_alert)
+ src.say(pick("Oh god the heat...","I'm meltiiinggg...","Someone turn off the heater!"))
+
+ regenerate_icons()
+
+/mob/living/simple_animal/hostile/retaliate/snowman/Retaliate()
+ ..()
+ if(!stat)
+ src.say(pick("You, come fight me!","I say!","Coward!"))
+
+/mob/living/simple_animal/hostile/retaliate/snowman/attackby(var/obj/item/W, var/mob/user)
+ if(!carrot && istype(W, /obj/item/weapon/reagent_containers/food/snacks/grown/carrot))
+ visible_message("[user] puts \a [W] on \the [src]'s nose.")
+ user.drop_item()
+ carrot = W
+ carrot.loc = src
+ overlays += "snowman_carrot"
+ speak -= "Would you happen to have a carrot for my nose?"
+ src.say("Ah, most excellent!")
+ if(prob(30))
+ call(/obj/item/weapon/winter_gift/proc/pick_a_gift)(src.loc)
+
+ else if(istype(W,/obj/item/clothing/head/))
+ if(hat)
+ hat.loc = get_turf(src)
+ overlays -= image('icons/mob/head.dmi', hat.icon_state)
+ hat = null
+ else
+ speak += "I feel so dandy!"
+ user.drop_item()
+ hat = W
+ hat.loc = src
+
+ overlays += image('icons/mob/head.dmi', hat.icon_state)
+
+ else ..()
+
+/obj/item/projectile/snowball
+ name = "flying snowball"
+ desc = "Think fast!"
+ icon = 'icons/obj/items.dmi'
+ icon_state = "snow"
+ nodamage = 1
+ stun = 1
+ weaken = 1
+ stutter = 1
+
+/obj/item/projectile/snowball/Bump(atom/A as mob|obj|turf|area)
+ .=..()
+ if(.)
+ playsound(A.loc, "swing_hit", 50, 1)
+ if(istype(A,/mob/living/carbon/))
+ var/mob/living/carbon/C = A
+ if(C.bodytemperature >= 265)
+ C.bodytemperature -= 5
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index ce3581ce793..8205ed5b777 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -3,6 +3,8 @@
icon = 'icons/mob/animal.dmi'
health = 20
maxHealth = 20
+ fire_dmi = 'icons/mob/OnFire.dmi'
+ fire_sprite = "Generic_mob_burning"
var/icon_living = ""
var/icon_dead = ""
diff --git a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm
index cfa3cb8b4fe..c59f7b84ec8 100644
--- a/code/modules/projectiles/projectile/special.dm
+++ b/code/modules/projectiles/projectile/special.dm
@@ -58,7 +58,7 @@
if(200 to 260)
name = "cold beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_1
icon_state = "temp_2"
- if(120 to 260)
+ if(120 to 200)
name = "ice beam" //temp at which mobs start taking COLD_DAMAGE_LEVEL_2
icon_state = "temp_1"
if(-INFINITY to 120)
@@ -78,6 +78,9 @@
if(temperature > 500)//emagged
M.adjust_fire_stacks(0.5)
M.on_fire = 1
+ if(M.fire_dmi && M.fire_sprite)
+ M.fire_overlay = image(M.fire_dmi,M.fire_sprite)
+ M.overlays += M.fire_overlay
M.update_icon = 1
playsound(M.loc, 'sound/effects/bamf.ogg', 50, 0)
return 1
diff --git a/code/setup.dm b/code/setup.dm
index 25f70aee4c9..122a888c6bd 100644
--- a/code/setup.dm
+++ b/code/setup.dm
@@ -419,6 +419,7 @@ var/MAX_EXPLOSION_RANGE = 14
#define POWEROFF 4 // tbd
#define MAINT 8 // under maintaince
#define EMPED 16 // temporary broken by EMP pulse
+#define FROZEN 32 // frozen by cosmic snow
//bitflags for door switches.
#define OPEN 1
diff --git a/icons/mob/animal.dmi b/icons/mob/animal.dmi
index 3dd0f114372..35e66020a21 100644
Binary files a/icons/mob/animal.dmi and b/icons/mob/animal.dmi differ
diff --git a/icons/obj/monitors.dmi b/icons/obj/monitors.dmi
index a817a42648c..79fab2018b6 100644
Binary files a/icons/obj/monitors.dmi and b/icons/obj/monitors.dmi differ