Files
Bubberstation/code/datums/status_effects/_status_effect_helpers.dm
SkyratBot 5fdf13293f [MIRROR] Crushers and PKAs: Coop Upgrades (#26882)
* Crushers and PKAs: Coop Upgrades (#81940)

## About The Pull Request

This PR makes 2 changes, one to the crusher and one to the PKA

Crushers: Their projectile no longer overrides eachother, so a mob can
have the blue bubble from several crushers. Triggering it will only
trigger the one that you own, so each player has to go hit the mob to
strike.

PKA: Fixed the minebot passthrough upgrade, and also adds a human
passthrough upgrade. They are incompatible with eachother, so you choose
between solo+minebot or coop, which is a compromise I thought as a
better alternative to taking mod space (the minebot passthrough
currently takes none). This upgrade is available solely at the mining
vendor, for 750 points.

## Why It's Good For The Game

The new mining has been great, and one thing I love is that it
encourages more coop play. Excavating boulders with other miners is much
more engaging and has good teamwork in it, and also is a good way to
encourage miners to stick together more and even fight megafauna in
pairs.
This hopes to make that easier to do, because currently having anyone
with a crusher is sort of a detriment to the whole team. Either the PKA
dude will accidentally shoot the crusher user while they're going in for
a melee kill, or 2 crusher users will be constantly erasing the mark of
the other. This will hopefully make that aspect better, and make mining
with friends a little better.

## Changelog

🆑
balance: Crusher marks no longer overwrite eachother, fauna can have one
from each crusher.
balance: Ash drake's crusher trophy no longer affects people the same
faction as you (like hiero trophy), so you won't friendly fire people
with it.
add: Added a new upgrade: Human Passthrough. You can shoot your PKA
without having to worry about friendly fire with this, for 750 mining
points at your mining vendor.
fix: Minebot passthrough upgrade now properly makes PKAs pass through
minebots.
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@ users.noreply.github.com>

* Crushers and PKAs: Coop Upgrades

---------

Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@ users.noreply.github.com>
2024-03-15 13:38:47 -04:00

148 lines
5.2 KiB
Plaintext

// Status effect helpers for living mobs
/**
* Applies a given status effect to this mob.
*
* new_effect - TYPEPATH of a status effect to apply.
* Additional status effect arguments can be passed.
*
* Returns the instance of the created effected, if successful.
* Returns 'null' if unsuccessful.
*/
/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
/**
* Removes all instances of a given status effect from this mob
*
* removed_effect - TYPEPATH of a status effect to remove.
* Additional status effect arguments can be passed - these are passed into before_remove.
*
* Returns TRUE if at least one was removed.
*/
/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(arglist(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
///Gets every status effect of an ID and returns all of them in a list, rather than the individual 'has_status_effect'
/mob/living/proc/get_all_status_effect_of_id(datum/status_effect/checked_effect)
RETURN_TYPE(/list/datum/status_effect)
var/list/all_effects_of_type = list()
for(var/datum/status_effect/present_effect as anything in status_effects)
if(present_effect.id == initial(checked_effect.id))
all_effects_of_type += present_effect
return all_effects_of_type
/**
* Checks if this mob has a status effect that shares the passed effect's ID
* and has the passed sources are in its list of sources (ONLY works for grouped efects!)
*
* 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_from_source(datum/status_effect/grouped/checked_effect, sources)
// See [/mob/proc/has_status_effect] for reason behind having this on the mob level
return null
/mob/living/has_status_effect_from_source(datum/status_effect/grouped/checked_effect, sources)
RETURN_TYPE(/datum/status_effect)
if(!ispath(checked_effect))
CRASH("has_status_effect_from_source passed with an improper status effect path.")
if(!islist(sources))
sources = list(sources)
for(var/datum/status_effect/grouped/present_effect in status_effects)
if(present_effect.id != initial(checked_effect.id))
continue
var/list/matching_sources = present_effect.sources & sources
if(length(matching_sources))
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