mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 18:22:14 +00:00
## About The Pull Request this PR improves the UX of pet commands a bit. i decided to expand on their radial menu. You can now hold shift and hover over your pet to display a menu of commands which you can choose from. alternatively, you can still type out commands in chat https://github.com/user-attachments/assets/9da7f7ea-58a3-4fd6-b040-45cc05cda51d ## Why It's Good For The Game makes pet commands easier to give out when you're managing more than 1 pet. also fixes the fishing command not working. ## Changelog 🆑 qol: holding shift and hovering over your pet will display a list of commands you can click from fix: fixes the fishing pet command not working /🆑
121 lines
4.8 KiB
Plaintext
121 lines
4.8 KiB
Plaintext
/**
|
|
* # Pet Command: Fetch
|
|
* Watch for someone throwing or pointing at something and then go get it and bring it back.
|
|
* If it's food we might eat it instead.
|
|
*/
|
|
/datum/pet_command/fetch
|
|
command_name = "Fetch"
|
|
command_desc = "Command your pet to retrieve something you throw or point at."
|
|
radial_icon_state = "fetch"
|
|
requires_pointing = TRUE
|
|
speech_commands = list("fetch")
|
|
command_feedback = "bounces"
|
|
pointed_reaction = "with great interest"
|
|
/// If true, this command will trigger if the pet sees a friend throw any item, if they're not doing anything else
|
|
var/trigger_on_throw = TRUE
|
|
/// If true, this is a poorly trained pet who will eat food you throw instead of bringing it back
|
|
var/will_eat_targets = TRUE
|
|
|
|
/datum/pet_command/fetch/New(mob/living/parent)
|
|
. = ..()
|
|
if(isnull(parent))
|
|
return
|
|
parent.AddElement(/datum/element/ai_held_item) // We don't remove this on destroy because they might still be holding something
|
|
|
|
/datum/pet_command/fetch/add_new_friend(mob/living/tamer)
|
|
. = ..()
|
|
RegisterSignal(tamer, COMSIG_MOB_THROW, PROC_REF(listened_throw))
|
|
|
|
/datum/pet_command/fetch/remove_friend(mob/living/unfriended)
|
|
. = ..()
|
|
UnregisterSignal(unfriended, COMSIG_MOB_THROW)
|
|
|
|
/datum/pet_command/fetch/retrieve_command_text(atom/living_pet, atom/target)
|
|
return isnull(target) ? null : "signals [living_pet] to fetch [target]!"
|
|
|
|
/// A friend has thrown something, if we're listening or at least not busy then go get it
|
|
/datum/pet_command/fetch/proc/listened_throw(mob/living/carbon/thrower)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/parent = weak_parent.resolve()
|
|
if (!parent)
|
|
return
|
|
|
|
var/list/blackboard = parent.ai_controller.blackboard
|
|
if (!trigger_on_throw && !blackboard[BB_ACTIVE_PET_COMMAND])
|
|
return // We don't have a command and we only listen to commands
|
|
if (blackboard[BB_ACTIVE_PET_COMMAND] && blackboard[BB_ACTIVE_PET_COMMAND] != src)
|
|
return // We have a command and it's not this one
|
|
if (blackboard[BB_CURRENT_PET_TARGET] || blackboard[BB_FETCH_DELIVER_TO])
|
|
return // We're already very fetching
|
|
if (!can_see(parent, thrower, length = sense_radius))
|
|
return // Can't see it
|
|
|
|
var/obj/item/thrown_thing = thrower.get_active_held_item()
|
|
if (!isitem(thrown_thing))
|
|
return
|
|
if (blackboard[BB_FETCH_IGNORE_LIST]?[thrown_thing])
|
|
return // We're ignoring it already
|
|
|
|
RegisterSignal(thrown_thing, COMSIG_MOVABLE_THROW_LANDED, PROC_REF(listen_throw_land))
|
|
|
|
/// A throw we were listening to has finished, see if it's in range for us to try grabbing it
|
|
/datum/pet_command/fetch/proc/listen_throw_land(obj/item/thrown_thing, datum/thrownthing/throwingdatum)
|
|
SIGNAL_HANDLER
|
|
|
|
UnregisterSignal(thrown_thing, COMSIG_MOVABLE_THROW_LANDED)
|
|
var/mob/living/parent = weak_parent.resolve()
|
|
if (!parent)
|
|
return
|
|
if (!isturf(thrown_thing.loc))
|
|
return
|
|
if (!can_see(parent, thrown_thing, length = sense_radius))
|
|
return
|
|
|
|
var/mob/thrower = throwingdatum?.get_thrower()
|
|
if(thrower)
|
|
try_activate_command(thrower)
|
|
set_command_target(parent, thrown_thing)
|
|
parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, thrower)
|
|
|
|
// Don't try and fetch turfs or anchored objects if someone points at them
|
|
/datum/pet_command/fetch/look_for_target(mob/living/pointing_friend, obj/item/pointed_atom)
|
|
if (!istype(pointed_atom))
|
|
return FALSE
|
|
if (pointed_atom.anchored)
|
|
return FALSE
|
|
. = ..()
|
|
if (!.)
|
|
return FALSE
|
|
|
|
var/mob/living/parent = weak_parent.resolve()
|
|
parent.ai_controller.set_blackboard_key(BB_FETCH_DELIVER_TO, pointing_friend)
|
|
|
|
// Finally, plan our actions
|
|
/datum/pet_command/fetch/execute_action(datum/ai_controller/controller)
|
|
controller.queue_behavior(/datum/ai_behavior/forget_failed_fetches)
|
|
|
|
var/atom/target = controller.blackboard[BB_CURRENT_PET_TARGET]
|
|
// We got something to fetch so go fetch it
|
|
if (!QDELETED(target))
|
|
if (get_dist(controller.pawn, target) > 1) // We're not there yet
|
|
controller.queue_behavior(/datum/ai_behavior/fetch_seek, BB_CURRENT_PET_TARGET, BB_FETCH_DELIVER_TO)
|
|
return SUBTREE_RETURN_FINISH_PLANNING
|
|
// If mobs could attack food you would branch here to call `eat_fetched_snack`, however that's a task for the future
|
|
controller.queue_behavior(/datum/ai_behavior/pick_up_item, BB_CURRENT_PET_TARGET, BB_SIMPLE_CARRY_ITEM)
|
|
return SUBTREE_RETURN_FINISH_PLANNING
|
|
|
|
var/obj/item/carried_item = controller.blackboard[BB_SIMPLE_CARRY_ITEM]
|
|
if (QDELETED(carried_item))
|
|
return
|
|
|
|
var/atom/delivery_target = controller.blackboard[BB_FETCH_DELIVER_TO]
|
|
if (QDELETED(delivery_target) || !can_see(controller.pawn, delivery_target, sense_radius))
|
|
// We don't know where to return this to so we're just going to keep it
|
|
controller.clear_blackboard_key(BB_ACTIVE_PET_COMMAND)
|
|
return
|
|
|
|
// We got something to deliver and someone to deliver it to
|
|
controller.queue_behavior(/datum/ai_behavior/deliver_fetched_item, BB_FETCH_DELIVER_TO, BB_SIMPLE_CARRY_ITEM)
|
|
return SUBTREE_RETURN_FINISH_PLANNING
|