Animal Feeding and Hunger (#634)

changes:

rscadd: "Added hunger and feeding system for simple animals, this includes cats, dogs, mice, lizards, chickens, cows, etc"
rscadd: "Animals can now actually consume food instead of nibbling them eternally."
rscadd: "Animals can now be hand-fed by using food on them."
rscadd: "Animals will move more slowly when starving. Examining an animal will show if its hungry."
Basically added a very simple metabolising system for animals, and fixed up various eating/feeding functions. They only metabolise food, any other reagents are just removed and ignored for now, since most chemicals were designed for carbon mobs and often aren't valid
This commit is contained in:
NanakoAC
2016-08-02 21:43:03 +03:00
committed by skull132
parent d1f79a6168
commit ecf8425a19
5 changed files with 174 additions and 8 deletions
@@ -30,6 +30,7 @@
universal_understand = 1
mob_size = 1
holder_type = /obj/item/weapon/holder/mouse
digest_factor = 0.05
/mob/living/simple_animal/mouse/Life()
..()
@@ -75,6 +76,8 @@
holder_type = /obj/item/weapon/holder/mouse/white
/mob/living/simple_animal/mouse/attack_hand(mob/living/carbon/human/M as mob)
if (src.stat == DEAD)//If the mouse is dead, we don't pet it, we just pickup the corpse on click
get_scooped(M)
@@ -66,9 +66,29 @@
var/supernatural = 0
var/purge = 0
var/max_nutrition = 75
var/nutrition_step = 0.2 //nutrition lost per tick and per step, calculated from mob_size, 0.4 is a fallback
var/bite_factor = 0.4
var/digest_factor = 0.2 //A multiplier on how quickly reagents are digested
/mob/living/simple_animal/New()
..()
verbs -= /mob/verb/observe
if (mob_size)
nutrition_step = mob_size * 0.05
bite_factor = mob_size * 0.3
max_nutrition *= 1 + (nutrition_step*3)//Max nutrition scales faster than costs, so bigger creatures eat less often
reagents = new/datum/reagents(5*mob_size, src)
else
reagents = new/datum/reagents(20, src)
nutrition = max_nutrition
/mob/living/simple_animal/Move(NewLoc, direct)
. = ..()
if(.)
if(src.nutrition && src.stat != DEAD)
src.nutrition -= nutrition_step
/mob/living/simple_animal/Login()
if(src && src.client)
@@ -78,6 +98,15 @@
/mob/living/simple_animal/updatehealth()
return
/mob/living/simple_animal/examine(mob/user)
..()
if (!nutrition)
user << "<span class='danger'>It looks starving!</span>"
else if (nutrition < max_nutrition *0.5)
user << "<span class='notice'>It looks hungry.</span>"
else if ((reagents.total_volume > 0 && nutrition > max_nutrition *0.75) || nutrition > max_nutrition *0.9)
user << "It looks full and contented."
/mob/living/simple_animal/Life()
..()
@@ -104,7 +133,7 @@
handle_paralysed()
update_canmove()
handle_supernatural()
process_food()
//Movement
if(!client && !stop_automated_movement && wander && !anchored)
if(isturf(src.loc) && !resting && !buckled && canmove) //This is so it only moves if it's not inside a closet, gentics machine, etc.
@@ -210,6 +239,40 @@
if(purge)
purge -= 1
//Simple reagent processing for simple animals
//This allows animals to digest food, and only food
//Most drugs, poisons etc, are designed to work on carbons and affect many values a simple animal doesnt have
/mob/living/simple_animal/proc/process_food()
if (nutrition)
nutrition -= nutrition_step//Bigger animals get hungry faster
nutrition = max(0,min(nutrition, max_nutrition))//clamp the value
else
if (prob(3))
src << "You feel hungry..."
if (!reagents || !reagents.total_volume)
return
for(var/datum/reagent/current in reagents.reagent_list)
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
current.remove_self(removed)//If its not food, it just does nothing. no fancy effects
/mob/living/simple_animal/proc/can_eat()
if (nutrition > max_nutrition * 0.9)
return 0//full
else if (nutrition > max_nutrition * 0.8)
return 1//content
else return 2//hungry
/mob/living/simple_animal/gib()
..(icon_gib,1)
@@ -284,7 +347,10 @@
M.show_message("<span class='notice'>[user] applies the [MED] on [src].</span>")
else
user << "<span class='notice'>\The [src] is dead, medical items won't bring \him back to life.</span>"
if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead.
else if(istype(O, /obj/item/weapon/reagent_containers))
..()
else if(meat_type && (stat == DEAD)) //if the animal has a meat, and if it is dead.
if(istype(O, /obj/item/weapon/material/knife) || istype(O, /obj/item/weapon/material/knife/butch))
harvest(user)
else
@@ -320,6 +386,9 @@
tally = 1
tally *= purge
if (!nutrition)
tally += 4
return tally+config.animal_delay
/mob/living/simple_animal/Stat()
+7 -3
View File
@@ -391,9 +391,13 @@
var/datum/reagents/R = C.touching
return trans_to_holder(R, amount, multiplier, copy)
else
var/datum/reagents/R = new /datum/reagents(amount)
. = trans_to_holder(R, amount, multiplier, copy)
R.touch_mob(target)
//If the target has a reagent holder, we'll try to put it there instead. This allows feeding simple animals
if(target.reagents && type == CHEM_BLOOD || type == CHEM_INGEST)
return trans_to_holder(target.reagents, amount, multiplier, copy)
else
var/datum/reagents/R = new /datum/reagents(amount)
. = trans_to_holder(R, amount, multiplier, copy)
R.touch_mob(target)
/datum/reagents/proc/trans_to_turf(var/turf/target, var/amount = 1, var/multiplier = 1, var/copy = 0) // Turfs don't have any reagents (at least, for now). Just touch it.
if(!target || !target.simulated)
@@ -108,6 +108,32 @@
On_Consume(M)
return 1
else if (isanimal(M))
var/mob/living/simple_animal/SA = M
var/m_bitesize = bitesize * SA.bite_factor//Modified bitesize based on creature size
var/amount_eaten = m_bitesize
if(reagents && SA.reagents)
m_bitesize = min(m_bitesize, reagents.total_volume)
//If the creature can't even stomach half a bite, then it eats nothing
if (!SA.can_eat() || ((user.reagents.maximum_volume - user.reagents.total_volume) < m_bitesize * 0.5))
amount_eaten = 0
else
amount_eaten = reagents.trans_to_mob(SA, m_bitesize, CHEM_INGEST)
else
return 0//The target creature can't eat
if (amount_eaten)
bitecount++
if (amount_eaten >= m_bitesize)
user.visible_message("<span class='notice'>[user] feeds [M] [src].</span>")
else
user.visible_message("<span class='notice'>[user] feeds [M] a tiny bit of [src]. <b>It looks full.</b></span>")
On_Consume(M)
return 1
else
user << "<span class='danger'>[M.name] can't stomach anymore food!</span>"
return 0
/obj/item/weapon/reagent_containers/food/snacks/examine(mob/user)
@@ -206,10 +232,34 @@
/obj/item/weapon/reagent_containers/food/snacks/attack_generic(var/mob/living/user)
if(!isanimal(user) && !isalien(user))
return
user.visible_message("<b>[user]</b> nibbles away at \the [src].","You nibble away at \the [src].")
bitecount++
var/amount_eaten = bitesize
var/m_bitesize = bitesize
if (isanimal(user))
var/mob/living/simple_animal/SA = user
m_bitesize = bitesize * SA.bite_factor//Modified bitesize based on creature size
amount_eaten = m_bitesize
if (!SA.can_eat())
user << "<span class='danger'>You're too full to eat anymore!</span>"
return
if(reagents && user.reagents)
reagents.trans_to_mob(user, bitesize, CHEM_INGEST)
m_bitesize = min(m_bitesize, reagents.total_volume)
//If the creature can't even stomach half a bite, then it eats nothing
if (((user.reagents.maximum_volume - user.reagents.total_volume) < m_bitesize * 0.5))
amount_eaten = 0
else
amount_eaten = reagents.trans_to_mob(user, m_bitesize, CHEM_INGEST)
if (amount_eaten)
bitecount++
if (amount_eaten < m_bitesize)
user.visible_message("<span class='notice'><b>[user]</b> reluctantly nibbles a tiny part of \the [src].</span>","<span class='notice'>You reluctantly nibble a tiny part of \the [src]. <b>You can't stomach much more!</b>.</span>")
else
user.visible_message("<span class='notice'><b>[user]</b> nibbles away at \the [src].</span>","<span class='notice'>You nibble away at \the [src].</span>")
else
user << "<span class='danger'>You're too full to eat anymore!</span>"
spawn(5)
if(!src && !user.client)
user.custom_emote(1,"[pick("burps", "cries for more", "burps twice", "looks at the area where the food was")]")