mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 18:22:14 +00:00
Adds a subsystem for ai movement (#57111)
* done * straight walk * movement * yep * removes unused macro * done * Update ai_movement.dm
This commit is contained in:
@@ -1064,6 +1064,8 @@
|
|||||||
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged"
|
#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged"
|
||||||
///From base of atom/ctrl_click(): (atom/A)
|
///From base of atom/ctrl_click(): (atom/A)
|
||||||
#define COMSIG_MOB_CTRL_CLICKED "mob_ctrl_clicked"
|
#define COMSIG_MOB_CTRL_CLICKED "mob_ctrl_clicked"
|
||||||
|
///From base of mob/update_movespeed():area
|
||||||
|
#define COMSIG_MOB_MOVESPEED_UPDATED "mob_update_movespeed"
|
||||||
///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
|
///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
|
||||||
#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
|
#define COMSIG_HUMAN_EARLY_UNARMED_ATTACK "human_early_unarmed_attack"
|
||||||
///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
|
///from mob/living/carbon/human/UnarmedAttack(): (atom/target, proximity)
|
||||||
|
|||||||
@@ -117,6 +117,8 @@
|
|||||||
#define INIT_ORDER_EVENTS 70
|
#define INIT_ORDER_EVENTS 70
|
||||||
#define INIT_ORDER_JOBS 65
|
#define INIT_ORDER_JOBS 65
|
||||||
#define INIT_ORDER_QUIRKS 60
|
#define INIT_ORDER_QUIRKS 60
|
||||||
|
#define INIT_ORDER_AI_MOVEMENT 56 //We need the movement setup
|
||||||
|
#define INIT_ORDER_AI_CONTROLLERS 55 //So the controller can get the ref
|
||||||
#define INIT_ORDER_TICKER 55
|
#define INIT_ORDER_TICKER 55
|
||||||
#define INIT_ORDER_TCG 55
|
#define INIT_ORDER_TCG 55
|
||||||
#define INIT_ORDER_REAGENTS 55 //HAS to be before mapping - mapping creates objects, which creates reagents, which relies on lists made in this subsystem
|
#define INIT_ORDER_REAGENTS 55 //HAS to be before mapping - mapping creates objects, which creates reagents, which relies on lists made in this subsystem
|
||||||
@@ -160,6 +162,7 @@
|
|||||||
#define FIRE_PRIORITY_WET_FLOORS 20
|
#define FIRE_PRIORITY_WET_FLOORS 20
|
||||||
#define FIRE_PRIORITY_AIR 20
|
#define FIRE_PRIORITY_AIR 20
|
||||||
#define FIRE_PRIORITY_NPC 20
|
#define FIRE_PRIORITY_NPC 20
|
||||||
|
#define FIRE_PRIORITY_NPC_MOVEMENT 21
|
||||||
#define FIRE_PRIORITY_PROCESS 25
|
#define FIRE_PRIORITY_PROCESS 25
|
||||||
#define FIRE_PRIORITY_THROWING 25
|
#define FIRE_PRIORITY_THROWING 25
|
||||||
#define FIRE_PRIORITY_REAGENTS 26
|
#define FIRE_PRIORITY_REAGENTS 26
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ PROCESSING_SUBSYSTEM_DEF(ai_controllers)
|
|||||||
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
|
flags = SS_POST_FIRE_TIMING|SS_BACKGROUND
|
||||||
priority = FIRE_PRIORITY_NPC
|
priority = FIRE_PRIORITY_NPC
|
||||||
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||||
|
init_order = INIT_ORDER_AI_CONTROLLERS
|
||||||
wait = 8 //Uses the value of CLICK_CD_MELEE because that seemed like a nice standard for the speed of AI behavior
|
wait = 8 //Uses the value of CLICK_CD_MELEE because that seemed like a nice standard for the speed of AI behavior
|
||||||
|
|
||||||
///an assoc list of all ai_behaviors by type, to
|
///an assoc list of all ai_behaviors by type, to
|
||||||
|
|||||||
21
code/controllers/subsystem/processing/ai_movement.dm
Normal file
21
code/controllers/subsystem/processing/ai_movement.dm
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/// The subsystem used to tick [/datum/ai_movement] instances. Handling the movement of individual AI instances
|
||||||
|
PROCESSING_SUBSYSTEM_DEF(ai_movement)
|
||||||
|
name = "AI movement"
|
||||||
|
flags = SS_KEEP_TIMING|SS_BACKGROUND
|
||||||
|
priority = FIRE_PRIORITY_NPC_MOVEMENT
|
||||||
|
runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME
|
||||||
|
init_order = INIT_ORDER_AI_MOVEMENT
|
||||||
|
wait = 1
|
||||||
|
|
||||||
|
///an assoc list of all ai_movement types. Assoc type to instance
|
||||||
|
var/list/movement_types
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/ai_movement/Initialize(timeofday)
|
||||||
|
SetupAIMovementInstances()
|
||||||
|
return ..()
|
||||||
|
|
||||||
|
/datum/controller/subsystem/processing/ai_movement/proc/SetupAIMovementInstances()
|
||||||
|
movement_types = list()
|
||||||
|
for(var/key as anything in subtypesof(/datum/ai_movement))
|
||||||
|
var/datum/ai_movement/ai_movement = new key
|
||||||
|
movement_types[key] = ai_movement
|
||||||
@@ -17,4 +17,5 @@
|
|||||||
controller.current_behaviors.Remove(src)
|
controller.current_behaviors.Remove(src)
|
||||||
if(behavior_flags & AI_BEHAVIOR_REQUIRE_MOVEMENT) //If this was a movement task, reset our movement target.
|
if(behavior_flags & AI_BEHAVIOR_REQUIRE_MOVEMENT) //If this was a movement task, reset our movement target.
|
||||||
controller.current_movement_target = null
|
controller.current_movement_target = null
|
||||||
|
controller.ai_movement.stop_moving_towards(controller)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -26,8 +26,15 @@ have ways of interacting with a specific atom and control it. They posses a blac
|
|||||||
var/continue_processing_when_client = FALSE
|
var/continue_processing_when_client = FALSE
|
||||||
///distance to give up on target
|
///distance to give up on target
|
||||||
var/max_target_distance = 14
|
var/max_target_distance = 14
|
||||||
|
///Reference to the movement datum we use. Is a type on initialize but becomes a ref afterwards.
|
||||||
|
var/datum/ai_movement/ai_movement = /datum/ai_movement/dumb
|
||||||
|
///Cooldown until next movement
|
||||||
|
COOLDOWN_DECLARE(movement_cooldown)
|
||||||
|
///Delay between movements. This is on the controller so we can keep the movement datum singleton
|
||||||
|
var/movement_delay = 0.1 SECONDS
|
||||||
|
|
||||||
/datum/ai_controller/New(atom/new_pawn)
|
/datum/ai_controller/New(atom/new_pawn)
|
||||||
|
ai_movement = SSai_movement.movement_types[ai_movement]
|
||||||
PossessPawn(new_pawn)
|
PossessPawn(new_pawn)
|
||||||
|
|
||||||
/datum/ai_controller/Destroy(force, ...)
|
/datum/ai_controller/Destroy(force, ...)
|
||||||
@@ -81,8 +88,7 @@ have ways of interacting with a specific atom and control it. They posses a blac
|
|||||||
/// Generates a plan and see if our existing one is still valid.
|
/// Generates a plan and see if our existing one is still valid.
|
||||||
/datum/ai_controller/process(delta_time)
|
/datum/ai_controller/process(delta_time)
|
||||||
if(!able_to_run())
|
if(!able_to_run())
|
||||||
var/atom/movable/movable_pawn = pawn
|
walk(pawn, 0) //stop moving
|
||||||
walk(movable_pawn, 0) //stop moving
|
|
||||||
return //this should remove them from processing in the future through event-based stuff.
|
return //this should remove them from processing in the future through event-based stuff.
|
||||||
if(!current_behaviors?.len)
|
if(!current_behaviors?.len)
|
||||||
SelectBehaviors(delta_time)
|
SelectBehaviors(delta_time)
|
||||||
@@ -90,40 +96,33 @@ have ways of interacting with a specific atom and control it. They posses a blac
|
|||||||
PerformIdleBehavior(delta_time) //Do some stupid shit while we have nothing to do
|
PerformIdleBehavior(delta_time) //Do some stupid shit while we have nothing to do
|
||||||
return
|
return
|
||||||
|
|
||||||
var/want_to_move = FALSE
|
|
||||||
|
if(current_movement_target && get_dist(pawn, current_movement_target) > max_target_distance) //The distance is out of range
|
||||||
|
CancelActions()
|
||||||
|
return
|
||||||
|
|
||||||
for(var/i in current_behaviors)
|
for(var/i in current_behaviors)
|
||||||
var/datum/ai_behavior/current_behavior = i
|
var/datum/ai_behavior/current_behavior = i
|
||||||
|
|
||||||
if(behavior_cooldowns[current_behavior] > world.time) //Still on cooldown
|
if(behavior_cooldowns[current_behavior] > world.time) //Still on cooldown
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if(current_behavior.behavior_flags & AI_BEHAVIOR_REQUIRE_MOVEMENT && current_movement_target && current_behavior.required_distance < get_dist(pawn, current_movement_target)) //Move closer
|
if(current_behavior.behavior_flags & AI_BEHAVIOR_REQUIRE_MOVEMENT && current_movement_target) //Might need to move closer
|
||||||
want_to_move = TRUE
|
if(current_behavior.required_distance >= get_dist(pawn, current_movement_target)) ///Are we close enough to engage?
|
||||||
if(current_behavior.behavior_flags & AI_BEHAVIOR_MOVE_AND_PERFORM) //Move and perform the action
|
if(ai_movement.moving_controllers[src] == current_movement_target) //We are close enough, if we're moving stop.else
|
||||||
|
ai_movement.stop_moving_towards(src)
|
||||||
current_behavior.perform(delta_time, src)
|
current_behavior.perform(delta_time, src)
|
||||||
else //Perform the action
|
return
|
||||||
|
|
||||||
|
else if(ai_movement.moving_controllers[src] != current_movement_target) //We're too far, if we're not already moving start doing it.
|
||||||
|
ai_movement.start_moving_towards(src, current_movement_target) //Then start moving
|
||||||
|
|
||||||
|
if(current_behavior.behavior_flags & AI_BEHAVIOR_MOVE_AND_PERFORM) //If we can move and perform then do so.
|
||||||
|
current_behavior.perform(delta_time, src)
|
||||||
|
return
|
||||||
|
else //No movement required
|
||||||
current_behavior.perform(delta_time, src)
|
current_behavior.perform(delta_time, src)
|
||||||
|
return
|
||||||
if(want_to_move)
|
|
||||||
MoveTo(delta_time) //Need to add some code to check if we can perform the actions now without too much overhead
|
|
||||||
|
|
||||||
|
|
||||||
///Move somewhere using dumb movement (byond base)
|
|
||||||
/datum/ai_controller/proc/MoveTo(delta_time)
|
|
||||||
var/current_loc = get_turf(pawn)
|
|
||||||
var/atom/movable/movable_pawn = pawn
|
|
||||||
|
|
||||||
var/turf/target_turf = get_step_towards(movable_pawn, current_movement_target)
|
|
||||||
|
|
||||||
if(!is_type_in_typecache(target_turf, GLOB.dangerous_turfs))
|
|
||||||
movable_pawn.Move(target_turf, get_dir(current_loc, target_turf))
|
|
||||||
if(get_dist(movable_pawn, current_movement_target) > max_target_distance)
|
|
||||||
CancelActions()
|
|
||||||
pathing_attempts = 0
|
|
||||||
if(current_loc == get_turf(movable_pawn))
|
|
||||||
if(++pathing_attempts >= MAX_PATHING_ATTEMPTS)
|
|
||||||
CancelActions()
|
|
||||||
pathing_attempts = 0
|
|
||||||
|
|
||||||
|
|
||||||
///Perform some dumb idle behavior.
|
///Perform some dumb idle behavior.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
/datum/ai_controller/haunted
|
/datum/ai_controller/haunted
|
||||||
|
movement_delay = 0.4 SECONDS
|
||||||
blackboard = list(BB_TO_HAUNT_LIST = list(),
|
blackboard = list(BB_TO_HAUNT_LIST = list(),
|
||||||
BB_HAUNT_TARGET,
|
BB_HAUNT_TARGET,
|
||||||
BB_HAUNTED_THROW_ATTEMPT_COUNT)
|
BB_HAUNTED_THROW_ATTEMPT_COUNT)
|
||||||
@@ -14,9 +15,6 @@
|
|||||||
UnregisterSignal(pawn, COMSIG_ITEM_EQUIPPED)
|
UnregisterSignal(pawn, COMSIG_ITEM_EQUIPPED)
|
||||||
return ..() //Run parent at end
|
return ..() //Run parent at end
|
||||||
|
|
||||||
/datum/ai_controller/haunted/able_to_run()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/datum/ai_controller/haunted/SelectBehaviors(delta_time)
|
/datum/ai_controller/haunted/SelectBehaviors(delta_time)
|
||||||
current_behaviors = list()
|
current_behaviors = list()
|
||||||
var/obj/item/item_pawn = pawn
|
var/obj/item/item_pawn = pawn
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
|
|
||||||
// Strong weapon
|
// Strong weapon
|
||||||
else if(target.force > best_force)
|
else if(target.force > best_force)
|
||||||
|
living_pawn.drop_all_held_items()
|
||||||
living_pawn.put_in_hands(target)
|
living_pawn.put_in_hands(target)
|
||||||
controller.blackboard[BB_MONKEY_BEST_FORCE_FOUND] = target.force
|
controller.blackboard[BB_MONKEY_BEST_FORCE_FOUND] = target.force
|
||||||
finish_action(controller, TRUE)
|
finish_action(controller, TRUE)
|
||||||
@@ -77,7 +78,7 @@
|
|||||||
|
|
||||||
var/mob/living/living_pawn = controller.pawn
|
var/mob/living/living_pawn = controller.pawn
|
||||||
|
|
||||||
victim.visible_message("<span class='warning'>[living_pawn] starts trying to take [target] from [controller.current_movement_target]!</span>", "<span class='danger'>[living_pawn] tries to take [target]!</span>")
|
victim.visible_message("<span class='warning'>[living_pawn] starts trying to take [target] from [victim]!</span>", "<span class='danger'>[living_pawn] tries to take [target]!</span>")
|
||||||
|
|
||||||
controller.blackboard[BB_MONKEY_PICKPOCKETING] = TRUE
|
controller.blackboard[BB_MONKEY_PICKPOCKETING] = TRUE
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ have ways of interacting with a specific mob and control it.
|
|||||||
///OOK OOK OOK
|
///OOK OOK OOK
|
||||||
|
|
||||||
/datum/ai_controller/monkey
|
/datum/ai_controller/monkey
|
||||||
|
movement_delay = 0.4 SECONDS
|
||||||
blackboard = list(BB_MONKEY_AGRESSIVE = FALSE,\
|
blackboard = list(BB_MONKEY_AGRESSIVE = FALSE,\
|
||||||
BB_MONKEY_BEST_FORCE_FOUND = 0,\
|
BB_MONKEY_BEST_FORCE_FOUND = 0,\
|
||||||
BB_MONKEY_ENEMIES = list(),\
|
BB_MONKEY_ENEMIES = list(),\
|
||||||
@@ -27,6 +28,7 @@ have ways of interacting with a specific mob and control it.
|
|||||||
/datum/ai_controller/monkey/TryPossessPawn(atom/new_pawn)
|
/datum/ai_controller/monkey/TryPossessPawn(atom/new_pawn)
|
||||||
if(!isliving(new_pawn))
|
if(!isliving(new_pawn))
|
||||||
return AI_CONTROLLER_INCOMPATIBLE
|
return AI_CONTROLLER_INCOMPATIBLE
|
||||||
|
var/mob/living/living_pawn = new_pawn
|
||||||
RegisterSignal(new_pawn, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
RegisterSignal(new_pawn, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
|
||||||
RegisterSignal(new_pawn, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
|
RegisterSignal(new_pawn, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand)
|
||||||
RegisterSignal(new_pawn, COMSIG_ATOM_ATTACK_PAW, .proc/on_attack_paw)
|
RegisterSignal(new_pawn, COMSIG_ATOM_ATTACK_PAW, .proc/on_attack_paw)
|
||||||
@@ -37,11 +39,13 @@ have ways of interacting with a specific mob and control it.
|
|||||||
RegisterSignal(new_pawn, COMSIG_LIVING_TRY_SYRINGE, .proc/on_try_syringe)
|
RegisterSignal(new_pawn, COMSIG_LIVING_TRY_SYRINGE, .proc/on_try_syringe)
|
||||||
RegisterSignal(new_pawn, COMSIG_ATOM_HULK_ATTACK, .proc/on_attack_hulk)
|
RegisterSignal(new_pawn, COMSIG_ATOM_HULK_ATTACK, .proc/on_attack_hulk)
|
||||||
RegisterSignal(new_pawn, COMSIG_CARBON_CUFF_ATTEMPTED, .proc/on_attempt_cuff)
|
RegisterSignal(new_pawn, COMSIG_CARBON_CUFF_ATTEMPTED, .proc/on_attempt_cuff)
|
||||||
|
RegisterSignal(new_pawn, COMSIG_MOB_MOVESPEED_UPDATED, .proc/update_movespeed)
|
||||||
|
movement_delay = living_pawn.cached_multiplicative_slowdown
|
||||||
return ..() //Run parent at end
|
return ..() //Run parent at end
|
||||||
|
|
||||||
/datum/ai_controller/monkey/UnpossessPawn(destroy)
|
/datum/ai_controller/monkey/UnpossessPawn(destroy)
|
||||||
UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_MOVABLE_CROSSED, COMSIG_LIVING_START_PULL,\
|
UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_ATTACK_PAW, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_MOVABLE_CROSSED, COMSIG_LIVING_START_PULL,\
|
||||||
COMSIG_LIVING_TRY_SYRINGE, COMSIG_ATOM_HULK_ATTACK, COMSIG_CARBON_CUFF_ATTEMPTED))
|
COMSIG_LIVING_TRY_SYRINGE, COMSIG_ATOM_HULK_ATTACK, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_MOB_MOVESPEED_UPDATED))
|
||||||
return ..() //Run parent at end
|
return ..() //Run parent at end
|
||||||
|
|
||||||
/datum/ai_controller/monkey/able_to_run()
|
/datum/ai_controller/monkey/able_to_run()
|
||||||
@@ -116,7 +120,7 @@ have ways of interacting with a specific mob and control it.
|
|||||||
for(var/obj/item/i in oview(2, living_pawn))
|
for(var/obj/item/i in oview(2, living_pawn))
|
||||||
if(!istype(i))
|
if(!istype(i))
|
||||||
continue
|
continue
|
||||||
if(HAS_TRAIT(i, TRAIT_NEEDS_TWO_HANDS) || blackboard[BB_MONKEY_BLACKLISTITEMS][i] || i.force > blackboard[BB_MONKEY_BEST_FORCE_FOUND])
|
if(HAS_TRAIT(i, TRAIT_NEEDS_TWO_HANDS) || blackboard[BB_MONKEY_BLACKLISTITEMS][i] || i.force < blackboard[BB_MONKEY_BEST_FORCE_FOUND])
|
||||||
continue
|
continue
|
||||||
W = i
|
W = i
|
||||||
break
|
break
|
||||||
@@ -216,3 +220,7 @@ have ways of interacting with a specific mob and control it.
|
|||||||
// chance of monkey retaliation
|
// chance of monkey retaliation
|
||||||
if(prob(MONKEY_CUFF_RETALIATION_PROB))
|
if(prob(MONKEY_CUFF_RETALIATION_PROB))
|
||||||
retaliate(user)
|
retaliate(user)
|
||||||
|
|
||||||
|
/datum/ai_controller/monkey/proc/update_movespeed(mob/living/pawn)
|
||||||
|
SIGNAL_HANDLER
|
||||||
|
movement_delay = pawn.cached_multiplicative_slowdown
|
||||||
|
|||||||
18
code/datums/ai/movement/_ai_movement.dm
Normal file
18
code/datums/ai/movement/_ai_movement.dm
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
///This datum is an abstract class that can be overriden for different types of movement
|
||||||
|
/datum/ai_movement
|
||||||
|
///Assoc list ist of controllers that are currently moving as key, and what they are moving to as value
|
||||||
|
var/list/moving_controllers = list()
|
||||||
|
|
||||||
|
/datum/ai_movement/proc/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target)
|
||||||
|
controller.pathing_attempts = 0
|
||||||
|
if(!moving_controllers.len)
|
||||||
|
START_PROCESSING(SSai_movement, src)
|
||||||
|
moving_controllers[controller] = current_movement_target
|
||||||
|
|
||||||
|
/datum/ai_movement/proc/stop_moving_towards(datum/ai_controller/controller)
|
||||||
|
controller.pathing_attempts = 0
|
||||||
|
moving_controllers -= controller
|
||||||
|
|
||||||
|
if(!moving_controllers.len)
|
||||||
|
STOP_PROCESSING(SSai_movement, src)
|
||||||
|
|
||||||
27
code/datums/ai/movement/ai_movement_dumb.dm
Normal file
27
code/datums/ai/movement/ai_movement_dumb.dm
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
///The most braindead type of movement, bee-line to the target with no concern of whats infront of us.
|
||||||
|
/datum/ai_movement/dumb
|
||||||
|
|
||||||
|
|
||||||
|
///Put your movement behavior in here!
|
||||||
|
/datum/ai_movement/dumb/process(delta_time)
|
||||||
|
for(var/datum/ai_controller/controller as anything in moving_controllers)
|
||||||
|
if(!COOLDOWN_FINISHED(controller, movement_cooldown))
|
||||||
|
continue
|
||||||
|
COOLDOWN_START(controller, movement_cooldown, controller.movement_delay)
|
||||||
|
|
||||||
|
var/atom/movable/movable_pawn = controller.pawn
|
||||||
|
|
||||||
|
if(!isturf(movable_pawn.loc)) //No moving if not on a turf
|
||||||
|
continue
|
||||||
|
|
||||||
|
var/current_loc = get_turf(movable_pawn)
|
||||||
|
|
||||||
|
var/turf/target_turf = get_step_towards(movable_pawn, controller.current_movement_target)
|
||||||
|
|
||||||
|
if(!is_type_in_typecache(target_turf, GLOB.dangerous_turfs))
|
||||||
|
movable_pawn.Move(target_turf, get_dir(current_loc, target_turf))
|
||||||
|
|
||||||
|
if(current_loc == get_turf(movable_pawn)) //Did we even move after trying to move?
|
||||||
|
controller.pathing_attempts++
|
||||||
|
if(controller.pathing_attempts >= MAX_PATHING_ATTEMPTS)
|
||||||
|
controller.CancelActions()
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
if(controller.blackboard[BB_VENDING_BUSY_TILTING])
|
if(controller.blackboard[BB_VENDING_BUSY_TILTING])
|
||||||
return
|
return
|
||||||
|
|
||||||
|
controller.ai_movement.stop_moving_towards(controller)
|
||||||
controller.blackboard[BB_VENDING_BUSY_TILTING] = TRUE
|
controller.blackboard[BB_VENDING_BUSY_TILTING] = TRUE
|
||||||
var/turf/target_turf = get_turf(controller.blackboard[BB_VENDING_CURRENT_TARGET])
|
var/turf/target_turf = get_turf(controller.blackboard[BB_VENDING_CURRENT_TARGET])
|
||||||
new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target_turf)
|
new /obj/effect/temp_visual/telegraphing/vending_machine_tilt(target_turf)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
///AI controller for vending machine gone rogue, Don't try using this on anything else, it wont work.
|
///AI controller for vending machine gone rogue, Don't try using this on anything else, it wont work.
|
||||||
/datum/ai_controller/vending_machine
|
/datum/ai_controller/vending_machine
|
||||||
|
movement_delay = 0.4 SECONDS
|
||||||
blackboard = list(BB_VENDING_CURRENT_TARGET = null,
|
blackboard = list(BB_VENDING_CURRENT_TARGET = null,
|
||||||
BB_VENDING_TILT_COOLDOWN = 0,
|
BB_VENDING_TILT_COOLDOWN = 0,
|
||||||
BB_VENDING_UNTILT_COOLDOWN = 0,
|
BB_VENDING_UNTILT_COOLDOWN = 0,
|
||||||
|
|||||||
@@ -186,6 +186,7 @@ GLOBAL_LIST_EMPTY(movespeed_modification_cache)
|
|||||||
continue
|
continue
|
||||||
. += amt
|
. += amt
|
||||||
cached_multiplicative_slowdown = .
|
cached_multiplicative_slowdown = .
|
||||||
|
SEND_SIGNAL(src, COMSIG_MOB_MOVESPEED_UPDATED)
|
||||||
|
|
||||||
/// Get the move speed modifiers list of the mob
|
/// Get the move speed modifiers list of the mob
|
||||||
/mob/proc/get_movespeed_modifiers()
|
/mob/proc/get_movespeed_modifiers()
|
||||||
|
|||||||
@@ -344,6 +344,7 @@
|
|||||||
#include "code\controllers\subsystem\weather.dm"
|
#include "code\controllers\subsystem\weather.dm"
|
||||||
#include "code\controllers\subsystem\processing\acid.dm"
|
#include "code\controllers\subsystem\processing\acid.dm"
|
||||||
#include "code\controllers\subsystem\processing\ai_controllers.dm"
|
#include "code\controllers\subsystem\processing\ai_controllers.dm"
|
||||||
|
#include "code\controllers\subsystem\processing\ai_movement.dm"
|
||||||
#include "code\controllers\subsystem\processing\fastprocess.dm"
|
#include "code\controllers\subsystem\processing\fastprocess.dm"
|
||||||
#include "code\controllers\subsystem\processing\fields.dm"
|
#include "code\controllers\subsystem\processing\fields.dm"
|
||||||
#include "code\controllers\subsystem\processing\fluids.dm"
|
#include "code\controllers\subsystem\processing\fluids.dm"
|
||||||
@@ -416,6 +417,8 @@
|
|||||||
#include "code\datums\ai\hauntium\haunted_controller.dm"
|
#include "code\datums\ai\hauntium\haunted_controller.dm"
|
||||||
#include "code\datums\ai\monkey\monkey_behaviors.dm"
|
#include "code\datums\ai\monkey\monkey_behaviors.dm"
|
||||||
#include "code\datums\ai\monkey\monkey_controller.dm"
|
#include "code\datums\ai\monkey\monkey_controller.dm"
|
||||||
|
#include "code\datums\ai\movement\_ai_movement.dm"
|
||||||
|
#include "code\datums\ai\movement\ai_movement_dumb.dm"
|
||||||
#include "code\datums\ai\objects\vending_machines\vending_machine_behaviors.dm"
|
#include "code\datums\ai\objects\vending_machines\vending_machine_behaviors.dm"
|
||||||
#include "code\datums\ai\objects\vending_machines\vending_machine_controller.dm"
|
#include "code\datums\ai\objects\vending_machines\vending_machine_controller.dm"
|
||||||
#include "code\datums\announcers\_announcer.dm"
|
#include "code\datums\announcers\_announcer.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user