Files
MrMelbert e68c1edad1 Streamlines Life() a little (#96215)
## About The Pull Request

Main changes

- `handle_mutations` is gone, DNA Injectors are now managed via a status
effect
- `handle_diseases` is gone, disease stages are just handled via life
signal
- `handle_bodyparts` is gone, it was unused and in the future any
implementations should use a life signal
- `spec_life` is gone, the main content of it is now in `human/Life`,
most children implementations now use life signal, zombie tongues now
handle zombie groans
- Life signal was split in two (pre and active)

Other changes

- DNA injector code was cleaned up considerably
- HARS now alerts admins when you inject someone else with it like
Monkey
- `COPY_DNA_SE` is no longer mistakenly unused (meaning stuff like
transformation sting no longer copies "active mutations")

## Why It's Good For The Game

Across the course of a full round we spend the same amount of time doing
literally nothing in life as we spend on handling human breathing.

Now in the context of a full round this is 8 seconds. Which in the grand
scheme of things, not a whole lot, but if we can get a tiny performance
gain from... not doing literally nothing (especially when we can do
these things cleaner with signals) that's a win in my book

## Changelog

🆑 Melbert
refactor: Refactored dna injectors (both the ones that change appearance
and activate mutations), report any oddities with them like failing to
revert your appearance or mutations not applying correctly
code: Ever so slightly changed how diseases tick, report any oddities
code: Ever so slightly changed how some species mechanics tick, like
golems and slimes, report any oddities
code: The code behind printing appearance modifying dna injectors from
genetics has changed, report any oddities
code: Some backend transformation sting code changed slightly, report
any oddities
code: Zombie "idle" groaning is now tied to the tongue rather than the
species itself
admin: Force-injecting someone with HARS give an admin alert, the same
as force-injecting someone with Monkey
fix: Several methods of copying DNA (including transformation sting)
mistakenly copied "active mutations", this has been fixed
/🆑

---------

Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com>
2026-05-29 22:48:16 -06:00

82 lines
2.7 KiB
Plaintext

/datum/mutation/void
name = "Void Magnet"
desc = "A rare genome that attracts odd forces not usually observed."
quality = MINOR_NEGATIVE //upsides and downsides
text_gain_indication = span_notice("You feel a heavy, dull force just beyond the walls watching you.")
instability = POSITIVE_INSTABILITY_MODERATE // useful, but has large drawbacks
power_path = /datum/action/cooldown/spell/void/cursed
energy_coeff = 1
synchronizer_coeff = 1
/datum/mutation/void/setup()
. = ..()
var/datum/action/cooldown/spell/void/cursed/to_modify = .
if(!istype(to_modify)) // null or invalid
return
to_modify.curse_probability_modifier = GET_MUTATION_SYNCHRONIZER(src)
return .
/// The base "void invocation" action. No side effects.
/datum/action/cooldown/spell/void
name = "Invoke Void"
desc = "Pulls you into a pocket of the void temporarily, making you invincible."
button_icon_state = "void_magnet"
school = SCHOOL_EVOCATION
cooldown_time = 1 MINUTES
invocation = "DOOOOOOOOOOOOOOOOOOOOM!!!"
invocation_type = INVOCATION_SHOUT
spell_requirements = NONE
antimagic_flags = NONE
/datum/action/cooldown/spell/void/is_valid_target(atom/cast_on)
return isturf(cast_on.loc)
/datum/action/cooldown/spell/void/cast(atom/cast_on)
. = ..()
new /obj/effect/immortality_talisman/void(get_turf(cast_on), cast_on)
/// The cursed "void invocation" action, that has a chance of casting itself on its owner randomly on life ticks.
/datum/action/cooldown/spell/void/cursed
name = "Convoke Void" //magic the gathering joke here
desc = "A rare genome that attracts odd forces not usually observed. May sometimes pull you in randomly."
/// A multiplier applied to the probability of the curse appearing every life tick
var/curse_probability_modifier = 1
/datum/action/cooldown/spell/void/cursed/Grant(mob/grant_to)
. = ..()
if(!owner)
return
RegisterSignal(grant_to, COMSIG_LIVING_LIFE, PROC_REF(on_life))
/datum/action/cooldown/spell/void/cursed/Remove(mob/remove_from)
UnregisterSignal(remove_from, COMSIG_LIVING_LIFE)
return ..()
/// Signal proc for [COMSIG_LIVING_LIFE]. Has a chance of casting itself randomly.
/datum/action/cooldown/spell/void/cursed/proc/on_life(mob/living/source, seconds_per_tick)
SIGNAL_HANDLER
if(HAS_TRAIT(source, TRAIT_STASIS) || source.stat == DEAD)
return
if(!is_valid_target(source))
return
var/prob_of_curse = 0.25
var/mob/living/carbon/carbon_source = source
if(istype(carbon_source) && carbon_source.dna)
// If we have DNA, the probability of curse changes based on how stable we are
prob_of_curse += ((100 - carbon_source.dna.stability) / 40)
prob_of_curse *= curse_probability_modifier
if(!SPT_PROB(prob_of_curse, seconds_per_tick))
return
cast(source)