From 2c7cedcbf10a1a2b1736c489bdb99e4131b306e8 Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Tue, 15 Apr 2025 18:19:06 +0100 Subject: [PATCH] Mice can play synthesisers (#90610) ## About The Pull Request ![image](https://github.com/user-attachments/assets/9d4ce934-bb40-4b05-8d25-5bfb4998c3cd) This PR allows mice to play synthesisers, which they will prioritise over running away from people if they see one (but eating cheese is more important than that). ## Why It's Good For The Game ![85786433-3946-4a94-a863-c12999082023_373x306](https://github.com/user-attachments/assets/f32c2ea3-6a85-4060-9bfb-1d8555feb35b) ## Changelog :cl: add: Mice can play synthesisers /:cl: --- code/__DEFINES/ai/ai_blackboard.dm | 1 + code/__DEFINES/song.dm | 2 ++ .../basic_ai_behaviors/travel_towards.dm | 3 +++ code/datums/ai/generic/generic_subtrees.dm | 8 +++++++ .../ai/hunting_behavior/hunting_mouse.dm | 23 +++++++++++++++++++ code/modules/instruments/piano_synth.dm | 8 +++++++ code/modules/mob/living/basic/vermin/mouse.dm | 12 +++++++--- 7 files changed, 54 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index b5169934a85..c09333c6ed7 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -61,6 +61,7 @@ #define BB_LOW_PRIORITY_HUNTING_TARGET "BB_low_priority_hunting_target" ///key that holds the cooldown for our hunting subtree #define BB_HUNTING_COOLDOWN(type) "BB_HUNTING_COOLDOWN_[type]" + ///Basic Mob Keys ///Targeting subtrees diff --git a/code/__DEFINES/song.dm b/code/__DEFINES/song.dm index 0e7e9f0ce06..c565dde7e71 100644 --- a/code/__DEFINES/song.dm +++ b/code/__DEFINES/song.dm @@ -21,3 +21,5 @@ #define VIBEBOT_GRIM_MUSIC "BPM: 92\nG5/0.5,C#7-F#5/1.08,G6-G5/0.52,D6-D5,B6-E5/0.52\nG6-G5/1.08,D6-D5/0.34,Cn6-C5-G6/0.5,D,B5-F#6/13\nB4/0.52,C6-C5-G,A4/0.28,G-G5/0.5\nC#7-F#-F#5/1.08,G6-G5/0.52,D6-D5,B6-E/0.52,G-G6\nB5,D7/13,D6/0.52,Cn6,B6-B5,G-G5,G/0.5\nF#-C#7/1.08,G6-G5/0.22,G/0.5,C#-F#/1.08\nG6-G5/0.52,D-D5,B6-E/0.52,G6-G5/1.08,D6-D5/0.34\nCn6-C5-G6/0.5,D,B5-F#6/13,B4/0.52,C6-G-C5/0.25\nG-G5/0.5,C#7-F#-F#5/1.08,G6-G5/0.52,D6-D5\nB6-E/0.52,G-G6,B5,D7/13,D6/0.52,Cn6,B6-B5,G-G5\nG/0.5,F#-C#7/1.08,G6-G5/0.65" ///happy birthday music we play to the birthday boy #define VIBEBOT_HAPPY_BIRTHDAY "BPM: 120\nG4/0.5,G4/0.25,A4/0.5,G4/0.5,C5/0.5,B4/1\nG4/0.5,G4/0.25,A4/0.5,G4/0.5,D5/0.5,C5/1\nG4/0.5,G4/0.5,G5/0.5,E5/0.5,C5/0.5,B4/0.5,A4/0.5\nF5/0.5,F5/0.5,E5/0.5,C5/0.5,D5/0.5,C5/1" +//music played by a mouse +#define MOUSE_SONG "BPM: 250\nD4/0,03,Eb4,C-En,C5,E3-G,E4,E3-C/0,5,Bb-C4-E4,C5\nF/0,5,A-C4/0,5,E3,C5,G-C4-D5,Eb5,G-En,C5,C4-E4-D\nE5,G,Bn4,B3-D/0,5,C-C5/0,5,G/0,5,C3/0,5,D4,Eb4\nC-En,C5,E3-G,E4,E3-C/0,5,Bb-C4-E4,C5,F/0,5\nA-C4/0,5,E3/0,5,Eb-A4,G4,D3-Gb,A,G3-A3-C5,En5,D,D5\nG-A-C,A4,Gn-Bn-D/0,5,G2/0,5,A2/0,5,B2-D4,Eb4,C3-En\nC5,E3-G3,E4,E3-C/0,5,Bb3-C4-E4,C5,F/0,5,A3-C4/0,5\nE3,C5,G-C4-D5,Eb5,G-En,C5,C4-E4-D,E5,G,Bn4\nB3-D/0,5,C-C5/0,5,G/0,5,C3/0,5,C5,D,C3-E3-G-E5,C5\nD,E,E3-Bb-C4,C5,D,C,F-A-C4-E5,C5,D,E,F-Ab-C4,C5,D\nC,G-C4-E4-E5,C5,D,E,G,Bn4,D/0,5,C4-C5/0,5,G/0,5,C3\nE4,F4,Gb4,C-Gn/0,5,G3-An4,G4,G2,E,G3-F,Gb4\nC-Gn/0,5,G3-A,G4,G2,E5,G3-C5,G4,F3-A,B,A3-C4-C5,D\nF-E,D,Ab-C4-C5,D,E3-G/0,5,G3-C4-E4,F4,D3-An4,G4\nB3-E,F,C3-G/0,5,G3-A,G4,G2,E,G3-F,Gb4,C-Gn/0,5\nG3-A,G4,E3,G,Eb-A,Bb4,D-Bn,B,B3,B4,D,A,A3-Gb,D4\nGn3-G4/0,5,F3/0,5,En,E4,D3-F4,Gb,C-Gn/0,5,G3-A4,G4\nG2,E,G3-F,Gb4,C-Gn/0,5,G3-A,G4,G2,E5,G3-C5,G4,F3-A\nB,A3-C4-C5,D5,F-E,D,Ab-C4-C5,D,E3-C/0,5,G3-C4/0,5\nE,G4,G3-C-Gb4,Gn,F-An-C-C5/0,5,A4,C,Gb3-A3-C4,A4\nC5,A,Gn-C4-E4-G4,C5,E5,G5,G3-C4-E4,E5,C5,G4\nD3-A/0,5,Gb3-C4-C5/0,5,Gn-B3-E,D5/0,5,C,C4/0,5\nG/0,5,C3/0,5,D4,Eb4,C-En,C5,E3-G,E4,E3-C/0,5\nBb-C4-E4,C5,F/0,5,A3-C4/0,5,E3,C5,G-C4-D5,Eb5,G-En\nC5,C4-E4-D,E5,G,Bn4,B3-D/0,5,C-C5/0,5,G/0,5,C3/0,5\nC5,D,C3-E3-G-E5,C5,D,E,E3-Bb-C4,C5,D,C,F-A-C4-E5\nC5,D,E,F-Ab-C4,C5,D,C,G-C4-E4-E5,C5,D,E,G,Bn4\nD/0,5,C4-C5/0,5,G/0" diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm index 808fe6b8873..f78eb3db4ec 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/travel_towards.dm @@ -31,6 +31,9 @@ /datum/ai_behavior/travel_towards/stop_on_arrival clear_target = TRUE +/datum/ai_behavior/travel_towards/adjacent + required_distance = 1 + /** * # Travel Towards Atom * Travel towards an atom you pass directly from the controller rather than a blackboard key. diff --git a/code/datums/ai/generic/generic_subtrees.dm b/code/datums/ai/generic/generic_subtrees.dm index 36bbbf35dd3..9d5ff8638fc 100644 --- a/code/datums/ai/generic/generic_subtrees.dm +++ b/code/datums/ai/generic/generic_subtrees.dm @@ -22,6 +22,14 @@ if(!song_player.song.playing) //we may stop playing if we weren't playing before, were setting up dk theme, or ran out of repeats (also causing setup behavior) controller.queue_behavior(/datum/ai_behavior/play_instrument, BB_SONG_INSTRUMENT) +/datum/ai_planning_subtree/generic_play_instrument/end_planning + +/datum/ai_planning_subtree/generic_play_instrument/end_planning/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + if (controller.blackboard_key_exists(BB_SONG_INSTRUMENT)) + return SUBTREE_RETURN_FINISH_PLANNING // Don't plan anything else if we're playing an instrument + + /** * Generic Resist Subtree, resist if it makes sense to! * diff --git a/code/datums/ai/hunting_behavior/hunting_mouse.dm b/code/datums/ai/hunting_behavior/hunting_mouse.dm index f97ebf27ddf..b5c9a7743a4 100644 --- a/code/datums/ai/hunting_behavior/hunting_mouse.dm +++ b/code/datums/ai/hunting_behavior/hunting_mouse.dm @@ -30,3 +30,26 @@ // Our hunts have a decent cooldown. /datum/ai_behavior/hunt_target/interact_with_target/mouse hunt_cooldown = 20 SECONDS + +/datum/ai_planning_subtree/approach_synthesizer + +/datum/ai_planning_subtree/approach_synthesizer/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/mob/living/pawn = controller.pawn + var/atom/instrument = controller.blackboard[BB_SONG_INSTRUMENT] + if(!isnull(instrument)) + if (!isturf(instrument.loc) || !can_see(pawn, instrument)) + controller.clear_blackboard_key(BB_SONG_INSTRUMENT) + return + if (pawn.CanReach(instrument)) + return + controller.queue_behavior(/datum/ai_behavior/travel_towards/adjacent, BB_SONG_INSTRUMENT) + return SUBTREE_RETURN_FINISH_PLANNING + + controller.queue_behavior(/datum/ai_behavior/find_and_set/piano_synth, BB_SONG_INSTRUMENT, /obj/item/instrument/piano_synth) + +/datum/ai_behavior/find_and_set/piano_synth // Disinclude subtypes + +/datum/ai_behavior/find_and_set/piano_synth/search_tactic(datum/ai_controller/controller, locate_path, search_range) + for(var/obj/item/instrument/piano_synth/synth in oview(search_range, controller.pawn)) + if(synth.type == /obj/item/instrument/piano_synth) + return synth diff --git a/code/modules/instruments/piano_synth.dm b/code/modules/instruments/piano_synth.dm index 5de8659b65e..0408737d868 100644 --- a/code/modules/instruments/piano_synth.dm +++ b/code/modules/instruments/piano_synth.dm @@ -7,12 +7,19 @@ allowed_instrument_ids = "piano" var/circuit_type = /obj/item/circuit_component/synth var/shell_capacity = SHELL_CAPACITY_SMALL + /// Can a mouse play this instrument? + var/mouse_playable = TRUE /obj/item/instrument/piano_synth/Initialize(mapload) . = ..() song.allowed_instrument_ids = SSinstruments.synthesizer_instrument_ids AddComponent(/datum/component/shell, list(new circuit_type), shell_capacity) +/obj/item/instrument/piano_synth/attack_animal(mob/living/simple_animal/user, list/modifiers) + if (!mouse_playable || !ismouse(user)) + return ..() + song.ui_interact(user) + /obj/item/instrument/piano_synth/headphones name = "headphones" desc = "Unce unce unce unce. Boop!" @@ -32,6 +39,7 @@ instrument_range = 1 circuit_type = /obj/item/circuit_component/synth/headphones shell_capacity = SHELL_CAPACITY_TINY + mouse_playable = FALSE /obj/item/instrument/piano_synth/headphones/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index 0ded016d1a0..5165df79b4c 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -407,21 +407,27 @@ 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 = STOP_MOVING_WHEN_PULLED 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, - // Top priority is to look for and execute hunts for cheese even if someone is looking at us + // 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, - // Try to speak, because it's cute - /datum/ai_planning_subtree/random_speech/mouse, // Otherwise, look for and execute hunts for cabling /datum/ai_planning_subtree/find_and_hunt_target/look_for_cables, )