Monkey eating glowup (#93759)

## About The Pull Request

1. Monkeys will only seek out food to eat if they are actually hungry,
rather than on an arbitrary cooldown.
2. Monkeys will no longer teleport-yoink food out of your hands.
Instead, they may get angry at you for stealing their food, and fight
you over it. The hungrier the monkey, the more likely they are to fight.
3. Monkeys will discard trash and empty glasses (on the floor) after
eating or drinking them.
4. Monkeys can target soup to eat
5. PunPun will no longer seek out drinks if they are hungry.
6. PunPun will now, if the bartender is absent and there are multiple
patrons around, attempt to find filled glasses or food to hand out to
patrons.
7. Several places that sought edible items no longer include drinking
glasses as edible items

<img width="656" height="185" alt="image"
src="https://github.com/user-attachments/assets/8b3a6ac1-ae2c-41a0-919f-b471ad93bb0f"
/>

## Why It's Good For The Game

PunPun shouldn't be yoinking glasses out of patron's hands - their
intended behavior is to serve drinks not steal them

Otherwise, monkey eating was a bit jank due to it being some of our
oldest ai code. I largely just brought it up to more modern ai
standards.

## Changelog

🆑 Melbert
add: If the bartender is absent, PunPun will serve filled drink glasses
to patrons that don't have one.
add: PunPun will now ignore filled drinks and items being held when
looking for stuff to eat.
add: Monkeys can eat soup.
add: Monkeys will no longer seek out food if they are not hungry.
add: Hungry monkeys might fight you over the food you are holding. The
hungrier the monkey, the angrier the monkey.
fix: Monkeys can no longer teleport items out of your hands to eat. 
/🆑
This commit is contained in:
MrMelbert
2025-11-07 18:32:46 -06:00
committed by GitHub
parent 90377aa997
commit c080b83c41
16 changed files with 196 additions and 92 deletions

View File

@@ -4,6 +4,8 @@
#define BB_CURRENT_MIN_MOVE_DISTANCE "min_move_distance"
///time until we should next eat, set by the generic hunger subtree
#define BB_NEXT_HUNGRY "BB_NEXT_HUNGRY"
///When looking for food, ignore drinks
#define BB_IGNORE_DRINKS "bb_ignore_drinks"
///what we're going to eat next
#define BB_FOOD_TARGET "bb_food_target"
///How close a mob must be for us to select it as a target, if that is less than how far we can maintain it as a target
@@ -237,5 +239,3 @@
// Used to hold state without making bigass lists
/// For /datum/ai_behavior/find_potential_targets, what if any field are we using currently
#define BB_FIND_TARGETS_FIELD(type) "bb_find_targets_field_[type]"

View File

@@ -15,3 +15,11 @@
#define BB_MONKEY_DISPOSING "BB_monkey_disposing"
#define BB_MONKEY_RECRUIT_COOLDOWN "BB_monkey_recruit_cooldown"
#define BB_RESISTING "BB_resisting"
/// Monkey is not necessarily a wild animal so it won't resort to fighting over food and such
#define BB_MONKEY_TAMED "BB_monkey_tamed"
/// Chance to give our held item to a nearby mob
#define BB_MONKEY_GIVE_CHANCE "BB_monkey_give_chance"
/// If set, the monkey will prefer this type of object when pressing things
#define BB_MONKEY_PRESS_TYPEPATH "BB_monkey_press_typepath"
/// The item the monkey is currently serving to someone
#define BB_MONKEY_CURRENT_SERVED_ITEM "BB_monkey_current_served_item"

View File

@@ -30,6 +30,8 @@
#define MONKEY_HATRED_AMOUNT 4
/// amount of aggro to add to an enemy when a monkey is recruited
#define MONKEY_RECRUIT_HATED_AMOUNT 2
/// amount of aggro to add if someone stole the food we wanted
#define MONKEY_FOOD_HATRED_AMOUNT 2
/// probability of reducing aggro by one when the monkey attacks
#define MONKEY_HATRED_REDUCTION_PROB 20

View File

@@ -28,15 +28,3 @@
top_force = item.force
return top_force_item
///returns if something can be consumed, drink or food
/proc/IsEdible(obj/item/thing)
if(!istype(thing))
return FALSE
if(IS_EDIBLE(thing))
return TRUE
if(istype(thing, /obj/item/reagent_containers/cup/glass/drinkingglass))
var/obj/item/reagent_containers/cup/glass/drinkingglass/glass = thing
if(glass.reagents.total_volume) // The glass has something in it, time to drink the mystery liquid!
return TRUE
return FALSE

View File

@@ -34,21 +34,42 @@
/**
* Variant of find and set that also requires the item to be edible. checks hands too
*/
/datum/ai_behavior/find_and_set/edible
/datum/ai_behavior/find_and_set/food_or_drink
var/force_find_drinks = FALSE
/datum/ai_behavior/find_and_set/edible/search_tactic(datum/ai_controller/controller, locate_path, search_range)
/datum/ai_behavior/find_and_set/food_or_drink/search_tactic(datum/ai_controller/controller, locate_path, search_range)
var/mob/living/living_pawn = controller.pawn
var/find_drinks = force_find_drinks || controller.blackboard[BB_IGNORE_DRINKS] || FALSE
for(var/atom/held_candidate as anything in living_pawn.held_items)
if(IsEdible(held_candidate))
for(var/atom/held_candidate in living_pawn.held_items)
if(is_food_or_drink(controller, held_candidate, find_drinks))
return held_candidate
for(var/atom/local_candidate as anything in oview(search_range, controller.pawn))
if(IsEdible(local_candidate) && istype(local_candidate, locate_path))
for(var/atom/local_candidate in oview(search_range, controller.pawn))
if(is_food_or_drink(controller, local_candidate, find_drinks) && istype(local_candidate, locate_path))
return local_candidate
return null
/datum/ai_behavior/find_and_set/food_or_drink/proc/is_food_or_drink(datum/ai_controller/controller, obj/item/thing, find_drinks = FALSE)
return is_food(thing) || (find_drinks && is_drink(thing))
/datum/ai_behavior/find_and_set/food_or_drink/proc/is_food(obj/item/thing)
if(IS_EDIBLE(thing))
return TRUE
if(istype(thing, /obj/item/reagent_containers/cup/bowl))
return thing.reagents.total_volume > 0
return FALSE
/datum/ai_behavior/find_and_set/food_or_drink/proc/is_drink(obj/item/thing)
if(istype(thing, /obj/item/reagent_containers/cup/glass))
return thing.reagents.total_volume > 0
return FALSE
/datum/ai_behavior/find_and_set/food_or_drink/to_eat
/datum/ai_behavior/find_and_set/food_or_drink/to_serve
force_find_drinks = TRUE
/**
* Variant of find and set that only checks in hands, search range should be excluded for this

View File

@@ -91,17 +91,11 @@
set_movement_target(controller, target)
/datum/ai_behavior/use_on_object/perform(seconds_per_tick, datum/ai_controller/controller, target_key)
var/mob/living/pawn = controller.pawn
var/obj/item/held_item = pawn.get_item_by_slot(pawn.get_active_hand())
var/atom/target = controller.blackboard[target_key]
if(QDELETED(target))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
if(held_item)
held_item.melee_attack_chain(pawn, target)
else
controller.ai_interact(target = target, combat_mode = FALSE)
controller.ai_interact(target = target, combat_mode = FALSE)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/give
@@ -120,10 +114,14 @@
if(!held_item) //if held_item is null, we pretend that action was successful
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
if(!target || !isliving(target))
if(QDELETED(target) || !target.IsReachableBy(pawn))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/mob/living/living_target = target
if(!isliving(living_target)) // target should reasonably only ever be set to a living mob
stack_trace("Tried to give an item to a non-living target!")
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
var/perform_flags = try_to_give_item(controller, living_target, held_item)
if(perform_flags & AI_BEHAVIOR_FAILED)
return perform_flags
@@ -163,36 +161,73 @@
target.put_in_hands(held_item)
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
/datum/ai_behavior/give/finish_action(datum/ai_controller/controller, succeeded, target_key)
. = ..()
controller.clear_blackboard_key(target_key)
/datum/ai_behavior/consume
action_cooldown = 2 SECONDS
/datum/ai_behavior/consume/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hunger_timer_key)
var/mob/living/living_pawn = controller.pawn
var/obj/item/target = controller.blackboard[target_key]
if(QDELETED(target) || !living_pawn.is_holding(target))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
controller.ai_interact(target = living_pawn, combat_mode = FALSE)
return AI_BEHAVIOR_DELAY | (is_content(living_pawn, target) ? AI_BEHAVIOR_SUCCEEDED : AI_BEHAVIOR_FAILED)
/datum/ai_behavior/consume/finish_action(datum/ai_controller/controller, succeeded, target_key, hunger_timer_key)
. = ..()
if(!succeeded)
return
controller.set_blackboard_key(hunger_timer_key, world.time + rand(12 SECONDS, 60 SECONDS))
var/mob/living/living_pawn = controller.pawn
var/obj/item/target = controller.blackboard[target_key]
if(!QDELETED(target) && !DOING_INTERACTION_WITH_TARGET(living_pawn, target))
controller.clear_blackboard_key(target_key)
living_pawn.dropItemToGround(target) // drops empty drink glasses
for(var/obj/item/trash/trash in living_pawn.held_items)
living_pawn.dropItemToGround(trash) // drops spawned trash items
/// Check if the target is fully consumed, or being actively consumed, or if we're just bored of eating it
/datum/ai_behavior/consume/proc/is_content(mob/living/living_pawm, obj/item/target)
if(QDELETED(target))
return TRUE
if(DOING_INTERACTION_WITH_TARGET(living_pawm, target))
return TRUE
if(target.reagents?.total_volume <= 0)
return TRUE
// Even if we don't finish it all we can randomly decide to be done
return prob(10)
// navigate to target item and pick it up if we can
/datum/ai_behavior/navigate_to_and_pick_up
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_REQUIRE_REACH
action_cooldown = 2 SECONDS
/datum/ai_behavior/consume/setup(datum/ai_controller/controller, target_key)
/datum/ai_behavior/navigate_to_and_pick_up/setup(datum/ai_controller/controller, target_key, drop_held = TRUE)
. = ..()
set_movement_target(controller, controller.blackboard[target_key])
/datum/ai_behavior/consume/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hunger_timer_key)
/datum/ai_behavior/navigate_to_and_pick_up/setup(datum/ai_controller/controller, target_key, drop_held = TRUE)
var/mob/living/living_pawn = controller.pawn
var/obj/item/target = controller.blackboard[target_key]
if(QDELETED(target))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
if(!(target in living_pawn.held_items))
if(!living_pawn.get_empty_held_indexes() || !living_pawn.put_in_hands(target))
if(living_pawn.is_holding(target)) // already in hands
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
if(!target.IsReachableBy(living_pawn)) // can't reach it, despite being adjacent
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
if(living_pawn.get_active_held_item()) // something is in our hands already
if(!drop_held || !living_pawn.dropItemToGround(living_pawn.get_active_held_item()))
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
target.melee_attack_chain(living_pawn, living_pawn)
if(QDELETED(target) || prob(10)) // Even if we don't finish it all we can randomly decide to be done
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_SUCCEEDED
return AI_BEHAVIOR_DELAY | AI_BEHAVIOR_FAILED
/datum/ai_behavior/consume/finish_action(datum/ai_controller/controller, succeeded, target_key, hunger_timer_key)
. = ..()
if(succeeded)
controller.set_blackboard_key(hunger_timer_key, world.time + rand(12 SECONDS, 60 SECONDS))
controller.ai_interact(target, combat_mode = FALSE)
return AI_BEHAVIOR_DELAY | (target.loc == living_pawn ? AI_BEHAVIOR_SUCCEEDED : AI_BEHAVIOR_FAILED)
/**
* Drops items in hands, very important for future behaviors that require the pawn to grab stuff

View File

@@ -53,7 +53,13 @@
* relevant blackboards:
* * BB_NEXT_HUNGRY - set by this subtree, is when the controller is next hungry
*/
/datum/ai_planning_subtree/generic_hunger
/datum/ai_planning_subtree/generic_hunger/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/mob/living/living_pawn = controller.pawn
if(living_pawn.nutrition > NUTRITION_LEVEL_HUNGRY)
return
var/next_eat = controller.blackboard[BB_NEXT_HUNGRY]
if(!next_eat)
//inits the blackboard timer
@@ -63,16 +69,30 @@
if(world.time < next_eat)
return
// find food
var/atom/food_target = controller.blackboard[BB_FOOD_TARGET]
if(isnull(food_target))
controller.queue_behavior(/datum/ai_behavior/find_and_set/edible, BB_FOOD_TARGET, /obj/item, 2)
return
var/mob/living/living_pawn = controller.pawn
if(!length(living_pawn.get_empty_held_indexes()) && !(food_target in living_pawn.held_items))
controller.queue_behavior(/datum/ai_behavior/drop_item)
controller.queue_behavior(/datum/ai_behavior/find_and_set/food_or_drink/to_eat, BB_FOOD_TARGET, /obj/item, 2)
return SUBTREE_RETURN_FINISH_PLANNING
controller.queue_behavior(/datum/ai_behavior/consume, BB_FOOD_TARGET, BB_NEXT_HUNGRY)
if(living_pawn.is_holding(food_target))
controller.queue_behavior(/datum/ai_behavior/consume, BB_FOOD_TARGET, BB_NEXT_HUNGRY)
// it's been moved since we found it
else if(!isturf(food_target.loc))
// someone took it. we will fight over it!
if(isliving(food_target.loc) && will_fight_for_food(food_target.loc, living_pawn, controller))
controller.add_blackboard_key_assoc(BB_MONKEY_ENEMIES, food_target.loc, MONKEY_FOOD_HATRED_AMOUNT)
// eh, find something else
else
controller.clear_blackboard_key(BB_FOOD_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
else
controller.queue_behavior(/datum/ai_behavior/navigate_to_and_pick_up, BB_FOOD_TARGET, TRUE)
return SUBTREE_RETURN_FINISH_PLANNING
/datum/ai_planning_subtree/generic_hunger/proc/will_fight_for_food(mob/living/thief, mob/living/monkey, datum/ai_controller/controller)
if(controller.blackboard[BB_MONKEY_AGGRESSIVE])
return TRUE
if(controller.blackboard[BB_MONKEY_TAMED])
return FALSE
return prob(100 * ((NUTRITION_LEVEL_HUNGRY - monkey.nutrition) / NUTRITION_LEVEL_HUNGRY))

View File

@@ -25,6 +25,7 @@ have ways of interacting with a specific mob and control it.
BB_MONKEY_GUN_NEURONS_ACTIVATED = FALSE,
BB_SONG_LINES = MONKEY_SONG,
BB_RESISTING = FALSE,
BB_MONKEY_GIVE_CHANCE = 5,
)
idle_behavior = /datum/idle_behavior/idle_monkey
@@ -63,12 +64,24 @@ have ways of interacting with a specific mob and control it.
planning_subtrees = list(
/datum/ai_planning_subtree/generic_resist,
/datum/ai_planning_subtree/monkey_combat,
/datum/ai_planning_subtree/serve_food,
/datum/ai_planning_subtree/generic_hunger,
/datum/ai_planning_subtree/generic_play_instrument,
/datum/ai_planning_subtree/punpun_shenanigans,
/datum/ai_planning_subtree/monkey_shenanigans,
)
idle_behavior = /datum/idle_behavior/idle_monkey/pun_pun
/datum/ai_controller/monkey/pun_pun/TryPossessPawn(atom/new_pawn)
. = ..()
if(. & AI_CONTROLLER_INCOMPATIBLE)
return
pawn = new_pawn
set_blackboard_key(BB_IGNORE_DRINKS, TRUE)
set_blackboard_key(BB_MONKEY_TAMED, TRUE)
set_blackboard_key(BB_MONKEY_GIVE_CHANCE, 30)
set_blackboard_key(BB_MONKEY_PRESS_TYPEPATH, /obj/structure/desk_bell)
set_trip_mode(mode = FALSE)
/datum/ai_controller/monkey/angry
/datum/ai_controller/monkey/angry/TryPossessPawn(atom/new_pawn)

View File

@@ -7,21 +7,22 @@
return
if(!controller.blackboard[BB_MONKEY_CURRENT_PRESS_TARGET])
controller.queue_behavior(/datum/ai_behavior/find_nearby, BB_MONKEY_CURRENT_PRESS_TARGET)
return
if(prob(50))
if(controller.blackboard[BB_MONKEY_PRESS_TYPEPATH])
controller.queue_behavior(/datum/ai_behavior/find_and_set, BB_MONKEY_CURRENT_PRESS_TARGET, controller.blackboard[BB_MONKEY_PRESS_TYPEPATH], 2)
else
controller.queue_behavior(/datum/ai_behavior/find_nearby, BB_MONKEY_CURRENT_PRESS_TARGET)
else if(prob(50))
controller.queue_behavior(/datum/ai_behavior/use_on_object, BB_MONKEY_CURRENT_PRESS_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
if(!controller.blackboard[BB_MONKEY_CURRENT_GIVE_TARGET])
controller.queue_behavior(/datum/ai_behavior/find_and_set/pawn_must_hold_item, BB_MONKEY_CURRENT_GIVE_TARGET, /mob/living, 2)
else
if(prob(5))
controller.queue_behavior(/datum/ai_behavior/give, BB_MONKEY_CURRENT_GIVE_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
controller.queue_behavior(/datum/ai_behavior/find_and_set/pawn_must_hold_item, BB_MONKEY_CURRENT_GIVE_TARGET, /mob/living/carbon/human, 2)
else if(prob(controller.blackboard[BB_MONKEY_GIVE_CHANCE]))
controller.queue_behavior(/datum/ai_behavior/give, BB_MONKEY_CURRENT_GIVE_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
controller.TryFindWeapon()
if(!controller.blackboard[BB_MONKEY_TAMED])
controller.TryFindWeapon()
///monkey combat subtree.
/datum/ai_planning_subtree/monkey_combat/SelectBehaviors(datum/ai_controller/monkey/controller, seconds_per_tick)
@@ -70,3 +71,42 @@
controller.queue_behavior(/datum/ai_behavior/disposal_mob, BB_MONKEY_CURRENT_ATTACK_TARGET, BB_MONKEY_TARGET_DISPOSAL)
return SUBTREE_RETURN_FINISH_PLANNING
/// Finds food or drinks, picks them up, then gives them to nearby humans
/datum/ai_planning_subtree/serve_food
/datum/ai_planning_subtree/serve_food/SelectBehaviors(datum/ai_controller/monkey/controller, seconds_per_tick)
var/mob/living/living_pawn = controller.pawn
var/list/nearby_patrons = list()
for(var/mob/living/carbon/human/human_mob in oview(5, living_pawn))
if(istype(human_mob.mind?.assigned_role, /datum/job/bartender))
return // my boss is on duty!
if(human_mob.stat != CONSCIOUS || ismonkey(human_mob))
continue
if(!human_mob.get_empty_held_indexes())
continue
nearby_patrons += human_mob
// Need at least 2 patrons to bother serving (bearing in mind the
if(length(nearby_patrons) < 1)
return
var/obj/item/serving = controller.blackboard[BB_MONKEY_CURRENT_SERVED_ITEM]
if(QDELETED(serving) || serving.reagents.total_volume <= 0)
controller.queue_behavior(/datum/ai_behavior/find_and_set/food_or_drink/to_serve, BB_MONKEY_CURRENT_SERVED_ITEM, /obj/item, 2)
return
// we have something to serve, pick a patron and go hand it over
if(living_pawn.is_holding(serving))
controller.blackboard[BB_MONKEY_CURRENT_GIVE_TARGET] ||= pick(nearby_patrons)
controller.queue_behavior(/datum/ai_behavior/give, BB_MONKEY_CURRENT_GIVE_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
// we have something to serve but aren't holding it yet
if(isturf(serving.loc))
// fetch the drink
controller.queue_behavior(/datum/ai_behavior/navigate_to_and_pick_up, BB_MONKEY_CURRENT_SERVED_ITEM, TRUE)
else
// give up on the dream
controller.clear_blackboard_key(BB_MONKEY_CURRENT_SERVED_ITEM)
return SUBTREE_RETURN_FINISH_PLANNING

View File

@@ -1,22 +0,0 @@
/datum/ai_planning_subtree/punpun_shenanigans/SelectBehaviors(datum/ai_controller/monkey/controller, seconds_per_tick)
controller.set_trip_mode(mode = FALSE) // pun pun doesn't fuck around
if(prob(5))
controller.queue_behavior(/datum/ai_behavior/use_in_hand)
if(!SPT_PROB(MONKEY_SHENANIGAN_PROB, seconds_per_tick))
return
if(!controller.blackboard[BB_MONKEY_CURRENT_PRESS_TARGET])
controller.queue_behavior(/datum/ai_behavior/find_and_set, BB_MONKEY_CURRENT_PRESS_TARGET, /obj/structure/desk_bell, 2)
else if(prob(50))
controller.queue_behavior(/datum/ai_behavior/use_on_object, BB_MONKEY_CURRENT_PRESS_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
if(!controller.blackboard[BB_MONKEY_CURRENT_GIVE_TARGET])
controller.queue_behavior(/datum/ai_behavior/find_and_set/pawn_must_hold_item, BB_MONKEY_CURRENT_GIVE_TARGET, /mob/living, 2)
else if(prob(30))
controller.queue_behavior(/datum/ai_behavior/give, BB_MONKEY_CURRENT_GIVE_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING

View File

@@ -155,7 +155,7 @@
LAZYADD(grilled_food.intrinsic_food_materials, original_food.intrinsic_food_materials)
grilled_result.set_custom_materials(original_object.custom_materials)
if(IsEdible(grilled_result) && positive_result)
if(IS_EDIBLE(grilled_result) && positive_result)
BLACKBOX_LOG_FOOD_MADE(grilled_result.type)
//make space and tranfer reagents if it has any, also let any bad result handle removing or converting the transferred reagents on its own terms
if(grilled_result.reagents && original_object.reagents)

View File

@@ -81,7 +81,7 @@
if (COOLDOWN_FINISHED(src, clack_cooldown))
click_clack()
return ..()
if (!IsEdible(attacked) || attacked.w_class > WEIGHT_CLASS_NORMAL || !isnull(tonged))
if (!IS_EDIBLE(attacked) || attacked.w_class > WEIGHT_CLASS_NORMAL || !isnull(tonged))
return ..()
tonged = attacked
attacked.do_pickup_animation(src)

View File

@@ -57,7 +57,7 @@
SIGNAL_HANDLER
if (ai_controller?.blackboard[BB_GOOSE_PANICKED])
return COMSIG_MOB_CANCEL_EAT
if (potential_food.has_material_type(/datum/material/plastic) || IsEdible(potential_food))
if (potential_food.has_material_type(/datum/material/plastic) || IS_EDIBLE(potential_food))
return NONE// Geese only eat FOOD or PLASTIC
return COMSIG_MOB_CANCEL_EAT

View File

@@ -62,7 +62,7 @@
var/list/filtered = list()
for (var/obj/item/thing as anything in found)
if (IsEdible(thing) || thing.has_material_type(/datum/material/plastic))
if (IS_EDIBLE(thing) || thing.has_material_type(/datum/material/plastic))
filtered += thing
if(length(filtered))

View File

@@ -333,7 +333,7 @@
if (isliving(nomnom)) // NO VORE ALLOWED
return 0
// Yeah maybe don't, if something edible ended up here it should either handle itself or not be digested
if (IsEdible(nomnom))
if (IS_EDIBLE(nomnom))
return 0
if (HAS_TRAIT(owner, TRAIT_STRONG_STOMACH))
return 10
@@ -521,7 +521,7 @@
/obj/item/organ/stomach/cybernetic/tier2/stomach_acid_power(atom/movable/nomnom)
if (isliving(nomnom))
return 0
if (IsEdible(nomnom))
if (IS_EDIBLE(nomnom))
return 0
return 20
@@ -537,7 +537,7 @@
/obj/item/organ/stomach/cybernetic/tier3/stomach_acid_power(atom/movable/nomnom)
if (isliving(nomnom))
return 0
if (IsEdible(nomnom))
if (IS_EDIBLE(nomnom))
return 0
return 35

View File

@@ -1031,7 +1031,6 @@
#include "code\datums\ai\monkey\monkey_behaviors.dm"
#include "code\datums\ai\monkey\monkey_controller.dm"
#include "code\datums\ai\monkey\monkey_subtrees.dm"
#include "code\datums\ai\monkey\punpun_subtrees.dm"
#include "code\datums\ai\movement\_ai_movement.dm"
#include "code\datums\ai\movement\ai_movement_basic_avoidance.dm"
#include "code\datums\ai\movement\ai_movement_complete_stop.dm"