mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-12 08:36:00 +01:00
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
493 lines
18 KiB
Plaintext
493 lines
18 KiB
Plaintext
/mob/living/basic/mouse
|
|
name = "mouse"
|
|
desc = "This cute little guy just loves the taste of insulated electrical cables. Isn't he adorable?"
|
|
icon_state = "mouse_gray"
|
|
icon_living = "mouse_gray"
|
|
icon_dead = "mouse_gray_dead"
|
|
held_state = "mouse_gray"
|
|
|
|
maxHealth = 5
|
|
health = 5
|
|
density = FALSE
|
|
pass_flags = PASSTABLE|PASSGRILLE|PASSMOB
|
|
mob_size = MOB_SIZE_TINY
|
|
can_be_held = TRUE
|
|
held_w_class = WEIGHT_CLASS_TINY
|
|
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
|
gold_core_spawnable = FRIENDLY_SPAWN
|
|
faction = list(FACTION_RAT, FACTION_MAINT_CREATURES)
|
|
butcher_results = list(/obj/item/food/meat/slab/mouse = 1)
|
|
|
|
speak_emote = list("squeaks")
|
|
response_help_continuous = "pets"
|
|
response_help_simple = "pet"
|
|
response_disarm_continuous = "gently pushes aside"
|
|
response_disarm_simple = "gently push aside"
|
|
response_harm_continuous = "splats"
|
|
response_harm_simple = "splat"
|
|
|
|
ai_controller = /datum/ai_controller/basic_controller/mouse
|
|
|
|
/// What color our mouse is. Brown, gray and white - leave blank for random.
|
|
var/body_color
|
|
/// Does this mouse contribute to the ratcap?
|
|
var/contributes_to_ratcap = TRUE
|
|
/// Probability that, if we successfully bite a shocked cable, that we will die to it.
|
|
var/cable_zap_prob = 85
|
|
///list of pet commands we follow
|
|
var/static/list/pet_commands = list(
|
|
/datum/pet_command/idle,
|
|
/datum/pet_command/free,
|
|
/datum/pet_command/follow/start_active,
|
|
/datum/pet_command/perform_trick_sequence,
|
|
)
|
|
|
|
/datum/emote/mouse
|
|
abstract_type = /datum/emote/mouse
|
|
mob_type_allowed_typecache = /mob/living/basic/mouse
|
|
mob_type_blacklist_typecache = list()
|
|
|
|
/datum/emote/mouse/squeak
|
|
key = "squeak"
|
|
key_third_person = "squeaks"
|
|
message = "squeak!"
|
|
emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE
|
|
vary = TRUE
|
|
sound = 'sound/mobs/non-humanoids/mouse/mousesqueek.ogg'
|
|
|
|
/mob/living/basic/mouse/Initialize(mapload, tame = FALSE, new_body_color)
|
|
. = ..()
|
|
if(contributes_to_ratcap)
|
|
SSmobs.cheeserats |= src
|
|
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
|
|
|
if(tame)
|
|
ADD_TRAIT(src, TRAIT_TAMED, INNATE_TRAIT)
|
|
if(!isnull(new_body_color))
|
|
body_color = new_body_color
|
|
if(isnull(body_color))
|
|
body_color = pick("brown", "gray", "white")
|
|
held_state = "mouse_[body_color]" // not handled by variety element
|
|
AddElement(/datum/element/animal_variety, "mouse", body_color, FALSE)
|
|
AddElement(/datum/element/swabable, CELL_LINE_TABLE_MOUSE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 10)
|
|
AddComponent(/datum/component/squeak, list('sound/mobs/non-humanoids/mouse/mousesqueek.ogg' = 1), 100, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) //as quiet as a mouse or whatever
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
|
)
|
|
AddComponent(/datum/component/obeys_commands, pet_commands)
|
|
AddElement(/datum/element/connect_loc, loc_connections)
|
|
make_tameable()
|
|
AddComponent(/datum/component/swarming, 16, 16) //max_x, max_y
|
|
|
|
/mob/living/basic/mouse/proc/make_tameable()
|
|
if (HAS_TRAIT(src, TRAIT_TAMED))
|
|
add_faction(FACTION_NEUTRAL)
|
|
else
|
|
var/static/list/food_types = list(/obj/item/food/cheese)
|
|
AddComponent(/datum/component/tameable, food_types = food_types, tame_chance = 100)
|
|
|
|
AddElement(/datum/element/regal_rat_minion, converted_path = /mob/living/basic/mouse/rat, pet_commands = GLOB.regal_rat_minion_commands)
|
|
|
|
/mob/living/basic/mouse/Destroy()
|
|
SSmobs.cheeserats -= src
|
|
return ..()
|
|
|
|
/mob/living/basic/mouse/examine(mob/user)
|
|
. = ..()
|
|
|
|
var/sameside = user.faction_check_atom(src, exact_match = TRUE)
|
|
if(isregalrat(user))
|
|
if(sameside)
|
|
. += span_notice("This rat serves under you.")
|
|
else
|
|
. += span_warning("This peasant serves a different king! Strike [p_them()] down!")
|
|
|
|
else if(user != src && ismouse(user))
|
|
if(sameside)
|
|
. += span_notice("You both serve the same king.")
|
|
else
|
|
. += span_warning("This fool serves a different king!")
|
|
|
|
/// Kills the rat and changes its icon state to be splatted (bloody).
|
|
/mob/living/basic/mouse/proc/splat()
|
|
icon_dead = "mouse_[body_color]_splat"
|
|
adjust_health(maxHealth)
|
|
|
|
// On revival, re-add the mouse to the ratcap, or block it if we're at it
|
|
/mob/living/basic/mouse/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE)
|
|
if(!contributes_to_ratcap)
|
|
return ..()
|
|
|
|
var/aheal_included = full_heal_flags & HEAL_ADMIN
|
|
var/cap = CONFIG_GET(number/ratcap)
|
|
if(!aheal_included && !ckey && length(SSmobs.cheeserats) >= cap)
|
|
visible_message(span_warning("[src] twitches, but does not continue moving \
|
|
due to the overwhelming rodent population on the station!"))
|
|
return
|
|
|
|
. = ..()
|
|
if(stat != DEAD)
|
|
SSmobs.cheeserats |= src
|
|
|
|
// On death, remove the mouse from the ratcap, and turn it into an item if applicable
|
|
/mob/living/basic/mouse/death(gibbed)
|
|
SSmobs.cheeserats -= src
|
|
// Rats with a mind will not turn into a lizard snack on death
|
|
if(mind)
|
|
return ..()
|
|
|
|
// Call parent with gibbed = TRUE, becuase we're getting rid of the body
|
|
. = ..(TRUE)
|
|
// Now if we were't ACTUALLY gibbed, spawn the dead mouse
|
|
if(!gibbed)
|
|
var/make_a_corpse = TRUE
|
|
var/place_to_make_corpse = loc
|
|
var/must_equip = FALSE
|
|
var/equip_slot
|
|
var/mob/holding_mob
|
|
var/obj/item/mob_holder/found_holder
|
|
if(istype(loc, /obj/item/mob_holder))//If our mouse is dying in place holder we want to put the dead mouse where the place holder was
|
|
found_holder = loc
|
|
place_to_make_corpse = found_holder.loc
|
|
if(istype(found_holder.loc,/mob/living/carbon))
|
|
holding_mob = found_holder.loc
|
|
place_to_make_corpse = get_turf(holding_mob)
|
|
equip_slot = holding_mob.get_slot_by_item(found_holder)
|
|
if(equip_slot == ITEM_SLOT_HANDS || equip_slot == ITEM_SLOT_RPOCKET || equip_slot == ITEM_SLOT_LPOCKET)
|
|
must_equip = TRUE
|
|
if(istype(found_holder.loc, /obj/machinery/microwave))//Microwaves gib things that die when cooked, so we don't need to make a dead body too
|
|
make_a_corpse = FALSE
|
|
if(make_a_corpse)
|
|
var/obj/item/food/deadmouse/mouse = new(place_to_make_corpse)
|
|
mouse.copy_corpse(src)
|
|
if(HAS_TRAIT(src, TRAIT_BEING_SHOCKED))
|
|
mouse.desc = "They're toast."
|
|
mouse.add_atom_colour("#3A3A3A", FIXED_COLOUR_PRIORITY)
|
|
found_holder?.release(FALSE)
|
|
if(must_equip)
|
|
if(equip_slot == ITEM_SLOT_HANDS)
|
|
holding_mob.dropItemToGround(found_holder)
|
|
holding_mob.equip_to_slot(mouse,equip_slot)
|
|
qdel(src)
|
|
|
|
/mob/living/basic/mouse/UnarmedAttack(atom/attack_target, proximity_flag, list/modifiers)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
if(!proximity_flag)
|
|
return
|
|
|
|
if(istype(attack_target, /obj/item/food/cheese))
|
|
try_consume_cheese(attack_target)
|
|
return TRUE
|
|
|
|
if(istype(attack_target, /obj/structure/cable))
|
|
try_bite_cable(attack_target)
|
|
return TRUE
|
|
|
|
/// Signal proc for [COMSIG_ATOM_ENTERED]. Sends a lil' squeak to chat when someone walks over us.
|
|
/mob/living/basic/mouse/proc/on_entered(datum/source, atom/movable/entered)
|
|
SIGNAL_HANDLER
|
|
|
|
if(ishuman(entered) && stat == CONSCIOUS)
|
|
to_chat(entered, span_notice("[icon2html(src, entered)] Squeak!"))
|
|
|
|
/// Called when a mouse is hand-fed some cheese, it will stop being afraid of humans
|
|
/mob/living/basic/mouse/tamed(mob/living/tamer, obj/item/food/cheese/cheese)
|
|
. = ..()
|
|
new /obj/effect/temp_visual/heart(loc)
|
|
add_faction(FACTION_NEUTRAL)
|
|
try_consume_cheese(cheese)
|
|
ai_controller.CancelActions() // Interrupt any current fleeing
|
|
|
|
/// Attempts to consume a piece of cheese, causing a few effects.
|
|
/mob/living/basic/mouse/proc/try_consume_cheese(obj/item/food/cheese/cheese)
|
|
// Royal cheese will evolve us into a regal rat
|
|
if(istype(cheese, /obj/item/food/cheese/royal))
|
|
visible_message(
|
|
span_warning("[src] devours [cheese]! They morph into something... greater!"),
|
|
span_notice("You devour [cheese], and start morphing into something... greater!"),
|
|
)
|
|
evolve_into_regal_rat()
|
|
qdel(cheese)
|
|
return
|
|
|
|
var/cap = CONFIG_GET(number/ratcap)
|
|
// Normal cheese will either heal us
|
|
if(prob(90) || health < maxHealth)
|
|
visible_message(
|
|
span_notice("[src] nibbles [cheese]."),
|
|
span_notice("You nibble [cheese][health < maxHealth ? ", restoring your health" : ""].")
|
|
)
|
|
adjust_health(-maxHealth)
|
|
|
|
// Or, if we're at full health, there's a 10% chance that normal cheese will spawn a new mouse
|
|
// ...if the rat cap allows us, that is
|
|
else if(length(SSmobs.cheeserats) >= cap)
|
|
visible_message(
|
|
span_warning("[src] carefully eats [cheese], hiding it from the [cap] mice on the station!"),
|
|
span_notice("You carefully nibble [cheese], hiding it from the [cap] other mice on board the station.")
|
|
)
|
|
else
|
|
visible_message(
|
|
span_notice("[src] nibbles through [cheese], attracting another mouse!"),
|
|
span_notice("You nibble through [cheese], attracting another mouse!")
|
|
)
|
|
create_a_new_rat()
|
|
|
|
qdel(cheese)
|
|
|
|
/// Evolves this rat into a regal rat
|
|
/mob/living/basic/mouse/proc/evolve_into_regal_rat()
|
|
var/mob/living/basic/regal_rat/controlled/regalrat = new(loc)
|
|
mind?.transfer_to(regalrat)
|
|
INVOKE_ASYNC(regalrat, TYPE_PROC_REF(/atom/movable, say), "RISE, MY SUBJECTS! SCREEEEEEE!")
|
|
qdel(src)
|
|
|
|
/// Creates a new mouse based on this mouse's subtype.
|
|
/mob/living/basic/mouse/proc/create_a_new_rat()
|
|
new /mob/living/basic/mouse(loc, HAS_TRAIT(src, TRAIT_TAMED))
|
|
|
|
/// Biting into a cable will cause a mouse to get shocked and die if applicable. Or do nothing if they're lucky.
|
|
/mob/living/basic/mouse/proc/try_bite_cable(obj/structure/cable/cable)
|
|
if(cable.avail() && !HAS_TRAIT(src, TRAIT_SHOCKIMMUNE) && prob(cable_zap_prob))
|
|
visible_message(
|
|
span_warning("[src] chews through \the [cable]. It's toast!"),
|
|
span_userdanger("As you bite deeply into [cable], you suddenly realize this may have been a bad idea."),
|
|
span_hear("You hear electricity crack."),
|
|
)
|
|
// Finely toasted
|
|
ADD_TRAIT(src, TRAIT_BEING_SHOCKED, TRAIT_GENERIC)
|
|
// Unfortunately we can't check the return value of electrocute_act before displaying a message,
|
|
// as it's possible the damage from electrocution results in our hunter being deleted.
|
|
// But what are the odds of the shock failing? Hahaha...
|
|
electrocute_act(maxHealth * 2, cable, flags = SHOCK_SUPPRESS_MESSAGE)
|
|
|
|
else
|
|
visible_message(
|
|
span_warning("[src] chews through \the [cable]."),
|
|
span_notice("You chew through \the [cable]."),
|
|
)
|
|
|
|
playsound(cable, 'sound/effects/sparks/sparks2.ogg', 100, TRUE)
|
|
cable.deconstruct()
|
|
|
|
/mob/living/basic/mouse/white
|
|
body_color = "white"
|
|
icon_state = "mouse_white"
|
|
held_state = "mouse_white"
|
|
|
|
/mob/living/basic/mouse/gray
|
|
body_color = "gray"
|
|
icon_state = "mouse_gray"
|
|
|
|
/mob/living/basic/mouse/brown
|
|
body_color = "brown"
|
|
icon_state = "mouse_brown"
|
|
held_state = "mouse_brown"
|
|
|
|
//TOM IS ALIVE! SQUEEEEEEEE~K :)
|
|
/mob/living/basic/mouse/brown/tom
|
|
name = "Tom"
|
|
desc = "Jerry the cat is not amused."
|
|
response_help_continuous = "pets"
|
|
response_help_simple = "pet"
|
|
response_disarm_continuous = "gently pushes aside"
|
|
response_disarm_simple = "gently push aside"
|
|
response_harm_continuous = "splats"
|
|
response_harm_simple = "splat"
|
|
gold_core_spawnable = NO_SPAWN
|
|
contributes_to_ratcap = FALSE
|
|
|
|
/mob/living/basic/mouse/brown/tom/make_tameable()
|
|
ADD_TRAIT(src, TRAIT_TAMED, INNATE_TRAIT)
|
|
return ..()
|
|
|
|
/mob/living/basic/mouse/brown/tom/Initialize(mapload)
|
|
. = ..()
|
|
// Tom fears no cable.
|
|
ADD_TRAIT(src, TRAIT_SHOCKIMMUNE, INNATE_TRAIT)
|
|
AddElement(/datum/element/pet_bonus, "squeak")
|
|
|
|
/mob/living/basic/mouse/brown/tom/create_a_new_rat()
|
|
new /mob/living/basic/mouse/brown(loc, HAS_TRAIT(src, TRAIT_TAMED)) // dominant gene
|
|
|
|
/mob/living/basic/mouse/rat
|
|
name = "rat"
|
|
desc = "They're a nasty, ugly, evil, disease-ridden rodent with anger issues."
|
|
|
|
gold_core_spawnable = HOSTILE_SPAWN
|
|
melee_damage_lower = 3
|
|
melee_damage_upper = 5
|
|
obj_damage = 5
|
|
maxHealth = 15
|
|
health = 15
|
|
|
|
ai_controller = /datum/ai_controller/basic_controller/mouse/rat
|
|
|
|
/mob/living/basic/mouse/rat/make_tameable()
|
|
return // Unlike in real life, space rats are horrible creatures who don't like you
|
|
|
|
/mob/living/basic/mouse/rat/create_a_new_rat()
|
|
new /mob/living/basic/mouse/rat(loc)
|
|
|
|
/// Mice turn into food when they die
|
|
/obj/item/food/deadmouse
|
|
name = "dead mouse"
|
|
desc = "They look like somebody dropped the bass on it. A lizard's favorite meal."
|
|
icon = 'icons/mob/simple/animal.dmi'
|
|
icon_state = "mouse_gray_dead"
|
|
bite_consumption = 3
|
|
eatverbs = list("devour")
|
|
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2)
|
|
foodtypes = GORE | MEAT | RAW
|
|
decomp_req_handle = TRUE
|
|
ant_attracting = FALSE
|
|
decomp_type = /obj/item/food/deadmouse/moldy
|
|
var/body_color = "gray"
|
|
var/critter_type = /mob/living/basic/mouse
|
|
|
|
/obj/item/food/deadmouse/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/swabable, CELL_LINE_TABLE_MOUSE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 10)
|
|
RegisterSignal(src, COMSIG_ATOM_ON_LAZARUS_INJECTOR, PROC_REF(use_lazarus))
|
|
|
|
/obj/item/food/deadmouse/grind_results()
|
|
return list(/datum/reagent/blood = 20, /datum/reagent/consumable/liquidgibs = 5)
|
|
|
|
/// Copy properties from an imminently dead mouse
|
|
/obj/item/food/deadmouse/proc/copy_corpse(mob/living/basic/mouse/dead_critter)
|
|
body_color = dead_critter.body_color
|
|
critter_type = dead_critter.type
|
|
name = dead_critter.name
|
|
icon_state = dead_critter.icon_dead
|
|
|
|
/obj/item/food/deadmouse/examine(mob/user)
|
|
. = ..()
|
|
if (reagents?.has_reagent(/datum/reagent/yuck) || reagents?.has_reagent(/datum/reagent/fuel))
|
|
. += span_warning("[p_Theyre()] dripping with fuel and smells terrible.")
|
|
|
|
///Spawn a new mouse from this dead mouse item when hit by a lazarus injector and conditions are met.
|
|
/obj/item/food/deadmouse/proc/use_lazarus(datum/source, obj/item/lazarus_injector/injector, mob/user)
|
|
SIGNAL_HANDLER
|
|
if(injector.revive_type != SENTIENCE_ORGANIC)
|
|
balloon_alert(user, "invalid creature!")
|
|
return
|
|
var/mob/living/basic/mouse/revived_critter = new critter_type (drop_location(), FALSE, body_color)
|
|
revived_critter.name = name
|
|
revived_critter.lazarus_revive(user, injector.malfunctioning)
|
|
injector.expend(revived_critter, user)
|
|
qdel(src)
|
|
return LAZARUS_INJECTOR_USED
|
|
|
|
/obj/item/food/deadmouse/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
|
|
var/mob/living/living_user = user
|
|
if(istype(living_user) && attacking_item.get_sharpness() && living_user.combat_mode)
|
|
if(!isturf(loc))
|
|
balloon_alert(user, "can't butcher here!")
|
|
return
|
|
|
|
balloon_alert(user, "butchering...")
|
|
if(!do_after(user, 0.75 SECONDS, src))
|
|
balloon_alert(user, "interrupted!")
|
|
return
|
|
|
|
loc.balloon_alert(user, "butchered")
|
|
new /obj/item/food/meat/slab/mouse(loc)
|
|
qdel(src)
|
|
return
|
|
|
|
return ..()
|
|
|
|
/obj/item/food/deadmouse/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
|
|
if(isnull(reagents) || !interacting_with.is_open_container())
|
|
return NONE
|
|
|
|
// is_open_container will not return truthy if target.reagents doesn't exist
|
|
var/datum/reagents/target_reagents = interacting_with.reagents
|
|
var/trans_amount = reagents.maximum_volume - reagents.total_volume * (4 / 3)
|
|
if(target_reagents.has_reagent(/datum/reagent/fuel) && target_reagents.trans_to(src, trans_amount))
|
|
to_chat(user, span_notice("You dip [src] into [interacting_with]."))
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/item/food/deadmouse/moldy
|
|
name = "moldy dead mouse"
|
|
desc = "A dead rodent, consumed by mold and rot. There is a slim chance that a lizard might still eat it."
|
|
icon_state = "mouse_gray_dead"
|
|
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2, /datum/reagent/consumable/mold = 10)
|
|
foodtypes = GORE | MEAT | RAW | GROSS
|
|
preserved_food = TRUE
|
|
|
|
/obj/item/food/deadmouse/moldy/grind_results()
|
|
return list(/datum/reagent/blood = 20, /datum/reagent/consumable/liquidgibs = 5, /datum/reagent/consumable/mold = 10)
|
|
|
|
/// The mouse AI controller
|
|
/datum/ai_controller/basic_controller/mouse
|
|
blackboard = list( // Always cowardly
|
|
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, // Use this to find people to run away from
|
|
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
|
BB_BASIC_MOB_FLEE_DISTANCE = 3,
|
|
BB_SONG_LINES = MOUSE_SONG,
|
|
)
|
|
|
|
ai_traits = PASSIVE_AI_FLAGS
|
|
ai_movement = /datum/ai_movement/basic_avoidance
|
|
idle_behavior = /datum/idle_behavior/idle_random_walk
|
|
planning_subtrees = list(
|
|
// Try to speak, because it's cute
|
|
/datum/ai_planning_subtree/random_speech/mouse,
|
|
// Follow the boss's orders
|
|
/datum/ai_planning_subtree/pet_planning,
|
|
// Look for and execute hunts for cheese even if someone is looking at us
|
|
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cheese,
|
|
// Next priority is to try and appreoach a keyboard
|
|
/datum/ai_planning_subtree/approach_synthesizer,
|
|
// And play it if we are near it
|
|
/datum/ai_planning_subtree/generic_play_instrument/end_planning,
|
|
// Next priority is see if anyone is looking at us
|
|
/datum/ai_planning_subtree/simple_find_nearest_target_to_flee,
|
|
// Skedaddle
|
|
/datum/ai_planning_subtree/flee_target/mouse,
|
|
// Otherwise, look for and execute hunts for cabling
|
|
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cables,
|
|
)
|
|
|
|
/// Don't look for anything to run away from if you are distracted by being adjacent to cheese
|
|
/datum/ai_planning_subtree/flee_target/mouse
|
|
|
|
/datum/ai_planning_subtree/flee_target/mouse/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
|
|
var/atom/hunted_cheese = controller.blackboard[BB_CURRENT_HUNTING_TARGET]
|
|
if (!isnull(hunted_cheese))
|
|
return // We see some cheese, which is more important than our life
|
|
return ..()
|
|
|
|
/// AI controller for rats, slightly more complex than mice becuase they attack people
|
|
/datum/ai_controller/basic_controller/mouse/rat
|
|
blackboard = list(
|
|
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic,
|
|
BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends,
|
|
BB_BASIC_MOB_CURRENT_TARGET = null, // heathen
|
|
BB_CURRENT_HUNTING_TARGET = null, // cheese
|
|
BB_LOW_PRIORITY_HUNTING_TARGET = null, // cable
|
|
BB_OWNER_SELF_HARM_RESPONSES = list(
|
|
"*me cleans its whiskers in disapproval.",
|
|
"*me squeaks sadly.",
|
|
"*me sheds a single small tear."
|
|
)
|
|
)
|
|
|
|
ai_traits = DEFAULT_AI_FLAGS | STOP_MOVING_WHEN_PULLED
|
|
ai_movement = /datum/ai_movement/basic_avoidance
|
|
idle_behavior = /datum/idle_behavior/idle_random_walk
|
|
planning_subtrees = list(
|
|
/datum/ai_planning_subtree/escape_captivity,
|
|
/datum/ai_planning_subtree/pet_planning,
|
|
/datum/ai_planning_subtree/simple_find_target,
|
|
/datum/ai_planning_subtree/attack_obstacle_in_path,
|
|
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
|
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cheese,
|
|
/datum/ai_planning_subtree/random_speech/mouse,
|
|
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cables,
|
|
)
|