diff --git a/code/__DEFINES/misc_defines.dm b/code/__DEFINES/misc_defines.dm index 18a99991f46..d9328e682ff 100644 --- a/code/__DEFINES/misc_defines.dm +++ b/code/__DEFINES/misc_defines.dm @@ -490,6 +490,7 @@ #define LINDA_SPAWN_N2O 64 #define LINDA_SPAWN_AGENT_B 128 #define LINDA_SPAWN_AIR 256 +#define LINDA_SPAWN_COLD 512 // Throwing these defines here for the TM to minimise conflicts #define MAPROTATION_MODE_NORMAL_VOTE "Vote" diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 92e50b3f80e..f3afc8f0226 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -96,6 +96,8 @@ #define STATUS_EFFECT_CLINGTENTACLE /datum/status_effect/cling_tentacle //Imobilises target for 3 seconds +#define STATUS_EFFECT_CRYO_BEAM /datum/status_effect/cryo_beam //Chills target, freezes reagents in their blood, breaks if sight is lost. + //#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse //#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured //#define CURSE_SPAWNING 2 //spawns creatures that attack the target only diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 1a88d3a07ad..1f8b01d7ccb 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -945,3 +945,29 @@ #undef FAKE_FOOD_POISONING #undef FAKE_RETRO_VIRUS #undef FAKE_TURBERCULOSIS + +/datum/status_effect/cryo_beam + id = "cryo beam" + alert_type = null + duration = -1 //Kill it, get out of sight, or be killed. Jump boots are *required* + tick_interval = 0.5 SECONDS + var/damage = 0.75 + var/source_UID + +/datum/status_effect/cryo_beam/on_creation(mob/living/new_owner, mob/living/source) + . = ..() + source_UID = source.UID() + +/datum/status_effect/cryo_beam/tick() + var/mob/living/simple_animal/hostile/megafauna/ancient_robot/attacker = locateUID(source_UID) + if(!(owner in view(attacker, 8))) + qdel(src) + return + + owner.apply_damage(damage, BURN) + owner.bodytemperature = max(0, owner.bodytemperature - 20) + owner.Beam(attacker.beam, icon_state = "medbeam", time = 0.5 SECONDS) + for(var/datum/reagent/R in owner.reagents.reagent_list) + owner.reagents.remove_reagent(R.id, 0.75) + if(prob(10)) + to_chat(owner, "Your blood freezes in your veins, get away!") diff --git a/code/game/objects/effects/anomalies.dm b/code/game/objects/effects/anomalies.dm index 31fa7d8e24c..8c4a00df573 100644 --- a/code/game/objects/effects/anomalies.dm +++ b/code/game/objects/effects/anomalies.dm @@ -365,6 +365,57 @@ ///////////////////// +/obj/effect/anomaly/cryo + name = "cryogenic anomaly" + desc = "Hope you brought a jacket!" + icon_state = "cryoanomaly" + aSignal = /obj/item/assembly/signaler/anomaly/cryo + +/obj/effect/anomaly/cryo/anomalyEffect() + ..() + + var/list/turf_targets = list() + for(var/turf/T in oview(get_turf(src), 7)) + turf_targets += T + + for(var/I in 1 to rand(1, 3)) + var/turf/target = pick(turf_targets) + shootAt(target) + + if(prob(50)) + for(var/turf/simulated/floor/nearby_floor in oview(get_turf(src), (drops_core ? 2 : 1))) + nearby_floor.MakeSlippery(TURF_WET_PERMAFROST) + + var/turf/simulated/T = get_turf(src) + if(istype(T)) + T.atmos_spawn_air(LINDA_SPAWN_COLD | LINDA_SPAWN_N2O | LINDA_SPAWN_CO2, 20) + + if(prob(10)) + var/obj/effect/nanofrost_container/A = new /obj/effect/nanofrost_container(get_turf(src)) + for(var/i in 1 to 5) + step_towards(A, pick(turf_targets)) + sleep(2) + A.Smoke() + +/obj/effect/anomaly/cryo/proc/shootAt(atom/movable/target) + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + if(!T || !U) + return + var/obj/item/projectile/temp/basilisk/O = new /obj/item/projectile/temp/basilisk(T) + playsound(get_turf(src), 'sound/weapons/taser2.ogg', 75, TRUE) + O.current = T + O.yo = U.y - T.y + O.xo = U.x - T.x + O.fire() + +/obj/effect/anomaly/cryo/detonate() + var/turf/simulated/T = get_turf(src) + if(istype(T) && drops_core) + T.atmos_spawn_air(LINDA_SPAWN_COLD | LINDA_SPAWN_CO2, 1000) + +///////////////////// + /obj/effect/anomaly/bhole name = "vortex anomaly" icon_state = "bhole3" diff --git a/code/game/turfs/simulated/floor/asteroid_floors.dm b/code/game/turfs/simulated/floor/asteroid_floors.dm index 9223d312c91..292fa382482 100644 --- a/code/game/turfs/simulated/floor/asteroid_floors.dm +++ b/code/game/turfs/simulated/floor/asteroid_floors.dm @@ -42,12 +42,6 @@ /turf/simulated/floor/plating/asteroid/burn_tile() return -/turf/simulated/floor/plating/asteroid/MakeSlippery(wet_setting) - return - -/turf/simulated/floor/plating/asteroid/MakeDry(wet_setting) - return - /turf/simulated/floor/plating/asteroid/remove_plating() return diff --git a/code/modules/atmospherics/environmental/LINDA_system.dm b/code/modules/atmospherics/environmental/LINDA_system.dm index c2c9c83f721..235e387135b 100644 --- a/code/modules/atmospherics/environmental/LINDA_system.dm +++ b/code/modules/atmospherics/environmental/LINDA_system.dm @@ -138,6 +138,9 @@ if(flag & LINDA_SPAWN_HEAT) G.temperature += 1000 + if(flag & LINDA_SPAWN_COLD) + G.temperature = TCMB + if(flag & LINDA_SPAWN_TOXINS) G.toxins += amount diff --git a/code/modules/clothing/suits/armor_suits.dm b/code/modules/clothing/suits/armor_suits.dm index b1e965ce99c..0b802239031 100644 --- a/code/modules/clothing/suits/armor_suits.dm +++ b/code/modules/clothing/suits/armor_suits.dm @@ -517,6 +517,54 @@ return TRUE return FALSE +/obj/item/clothing/suit/armor/reactive/cryo + name = "reactive gelidic armor" //is "gelidic" a word? probably not, but it sounds cool + desc = "This armor harnesses a cryogenic anomaly core to defend its user from the cold and attacks alike. Its unstable thermal regulation system occasionally vents gasses." + +/obj/item/clothing/suit/armor/reactive/cryo/equipped(mob/user, slot) + ..() + if(slot != slot_wear_suit) + return + ADD_TRAIT(user, TRAIT_RESISTCOLD, "[UID()]") + +/obj/item/clothing/suit/armor/reactive/cryo/dropped(mob/user, silent) + ..() + REMOVE_TRAIT(user, TRAIT_RESISTCOLD, "[UID()]") + +/obj/item/clothing/suit/armor/reactive/cryo/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(!active) + return FALSE + if(reaction_check(hitby) && use_power()) + owner.visible_message("[src] blocks [attack_text], sending out freezing bolts!") + + for(var/mob/M in oview(get_turf(src), 7)) + shootAt(M) + + if(prob(10)) //rarely vent gasses + owner.visible_message("[src] vents excess coolant!") + playsound(loc, 'sound/effects/refill.ogg', 50, TRUE) + + var/turf/simulated/T = get_turf(src) + if(istype(T)) + T.atmos_spawn_air(LINDA_SPAWN_COLD | LINDA_SPAWN_N2O | LINDA_SPAWN_CO2, 20) + + disable(rand(1, 3)) + + return TRUE + return FALSE + +/obj/item/clothing/suit/armor/reactive/cryo/proc/shootAt(atom/movable/target) + var/turf/T = get_turf(src) + var/turf/U = get_turf(target) + if(!T || !U) + return + var/obj/item/projectile/temp/basilisk/O = new /obj/item/projectile/temp/basilisk(T) + playsound(get_turf(src), 'sound/weapons/taser2.ogg', 75, TRUE) + O.current = T + O.yo = U.y - T.y + O.xo = U.x - T.x + O.fire() + /obj/item/clothing/suit/armor/reactive/stealth name = "reactive stealth armor" diff --git a/code/modules/events/anomaly_cryo.dm b/code/modules/events/anomaly_cryo.dm new file mode 100644 index 00000000000..614c2afae8b --- /dev/null +++ b/code/modules/events/anomaly_cryo.dm @@ -0,0 +1,8 @@ +/datum/event/anomaly/anomaly_cryo + name = "Anomaly: Cryogenic" + startWhen = 3 + announceWhen = 10 + anomaly_path = /obj/effect/anomaly/cryo + +/datum/event/anomaly/anomaly_cryo/announce() + GLOB.minor_announcement.Announce("Cryogenic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_pyro.ogg') diff --git a/code/modules/events/anomaly_pyro.dm b/code/modules/events/anomaly_pyro.dm index 17ac978d566..be2a2573500 100644 --- a/code/modules/events/anomaly_pyro.dm +++ b/code/modules/events/anomaly_pyro.dm @@ -5,4 +5,4 @@ anomaly_path = /obj/effect/anomaly/pyro /datum/event/anomaly/anomaly_pyro/announce() - GLOB.minor_announcement.Announce("Atmospheric anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_pyro.ogg') + GLOB.minor_announcement.Announce("Pyroclastic anomaly detected on long range scanners. Expected location: [impact_area.name].", "Anomaly Alert", 'sound/AI/anomaly_pyro.ogg') diff --git a/code/modules/events/event_container.dm b/code/modules/events/event_container.dm index e5a87ca7fe1..7143d0e4b4c 100644 --- a/code/modules/events/event_container.dm +++ b/code/modules/events/event_container.dm @@ -70,7 +70,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) for(var/event_meta in last_event_time) if(possible_events[event_meta]) var/time_passed = world.time - GLOB.event_last_fired[event_meta] var/half_of_round = GLOB.configuration.event.expected_round_length / 2 - var/weight_modifier = min(1, 1 - ((half_of_round - time_passed) / half_of_round)) + var/weight_modifier = min(1, 1 - ((half_of_round - time_passed) / half_of_round)) //With this formula, an event ran 30 minutes ago has half weight, and an event ran an hour ago, has 100 % weight. This works better in general for events, as super high weight events are impacted in a meaningful way. var/new_weight = max(possible_events[event_meta] * weight_modifier, 0) if(new_weight) @@ -179,6 +179,7 @@ GLOBAL_LIST_EMPTY(event_last_fired) new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vent Clog", /datum/event/vent_clog, 250), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Wormholes", /datum/event/wormholes, 150), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Pyro Anomaly", /datum/event/anomaly/anomaly_pyro, 75, list(ASSIGNMENT_ENGINEER = 60)), + new /datum/event_meta(EVENT_LEVEL_MODERATE, "Cryo Anomaly", /datum/event/anomaly/anomaly_cryo, 75, list(ASSIGNMENT_ENGINEER = 60)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Vortex Anomaly", /datum/event/anomaly/anomaly_vortex, 75, list(ASSIGNMENT_ENGINEER = 25)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Bluespace Anomaly", /datum/event/anomaly/anomaly_bluespace, 75, list(ASSIGNMENT_ENGINEER = 25)), new /datum/event_meta(EVENT_LEVEL_MODERATE, "Flux Anomaly", /datum/event/anomaly/anomaly_flux, 75, list(ASSIGNMENT_ENGINEER = 50)), diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm index d1a1f44d333..6c760849892 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/ancient_robot.dm @@ -6,6 +6,7 @@ #define PYRO 3 #define FLUX 4 #define VORTEX 5 +#define CRYO 6 #define TOP_RIGHT 1 #define TOP_LEFT 2 #define BOTTOM_RIGHT 3 @@ -101,7 +102,7 @@ Difficulty: Hard BR = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, BOTTOM_RIGHT) BL = new /mob/living/simple_animal/hostile/ancient_robot_leg(loc, src, BOTTOM_LEFT) beam = new /obj/effect/abstract(loc) - mode = pick(BLUESPACE, GRAV, PYRO, FLUX, VORTEX) //picks one of the 5 cores. + mode = pick(BLUESPACE, GRAV, PYRO, FLUX, VORTEX, CRYO) //picks one of the 6 cores if(mode == FLUX) // Main attack is shock, so flux makes it stronger melee_damage_lower = 25 melee_damage_upper = 25 @@ -160,6 +161,8 @@ Difficulty: Hard core_type = /obj/item/assembly/signaler/anomaly/flux if(VORTEX) core_type = /obj/item/assembly/signaler/anomaly/vortex + if(CRYO) + core_type = /obj/item/assembly/signaler/anomaly/cryo var/crate_type = pick(loot) var/obj/structure/closet/crate/C = new crate_type(loc) @@ -345,6 +348,10 @@ Difficulty: Hard for(var/turf/turf in range(9,get_turf(target))) if(prob(15)) new /obj/effect/temp_visual/target/ancient(turf) + if(CRYO) + visible_message("[src]'s shell opens slightly, as sensors begin locking on to everyone around it!") + for(var/mob/living/carbon/human/H in view(7, src)) + H.apply_status_effect(STATUS_EFFECT_CRYO_BEAM, src) /mob/living/simple_animal/hostile/megafauna/ancient_robot/proc/spawn_anomalies() say(pick("JKVRUEOTM XGC VUCKX", "KXXUX OT GTUSGRE IUTZGOTSKTZ", "YZGHOROZE OT OTYZGHOROZE OT YZGHOROZE OT OTYZGH-")) @@ -373,6 +380,8 @@ Difficulty: Hard A.knockdown = TRUE if(VORTEX) new /obj/effect/anomaly/bhole(spot, 150, FALSE) + if(CRYO) + new /obj/effect/anomaly/cryo(spot, 150, FALSE) anomalies++ return @@ -518,6 +527,14 @@ Difficulty: Hard for(var/atom/A in T) A.ex_act(3) //Body is immune to explosions of this strength. T.ex_act(3) + if(mode == CRYO) + var/turf/simulated/S = get_turf(src) + S.MakeSlippery(TURF_WET_ICE) + for(var/turf/T in range (1, src)) + new /obj/effect/snowcloud(T) + for(var/mob/living/carbon/C in T.contents) + C.bodytemperature = max(0, C.bodytemperature - 300) //Take a chill pill. + C.apply_status_effect(/datum/status_effect/freon/watcher) // 0.8 seconds of no moving, should be funny. beam.forceMove(get_turf(src)) return ..() @@ -775,4 +792,5 @@ Difficulty: Hard #undef GRAV #undef PYRO #undef FLUX +#undef CRYO #undef VORTEX diff --git a/code/modules/research/anomaly/anomaly.dm b/code/modules/research/anomaly/anomaly.dm index 632f9a74c5b..e3d80b984ed 100644 --- a/code/modules/research/anomaly/anomaly.dm +++ b/code/modules/research/anomaly/anomaly.dm @@ -24,6 +24,13 @@ anomaly_type = /obj/effect/anomaly/pyro origin_tech = "plasmatech=7" +/obj/item/assembly/signaler/anomaly/cryo + name = "\improper cryogenic anomaly core" + desc = "The neutralized core of a cryogenic anomaly. Rime is forming on its cold surface. It'd probably be valuable for research." + icon_state = "cryo_core" + anomaly_type = /obj/effect/anomaly/cryo + origin_tech = "biotech=7" + /obj/item/assembly/signaler/anomaly/grav name = "\improper gravitational anomaly core" desc = "The neutralized core of a gravitational anomaly. It feels much heavier than it looks. It'd probably be valuable for research." @@ -57,7 +64,7 @@ /obj/item/assembly/signaler/anomaly/random/New() ..() - var/list/types = list(/obj/item/assembly/signaler/anomaly/pyro, /obj/item/assembly/signaler/anomaly/grav, /obj/item/assembly/signaler/anomaly/flux, /obj/item/assembly/signaler/anomaly/bluespace, /obj/item/assembly/signaler/anomaly/vortex) + var/list/types = list(/obj/item/assembly/signaler/anomaly/pyro, /obj/item/assembly/signaler/anomaly/cryo, /obj/item/assembly/signaler/anomaly/grav, /obj/item/assembly/signaler/anomaly/flux, /obj/item/assembly/signaler/anomaly/bluespace, /obj/item/assembly/signaler/anomaly/vortex) var/A = pick(types) new A(loc) qdel(src) @@ -74,23 +81,17 @@ /obj/item/assembly/signaler/anomaly/grav = /obj/item/clothing/suit/armor/reactive/repulse, /obj/item/assembly/signaler/anomaly/flux = /obj/item/clothing/suit/armor/reactive/tesla, /obj/item/assembly/signaler/anomaly/bluespace = /obj/item/clothing/suit/armor/reactive/teleport, - /obj/item/assembly/signaler/anomaly/pyro = /obj/item/clothing/suit/armor/reactive/fire + /obj/item/assembly/signaler/anomaly/pyro = /obj/item/clothing/suit/armor/reactive/fire, + /obj/item/assembly/signaler/anomaly/cryo = /obj/item/clothing/suit/armor/reactive/cryo, + /obj/item/assembly/signaler/anomaly/vortex = /obj/item/clothing/suit/armor/reactive/stealth ) if(istype(I, /obj/item/assembly/signaler/anomaly)) var/obj/item/assembly/signaler/anomaly/A = I - var/armour_path = /obj/item/clothing/suit/armor/reactive/stealth //Fallback - if(istype(I, /obj/item/assembly/signaler/anomaly/grav)) - armour_path = /obj/item/clothing/suit/armor/reactive/repulse - if(istype(I, /obj/item/assembly/signaler/anomaly/flux)) - armour_path = /obj/item/clothing/suit/armor/reactive/tesla - if(istype(I, /obj/item/assembly/signaler/anomaly/bluespace)) - armour_path = /obj/item/clothing/suit/armor/reactive/teleport - if(istype(I, /obj/item/assembly/signaler/anomaly/pyro)) - armour_path = /obj/item/clothing/suit/armor/reactive/fire - if(istype(I, /obj/item/assembly/signaler/anomaly/vortex)) - armour_path = /obj/item/clothing/suit/armor/reactive/stealth // Vortex needs one, this is just temporary(TM) till one is coded for them. - to_chat(user, "You insert [A] into the chest plate, and the armour gently hums to life.") + var/armour_path = anomaly_armour_types[A.type] + if(!armour_path) + armour_path = /obj/item/clothing/suit/armor/reactive/stealth //Fallback + to_chat(user, "You insert [A] into the chest plate, and the armor gently hums to life.") new armour_path(get_turf(src)) qdel(src) qdel(A) diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 3776d516560..9db0364de2e 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ diff --git a/icons/mob/lavaland/64x64megafauna.dmi b/icons/mob/lavaland/64x64megafauna.dmi index 706b4369dbf..cd31b76fce7 100644 Binary files a/icons/mob/lavaland/64x64megafauna.dmi and b/icons/mob/lavaland/64x64megafauna.dmi differ diff --git a/icons/obj/assemblies/new_assemblies.dmi b/icons/obj/assemblies/new_assemblies.dmi index 18ea88b5dd5..bd63a90e153 100644 Binary files a/icons/obj/assemblies/new_assemblies.dmi and b/icons/obj/assemblies/new_assemblies.dmi differ diff --git a/paradise.dme b/paradise.dme index 5d4bcf5629d..30f214fd036 100644 --- a/paradise.dme +++ b/paradise.dme @@ -1609,6 +1609,7 @@ #include "code\modules\events\abductor_event.dm" #include "code\modules\events\alien_infestation.dm" #include "code\modules\events\anomaly_bluespace.dm" +#include "code\modules\events\anomaly_cryo.dm" #include "code\modules\events\anomaly_event.dm" #include "code\modules\events\anomaly_flux.dm" #include "code\modules\events\anomaly_grav.dm"