mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
* Update kinetic_javelin.dm * Update kinetic_javelin.dm * Update kinetic_javelin.dm * holy fire * done * done * Update holy_fire.dm
284 lines
10 KiB
Plaintext
284 lines
10 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
|
|
///If defined, this text will appear when the mob is examined - to use he, she etc. use "SUBJECTPRONOUN" and replace it in the examines themselves
|
|
var/examine_text
|
|
/// A particle effect, for things like embers - Should be set on update_particles()
|
|
var/obj/effect/abstract/particle_holder/particle_effect
|
|
|
|
/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)
|
|
update_particles()
|
|
|
|
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
|
|
if(particle_effect)
|
|
QDEL_NULL(particle_effect)
|
|
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)
|
|
|
|
/datum/status_effect/proc/on_apply() //Called whenever the buff is applied; returning FALSE will cause it to autoremove itself.
|
|
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
|
|
|
|
/datum/status_effect/proc/interact_speed_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
|
|
|
|
/**
|
|
* Updates the particles for the status effects
|
|
* Should be handled by subtypes!
|
|
*/
|
|
|
|
/datum/status_effect/proc/update_particles()
|
|
SHOULD_CALL_PARENT(FALSE)
|
|
|
|
////////////////
|
|
// ALERT HOOK //
|
|
////////////////
|
|
|
|
/atom/movable/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(datum/status_effect/new_effect, ...)
|
|
RETURN_TYPE(/datum/status_effect)
|
|
|
|
// The arguments we pass to the start effect. The 1st argument is this mob.
|
|
var/list/arguments = args.Copy()
|
|
arguments[1] = src
|
|
|
|
// If the status effect we're applying doesn't allow multiple effects, we need to handle it
|
|
if(initial(new_effect.status_type) != STATUS_EFFECT_MULTIPLE)
|
|
for(var/datum/status_effect/existing_effect as anything in status_effects)
|
|
if(existing_effect.id != initial(new_effect.id))
|
|
continue
|
|
|
|
switch(existing_effect.status_type)
|
|
// Multiple are allowed, continue as normal. (Not normally reachable)
|
|
if(STATUS_EFFECT_MULTIPLE)
|
|
break
|
|
// Only one is allowed of this type - early return
|
|
if(STATUS_EFFECT_UNIQUE)
|
|
return
|
|
// Replace the existing instance (deletes it).
|
|
if(STATUS_EFFECT_REPLACE)
|
|
existing_effect.be_replaced()
|
|
// Refresh the existing type, then early return
|
|
if(STATUS_EFFECT_REFRESH)
|
|
existing_effect.refresh(arglist(arguments))
|
|
return
|
|
|
|
// Create the status effect with our mob + our arguments
|
|
var/datum/status_effect/new_instance = new new_effect(arguments)
|
|
if(!QDELETED(new_instance))
|
|
return new_instance
|
|
|
|
/mob/living/proc/remove_status_effect(datum/status_effect/removed_effect, ...)
|
|
var/list/arguments = args.Copy(2)
|
|
|
|
. = FALSE
|
|
for(var/datum/status_effect/existing_effect as anything in status_effects)
|
|
if(existing_effect.id == initial(removed_effect.id) && existing_effect.before_remove(arguments))
|
|
qdel(existing_effect)
|
|
. = TRUE
|
|
|
|
return .
|
|
|
|
/**
|
|
* Checks if this mob has a status effect that shares the passed effect's ID
|
|
*
|
|
* checked_effect - TYPEPATH of a status effect to check for. Checks for its ID, not it's typepath
|
|
*
|
|
* Returns an instance of a status effect, or NULL if none were found.
|
|
*/
|
|
/mob/proc/has_status_effect(datum/status_effect/checked_effect)
|
|
// Yes I'm being cringe and putting this on the mob level even though status effects only apply to the living level
|
|
// There's quite a few places (namely examine and, bleh, cult code) where it's easier to not need to cast to living before checking
|
|
// for an effect such as blindness
|
|
return null
|
|
|
|
/mob/living/has_status_effect(datum/status_effect/checked_effect)
|
|
RETURN_TYPE(/datum/status_effect)
|
|
|
|
for(var/datum/status_effect/present_effect as anything in status_effects)
|
|
if(present_effect.id == initial(checked_effect.id))
|
|
return present_effect
|
|
|
|
return null
|
|
|
|
/**
|
|
* Returns a list of all status effects that share the passed effect type's ID
|
|
*
|
|
* checked_effect - TYPEPATH of a status effect to check for. Checks for its ID, not it's typepath
|
|
*
|
|
* Returns a list
|
|
*/
|
|
/mob/proc/has_status_effect_list(datum/status_effect/checked_effect)
|
|
// See [/mob/proc/has_status_effect] for reason behind having this on the mob level
|
|
return null
|
|
|
|
/mob/living/has_status_effect_list(datum/status_effect/checked_effect)
|
|
RETURN_TYPE(/list)
|
|
|
|
var/list/effects_found = list()
|
|
for(var/datum/status_effect/present_effect as anything in status_effects)
|
|
if(present_effect.id == initial(checked_effect.id))
|
|
effects_found += present_effect
|
|
|
|
return effects_found
|