Skip to content

Stamina container optimizations #5869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/mob/living/Initialize(mapload)
. = ..()
stamina = new(src)
stamina = new(src) // monkestation edit: stamina rework
if(current_size != RESIZE_DEFAULT_SIZE)
update_transform(current_size)
AddElement(/datum/element/movetype_handler)
Expand Down
3 changes: 2 additions & 1 deletion monkestation/code/controllers/subsystem/stamina.dm
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ SUBSYSTEM_DEF(stamina)
//cache for sanic speed (lists are references anyways)
var/list/current_run = currentrun

var/seconds_per_tick = world.tick_lag * wait * 0.1
while(length(current_run))
var/datum/stamina_container/thing = current_run[length(current_run)]
current_run.len--
thing.update(world.tick_lag * wait * 0.1)
thing.update(seconds_per_tick)
if (MC_TICK_CHECK)
return
74 changes: 69 additions & 5 deletions monkestation/code/datums/stamina_container.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@
var/is_regenerating = TRUE
//unga bunga
var/process_stamina = TRUE
/// Used to determine when the stamina changes, to properly run on_stamina_update on the parent.
VAR_PRIVATE/should_notify_parent = FALSE

///cooldowns
///how long until we can lose stamina again
COOLDOWN_DECLARE(stamina_grace_period)
///how long stamina is paused for
COOLDOWN_DECLARE(paused_stamina)

/// Signals which we react in order to re-check if we should be processing or not.
var/static/list/update_on_signals = list(
COMSIG_MOB_STATCHANGE,
SIGNAL_ADDTRAIT(TRAIT_NO_TRANSFORM),
SIGNAL_REMOVETRAIT(TRAIT_NO_TRANSFORM),
)

/datum/stamina_container/New(parent, maximum = STAMINA_MAX, regen_rate = STAMINA_REGEN)
if(maximum <= 0)
stack_trace("Attempted to initialize stamina container with an invalid maximum limit of [maximum], defaulting to [STAMINA_MAX]")
Expand All @@ -32,15 +41,21 @@
src.maximum = maximum
src.regen_rate = regen_rate
src.current = maximum
START_PROCESSING(SSstamina, src)
RegisterSignals(parent, update_on_signals, PROC_REF(update_process))
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(nullspace_move_check))
update_process()

/datum/stamina_container/Destroy()
parent?.stamina = null
if(!isnull(parent))
parent.stamina = null
UnregisterSignal(parent, update_on_signals)
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED)
parent = null
STOP_PROCESSING(SSstamina, src)
return ..()

/datum/stamina_container/proc/update(seconds_per_tick = 1)
var/last_current = current
if(process_stamina == TRUE)
if(!is_regenerating)
if(!COOLDOWN_FINISHED(src, paused_stamina))
Expand All @@ -49,8 +64,10 @@

if(seconds_per_tick)
current = min(current + (regen_rate*seconds_per_tick), maximum)
if(seconds_per_tick && decrement)
current = max(current + (-decrement*seconds_per_tick), 0)
if(decrement)
current = max(current + (-decrement*seconds_per_tick), 0)
if(current != last_current)
should_notify_parent = TRUE
loss = maximum - current
loss_as_percent = loss ? (loss == maximum ? 0 : loss / maximum * 100) : 0

Expand All @@ -59,7 +76,9 @@
else if(!(current == maximum))
process_stamina = TRUE

parent.on_stamina_update()
if(should_notify_parent)
parent.on_stamina_update()
should_notify_parent = FALSE

///Pause stamina regeneration for some period of time. Does not support doing this from multiple sources at once because I do not do that and I will add it later if I want to.
/datum/stamina_container/proc/pause(time)
Expand All @@ -86,7 +105,10 @@
var/modify = parent.pre_stamina_change(amt, forced)
if(base_modify)
modify = amt
var/old_current = current
current = round(clamp(current + modify, 0, maximum), DAMAGE_PRECISION)
if(current != old_current)
should_notify_parent = TRUE
update()
if((amt < 0) && is_regenerating)
pause(STAMINA_REGEN_TIME)
Expand All @@ -104,12 +126,42 @@
if(stamina_after_loss < lowest_stamina_value)
amount = current - lowest_stamina_value

var/old_current = current
current = round(clamp(current + amount, 0, maximum), DAMAGE_PRECISION)
if(current != old_current)
should_notify_parent = TRUE
update()
if((amount < 0) && is_regenerating)
pause(STAMINA_REGEN_TIME)
return amount

/// Signal handler for COMSIG_MOVABLE_MOVED to ensure that update_process() gets called whenever moving to/from nullspace.
/datum/stamina_container/proc/nullspace_move_check(atom/movable/mover, atom/old_loc, dir, force)
SIGNAL_HANDLER
if(isnull(old_loc) || isnull(mover.loc))
update_process()

/// Returns if the container should currently be processing or not.
/datum/stamina_container/proc/should_process()
SHOULD_BE_PURE(TRUE)
if(QDELETED(parent) || isnull(parent.loc))
return FALSE
if(!parent.uses_stamina)
return FALSE
if(parent.stat == DEAD)
return FALSE
if(HAS_TRAIT(parent, TRAIT_NO_TRANSFORM))
return FALSE
return TRUE

/// Checks to see if the container should be processing, and starts/stops it.
/datum/stamina_container/proc/update_process()
SIGNAL_HANDLER
if(should_process())
START_PROCESSING(SSstamina, src)
else
STOP_PROCESSING(SSstamina, src)

/// Sets the maximum amount of stamina.
/// Always use this instead of directly setting the stamina var, as this has sanity checks, and immediately updates afterwards.
/datum/stamina_container/proc/set_maximum(value = STAMINA_MAX)
Expand All @@ -122,3 +174,15 @@
maximum = value
update()
return TRUE

/mob/living/carbon
uses_stamina = TRUE

/mob/living/carbon/alien
uses_stamina = FALSE

/mob/living/basic
uses_stamina = TRUE

/mob/living/simple_animal
uses_stamina = TRUE
2 changes: 2 additions & 0 deletions monkestation/code/modules/mob/living/living_defines.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@
///The talk chime set to use when speaking.
var/voice_type

/// If TRUE, then this mob has a stamina container initialized, and will use stamina.
var/uses_stamina = FALSE
Loading