diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index f654d213b4e..ee8ac90b88f 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -641,6 +641,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai /// trait denoting someone will sometimes recover out of crit #define TRAIT_UNBREAKABLE "unbreakable" +/// trait that prevents AI controllers from planning detached from ai_status to prevent weird state stuff. +#define TRAIT_AI_PAUSED "TRAIT_AI_PAUSED" + //Medical Categories for quirks #define CAT_QUIRK_ALL 0 #define CAT_QUIRK_NOTES 1 diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 9298ff91b3e..26b9399f65b 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -123,6 +123,8 @@ multiple modular subtrees with behaviors ///Returns TRUE if the ai controller can actually run at the moment. /datum/ai_controller/proc/able_to_run() + if(HAS_TRAIT(pawn, TRAIT_AI_PAUSED)) + return FALSE if(world.time < paused_until) return FALSE return TRUE diff --git a/code/datums/ai/basic_mobs/base_basic_controller.dm b/code/datums/ai/basic_mobs/base_basic_controller.dm index cc74b412105..31ce1f5c9aa 100644 --- a/code/datums/ai/basic_mobs/base_basic_controller.dm +++ b/code/datums/ai/basic_mobs/base_basic_controller.dm @@ -19,7 +19,6 @@ var/mob/living/living_pawn = pawn if(IS_DEAD_OR_INCAP(living_pawn)) return FALSE - return TRUE /datum/ai_controller/basic_controller/proc/update_speed(mob/living/basic/basic_mob) SIGNAL_HANDLER diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index f02a323baa7..c6d7c10cf5f 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -30,6 +30,7 @@ if(isanimal(parent)) var/mob/living/simple_animal/simple_parent = parent simple_parent.stop_automated_movement = FALSE + REMOVE_TRAIT(parent, TRAIT_AI_PAUSED, REF(src)) return ..() /datum/component/riding/creature/RegisterWithParent() @@ -69,20 +70,36 @@ rider.Knockdown(4 SECONDS) living_parent.unbuckle_mob(rider) -/datum/component/riding/creature/vehicle_mob_buckle(datum/source, mob/living/rider, force = FALSE) +/datum/component/riding/creature/vehicle_mob_buckle(mob/living/ridden, mob/living/rider, force = FALSE) // Ensure that the /mob/post_buckle_mob(mob/living/M) does not mess us up with layers // If we do not do this override we'll be stuck with the above proc (+ 0.1)-ing our rider's layer incorrectly rider.layer = initial(rider.layer) + if(can_be_driven) + //let the player take over if they should be controlling movement + ADD_TRAIT(ridden, TRAIT_AI_PAUSED, REF(src)) + if(rider.pulling == ridden) + rider.stop_pulling() + RegisterSignal(rider, COMSIG_LIVING_TRY_PULL, .proc/on_rider_try_pull) return ..() -/datum/component/riding/creature/vehicle_mob_unbuckle(mob/living/living_parent, mob/living/former_rider, force = FALSE) - if(istype(living_parent) && istype(former_rider)) - living_parent.log_message("is no longer being ridden by [former_rider].", LOG_GAME, color="pink") - former_rider.log_message("is no longer riding [living_parent].", LOG_GAME, color="pink") +/datum/component/riding/creature/proc/on_rider_try_pull(mob/living/rider_pulling, atom/movable/target, force) + SIGNAL_HANDLER + if(target == parent) + var/mob/living/ridden = parent + ridden.balloon_alert(rider_pulling, "not while riding it!") + return COMSIG_LIVING_CANCEL_PULL + +/datum/component/riding/creature/vehicle_mob_unbuckle(mob/living/formerly_ridden, mob/living/former_rider, force = FALSE) + if(istype(formerly_ridden) && istype(former_rider)) + formerly_ridden.log_message("is no longer being ridden by [former_rider].", LOG_GAME, color="pink") + former_rider.log_message("is no longer riding [formerly_ridden].", LOG_GAME, color="pink") remove_abilities(former_rider) + if(!formerly_ridden.buckled_mobs.len) + REMOVE_TRAIT(formerly_ridden, TRAIT_AI_PAUSED, REF(src)) + UnregisterSignal(former_rider, COMSIG_LIVING_TRY_PULL) // We gotta reset those layers at some point, don't we? former_rider.layer = MOB_LAYER - living_parent.layer = MOB_LAYER + formerly_ridden.layer = MOB_LAYER return ..() /datum/component/riding/creature/driver_move(atom/movable/movable_parent, mob/living/user, direction) diff --git a/code/modules/mob/living/basic/farm_animals/cows.dm b/code/modules/mob/living/basic/farm_animals/cows.dm index 130a43e4342..52d513e0435 100644 --- a/code/modules/mob/living/basic/farm_animals/cows.dm +++ b/code/modules/mob/living/basic/farm_animals/cows.dm @@ -28,6 +28,8 @@ gold_core_spawnable = FRIENDLY_SPAWN blood_volume = BLOOD_VOLUME_NORMAL ai_controller = /datum/ai_controller/basic_controller/cow + var/tame_message = "lets out a happy moo" + var/self_tame_message = "let out a happy moo" /mob/living/basic/cow/Initialize(mapload) AddComponent(/datum/component/tippable, \ @@ -51,6 +53,7 @@ /mob/living/basic/cow/proc/tamed(mob/living/tamer) buckle_lying = 0 + visible_message("[src] [tame_message] as it seems to bond with [tamer].", "You [self_tame_message], recognizing [tamer] as your new pal.") AddElement(/datum/element/ridable, /datum/component/riding/creature/cow) /* @@ -132,6 +135,8 @@ attack_sound = 'sound/weapons/bladeslice.ogg' attack_vis_effect = ATTACK_EFFECT_SLASH ai_controller = /datum/ai_controller/basic_controller/cow/moonicorn + tame_message = "nods with respect" + self_tame_message = "nod with respect" /mob/living/basic/cow/moonicorn/Initialize(mapload) . = ..() @@ -146,7 +151,6 @@ /mob/living/basic/cow/moonicorn/tamed(mob/living/tamer) . = ..() - visible_message(span_notice("[src] nods with respect.")) ///stop killing my FRIENDS faction |= tamer.faction