mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 20:11:56 +00:00
* Cardboard cutouts are now tactical. (#81245) ## About The Pull Request Basically, this means players holding cardboard cutouts will now assume their appearance, just like for potted plants. Good for pranking. I've had to tweak the tactical component and the waddling element a bit to get them to work as intended while dealing with the multiple sources of the waddling element. ## Why It's Good For The Game  ## Changelog 🆑 add: Players holding cardboard cutouts will now assume their appearance, just like for potted plants. /🆑 * Cardboard cutouts are now tactical. --------- Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
104 lines
3.8 KiB
Plaintext
104 lines
3.8 KiB
Plaintext
/**
|
|
* A holder for simple behaviour that can be attached to many different types
|
|
*
|
|
* Only one element of each type is instanced during game init.
|
|
* Otherwise acts basically like a lightweight component.
|
|
*/
|
|
/datum/element
|
|
/// Option flags for element behaviour
|
|
var/element_flags = NONE
|
|
/**
|
|
* The index of the first attach argument to consider for duplicate elements
|
|
*
|
|
* All arguments from this index onwards (1 based) are hashed into the key to determine
|
|
* if this is a new unique element or one already exists
|
|
*
|
|
* Is only used when flags contains [ELEMENT_BESPOKE]
|
|
*
|
|
* This is infinity so you must explicitly set this
|
|
*/
|
|
var/argument_hash_start_idx = INFINITY
|
|
|
|
/// Activates the functionality defined by the element on the given target datum
|
|
/datum/element/proc/Attach(datum/target)
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
if(type == /datum/element)
|
|
return ELEMENT_INCOMPATIBLE
|
|
SEND_SIGNAL(target, COMSIG_ELEMENT_ATTACH, src)
|
|
if(element_flags & ELEMENT_DETACH_ON_HOST_DESTROY)
|
|
RegisterSignal(target, COMSIG_QDELETING, PROC_REF(OnTargetDelete), override = TRUE)
|
|
|
|
/datum/element/proc/OnTargetDelete(datum/source)
|
|
SIGNAL_HANDLER
|
|
Detach(source)
|
|
|
|
/// Deactivates the functionality defines by the element on the given datum
|
|
/datum/element/proc/Detach(datum/source, ...)
|
|
SIGNAL_HANDLER
|
|
SHOULD_CALL_PARENT(TRUE)
|
|
|
|
SEND_SIGNAL(source, COMSIG_ELEMENT_DETACH, src)
|
|
UnregisterSignal(source, COMSIG_QDELETING)
|
|
|
|
/datum/element/Destroy(force)
|
|
if(!force)
|
|
return QDEL_HINT_LETMELIVE
|
|
SSdcs.elements_by_type -= type
|
|
return ..()
|
|
|
|
//DATUM PROCS
|
|
|
|
/// Finds the singleton for the element type given and attaches it to src
|
|
/datum/proc/_AddElement(list/arguments)
|
|
if(QDELING(src))
|
|
var/datum/element/element_type = arguments[1]
|
|
stack_trace("We just tried to add the element [element_type] to a qdeleted datum, something is fucked")
|
|
return
|
|
|
|
var/datum/element/ele = SSdcs.GetElement(arguments)
|
|
if(!ele) // We couldn't fetch the element, likely because it was not an element.
|
|
return // the crash message has already been sent
|
|
arguments[1] = src
|
|
if(ele.Attach(arglist(arguments)) == ELEMENT_INCOMPATIBLE)
|
|
CRASH("Incompatible element [ele.type] was assigned to a [type]! args: [json_encode(args)]")
|
|
|
|
/**
|
|
* Finds the singleton for the element type given and detaches it from src
|
|
* You only need additional arguments beyond the type if you're using [ELEMENT_BESPOKE]
|
|
*/
|
|
/datum/proc/_RemoveElement(list/arguments)
|
|
var/datum/element/ele = SSdcs.GetElement(arguments, FALSE)
|
|
if(!ele) // We couldn't fetch the element, likely because it didn't exist.
|
|
return
|
|
if(ele.element_flags & ELEMENT_COMPLEX_DETACH)
|
|
arguments[1] = src
|
|
ele.Detach(arglist(arguments))
|
|
else
|
|
ele.Detach(src)
|
|
|
|
/**
|
|
* Used to manage (typically non_bespoke) elements with multiple sources through traits
|
|
* so we don't have to make them a components again.
|
|
* The element will be later removed once all trait sources are gone, there's no need of a
|
|
* "RemoveElementTrait" counterpart.
|
|
*/
|
|
/datum/proc/AddElementTrait(trait, source, datum/element/eletype, ...)
|
|
if(!ispath(eletype, /datum/element))
|
|
CRASH("AddElementTrait called, but [eletype] is not of a /datum/element path")
|
|
ADD_TRAIT(src, trait, source)
|
|
if(HAS_TRAIT_NOT_FROM(src, trait, source))
|
|
return
|
|
var/list/arguments = list(eletype)
|
|
/// 3 is the length of fixed args of this proc, any further one is passed down to AddElement.
|
|
if(length(args) > 3)
|
|
arguments += args.Copy(4)
|
|
/// We actually pass down a copy of the arguments since it's manipulated by the end of the proc.
|
|
_AddElement(arguments.Copy())
|
|
var/datum/ele = SSdcs.GetElement(arguments)
|
|
ele.RegisterSignal(src, SIGNAL_REMOVETRAIT(trait), TYPE_PROC_REF(/datum/element, _detach_on_trait_removed))
|
|
|
|
/datum/element/proc/_detach_on_trait_removed(datum/source, trait)
|
|
SIGNAL_HANDLER
|
|
Detach(source)
|
|
UnregisterSignal(source, SIGNAL_REMOVETRAIT(trait))
|