Merge pull request #6870 from VOREStation/pol-aibash

Makes AI give up bashing if nothing to bash
This commit is contained in:
Atermonera
2020-03-22 11:51:07 -07:00
committed by GitHub
5 changed files with 28 additions and 21 deletions
+5
View File
@@ -20,6 +20,11 @@
#define MOVEMENT_FAILED 0 // Move() returned false for whatever reason and the mob didn't move.
#define MOVEMENT_SUCCESSFUL 1 // Move() returned true and the mob hopefully moved.
// Results of pre-attack checks
#define ATTACK_ON_COOLDOWN -1 // Recently attacked and needs to try again soon.
#define ATTACK_FAILED 0 // Something else went wrong! Maybe they moved away!
#define ATTACK_SUCCESSFUL 1 // We attacked (or tried to, misses count too)
// Reasons for targets to not be valid. Based on why, the AI responds differently.
#define AI_TARGET_VALID 0 // We can fight them.
#define AI_TARGET_INVIS 1 // They were in field of view but became invisible. Switch to STANCE_BLINDFIGHT if no other viable targets exist.
+10 -11
View File
@@ -70,21 +70,21 @@
/datum/ai_holder/proc/melee_attack(atom/A)
pre_melee_attack(A)
. = holder.IAttack(A)
if(.)
if(. == ATTACK_SUCCESSFUL)
post_melee_attack(A)
// Ditto.
/datum/ai_holder/proc/ranged_attack(atom/A)
pre_ranged_attack(A)
. = holder.IRangedAttack(A)
if(.)
if(. == ATTACK_SUCCESSFUL)
post_ranged_attack(A)
// Most mobs probably won't have this defined but we don't care.
/datum/ai_holder/proc/special_attack(atom/movable/AM)
pre_special_attack(AM)
. = holder.ISpecialAttack(AM)
if(.)
if(. == ATTACK_SUCCESSFUL)
post_special_attack(AM)
// Called when within striking/shooting distance, however cooldown is not considered.
@@ -218,7 +218,6 @@
var/dir_to_target = get_dir(holder, target_atom)
holder.face_atom(target_atom)
ai_log("breakthrough() : Exiting", AI_LOG_DEBUG)
// Sometimes the mob will try to hit something diagonally, and generally this fails.
// So instead we will try two more times with some adjustments if the attack fails.
@@ -274,32 +273,32 @@
for(var/obj/structure/window/W in problem_turf)
if(W.dir == reverse_dir[holder.dir]) // So that windows get smashed in the right order
ai_log("destroy_surroundings() : Attacking side window.", AI_LOG_INFO)
return holder.IAttack(W)
return melee_attack(W)
else if(W.is_fulltile())
ai_log("destroy_surroundings() : Attacking full tile window.", AI_LOG_INFO)
return holder.IAttack(W)
return melee_attack(W)
// Kill hull shields in the way.
for(var/obj/effect/energy_field/shield in problem_turf)
if(shield.density) // Don't attack shields that are already down.
ai_log("destroy_surroundings() : Attacking hull shield.", AI_LOG_INFO)
return holder.IAttack(shield)
return melee_attack(shield)
// Kill common obstacle in the way like tables.
var/obj/structure/obstacle = locate(/obj/structure, problem_turf)
if(istype(obstacle, /obj/structure/window) || istype(obstacle, /obj/structure/closet) || istype(obstacle, /obj/structure/table) || istype(obstacle, /obj/structure/grille))
ai_log("destroy_surroundings() : Attacking generic structure.", AI_LOG_INFO)
return holder.IAttack(obstacle)
return melee_attack(obstacle)
for(var/obj/machinery/door/D in problem_turf) // Required since firelocks take up the same turf.
if(D.density)
ai_log("destroy_surroundings() : Attacking closed door.", AI_LOG_INFO)
return holder.IAttack(D)
return melee_attack(D)
ai_log("destroy_surroundings() : Exiting due to nothing to attack.", AI_LOG_INFO)
return FALSE // Nothing to attack.
return ATTACK_FAILED // Nothing to attack.
// Override for special behaviour.
/datum/ai_holder/proc/can_violently_breakthrough()
return violent_breakthrough
return violent_breakthrough
+8 -3
View File
@@ -9,13 +9,14 @@
var/home_low_priority = FALSE // If true, the mob will not go home unless it has nothing better to do, e.g. its following someone.
var/max_home_distance = 3 // How far the mob can go away from its home before being told to go_home().
// Note that there is a 'BYOND cap' of 14 due to limitations of get_/step_to().
// Wandering.
var/wander = FALSE // If true, the mob will randomly move in the four cardinal directions when idle.
var/wander_delay = 0 // How many ticks until the mob can move a tile in handle_wander_movement().
var/base_wander_delay = 2 // What the above var gets set to when it wanders. Note that a tick happens every half a second.
var/wander_when_pulled = FALSE // If the mob will refrain from wandering if someone is pulling it.
// Breakthrough
var/failed_breakthroughs = 0 // How many times we've failed to breakthrough something lately
/datum/ai_holder/proc/walk_to_destination()
ai_log("walk_to_destination() : Entering.",AI_LOG_TRACE)
@@ -90,7 +91,9 @@
// step_to(holder, A)
if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED)
ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO)
breakthrough(A) // We failed to move, time to smash things.
if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things.
give_up_movement()
failed_breakthroughs = 0
return
if(move_once() == FALSE) // Start walking the path.
@@ -106,7 +109,9 @@
ai_log("walk_path() : Going to IMove().", AI_LOG_TRACE)
if(holder.IMove(get_step_to(holder, A)) == MOVEMENT_FAILED )
ai_log("walk_path() : Failed to move, attempting breakthrough.", AI_LOG_INFO)
breakthrough(A) // We failed to move, time to smash things.
if(!breakthrough(A) && failed_breakthroughs++ >= 5) // We failed to move, time to smash things.
give_up_movement()
failed_breakthroughs = 0
ai_log("walk_path() : Exited.", AI_LOG_TRACE)
+2 -2
View File
@@ -8,7 +8,7 @@
/mob/living/simple_mob/IAttack(atom/A)
if(!canClick()) // Still on cooldown from a "click".
return FALSE
return ATTACK_ON_COOLDOWN
return attack_target(A) // This will set click cooldown.
/mob/living/proc/IRangedAttack(atom/A)
@@ -16,7 +16,7 @@
/mob/living/simple_mob/IRangedAttack(atom/A)
if(!canClick()) // Still on cooldown from a "click".
return FALSE
return ATTACK_ON_COOLDOWN
return shoot_target(A)
// Test if the AI is allowed to attempt a ranged attack.
+3 -5
View File
@@ -3,26 +3,24 @@
set waitfor = FALSE // For attack animations. Don't want the AI processor to get held up.
if(!A.Adjacent(src))
return FALSE
return ATTACK_FAILED
var/turf/their_T = get_turf(A)
face_atom(A)
if(melee_attack_delay)
// their_T.color = "#FF0000"
melee_pre_animation(A)
. = ATTACK_SUCCESSFUL //Shoving this in here as a 'best guess' since this proc is about to sleep and return and we won't be able to know the real value
handle_attack_delay(A, melee_attack_delay) // This will sleep this proc for a bit, which is why waitfor is false.
// Cooldown testing is done at click code (for players) and interface code (for AI).
setClickCooldown(get_attack_speed())
// Returns a value, but will be lost if
. = do_attack(A, their_T)
if(melee_attack_delay)
melee_post_animation(A)
// their_T.color = "#FFFFFF"
// This does the actual attack.
// This is a seperate proc for the purposes of attack animations.