diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index 096f9ebc52b..edaab91a722 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -184,6 +184,8 @@ GLOB.chemical_reactions_list[reagent] = list() GLOB.chemical_reactions_list[reagent] += reaction_datum + init_datum_subtypes(/datum/hunger_level, GLOB.hunger_levels, null, "type") + // Init disease archive GLOB.archive_diseases += list( "sneeze" = new /datum/disease/virus/advance/preset/sneezing(), diff --git a/code/datums/components/hunger_effects.dm b/code/datums/components/hunger_effects.dm new file mode 100644 index 00000000000..4d3a0f6ca7b --- /dev/null +++ b/code/datums/components/hunger_effects.dm @@ -0,0 +1,64 @@ +#define COMSIG_CARBON_NUTRITION_UPDATE "carbon_nutrition_update" +/datum/component/hunger_effects + var/datum/hunger_level/current_level + +/datum/component/hunger_effects/Initialize() + if(!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_CARBON_NUTRITION_UPDATE, PROC_REF(update_hunger_effects)) + RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(on_life)) + update_hunger_effects() + return ..() + +/datum/component/hunger_effects/proc/update_hunger_effects() + var/mob/living/carbon/human/target = parent + if(!istype(target)) + return + var/current_nutrition = target.nutrition + var/datum/hunger_level/new_level = find_hunger_level(current_nutrition) + current_level = new_level + apply_hunger_effects(target) + +/datum/component/hunger_effects/proc/find_hunger_level(nutrition) + var/list/valid_levels = list() + for(var/level_type in GLOB.hunger_levels) + var/datum/hunger_level/level = GLOB.hunger_levels[level_type] + valid_levels += level + sortTim(valid_levels, /proc/hunger_levels_update) + for(var/datum/hunger_level/level in valid_levels) + if(nutrition >= level.min_nutrition) + return level + return GLOB.hunger_levels[/datum/hunger_level/starving] + +/proc/hunger_levels_update(datum/hunger_level/A, datum/hunger_level/B) + return B.min_nutrition - A.min_nutrition + +/datum/component/hunger_effects/proc/apply_hunger_effects(mob/living/carbon/human/target) + target.remove_movespeed_modifier(/datum/movespeed_modifier/hunger) + target.remove_actionspeed_modifier(/datum/actionspeed_modifier/species_tool_mod) + if(!isnull(current_level?.move_mod) && current_level.move_mod != 0) + target.add_or_update_variable_movespeed_modifier( + /datum/movespeed_modifier/hunger, + multiplicative_slowdown = current_level.move_mod + ) + var/base_toolspeed = target.dna.species.toolspeedmod + var/new_toolspeed = base_toolspeed + (current_level?.tool_mod || 0) + if(new_toolspeed != base_toolspeed) + target.add_or_update_variable_actionspeed_modifier( + /datum/actionspeed_modifier/species_tool_mod, + multiplicative_slowdown = new_toolspeed + ) + else + target.remove_actionspeed_modifier(/datum/actionspeed_modifier/species_tool_mod) + target.sound_environment_override = current_level?.sound_env || SOUND_ENVIRONMENT_NONE + if(!isnull(current_level?.stamina_max)) + target.set_stamina_max(current_level.stamina_max) + +/datum/component/hunger_effects/proc/on_life() + var/mob/living/carbon/human/target = parent + if(!istype(target) || !current_level) + return + if(current_level.regen_stamina && target.getStaminaLoss() > 0) + target.adjustStaminaLoss(-0.5, TRUE) + if(current_level.regen_blood) + target.blood_volume = min(target.blood_volume + 0.2, BLOOD_VOLUME_NORMAL) diff --git a/code/datums/hunger_levels.dm b/code/datums/hunger_levels.dm new file mode 100644 index 00000000000..48be3af0e07 --- /dev/null +++ b/code/datums/hunger_levels.dm @@ -0,0 +1,58 @@ +GLOBAL_LIST_EMPTY(hunger_levels) +/datum/hunger_level + var/above = null + var/below = null + var/min_nutrition = 0 + var/move_mod = 0 + var/tool_mod = 0 + var/stamina_max = MAX_STAMINA_LOSS + var/sound_env = SOUND_ENVIRONMENT_NONE + var/regen_stamina = FALSE + var/regen_blood = FALSE + +/datum/hunger_level/starving + min_nutrition = 0 + move_mod = 2 + tool_mod = 0.5 + stamina_max = MAX_STAMINA_LOSS - 10 + sound_env = SOUND_ENVIRONMENT_DRUGGED + above = /datum/hunger_level/hungry + below = null + +/datum/hunger_level/hungry + min_nutrition = NUTRITION_LEVEL_HYPOGLYCEMIA + 1 + move_mod = 1 + tool_mod = 0.25 + stamina_max = MAX_STAMINA_LOSS - 5 + sound_env = SOUND_ENVIRONMENT_NONE + above = /datum/hunger_level/normal + below = /datum/hunger_level/starving + +/datum/hunger_level/normal + min_nutrition = NUTRITION_LEVEL_HUNGRY + 1 + move_mod = 0 + tool_mod = 0 + stamina_max = MAX_STAMINA_LOSS + sound_env = SOUND_ENVIRONMENT_NONE + above = /datum/hunger_level/fed + below = /datum/hunger_level/hungry + +/datum/hunger_level/fed + min_nutrition = NUTRITION_LEVEL_FED + 1 + move_mod = 0 + tool_mod = 0 + stamina_max = MAX_STAMINA_LOSS + 5 + sound_env = SOUND_ENVIRONMENT_NONE + above = /datum/hunger_level/full + below = /datum/hunger_level/normal + +/datum/hunger_level/full + min_nutrition = NUTRITION_LEVEL_WELL_FED + 1 + move_mod = 0 + tool_mod = 0 + stamina_max = MAX_STAMINA_LOSS + 10 + sound_env = SOUND_ENVIRONMENT_NONE + regen_stamina = TRUE + regen_blood = TRUE + above = null + below = /datum/hunger_level/fed diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 4d4a84625c0..3d44a12a28e 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -18,6 +18,8 @@ create_reagents(330) + AddComponent(/datum/component/hunger_effects) + handcrafting = new() AddElement(/datum/element/ridable, /datum/component/riding/creature/human) AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6) @@ -1760,11 +1762,7 @@ Eyes need to have significantly high darksight to shine unless the mob has the X /mob/living/carbon/human/proc/update_hunger_slowdown() - var/hungry = (500 - nutrition) / 5 //So overeat would be 100 and default level would be 80 - if(hungry >= 70) - add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/hunger, multiplicative_slowdown = (hungry / 50)) - else - remove_movespeed_modifier(/datum/movespeed_modifier/hunger) + SEND_SIGNAL(src, COMSIG_CARBON_NUTRITION_UPDATE) /mob/living/carbon/human/proc/special_post_clone_handling() diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 8db896599a9..e2194d049a9 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -755,7 +755,7 @@ if(amount <= 0) return STATUS_UPDATE_NONE var/old_stamloss = getStaminaLoss() - staminaloss = clamp(round(staminaloss + amount, DAMAGE_PRECISION), 0, MAX_STAMINA_LOSS) + staminaloss = clamp(round(staminaloss + amount, DAMAGE_PRECISION), 0, (max_stamina_loss || MAX_STAMINA_LOSS)) if(old_stamloss == getStaminaLoss()) updating_health = FALSE . = STATUS_UPDATE_NONE @@ -784,7 +784,7 @@ updatehealth("setStaminaLoss") return STATUS_UPDATE_NONE var/old_stamloss = getStaminaLoss() - staminaloss = clamp(round(amount, DAMAGE_PRECISION), 0, MAX_STAMINA_LOSS) + staminaloss = clamp(round(amount, DAMAGE_PRECISION), 0, (max_stamina_loss || MAX_STAMINA_LOSS)) if(old_stamloss == getStaminaLoss()) updating_health = FALSE . = STATUS_UPDATE_NONE @@ -795,6 +795,14 @@ if(updating_health) updatehealth("setStaminaLoss") +/mob/living/proc/set_stamina_max(amount) + max_stamina_loss = max(0, min(amount, MAX_STAMINA_LOSS)) + if(staminaloss > (max_stamina_loss || MAX_STAMINA_LOSS)) + setStaminaLoss(max_stamina_loss) + +/mob/living/proc/defaultStaminaMax() + max_stamina_loss = MAX_STAMINA_LOSS + /// Maxhealth var getter /mob/living/proc/getMaxHealth() diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 03e34d89994..9b899503abf 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -20,7 +20,7 @@ var/fireloss = 0 //Burn damage caused by being way too hot, too cold or burnt. var/cloneloss = 0 //Damage caused by being cloned or ejected from the cloner early. slimes also deal cloneloss damage to victims var/staminaloss = 0 //Stamina damage, or exhaustion. You recover it slowly naturally, and are stunned if it gets too high. Holodeck and hallucinations deal this. - + var/max_stamina_loss = MAX_STAMINA_LOSS var/last_special = 0 //Used by the resist verb, likely used to prevent players from bypassing next_move by logging in/out. diff --git a/paradise.dme b/paradise.dme index ad308b3bf6e..5f7c7c755ca 100644 --- a/paradise.dme +++ b/paradise.dme @@ -446,6 +446,7 @@ #include "code\datums\holocall.dm" #include "code\datums\http.dm" #include "code\datums\hud.dm" +#include "code\datums\hunger_levels.dm" #include "code\datums\input_data.dm" #include "code\datums\log_record.dm" #include "code\datums\log_viewer.dm" @@ -552,6 +553,7 @@ #include "code\datums\components\ghost_direct_control.dm" #include "code\datums\components\hide_highest_offset.dm" #include "code\datums\components\holderloving.dm" +#include "code\datums\components\hunger_effects.dm" #include "code\datums\components\jackboots.dm" #include "code\datums\components\jetpack.dm" #include "code\datums\components\label.dm"