diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index b214077b684..13c341c6d05 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -10,6 +10,7 @@
#define STATUS_EFFECT_SHADOW_MEND /datum/status_effect/shadow_mend //Quick, powerful heal that deals damage afterwards. Heals 15 brute/burn every second for 3 seconds.
#define STATUS_EFFECT_VOID_PRICE /datum/status_effect/void_price //The price of healing yourself with void energy. Deals 3 brute damage every 3 seconds for 30 seconds.
+#define STATUS_EFFECT_VANGUARD /datum/status_effect/vanguard_shield //Grants temporary stun absorption, but will stun the user based on how many stuns they absorbed.
#define STATUS_EFFECT_INATHNEQS_ENDOWMENT /datum/status_effect/inathneqs_endowment //A 15-second invulnerability and stun absorption, granted by Inath-neq.
/////////////
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 60f0df97dc1..b0d8930bf70 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -3,7 +3,7 @@
//PUBLIC - call these wherever you want
-/mob/proc/throw_alert(category, type, severity, obj/new_master, datum/status_effect/effect)
+/mob/proc/throw_alert(category, type, severity, obj/new_master)
/* Proc to create or update an alert. Returns the alert if the alert is new or updated, 0 if it was thrown already
category is a text string. Each mob may only have one alert per category; the previous one will be replaced
@@ -43,13 +43,7 @@
alert.icon_state = "template" // We'll set the icon to the client's ui pref in reorganize_alerts()
alert.master = new_master
else
- if(effect)
- alert.name = effect.name
- alert.desc = effect.desc
- alert.icon = 'icons/mob/status_effects.dmi'
- alert.icon_state = effect.icon_state
- else
- alert.icon_state = "[initial(alert.icon_state)][severity]"
+ alert.icon_state = "[initial(alert.icon_state)][severity]"
alert.severity = severity
alerts[category] = alert
diff --git a/code/datums/status_effects/buffs.dm b/code/datums/status_effects/buffs.dm
index 8a5a1543e84..a64a16fb836 100644
--- a/code/datums/status_effects/buffs.dm
+++ b/code/datums/status_effects/buffs.dm
@@ -1,11 +1,14 @@
//Largely beneficial effects go here, even if they have drawbacks. An example is provided in Shadow Mend.
/datum/status_effect/shadow_mend
+ id = "shadow_mend"
+ duration = 3
+ alert_type = /obj/screen/alert/status_effect/shadow_mend
+
+/obj/screen/alert/status_effect/shadow_mend
name = "Shadow Mend"
desc = "Shadowy energies wrap around your wounds, sealing them at a price. After healing, you will slowly lose health every three seconds for thirty seconds."
- id = "shadow_mend"
icon_state = "shadow_mend"
- duration = 3
/datum/status_effect/shadow_mend/on_apply()
owner.visible_message("Violet light wraps around [owner]'s body!", "Violet light wraps around your body!")
@@ -20,13 +23,17 @@
playsound(owner, 'sound/magic/Teleport_diss.ogg', 50, 1)
owner.apply_status_effect(STATUS_EFFECT_VOID_PRICE)
+
/datum/status_effect/void_price
- name = "Void Price"
- desc = "Black tendrils cinch tightly against you, digging wicked barbs into your flesh."
id = "void_price"
- icon_state = "shadow_mend"
duration = 30
tick_interval = 3
+ alert_type = /obj/screen/alert/status_effect/void_price
+
+/obj/screen/alert/status_effect/void_price
+ name = "Void Price"
+ desc = "Black tendrils cinch tightly against you, digging wicked barbs into your flesh."
+ icon_state = "shadow_mend"
/datum/status_effect/void_price/tick()
owner << sound('sound/magic/Summon_Karp.ogg', volume = 25)
@@ -34,23 +41,73 @@
+/datum/status_effect/vanguard_shield
+ id = "vanguard"
+ duration = 20
+ alert_type = /obj/screen/alert/status_effect/vanguard
+
+/obj/screen/alert/status_effect/vanguard
+ name = "Vanguard"
+ desc = "You're absorbing stuns! 25% of all stuns taken will affect you after this effect ends."
+ icon_state = "vanguard"
+ alerttooltipstyle = "clockcult"
+
+/obj/screen/alert/status_effect/vanguard/MouseEntered(location,control,params)
+ var/mob/living/L = usr
+ if(istype(L)) //this is probably more safety than actually needed
+ var/vanguard = L.stun_absorption["vanguard"]
+ desc = initial(desc)
+ desc += "
[vanguard["stuns_absorbed"] * 2] seconds of stuns held back.
[round(min(vanguard["stuns_absorbed"] * 0.25, 20)) * 2] seconds of stun will affect you."
+ ..()
+
+/datum/status_effect/vanguard_shield/on_apply()
+ owner.add_stun_absorption("vanguard", 200, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " is radiating with a soft yellow light!")
+ owner.visible_message("[owner] begins to faintly glow!", "You will absorb all stuns for the next twenty seconds.")
+
+/datum/status_effect/vanguard_shield/on_remove()
+ var/vanguard = owner.stun_absorption["vanguard"]
+ var/stuns_blocked = 0
+ if(vanguard)
+ stuns_blocked = round(min(vanguard["stuns_absorbed"] * 0.25, 20))
+ if(owner.stat != DEAD)
+ var/message_to_owner = "You feel your Vanguard quietly fade..."
+ var/otheractiveabsorptions = FALSE
+ for(var/i in owner.stun_absorption)
+ if(owner.stun_absorption[i]["end_time"] > world.time && owner.stun_absorption[i]["priority"] > vanguard["priority"])
+ otheractiveabsorptions = TRUE
+ if(!ratvar_awakens && stuns_blocked && !otheractiveabsorptions)
+ vanguard["end_time"] = 0 //so it doesn't absorb the stuns we're about to apply
+ owner.Stun(stuns_blocked)
+ owner.Weaken(stuns_blocked)
+ message_to_owner = "The weight of the Vanguard's protection crashes down upon you!"
+ if(stuns_blocked >= 15)
+ message_to_owner += "\nYou faint from the exertion!"
+ owner.Paralyse(stuns_blocked * 2)
+ owner.visible_message("[owner]'s glowing aura fades!", message_to_owner)
+
+
+
/datum/status_effect/inathneqs_endowment
- name = "Inath-neq's Endowment"
- desc = "Adrenaline courses through you as the Cogwheel's energy shields you from all harm!"
id = "inathneqs_endowment"
- icon_state = "inathneqs_endowment"
duration = 15
+ alert_type = /obj/screen/alert/status_effect/inathneqs_endowment
+
+/obj/screen/alert/status_effect/inathneqs_endowment
+ name = "Inath-neq's Endowment"
+ desc = "Adrenaline courses through you as the Resonant Cogwheel's energy shields you from all harm!"
+ icon_state = "inathneqs_endowment"
+ alerttooltipstyle = "clockcult"
/datum/status_effect/inathneqs_endowment/on_apply()
owner.visible_message("[owner] shines with azure light!", "You feel Inath-neq's power flow through you! You're invincible!")
owner.color = "#1E8CE1"
owner.fully_heal()
- owner.add_stun_absorption("inathneq", 150, 1, "'s flickering blue aura momentarily intensifies!", "Inath-neq's power absorbs the stun!", " is surrounded by blue light!")
+ owner.add_stun_absorption("inathneq", 150, 2, "'s flickering blue aura momentarily intensifies!", "Inath-neq's power absorbs the stun!", " is glowing with a flickering blue light!")
owner.status_flags |= GODMODE
animate(owner, color = initial(owner.color), time = 150, easing = EASE_IN)
playsound(owner, 'sound/magic/Ethereal_Enter.ogg', 50, 1)
/datum/status_effect/inathneqs_endowment/on_remove()
- owner.visible_message("The light around [owner] flickers and dissipates!", "Inath-neq's shield wavers and fails!")
+ owner.visible_message("The light around [owner] flickers and dissipates!", "You feel Inath-neq's power fade from your body!")
owner.status_flags &= ~GODMODE
playsound(owner, 'sound/magic/Ethereal_Exit.ogg', 50, 1)
diff --git a/code/datums/status_effects/gas.dm b/code/datums/status_effects/gas.dm
index 2b477d4cba3..763654605a9 100644
--- a/code/datums/status_effects/gas.dm
+++ b/code/datums/status_effects/gas.dm
@@ -1,12 +1,15 @@
/datum/status_effect/freon
- name = "Frozen Solid"
- desc = "You're frozen inside of an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!"
id = "frozen"
- icon_state = "frozen"
duration = 10
unique = TRUE
+ alert_type = /obj/screen/alert/status_effect/freon
var/icon/cube
+/obj/screen/alert/status_effect/freon
+ name = "Frozen Solid"
+ desc = "You're frozen inside of an ice cube, and cannot move! You can still do stuff, like shooting. Resist out of the cube!"
+ icon_state = "frozen"
+
/datum/status_effect/freon/on_apply()
if(!owner.stat)
owner << "You become frozen in a cube!"
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index 5f7d95d902d..3bf25eb02a2 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -3,78 +3,90 @@
//When making a new status effect, add a define to status_effects.dm in __DEFINES for ease of use!
var/list/status_effects = list() //All status effects affecting literally anyone
/datum/status_effect
- var/name = "Curse of Mundanity"
- var/desc = "You don't feel any different..."
var/id = "effect" //Used for screen alerts.
- var/icon_state //Used for displaying the status effect.
var/duration = -1 //How long the status effect lasts in SECONDS. Enter -1 for an effect that never ends unless removed through some means.
var/tick_interval = 1 //How many seconds between ticks. Leave at 1 for every second.
var/mob/living/owner //The mob affected by the status effect.
var/cosmetic = FALSE //If the status effect only exists for flavor.
var/unique = TRUE //If there can be multiple status effects of this type on one mob.
+ var/alert_type = /obj/screen/alert/status_effect //the alert thrown by the status effect, contains name and description
/datum/status_effect/New()
..()
status_effects += src
- spawn(1) //Give us time to set any variables
- start_ticking()
+ addtimer(src, "start_ticking", 1) //Give us time to set any variables
/datum/status_effect/Destroy()
status_effects -= src
- ..()
+ return ..()
/datum/status_effect/proc/start_ticking()
if(!src)
return
- if(owner)
- on_apply()
- owner.throw_alert(id, /obj/screen/alert, effect = src)
+ if(!owner)
+ qdel(src)
+ return
+ on_apply()
+ var/obj/screen/alert/status_effect/A = owner.throw_alert(id, alert_type)
+ A.attached_effect = src //so the alert can reference us, if it needs to
START_PROCESSING(SSprocessing, src)
/datum/status_effect/process()
+ if(!owner)
+ cancel_effect()
+ return
if(duration != -1)
duration--
tick_interval--
if(!tick_interval)
tick()
tick_interval = initial(tick_interval)
- if(!duration && duration != -1)
+ if(!duration)
cancel_effect()
/datum/status_effect/proc/cancel_effect()
STOP_PROCESSING(SSprocessing, src)
- owner.clear_alert(id)
- on_remove()
+ if(owner)
+ owner.clear_alert(id)
+ on_remove()
qdel(src)
/datum/status_effect/proc/on_apply() //Called whenever the buff is applied.
/datum/status_effect/proc/tick() //Called every tick.
/datum/status_effect/proc/on_remove() //Called whenever the buff expires or is removed.
+////////////////
+// ALERT HOOK //
+////////////////
+
+/obj/screen/alert/status_effect
+ name = "Curse of Mundanity"
+ desc = "You don't feel any different..."
+ var/datum/status_effect/attached_effect
+
//////////////////
// HELPER PROCS //
//////////////////
-/mob/living/proc/apply_status_effect(effect)
+
+/mob/living/proc/apply_status_effect(effect) //applies a given status effect to this mob, returning the effect if it was successful
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.unique) && S.id == initial(S1.id) && S.owner == src)
return
S1 = new effect
S1.owner = src
- return 1
+ . = S1
-
-/mob/living/proc/remove_status_effect(effect)
+/mob/living/proc/remove_status_effect(effect) //removes all of a given status effect from this mob, returning TRUE if at least one was removed
+ . = FALSE
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id && S.owner == src)
S.cancel_effect()
- return
- return 1
+ . = TRUE
-/mob/living/proc/has_status_effect(effect)
+/mob/living/proc/has_status_effect(effect) //returns TRUE if the mob calling the proc owns the given status effect
var/datum/status_effect/S1 = effect
for(var/datum/status_effect/S in status_effects)
if(initial(S1.id) == S.id && S.owner == src)
- return 1
- return 0
+ return TRUE
diff --git a/code/game/gamemodes/clock_cult/clock_scripture.dm b/code/game/gamemodes/clock_cult/clock_scripture.dm
index 00abf88c55b..ff7a04995b8 100644
--- a/code/game/gamemodes/clock_cult/clock_scripture.dm
+++ b/code/game/gamemodes/clock_cult/clock_scripture.dm
@@ -238,7 +238,6 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
required_components = list("vanguard_cogwheel" = 1)
usage_tip = "You cannot reactivate Vanguard while still shielded by it."
tier = SCRIPTURE_DRIVER
- var/total_duration = 200
/datum/clockwork_scripture/vanguard/check_special_requirements()
if(islist(invoker.stun_absorption) && invoker.stun_absorption["vanguard"] && invoker.stun_absorption["vanguard"]["end_time"] > world.time)
@@ -247,31 +246,7 @@ Judgement: 10 servants, 100 CV, and any existing AIs are converted or destroyed
return 1
/datum/clockwork_scripture/vanguard/scripture_effects()
- invoker.add_stun_absorption("vanguard", total_duration, 1, "'s yellow aura momentarily intensifies!", "Your ward absorbs the stun!", " is radiating with a soft yellow light!")
- invoker.visible_message("[invoker] begins to faintly glow!", "You will absorb all stuns for the next twenty seconds.")
- spawn(total_duration)
- if(!invoker)
- return
-
- var/vanguard = invoker.stun_absorption["vanguard"]
- var/stuns_blocked = 0
- if(vanguard)
- stuns_blocked = min(vanguard["stuns_absorbed"] * 0.25, 20)
- if(invoker.stat != DEAD)
- var/message_to_invoker = "You feel your Vanguard quietly fade..."
- var/otheractiveabsorptions = FALSE
- for(var/i in invoker.stun_absorption)
- if(invoker.stun_absorption[i]["end_time"] > world.time && invoker.stun_absorption[i]["priority"] > vanguard["priority"])
- otheractiveabsorptions = TRUE
- if(!ratvar_awakens && stuns_blocked && !otheractiveabsorptions)
- vanguard["end_time"] = 0 //so it doesn't absorb the stuns we're about to apply
- invoker.Stun(stuns_blocked)
- invoker.Weaken(stuns_blocked)
- message_to_invoker = "The weight of the Vanguard's protection crashes down upon you!"
- if(stuns_blocked >= 15)
- message_to_invoker += "\nYou faint from the exertion!"
- invoker.Paralyse(stuns_blocked * 2)
- invoker.visible_message("[invoker]'s glowing aura fades!", message_to_invoker)
+ invoker.apply_status_effect(STATUS_EFFECT_VANGUARD)
return 1
diff --git a/code/game/turfs/open.dm b/code/game/turfs/open.dm
index fe27c5dd20e..07d70bfc4b7 100644
--- a/code/game/turfs/open.dm
+++ b/code/game/turfs/open.dm
@@ -5,12 +5,6 @@
var/wet_time = 0 // Time in seconds that this floor will be wet for.
var/image/wet_overlay = null
-/turf/open/freon_gas_act()
- for(var/obj/I in contents)
- if(!I.is_frozen) // let it go
- I.make_frozen_visual(I)
- MakeSlippery(TURF_WET_PERMAFROST, 5)
- return
/turf/open/indestructible
name = "floor"
icon = 'icons/turf/floors.dmi'
@@ -74,6 +68,12 @@
air.temperature += temp
air_update_turf()
+/turf/open/freon_gas_act()
+ for(var/obj/I in contents)
+ if(!I.is_frozen) //let it go
+ I.make_frozen_visual(I)
+ MakeSlippery(TURF_WET_PERMAFROST, 5)
+
/turf/open/handle_fall(mob/faller, forced)
faller.lying = pick(90, 270)
if(!forced)
diff --git a/icons/mob/screen_alert.dmi b/icons/mob/screen_alert.dmi
index 3408a3e8262..c5eb9d42239 100644
Binary files a/icons/mob/screen_alert.dmi and b/icons/mob/screen_alert.dmi differ
diff --git a/icons/mob/status_effects.dmi b/icons/mob/status_effects.dmi
deleted file mode 100644
index a86af8ccc10..00000000000
Binary files a/icons/mob/status_effects.dmi and /dev/null differ