Thirst Mechanics (#5255)

Overview
Adds thirst mechanics. Thirst mechanics work exactly like hunger mechanics where if you don't drink enough liquid, you become thirsty and move slower. Several other mechanics involving drinks were also changed.

For organic races, you gain hydration by consuming beverages and water. Water is the most effective way of hydrating yourself. IPCs are not affected by hydration and do not have to worry about it. If you overeat or overdrink, your nutrition decreases faster until you are of normal hunger and thirst levels.

Penalties for not eating or drinking are now more severe. If you refuse to drink or eat all shift, you will be up to 33% slower and take twice as much pain damage. The amount scales based on your hunger or thirst levels. If you are considered hungry or thirsty, it starts scaling until you're starving or seriously dehydrated. If you overeat and overdrink as well, you get a ~5% reduced movement and pain tolerance with each mechanic.

The icons for hunger have been updated to be more specific, and they match the new thirst indicators as well. https://i.imgur.com/QQbWxYI.png

You can now also inject beverages into your blood for x4 effectiveness. Before, IV dripping yourself with vodka did nothing but give you a small amount of toxins, but now it should be a hell of a party.

Dionaea can now be affected by beverages with respect to nutrition gains and temperature changes. Dionaea cannot be affected by some effects, such as stuttering and intoxication, still.

Healing effects for certain beverages (tea, milk) were removed. This a HRP server, milk shouldn't heal you.
This commit is contained in:
BurgerLUA
2018-10-07 00:14:47 +03:00
committed by Erki
parent 142af5ea08
commit 4319c45133
61 changed files with 8677 additions and 9329 deletions
@@ -119,7 +119,7 @@
return
if (D.stat == DEAD)
src.nutrition += NYMPH_ABSORB_NUTRITION * NYMPH_ABSORB_DEAD_FACTOR //Consuming dead nymphs gives far less nutrition
src.adjustNutritionLoss(-NYMPH_ABSORB_NUTRITION * NYMPH_ABSORB_DEAD_FACTOR)
qdel(D)
return 1
else
@@ -129,8 +129,8 @@
D.update_verbs()
sleep(2)
if (is_diona() == DIONA_NYMPH)//We only care about biomass if we're a nymph
src.nutrition += NYMPH_ABSORB_NUTRITION
src.nutrition += D.nutrition //Any biomass in the absorbed nymph is transferred to the host
src.adjustNutritionLoss(-NYMPH_ABSORB_NUTRITION)
src.adjustNutritionLoss(-D.nutrition)
D.nutrition = 0
D << "<span class='notice'>You feel your being twine with that of \the [src] as you merge with its biomass.</span>"
@@ -167,12 +167,11 @@
if (r != "Time to leaf")
return
src.loc << span("warning", "You feel a pang of loss as [src] splits away from your biomass.")
src << "<span class='notice'>You wiggle out of the depths of [src.loc]'s biomass and plop to the ground.</span>"
if (gestalt.is_diona() == DIONA_NYMPH)
gestalt.nutrition -= NYMPH_ABSORB_NUTRITION//Preventing an exploit with repeatedly absorbing and splitting
gestalt.adjustNutritionLoss(NYMPH_ABSORB_NUTRITION)
split_languages(gestalt)
src.forceMove(get_turf(src))
@@ -180,8 +179,6 @@
gestalt = null
update_verbs()
//Draws a sizeable blood sample from a victim to read their DNA and learn languages
/mob/living/carbon/alien/diona/proc/sample()
set category = "Abilities"
@@ -220,7 +217,7 @@
src.visible_message("<span class='danger'>[src] bites into [donor.name] and drains some of their blood</span>", "<span class='danger'>You bite into [donor.name] and drain some blood.</span>")
src << "<span class='danger'>This simple creature has insufficient intelligence for you to learn anything!</span>"
donor.adjustBruteLoss(4)
nutrition += 20
adjustNutritionLoss(-20)
return
else if (types & TYPE_WEIRD)
src.visible_message("<span class='danger'>[src] attempts to bite into [donor.name] but passes right through it!.</span>", "<span class='danger'>You attempt to sink your fangs into [donor.name] but pass right through it!</span>")
@@ -245,7 +242,7 @@
var/remove_amount = (total_blood - 280) * 0.3
if (remove_amount > 0)
vessel.remove_reagent("blood", remove_amount, 1)//85 units of blood is enough to affect a human and make them woozy
nutrition += remove_amount*0.5
adjustNutritionLoss(-remove_amount*0.5)
var/list/data = vessel.get_data("blood")
newDNA = data["blood_DNA"]
@@ -15,10 +15,7 @@
// nutrition decrease
if (nutrition > 0 && stat != 2)
nutrition = max (0, nutrition - nutrition_loss)
if (nutrition > max_nutrition)
nutrition = max_nutrition
adjustNutritionLoss(nutrition_loss)
//handle_trace_chems() implement this later maybe
updatehealth()
+1 -1
View File
@@ -29,7 +29,7 @@
var/rads = total_radiation/25
apply_radiation(rads*-1)
nutrition += rads
adjustNutritionLoss(-rads)
heal_overall_damage(rads,rads)
adjustOxyLoss(-(rads))
adjustToxLoss(-(rads))
+7 -4
View File
@@ -35,10 +35,13 @@
/mob/living/carbon/Move(NewLoc, direct)
. = ..()
if(.)
if(src.nutrition && src.stat != 2)
src.nutrition -= nutrition_loss*0.1//Multiplication is faster than division
if(src.m_intent == "run")
src.nutrition -= nutrition_loss*0.1
if(src.stat != 2)
if(src.nutrition)
adjustNutritionLoss(nutrition_loss*0.1)
if(src.hydration)
adjustHydrationLoss(hydration_loss*0.1)
if((FAT in src.mutations) && src.m_intent == "run" && src.bodytemperature <= 360)
src.bodytemperature += 2
+6 -4
View File
@@ -92,7 +92,9 @@ var/list/diona_banned_languages = list(
if(DS.nutrient_organ.is_bruised())
plus *= 0.5
plus = min(plus, max_nutrition - nutrition)
nutrition += plus
adjustNutritionLoss(-plus)
return plus*7 //The return value is the number of moles to remove from the local environment
/mob/living/carbon/proc/diona_handle_temperature(var/datum/dionastats/DS)
@@ -300,7 +302,7 @@ var/list/diona_banned_languages = list(
to_chat(src, "<span class='danger'>You try to regrow a lost limb, but you lack the biomass. Find some food!</span>")
return
DS.stored_energy -= REGROW_ENERGY_REQ
nutrition -= REGROW_FOOD_REQ
adjustNutritionLoss(REGROW_FOOD_REQ)
playsound(src, 'sound/species/diona/gestalt_grow.ogg', 30, 1)
visible_message("<span class='warning'>[src] begins to shift and quiver.</span>",
"<span class='warning'>You begin to shift and quiver, feeling a stirring within your trunk</span>")
@@ -334,7 +336,7 @@ var/list/diona_banned_languages = list(
return
DS.stored_energy -= REGROW_ENERGY_REQ
nutrition -= REGROW_FOOD_REQ
adjustNutritionLoss(REGROW_FOOD_REQ)
var/obj/item/organ/O = new path(src)
internal_organs_by_name[O.organ_tag] = O
internal_organs.Add(O)
@@ -360,7 +362,7 @@ var/list/diona_banned_languages = list(
//If we have less than six nymphs, we add one each proc
if (topup_nymphs(1))
DS.stored_energy -= REGROW_ENERGY_REQ
nutrition -= REGROW_FOOD_REQ
adjustNutritionLoss(REGROW_FOOD_REQ)
to_chat(src, "<span class='danger'>You feel a stirring inside you as a new nymph is born within your trunk!</span>")
updatehealth()
@@ -222,14 +222,14 @@
if(on_fire)
msg += "<span class='danger'>[T.He] [T.is] on fire!</span>\n"
msg += "<span class='warning'>"
if (!(src.species.flags & NO_CHUBBY))
if(nutrition < max(max_nutrition - 300, 0))
if (!(src.species.flags & NO_CHUBBY) && max_nutrition > 0)
if(nutrition / max_nutrition <= CREW_NUTRITION_VERYHUNGRY)
msg += "[T.He] [T.is] severely malnourished.\n"
else if(nutrition >= max_nutrition + 100)
else if(nutrition / max_nutrition >= CREW_NUTRITION_OVEREATEN)
msg += "[T.He] [T.is] quite chubby.\n"
if(max_hydration > 0)
if(hydration / max_hydration <= CREW_HYDRATION_VERYTHIRSTY)
msg += "[T.He] [T.is] severely dehydrated.\n"
msg += "</span>"
@@ -1315,8 +1315,11 @@
exhaust_threshold = species.exhaust_threshold
max_nutrition = BASE_MAX_NUTRITION * species.max_nutrition_factor
max_hydration = BASE_MAX_HYDRATION * species.max_hydration_factor
nutrition_loss = HUNGER_FACTOR * species.nutrition_loss_factor
hydration_loss = THIRST_FACTOR * species.hydration_loss_factor
if(species)
return 1
else
@@ -19,13 +19,6 @@
if (!(species && (species.flags & NO_PAIN)))
if(halloss >= 10) tally += (halloss / 10) //halloss shouldn't slow you down if you can't even feel it
//Simpler hunger slowdown calculations, this should be a little faster due to no division, and more scaleable
if (nutrition < (max_nutrition * 0.4))
tally++
if (nutrition < (max_nutrition * 0.1))
tally++
if(wear_suit)
tally += wear_suit.slowdown
@@ -77,7 +70,13 @@
if(T)
tally += T.movement_cost
return (tally+config.human_delay)
tally += config.human_delay
tally *= 2/(get_hydration_mul(0.75,1) + get_nutrition_mul(0.75,1))
tally = round(tally,1)
return tally
/mob/living/carbon/human/Allow_Spacemove(var/check_drift = 0)
+44 -28
View File
@@ -769,7 +769,7 @@
if(bodytemperature < species.cold_level_1) //260.15 is 310.15 - 50, the temperature where you start to feel effects.
if(nutrition >= 2) //If we are very, very cold we'll use up quite a bit of nutriment to heat us up.
nutrition -= 2
adjustNutritionLoss(2)
var/recovery_amt = max((body_temperature_difference / BODYTEMP_AUTORECOVERY_DIVISOR), BODYTEMP_AUTORECOVERY_MINIMUM)
//world << "Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]"
// log_debug("Cold. Difference = [body_temperature_difference]. Recovering [recovery_amt]")
@@ -940,16 +940,30 @@
heal_overall_damage(5,5)
// nutrition decrease
if (nutrition > 0 && stat != 2)
nutrition = max(0, nutrition - (nutrition_loss * nutrition_attrition_rate))
if(max_nutrition > 0)
if (nutrition > 0 && stat != 2)
adjustNutritionLoss(nutrition_loss * nutrition_attrition_rate)
if (nutrition > max_nutrition)
if(overeatduration < 600) //capped so people don't take forever to unfat
overeatduration++
else
if(overeatduration > 1)
overeatduration -= 2 //doubled the unfat rate
if (nutrition / max_nutrition > CREW_NUTRITION_OVEREATEN)
adjustNutritionLoss(1)
if(overeatduration < 600) //capped so people don't take forever to unfat
overeatduration++
else
if(overeatduration > 1)
overeatduration -= 2 //doubled the unfat rate
// hydration decrease
if(max_hydration > 0)
if (hydration > 0 && stat != 2)
adjustHydrationLoss(hydration_loss * hydration_attrition_rate)
if (hydration / max_hydration > CREW_HYDRATION_OVERHYDRATED)
adjustHydrationLoss(1)
if(overdrinkduration < 600) //capped so people don't take forever to undrink
overdrinkduration++
else
if(overdrinkduration > 1)
overdrinkduration -= 2 //doubled the undrink rate
// TODO: stomach and bloodstream organ.
if(!isSynthetic())
@@ -1178,24 +1192,20 @@
update_health_display()
//Update hunger UI less often, its not important
if((life_tick % 3 == 0) && nutrition_icon)
var/nut_factor = max(1,nutrition) / max_nutrition
var/new_val = ""
switch(nut_factor)
if(1 to INFINITY)
new_val = "nutrition0"
if(0.75 to 1)
new_val = "nutrition1"
if(0.5 to 0.75)
new_val = "nutrition2"
if(0.25 to 0.5)
new_val = "nutrition3"
else
new_val = "nutrition4"
if (nutrition_icon.icon_state != new_val)
nutrition_icon.icon_state = new_val
//Update hunger and thirst UI less often, its not important
if((life_tick % 3 == 0))
if(nutrition_icon)
var/nut_factor = max(0,min(nutrition / max_nutrition,1))
var/nutrition_icons = 5 //Misnomer, basically the highest nutrition icon value.
var/new_val = "nutrition[nutrition_icons - round(nut_factor*nutrition_icons)]"
if (nutrition_icon.icon_state != new_val)
nutrition_icon.icon_state = new_val
if(hydration_icon)
var/hyd_factor = max(0,min(hydration / max_hydration,1))
var/hydration_icons = 5 //Misnomer, basically the highest thirst icon value.
var/new_val = "thirst[hydration_icons - round(hyd_factor*hydration_icons)]"
if (hydration_icon.icon_state != new_val)
hydration_icon.icon_state = new_val
if(pressure)
var/new_pressure = "pressure[pressure_alert]"
@@ -1643,6 +1653,11 @@
if (prob(1.5))
src << span("warning", "You feel hungry and exhausted, eat something to regain your energy!")
return
if (hydration <= 0)
if (prob(1.5))
src << span("warning", "You feel thirsty and exhausted, drink something to regain your energy!")
return
if (stamina != max_stamina)
//Any suffocation damage slows stamina regen.
@@ -1650,7 +1665,8 @@
var/regen = stamina_recovery * (1 - min(((oxyloss) / exhaust_threshold) + ((halloss) / exhaust_threshold), 1))
if (regen > 0)
stamina = min(max_stamina, stamina+regen)
nutrition = max(0, nutrition - stamina_recovery*0.18)
adjustNutritionLoss(stamina_recovery*0.9)
adjustHydrationLoss(stamina_recovery*0.18)
if (client)
hud_used.move_intent.update_move_icon(src)
@@ -156,6 +156,9 @@
var/max_nutrition_factor = 1 //Multiplier on maximum nutrition
var/nutrition_loss_factor = 1 //Multiplier on passive nutrition losses
var/max_hydration_factor = 1 //Multiplier on maximum thirst
var/hydration_loss_factor = 1 //Multiplier on passive thirst losses
// Determines the organs that the species spawns with and
var/list/has_organ = list( // which required-organ checks are conducted.
"heart" = /obj/item/organ/heart,
@@ -5,6 +5,7 @@
var/has_warnings = 1 // Set to draw environment warnings.
var/has_pressure = 1 // Draw the pressure indicator.
var/has_nutrition = 1 // Draw the nutrition indicator.
var/has_hydration = 1 // Draw the hydration indicator.
var/has_bodytemp = 1 // Draw the bodytemp indicator.
var/has_hands = 1 // Set to draw hands.
var/has_drop = 1 // Set to draw drop button.
@@ -76,3 +77,7 @@
"mask" = list("loc" = ui_shoes, "name" = "Mask", "slot" = slot_wear_mask, "state" = "mask", "toggle" = 1),
"back" = list("loc" = ui_sstore1, "name" = "Back", "slot" = slot_back, "state" = "back")
)
/datum/hud_data/ipc
has_hydration = 0
@@ -342,6 +342,7 @@
eyes_icon_blend = ICON_MULTIPLY
sprint_charge_factor = 0.25
max_nutrition_factor = 1.75
brute_mod = 1.2
appearance_flags = HAS_EYE_COLOR
@@ -424,6 +424,7 @@
radiation_mod = 0 // not affected by radiation
remains_type = /obj/effect/decal/remains/robot
hud_type = /datum/hud_data/ipc
brute_mod = 1.0
burn_mod = 1.2
@@ -487,6 +488,8 @@
stamina = -1 // Machines use power and generate heat, stamina is not a thing
sprint_speed_factor = 1 // About as capable of speed as a human
max_hydration_factor = -1
// Special snowflake machine vars.
var/sprint_temperature_factor = 1.15
var/sprint_charge_factor = 0.65
@@ -499,15 +502,16 @@ datum/species/machine/handle_post_spawn(var/mob/living/carbon/human/H)
/datum/species/machine/handle_sprint_cost(var/mob/living/carbon/human/H, var/cost)
if (H.stat == CONSCIOUS)
H.bodytemperature += cost * sprint_temperature_factor
H.nutrition -= cost * sprint_charge_factor
if (H.nutrition > 0)
return 1
else
H.adjustNutritionLoss(cost * sprint_charge_factor)
if(H.nutrition <= 0 && H.max_nutrition > 0)
H.Weaken(15)
H.m_intent = "walk"
H.hud_used.move_intent.update_move_icon(H)
H << span("danger", "ERROR: Power reserves depleted, emergency shutdown engaged. Backup power will come online in approximately 30 seconds, initiate charging as primary directive.")
playsound(H.loc, 'sound/machines/buzz-two.ogg', 100, 0)
else
return 1
return 0
/datum/species/machine/handle_death(var/mob/living/carbon/human/H)
@@ -340,6 +340,7 @@
has_resist = 1
has_pressure = 0
has_nutrition = 0
has_hydration = 0
has_bodytemp = 0
has_internals = 0
@@ -159,7 +159,7 @@
/mob/living/carbon/slime/proc/handle_nutrition()
if (prob(15))
nutrition -= 1 + is_adult
adjustNutritionLoss(1 + is_adult)
if(nutrition <= 0)
nutrition = 0
@@ -168,7 +168,7 @@
src << "<span class='danger'>You are starving!</span>"
else if (nutrition >= get_grow_nutrition() && amount_grown < 10)
nutrition -= 20
adjustNutritionLoss(20)
amount_grown++
/mob/living/carbon/slime/proc/handle_targets()
@@ -379,7 +379,7 @@
return
/mob/living/carbon/slime/proc/gain_nutrition(var/amount)
nutrition += amount
adjustNutritionLoss(-10)
if(prob(amount * 2)) // Gain around one level per 50 nutrition
powerlevel++
if(powerlevel > 10)
+11 -1
View File
@@ -307,7 +307,12 @@ default behaviour is:
return halloss
/mob/living/proc/adjustHalLoss(var/amount)
if(status_flags & GODMODE) return 0 //godmode
if(status_flags & GODMODE)
return 0
if(amount > 0)
amount *= 2/(get_nutrition_mul(0.5,1) + get_hydration_mul(0.5,1))
halloss = min(max(halloss + amount, 0),(maxHealth*2))
/mob/living/carbon/adjustHalLoss(var/amount, var/ignoreImmunity = 0)//An inherited version so this doesnt affect cyborgs
@@ -316,6 +321,10 @@ default behaviour is:
if (species && species.flags & NO_PAIN)//Species with this flag will only gather halloss through species-specific mechanics, which apply it with the ignoreImmunity flag
return 0
if(amount > 0)
amount *= 1/get_hydration_mul()
amount *= 1/get_nutrition_mul()
halloss = min(max(halloss + amount, 0),(maxHealth*2))
/mob/living/proc/setHalLoss(var/amount)
@@ -470,6 +479,7 @@ default behaviour is:
// shut down ongoing problems
total_radiation = 0
nutrition = 400
hydration = 400
bodytemperature = T20C
sdisabilities = 0
disabilities = 0
@@ -130,7 +130,7 @@
. = ..()
if(.)
if(src.nutrition && src.stat != DEAD && hunger_enabled)
src.nutrition -= nutrition_step
src.adjustNutritionLoss(nutrition_step)
/mob/living/simple_animal/Released()
//These will cause mobs to immediately do things when released.
@@ -289,8 +289,7 @@
/mob/living/simple_animal/proc/process_food()
if (hunger_enabled)
if (nutrition)
nutrition -= nutrition_step//Bigger animals get hungry faster
nutrition = max(0,min(nutrition, max_nutrition))//clamp the value
adjustNutritionLoss(nutrition_step)//Bigger animals get hungry faster
else
if (prob(3))
src << "You feel hungry..."
@@ -303,7 +302,7 @@
var/removed = min(current.metabolism*digest_factor, current.volume)
if (istype(current, /datum/reagent/nutriment))//If its food, it feeds us
var/datum/reagent/nutriment/N = current
nutrition += removed*N.nutriment_factor
adjustNutritionLoss(-removed*N.nutriment_factor)
var/heal_amount = removed*N.regen_factor
if (bruteloss > 0)
var/n = min(heal_amount, bruteloss)
+1
View File
@@ -57,6 +57,7 @@
healths = null
throw_icon = null
nutrition_icon = null
hydration_icon = null
pressure = null
damageoverlay = null
pain = null
+9 -1
View File
@@ -23,6 +23,7 @@
var/obj/screen/healths = null
var/obj/screen/throw_icon = null
var/obj/screen/nutrition_icon = null
var/obj/screen/hydration_icon = null
var/obj/screen/pressure = null
var/obj/screen/damageoverlay = null
var/obj/screen/pain = null
@@ -112,10 +113,17 @@
var/charges = 0.0
var/nutrition = 400.0//Carbon
var/nutrition_loss = HUNGER_FACTOR //How much hunger is lost per tick. This is modified by species
var/nutrition_attrition_rate = 1 // A multiplier for how much this specific mob loses per tick.
var/nutrition_attrition_rate = 1 // A multiplier for how much nutrition this specific mob loses per tick.
var/max_nutrition = 400
var/hydration = 400.0//Carbon
var/hydration_loss = THIRST_FACTOR //How much hunger is lost per tick. This is modified by species
var/hydration_attrition_rate = 1 // A multiplier for how much hydration this specific mob loses per tick.
var/max_hydration = 400
var/overeatduration = 0 // How long this guy is overeating //Carbon
var/overdrinkduration = 0 // How long this guy is overdrinking //Carbon
var/paralysis = 0.0
var/stunned = 0.0
var/weakened = 0.0
+66 -2
View File
@@ -724,8 +724,8 @@ proc/is_blind(A)
var/turf/location = loc
if (istype(location, /turf/simulated))
location.add_vomit_floor(src, 1)
nutrition -= 60
adjustNutritionLoss(60)
adjustHydrationLoss(30)
if (intoxication)//The pain and system shock of vomiting, sobers you up a little
intoxication *= 0.9
@@ -1178,3 +1178,67 @@ proc/is_blind(A)
/mob/living/silicon/ai/get_multitool()
return ..(aiMulti)
/mob/proc/get_hydration_mul(var/minscale = 0, var/maxscale = 1)
if(status_flags & GODMODE) //Godmode
return maxscale
if(max_hydration <= 0) //Has no hydration
return maxscale
var/hydration_mul = hydration/max_hydration
if(hydration_mul >= CREW_HYDRATION_OVERHYDRATED)
return minscale + ( (maxscale - minscale) * 0.75)
if(hydration_mul <= CREW_HYDRATION_DEHYDRATED)
return minscale + ( (maxscale - minscale) * 0.25)
if(hydration_mul <= CREW_HYDRATION_VERYTHIRSTY)
return minscale + ( (maxscale - minscale) * 0.5)
if(hydration_mul <= CREW_HYDRATION_THIRSTY)
return minscale + ( (maxscale - minscale) * 0.75)
return minscale + ( (maxscale - minscale) * 1)
/mob/proc/get_nutrition_mul(var/minscale = 0, var/maxscale = 1)
if(status_flags & GODMODE) //Godmode
return maxscale
if(max_nutrition <= 0) //Has no nutrition
return maxscale
var/nutrition_mul = nutrition/max_nutrition
if(nutrition_mul >= CREW_NUTRITION_OVEREATEN)
return minscale + ( (maxscale - minscale) * 0.75)
if(nutrition_mul <= CREW_NUTRITION_STARVING)
return minscale + ( (maxscale - minscale) * 0.25)
if(nutrition_mul <= CREW_NUTRITION_VERYHUNGRY)
return minscale + ( (maxscale - minscale) * 0.5)
if(nutrition_mul <= CREW_NUTRITION_HUNGRY)
return minscale + ( (maxscale - minscale) * 0.75)
return minscale + ( (maxscale - minscale) * 1)
/mob/proc/adjustNutritionLoss(var/amount)
if(max_nutrition <= 0)
return FALSE
nutrition = max(0,min(max_nutrition,nutrition - amount))
return TRUE
/mob/proc/adjustHydrationLoss(var/amount)
if(max_nutrition <= 0)
return FALSE
hydration = max(0,min(max_hydration,hydration - amount))
return TRUE