diff --git a/code/game/objects/structures/flora/flora.dm b/code/game/objects/structures/flora/flora.dm
index aafdc194a7..78e85b802b 100644
--- a/code/game/objects/structures/flora/flora.dm
+++ b/code/game/objects/structures/flora/flora.dm
@@ -91,21 +91,29 @@
var/mob/living/simple_mob/animal/critter = user
if(!critter.forager)
return ..()
+
+ if(!critter.has_appetite())
+ to_chat(critter, SPAN_WARNING("You don't have much of an appetite at the moment."))
+ return TRUE
+
if(!can_forage(critter))
to_chat(critter, SPAN_WARNING("You cannot see any edible fruit on \the [src]."))
return TRUE
+
critter.set_AI_busy(TRUE)
show_animal_foraging_message(critter)
critter.setClickCooldown(5 SECONDS)
+
if(!do_after(critter, 5 SECONDS, src) || QDELETED(src) || !can_forage(user))
critter.set_AI_busy(FALSE)
return TRUE
+
critter.set_AI_busy(FALSE)
show_animal_eating_message(critter)
- playsound(critter, 'sound/items/eatfood.ogg', rand(10,50), 1)
harvest_count++
critter.eat_food_item(spawn_harvest(pickweight(harvest_loot)))
return TRUE
+
return ..()
/obj/structure/flora/proc/can_forage(var/mob/critter)
diff --git a/code/modules/food/food/snacks.dm b/code/modules/food/food/snacks.dm
index ed338ec586..42c2e15f93 100644
--- a/code/modules/food/food/snacks.dm
+++ b/code/modules/food/food/snacks.dm
@@ -232,6 +232,9 @@
return
if(isanimal(user))
var/mob/living/simple_mob/animal/critter = user
+ if(!critter.has_appetite())
+ to_chat(critter, SPAN_WARNING("You don't have much of an appetite at the moment."))
+ return TRUE
critter.eat_food_item(src, bitesize)
else
user.visible_message("[user] nibbles away at \the [src].","You nibble away at \the [src].")
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm b/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
index e0d4b6addc..01d75be657 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/animal.dm
@@ -31,6 +31,9 @@
/decl/mob_organ_names/quadruped //Most subtypes have this basic body layout.
hit_zones = list("head", "torso", "left foreleg", "right foreleg", "left hind leg", "right hind leg", "tail")
+/mob/living/simple_mob/animal/proc/has_appetite()
+ return TRUE
+
/mob/living/simple_mob/animal/do_interaction(var/atom/A)
// Can we do some critter interaction?
@@ -50,6 +53,11 @@
if(scavenger && isliving(A) && a_intent == I_HURT)
var/mob/living/M = A
if(M.stat == DEAD && length(M.internal_organs))
+
+ if(!has_appetite())
+ to_chat(src, SPAN_WARNING("You don't have much of an appetite at the moment."))
+ return TRUE
+
to_chat(src, SPAN_NOTICE("You dig into the guts of \the [M], hunting for the sweetest meat."))
set_AI_busy(TRUE)
if(do_after(src, 2 SECONDS, M) && !QDELETED(M) && length(M.internal_organs))
@@ -65,18 +73,21 @@
/mob/living/simple_mob/animal/proc/eat_food_item(var/obj/item/snack, var/override_bitesize, var/silent)
- if(!silent)
- visible_message("\The [src] nibbles away at \the [snack].")
- playsound(src, 'sound/items/eatfood.ogg', rand(10,50), 1)
-
if(istype(snack, /obj/item/organ))
var/obj/item/organ/organ = snack
if(organ.meat_type)
snack = new organ.meat_type(src)
qdel(organ)
+ else if(!istype(snack) || !snack.reagents?.total_volume)
+ to_chat(src, SPAN_WARNING("\The [snack] doesn't seem edible."))
+ return
+
+ if(!silent)
+ visible_message("\The [src] nibbles away at \the [snack].")
+ playsound(src, 'sound/items/eatfood.ogg', rand(10,50), 1)
if(snack.reagents?.total_volume)
- var/use_bitesize = (override_bitesize || bitesize)
+ var/use_bitesize = max(override_bitesize, bitesize)
var/removing_reagents = clamp(use_bitesize, 0, min(max(0, reagents?.maximum_volume - reagents?.total_volume), snack.reagents.total_volume))
if(reagents && removing_reagents)
snack.reagents.trans_to_holder(reagents, removing_reagents)
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
index a253afca46..396ddedfc7 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka.dm
@@ -7,9 +7,16 @@
on_expired_text = "The last of the sap in your wounds is absorbed by your body."
/datum/modifier/sifsap_salve/tick()
+
if(holder.stat == DEAD)
expire()
+
if(istype(holder, /mob/living/simple_mob/animal/sif))
+
+ var/mob/living/simple_mob/animal/sif/critter = holder
+ if(critter.health >= critter.sap_heal_threshold)
+ return
+
if(holder.resting)
if(istype(holder.loc, /obj/structure/animal_den))
holder.adjustBruteLoss(-3)
@@ -116,6 +123,11 @@ var/global/list/last_drake_howl = list()
tt_desc = "S tesca pabulator"
faction = "grafadreka"
+ mob_size = MOB_LARGE
+ mob_bump_flag = SIMPLE_ANIMAL
+ mob_swap_flags = SIMPLE_ANIMAL
+ mob_push_flags = SIMPLE_ANIMAL
+
maxHealth = 150
health = 150
movement_cooldown = 2
@@ -167,7 +179,6 @@ var/global/list/last_drake_howl = list()
var/max_stored_sap = 100
var/attacked_by_human = FALSE
-
/mob/living/simple_mob/animal/sif/grafadreka/proc/can_tend_wounds(var/mob/living/friend)
if(ishuman(friend))
var/mob/living/carbon/human/H = friend
@@ -175,6 +186,9 @@ var/global/list/last_drake_howl = list()
if(E.status & ORGAN_BLEEDING)
return TRUE
return FALSE
+ if(istype(friend, /mob/living/simple_mob/animal/sif))
+ var/mob/living/simple_mob/animal/sif/critter = friend
+ return critter.health < critter.sap_heal_threshold
return (friend.health < friend.maxHealth)
/mob/living/simple_mob/animal/sif/grafadreka/Initialize()
@@ -219,7 +233,7 @@ var/global/list/last_drake_howl = list()
// Process food and sap chems.
if(stat == CONSCIOUS) // Hibernating drakes don't get hungy.
// by default we lose nutrition. Hungry hungry drakes.
- var/food_val = resting ? -0.2 : -0.5
+ var/food_val = resting ? 0 : -0.3
// Very basic metabolism.
if(reagents?.total_volume)
@@ -227,7 +241,7 @@ var/global/list/last_drake_howl = list()
var/removing = min(REM, chem.volume)
if(istype(chem, /datum/reagent/nutriment))
var/datum/reagent/nutriment/food = chem
- food_val += (food.nutriment_factor * removing) * ((food.allergen_type & ALLERGEN_MEAT) ? 0.5 : 0.1)
+ food_val += (food.nutriment_factor * removing) * ((food.allergen_type & ALLERGEN_MEAT) ? 0.3 : 0.1)
else if(istype(chem, /datum/reagent/toxin/sifslurry))
add_sap(removing * 3)
reagents.remove_reagent(chem.id, removing)
@@ -341,9 +355,14 @@ var/global/list/last_drake_howl = list()
if(!can_tend_wounds(friend))
if(friend == src)
- to_chat(src, SPAN_WARNING("You are unwounded."))
+ if(health == maxHealth)
+ to_chat(src, SPAN_WARNING("You are unwounded."))
+ else
+ to_chat(src, SPAN_WARNING("You cannot tend any of your wounds."))
else
- return ..()
+ if(friend.health == friend.maxHealth)
+ return ..()
+ to_chat(src, SPAN_WARNING("You cannot tend any of \the [friend]'s wounds."))
return TRUE
if(friend.has_modifier_of_type(/datum/modifier/sifsap_salve))
@@ -460,7 +479,7 @@ var/global/list/last_drake_howl = list()
to_chat(src, SPAN_WARNING("You aren't the pack leader! Sit down!"))
return
- for(var/mob/living/simple_mob/animal/sif/grafadreka/drake in hearers(7, src))
+ for(var/mob/living/simple_mob/animal/sif/grafadreka/drake in hearers(world.view * 3, src))
if(drake == src || drake.faction != faction)
continue
if(drake.client)
@@ -470,6 +489,9 @@ var/global/list/last_drake_howl = list()
audible_message("\The [src] barks loudly and rattles its neck spines.")
+/mob/living/simple_mob/animal/sif/grafadreka/has_appetite()
+ return reagents && abs(reagents.total_volume - reagents.maximum_volume) >= 10
+
/datum/say_list/grafadreka
speak = list("Chff!","Skhh.", "Rrrss...")
emote_see = list("scratches its ears","grooms its spines", "sways its tail", "claws at the ground")
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka_ai.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka_ai.dm
index 9fdcc7b1a0..fd7c18ff2f 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka_ai.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/grafadreka_ai.dm
@@ -24,14 +24,15 @@
drake_brain.hostile = TRUE
/datum/ai_holder/simple_mob/intentional/grafadreka
- hostile = TRUE
- retaliate = TRUE
- cooperative = TRUE
- can_flee = TRUE
- flee_when_dying = TRUE
- var/next_food_check
- var/next_sap_check
- var/next_heal_check
+ hostile = TRUE
+ retaliate = TRUE
+ cooperative = TRUE
+ can_flee = TRUE
+ flee_when_dying = TRUE
+ home_low_priority = TRUE
+ var/next_food_check = 0
+ var/next_sap_check = 0
+ var/next_heal_check = 0
/datum/ai_holder/simple_mob/intentional/grafadreka/should_flee(force)
. = ..()
@@ -105,7 +106,7 @@
return
// These actions need space in our stomach to be worth considering at all.
- if(drake.reagents && abs(drake.reagents.total_volume - drake.reagents.maximum_volume) >= 10)
+ if(drake.has_appetite() && !(locate(/datum/reagent/nutriment) in drake.reagents.reagent_list))
// Find some sap if we're low and aren't already digesting some.
if(!drake.has_sap(20) && !drake.reagents.has_reagent("sifsap"))
diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/sif/sif.dm b/code/modules/mob/living/simple_mob/subtypes/animal/sif/sif.dm
index e3573025ae..8856abca11 100644
--- a/code/modules/mob/living/simple_mob/subtypes/animal/sif/sif.dm
+++ b/code/modules/mob/living/simple_mob/subtypes/animal/sif/sif.dm
@@ -5,6 +5,23 @@
heat_resist = -0.5
tame_items = list(
- /obj/item/reagent_containers/food/snacks/meat/crab = 20,
- /obj/item/reagent_containers/food/snacks/meat = 10
+ /obj/item/reagent_containers/food/snacks/meat/crab = 20,
+ /obj/item/reagent_containers/food/snacks/meat = 10
)
+
+ // Healing threshold for grafadreka healing spit effect.
+ var/sap_heal_threshold
+ var/sap_heal_gradient = 0.25 // 25% of health each regen threshold
+
+/mob/living/simple_mob/animal/sif/Initialize()
+ . = ..()
+ sap_heal_threshold = round(maxHealth * 0.15)
+
+/mob/living/simple_mob/animal/sif/updatehealth()
+ . = ..()
+ var/sap_threshold = round(maxHealth * sap_heal_gradient)
+ sap_heal_threshold = min(maxHealth, min(sap_heal_threshold, n_ceil(health % sap_threshold)*sap_threshold))
+
+/mob/living/simple_mob/animal/sif/rejuvenate()
+ sap_heal_threshold = maxHealth
+ . = ..()
diff --git a/code/modules/organs/organ.dm b/code/modules/organs/organ.dm
index eb7f169c47..ae12db9e21 100644
--- a/code/modules/organs/organ.dm
+++ b/code/modules/organs/organ.dm
@@ -562,6 +562,9 @@ var/global/list/organ_cache = list()
/obj/item/organ/attack_generic(mob/user)
if(isanimal(user))
var/mob/living/simple_mob/animal/critter = user
- critter.eat_food_item(src)
+ if(!critter.has_appetite())
+ to_chat(critter, SPAN_WARNING("You don't have much of an appetite at the moment."))
+ else
+ critter.eat_food_item(src)
return TRUE
return ..()