Files
Bubberstation/code/datums/status_effects/_status_effect.dm
MrMelbert 0d4b56435b Converts drowsy and eye blur to status effects, striking yet another two carbon level status vars (#71950)
## About The Pull Request

You know the deal by now.

- Drowsiness is now tracked via status effect.
- Eye blue is now tracked via status effect.

In converting these over, cleaned up a bit of code relating to some
other effects. Attempts to unify behavior between some of them, namely
certain biotypes or mob types shouldn't be experiencing certain effects.

## Why It's Good For The Game

More stuff moved to status effects, slightly more cleaner and better to
work with code. Allows for all mobs that can sleep to be able to get
drowsy, too.

## Changelog

🆑 Melbert
refactor: Drowsiness and Blurred Eyes are now tracked via status effect.
/🆑
2022-12-26 19:58:21 +01:00

179 lines
6.5 KiB
Plaintext

/// Status effects are used to apply temporary or permanent effects to mobs.
/// This file contains their code, plus code for applying and removing them.
/datum/status_effect
/// The ID of the effect. ID is used in adding and removing effects to check for duplicates, among other things.
var/id = "effect"
/// When set initially / in on_creation, this is how long the status effect lasts in deciseconds.
/// While processing, this becomes the world.time when the status effect will expire.
/// -1 = infinite duration.
var/duration = -1
/// When set initially / in on_creation, this is how long between [proc/tick] calls in deciseconds.
/// While processing, this becomes the world.time when the next tick will occur.
/// -1 = will stop processing, if duration is also unlimited (-1).
var/tick_interval = 1 SECONDS
/// The mob affected by the status effect.
var/mob/living/owner
/// How many of the effect can be on one mob, and/or what happens when you try to add a duplicate.
var/status_type = STATUS_EFFECT_UNIQUE
/// If TRUE, we call [proc/on_remove] when owner is deleted. Otherwise, we call [proc/be_replaced].
var/on_remove_on_mob_delete = FALSE
/// The typepath to the alert thrown by the status effect when created.
/// Status effect "name"s and "description"s are shown to the owner here.
var/alert_type = /atom/movable/screen/alert/status_effect
/// The alert itself, created in [proc/on_creation] (if alert_type is specified).
var/atom/movable/screen/alert/status_effect/linked_alert
/// Used to define if the status effect should be using SSfastprocess or SSprocessing
var/processing_speed = STATUS_EFFECT_FAST_PROCESS
/// Do we self-terminate when a fullheal is called?
var/remove_on_fullheal = FALSE
/// If remove_on_fullheal is TRUE, what flag do we need to be removed?
var/heal_flag_necessary = HEAL_STATUS
/datum/status_effect/New(list/arguments)
on_creation(arglist(arguments))
/// Called from New() with any supplied status effect arguments.
/// Not guaranteed to exist by the end.
/// Returning FALSE from on_apply will stop on_creation and self-delete the effect.
/datum/status_effect/proc/on_creation(mob/living/new_owner, ...)
if(new_owner)
owner = new_owner
if(QDELETED(owner) || !on_apply())
qdel(src)
return
if(owner)
LAZYADD(owner.status_effects, src)
RegisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL, PROC_REF(remove_effect_on_heal))
if(duration != -1)
duration = world.time + duration
tick_interval = world.time + tick_interval
if(alert_type)
var/atom/movable/screen/alert/status_effect/new_alert = owner.throw_alert(id, alert_type)
new_alert.attached_effect = src //so the alert can reference us, if it needs to
linked_alert = new_alert //so we can reference the alert, if we need to
if(duration > 0 || initial(tick_interval) > 0) //don't process if we don't care
switch(processing_speed)
if(STATUS_EFFECT_FAST_PROCESS)
START_PROCESSING(SSfastprocess, src)
if(STATUS_EFFECT_NORMAL_PROCESS)
START_PROCESSING(SSprocessing, src)
return TRUE
/datum/status_effect/Destroy()
switch(processing_speed)
if(STATUS_EFFECT_FAST_PROCESS)
STOP_PROCESSING(SSfastprocess, src)
if(STATUS_EFFECT_NORMAL_PROCESS)
STOP_PROCESSING(SSprocessing, src)
if(owner)
linked_alert = null
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
on_remove()
UnregisterSignal(owner, COMSIG_LIVING_POST_FULLY_HEAL)
owner = null
return ..()
// Status effect process. Handles adjusting its duration and ticks.
// If you're adding processed effects, put them in [proc/tick]
// instead of extending / overriding the process() proc.
/datum/status_effect/process(delta_time, times_fired)
SHOULD_NOT_OVERRIDE(TRUE)
if(QDELETED(owner))
qdel(src)
return
if(tick_interval < world.time)
tick(delta_time, times_fired)
tick_interval = world.time + initial(tick_interval)
if(duration != -1 && duration < world.time)
qdel(src)
/// Called whenever the effect is applied in on_created
/// Returning FALSE will cause it to delete itself during creation instead.
/datum/status_effect/proc/on_apply()
return TRUE
/// Gets and formats examine text associated with our status effect.
/// Return 'null' to have no examine text appear (default behavior).
/datum/status_effect/proc/get_examine_text()
return null
/// Called every tick from process().
/datum/status_effect/proc/tick(delta_time, times_fired)
return
/// Called whenever the buff expires or is removed (qdeleted)
/// Note that at the point this is called, it is out of the
/// owner's status_effects list, but owner is not yet null
/datum/status_effect/proc/on_remove()
return
/// Called instead of on_remove when a status effect
/// of status_type STATUS_EFFECT_REPLACE is replaced by itself,
/// or when a status effect with on_remove_on_mob_delete
/// set to FALSE has its mob deleted
/datum/status_effect/proc/be_replaced()
linked_alert = null
owner.clear_alert(id)
LAZYREMOVE(owner.status_effects, src)
owner = null
qdel(src)
/// Called before being fully removed (before on_remove)
/// Returning FALSE will cancel removal
/datum/status_effect/proc/before_remove()
return TRUE
/// Called when a status effect of status_type STATUS_EFFECT_REFRESH
/// has its duration refreshed in apply_status_effect - is passed New() args
/datum/status_effect/proc/refresh(effect, ...)
var/original_duration = initial(duration)
if(original_duration == -1)
return
duration = world.time + original_duration
/// Adds nextmove modifier multiplicatively to the owner while applied
/datum/status_effect/proc/nextmove_modifier()
return 1
/// Adds nextmove adjustment additiviely to the owner while applied
/datum/status_effect/proc/nextmove_adjust()
return 0
/// Signal proc for [COMSIG_LIVING_POST_FULLY_HEAL] to remove us on fullheal
/datum/status_effect/proc/remove_effect_on_heal(datum/source, heal_flags)
SIGNAL_HANDLER
if(!remove_on_fullheal)
return
if(!heal_flag_necessary || (heal_flags & heal_flag_necessary))
qdel(src)
/// Remove [seconds] of duration from the status effect, qdeling / ending if we eclipse the current world time.
/datum/status_effect/proc/remove_duration(seconds)
if(duration == -1) // Infinite duration
return FALSE
duration -= seconds
if(duration <= world.time)
qdel(src)
return TRUE
return FALSE
/// Alert base type for status effect alerts
/atom/movable/screen/alert/status_effect
name = "Curse of Mundanity"
desc = "You don't feel any different..."
/// The status effect we're linked to
var/datum/status_effect/attached_effect
/atom/movable/screen/alert/status_effect/Destroy()
attached_effect = null //Don't keep a ref now
return ..()