Files
CHOMPStation2/code/modules/ai/ai_holder_combat_unseen.dm
Novacat 33f92d51ac Merge pull request #10348 from VOREStation/upstream-merge-8052
[MIRROR] Simplemobs seek lost targets
2021-05-18 12:30:56 +00:00

91 lines
3.3 KiB
Plaintext

// Used for fighting invisible things.
// Used when a target is out of sight or invisible.
/datum/ai_holder/proc/engage_unseen_enemy()
ai_log("engage_unseen_enemy() : Entering.", AI_LOG_TRACE)
// Lets do some last things before giving up.
if(conserve_ammo || !holder.ICheckRangedAttack(target_last_seen_turf))
if(get_dist(holder, target_last_seen_turf) > 1) // We last saw them over there.
// Go to where you last saw the enemy.
return give_destination(target_last_seen_turf, 1, TRUE) // Sets stance as well
else if(lose_target_time < world.time) // We last saw them next to us, so do a blind attack on that tile.
if(melee_on_tile(target_last_seen_turf) != ATTACK_SUCCESSFUL && intelligence_level >= AI_NORMAL)
var/obj/O = find_escape_route()
if(istype(O))
return give_destination(get_turf(O), 0, TRUE)
else
return find_target()
else
return shoot_near_turf(target_last_seen_turf)
// This shoots semi-randomly near a specific turf.
/datum/ai_holder/proc/shoot_near_turf(turf/targeted_turf)
if(get_dist(holder, targeted_turf) > max_range(targeted_turf))
return ATTACK_FAILED// Too far to shoot.
var/turf/T = pick(RANGE_TURFS(2, targeted_turf)) // The turf we're actually gonna shoot at.
on_engagement(T)
if(firing_lanes && !test_projectile_safety(T))
step_rand(holder)
holder.face_atom(T)
return ATTACK_FAILED
return ranged_attack(T)
// Attempts to attack something on a specific tile.
// TODO: Put on mob/living?
/datum/ai_holder/proc/melee_on_tile(turf/T)
ai_log("melee_on_tile() : Entering.", AI_LOG_TRACE)
var/mob/living/L = locate() in T
if(!L)
T.visible_message("\The [holder] attacks nothing around \the [T].")
return ATTACK_FAILED
if(holder.IIsAlly(L)) // Don't hurt our ally.
return ATTACK_FAILED
return melee_attack(L)
// Attempts to locate any possible avenues that the target might have escaped via
// Could be an open door, could be a stairwell or a ladder
// Returns object to path to. If multiple targets are equidistant, picks randomly
/datum/ai_holder/proc/find_escape_route()
ai_log("find_escape_route() : Entering.", AI_LOG_DEBUG)
var/list/closest_escape = list()
var/closest_dist = world.view // We can't see any further than this
var/list/possible_escape_types = list(
/obj/machinery/door,
/obj/structure/stairs/top,
/obj/structure/stairs/bottom
)
if(intelligence_level >= AI_SMART)
possible_escape_types += /obj/structure/ladder
for(var/atom/A in view(world.view, holder))
if(!is_type_in_list(A, possible_escape_types))
continue // Not something they could have escaped through
if(turn(holder.dir, 180) & get_dir(get_turf(holder), get_turf(A)))
continue // Surely, they couldn't have escaped *behind* us!
if(istype(A, /obj/machinery/door))
var/obj/machinery/door/D = A
if(D.glass) // Surely, they couldn't hide behind a transparent door!
continue
if(D.density && intelligence_level < AI_SMART) // Surely, they couldn't have escaped through a *closed* door
continue
var/dist = get_dist(holder, A)
if(dist == closest_dist)
closest_escape += A
else if(dist < closest_dist)
closest_escape.Cut()
closest_escape += A
closest_dist = dist
ai_log("find_escape_route() : Found [closest_escape.len] candidates [closest_dist] tiles away.", AI_LOG_DEBUG)
if(closest_escape.len)
return pick(closest_escape)
return null