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