diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm index 15ae5c68270..c8dd9a90e36 100644 --- a/code/modules/mob/living/carbon/monkey/monkey.dm +++ b/code/modules/mob/living/carbon/monkey/monkey.dm @@ -60,14 +60,13 @@ /mob/living/carbon/monkey/on_reagent_change() . = ..() - remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE) var/amount if(reagents.has_reagent(/datum/reagent/medicine/morphine)) amount = -1 if(reagents.has_reagent(/datum/reagent/consumable/nuka_cola)) amount = -1 if(amount) - add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount) + add_or_update_movespeed_modifier(/datum/movespeed_modifier/variable/monkey_reagent_speedmod, TRUE, amount) /mob/living/carbon/monkey/updatehealth() . = ..() @@ -76,14 +75,14 @@ var/health_deficiency = (maxHealth - health) if(health_deficiency >= 45) slow += (health_deficiency / 25) - add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow) + add_or_update_movespeed_modifier(/datum/movespeed_modifier/variable/monkey_health_speedmod, TRUE, slow) /mob/living/carbon/monkey/adjust_bodytemperature(amount) . = ..() var/slow = 0 if (bodytemperature < 283.222) slow += ((283.222 - bodytemperature) / 10) * 1.75 - add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow) + add_or_update_movespeed_modifier(/datum/movespeed_modifier/variable/monkey_temperature_speedmod, TRUE, slow) /mob/living/carbon/monkey/Stat() ..() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 98a59b851cd..4f49da4c02a 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -38,17 +38,17 @@ * Move a client in a direction * * Huge proc, has a lot of functionality - * + * * Mostly it will despatch to the mob that you are the owner of to actually move * in the physical realm - * + * * Things that stop you moving as a mob: * * world time being less than your next move_delay * * not being in a mob, or that mob not having a loc * * missing the n and direction parameters * * being in remote control of an object (calls Moveobject instead) * * being dead (it ghosts you instead) - * + * * Things that stop you moving as a mob living (why even have OO if you're just shoving it all * in the parent proc with istype checks right?): * * having incorporeal_move set (calls Process_Incorpmove() instead) @@ -68,7 +68,7 @@ * * Finally if you're pulling an object and it's dense, you are turned 180 after the move * (if you ask me, this should be at the top of the move so you don't dance around) - * + * */ /client/Move(n, direct) if(world.time < move_delay) //do not move anything ahead of this check please @@ -175,7 +175,7 @@ * Allows mobs to ignore density and phase through objects * * Called by client/Move() - * + * * The behaviour depends on the incorporeal_move value of the mob * * * INCORPOREAL_MOVE_BASIC - forceMoved to the next tile with no stop @@ -263,9 +263,9 @@ * Handles mob/living movement in space (or no gravity) * * Called by /client/Move() - * + * * return TRUE for movement or FALSE for none - * + * * You can move in space if you have a spacewalk ability */ /mob/Process_Spacemove(movement_dir = 0) @@ -443,7 +443,7 @@ /** * Toggle the move intent of the mob - * + * * triggers an update the move intent hud as well */ /mob/proc/toggle_move_intent(mob/user) diff --git a/code/modules/movespeed/_movespeed_modifier.dm b/code/modules/movespeed/_movespeed_modifier.dm index 2df0435bfb5..a9315a4f9f9 100644 --- a/code/modules/movespeed/_movespeed_modifier.dm +++ b/code/modules/movespeed/_movespeed_modifier.dm @@ -63,14 +63,21 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) /// Grabs a STATIC MODIFIER datum from cache. YOU MUST NEVER EDIT THESE DATUMS, OR IT WILL AFFECT ANYTHING ELSE USING IT TOO! /proc/get_cached_movespeed_modification(modtype) if(!ispath(modtype, /datum/movespeed_modifier)) - CRASH("[modtype] is not a movespeed modification type.") + CRASH("[modtype] is not a movespeed modification typepath.") + if(ispath(modtype, /datum/movespeed_modifier/variable)) + CRASH("[modtype] is a variable modifier, and can never be cached.") var/datum/movespeed_modifier/M = GLOB.movespeed_modification_cache[modtype] || ((GLOB.movespeed_modification_cache[modtype] = new modtype)) return M -///Add a move speed modifier to a mob +///Add a move speed modifier to a mob. If a variable subtype is passed in as the first argument, it will make a new datum. /mob/proc/_REFACTORING_add_movespeed_modifier(datum/movespeed_modifier/type_or_datum, update = TRUE, override = FALSE) + var/created = FALSE if(ispath(type_or_datum)) - type_or_datum = get_cached_movespeed_modification(type_or_datum) + if(!ispath(type_or_datum, /datum/movespeed_modifier/variable)) + type_or_datum = get_cached_movespeed_modification(type_or_datum) + else + created = TRUE + type_or_datum = new type_or_datum if(!istype(type_or_datum)) CRASH("Invalid modification datum") var/oldpriority @@ -79,19 +86,24 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) if(existing == type_or_datum) //same thing don't need to touch return TRUE if(!override) //not overriding, do not overwrite same ID. + if(created) //make sure we clean up after ourselves. + qdel(type_or_datum) return FALSE oldpriority = existing.priority - remove_movespeed_modifier(existing, FLASE) + remove_movespeed_modifier(existing, FALSE) LAZYSET(movespeed_modification, type_or_datum.id, type_or_datum) var/resort = type_or_datum.priority == oldpriority if(update) update_movespeed(resort) return TRUE -///Remove a move speed modifier from a mob +///Remove a move speed modifier from a mob, whether static or variable. /mob/proc/_REFACTORING_remove_movespeed_modifier(datum/movespeed_modifier/type_id_datum, update = TRUE) if(ispath(type_id_datum)) - type_id_datum = get_cached_movespeed_modification(type_id_datum) + if(!ispath(type_id_datum, /datum/movespeed_modifier/variable)) + type_id_datum = get_cached_movespeed_modification(type_id_datum) + else + type_id_datum = initial(type_id_datum.id) if(istype(type_id_datum)) type_id_datum = type_id_datum.id if(!LAZYACCESS(movespeed_modification, type_id_datum)) @@ -102,6 +114,48 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) update_movespeed(FALSE) return TRUE +/// Used for variable slowdowns like hunger/health loss/etc, works somewhat like the old list-based modification adds. +/// Implies override. +/mob/proc/add_or_update_variable_movespeed_modifier(datum/movespeed_modifier/variable/type_id_datum, update = TRUE, multiplicative_slowdown) + /* + How this SHOULD work is: + 1. Ensures type_id_datum one way or another refers to a /variable datum. This makes sure it can't be cached. This includes if it's already in the modification list. + 2. Instantiate a new datum if type_id_datum isn't already instantiated + in the list, using the type. Obviously, wouldn't work for ID only. + 3. Add the datum if necessary using the regular add proc + 4. If any of the rest of the args are not null (see: multiplicative slowdown), modify the datum + 5. Update if necessary + */ + . = FALSE + var/modified = FALSE + var/inject = FALSE + var/datum/movespeed_modifier/variable/final + if(istext(type_id_datum)) + final = LAZYACCESS(movespeed_modification, type_id_datum) + if(!istype(final)) + CRASH("Couldn't find existing modification when only provided an ID.") + else if(ispath(type_id_datum)) + var/id = initial(type_id_datum.id) + final = LAZYACCESS(movespeed_modification, type_id_datum) + if(!istype(final)) + final = new + inject = TRUE + modified = TRUE + else if(istype(type_id_datum)) + final = type_id_datum + if(!LAZYACCESS(movespeed_modification, final.id)) + inject = TRUE + modified = TRUE + else + CRASH("Invalid modifier") + if(!isnull(multiplicative_slowdown) + final.multiplicative_slowdown = multiplicative_slowdown + modified = TRUE + if(inject) + _REFACTORING_add_movespeed_modifier(final, FALSE, TRUE) + if(update && modified) + update_movespeed(TRUE) + return TRUE + ///Handles the special case of editing the movement var /mob/vv_edit_var(var_name, var_value) var/slowdown_edit = (var_name == NAMEOF(src, cached_multiplicative_slowdown)) @@ -164,13 +218,13 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache) /mob/proc/total_multiplicative_slowdown() . = 0 for(var/id in get_movespeed_modifiers()) - var/list/data = movespeed_modification[id] - . += data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN] + var/datum/movespeed_modifier/M = movespeed_modification[id] + . += M.multiplicative_slowdown() ///Checks if a move speed modifier is valid and not missing any data -/proc/movespeed_data_null_check(list/data) //Determines if a data list is not meaningful and should be discarded. +/proc/movespeed_data_null_check(datum/movespeed_modifier/M) //Determines if a data list is not meaningful and should be discarded. . = TRUE - if(data[MOVESPEED_DATA_INDEX_MULTIPLICATIVE_SLOWDOWN]) + if(M.multiplicative_slowdown) . = FALSE /** diff --git a/code/modules/movespeed/modifiers/variable.dm b/code/modules/movespeed/modifiers/variable.dm new file mode 100644 index 00000000000..f7836a90c9e --- /dev/null +++ b/code/modules/movespeed/modifiers/variable.dm @@ -0,0 +1,10 @@ +/datum/movespeed_modifier/variable + +/datum/movespeed_modifier/variable/monkey_reagent_speedmod + id = MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD + +/datum/movespeed_modifier/variable/monkey_health_speedmod + id = MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD + +/datum/movespeed_modifier/variable/monkey_temperature_speedmod + id = MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD diff --git a/tgstation.dme b/tgstation.dme index e550eeec980..7642b2722b8 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2383,6 +2383,7 @@ #include "code\modules\movespeed\modifiers\innate.dm" #include "code\modules\movespeed\modifiers\reagent.dm" #include "code\modules\movespeed\modifiers\status_effects.dm" +#include "code\modules\movespeed\modifiers\variable.dm" #include "code\modules\ninja\__ninjaDefines.dm" #include "code\modules\ninja\energy_katana.dm" #include "code\modules\ninja\ninja_event.dm"