Fixes turrets, AI shooting, and makes mob AI shooting a little smarter.

This commit is contained in:
Anewbe
2019-02-11 22:06:11 -06:00
committed by Novacat
parent f1da5f1f55
commit d2e8078348
3 changed files with 35 additions and 18 deletions

View File

@@ -570,7 +570,7 @@ var/list/turret_icons
if(get_dist(src, L) > 7) //if it's too far away, why bother?
return TURRET_NOT_TARGET
if(!check_trajectory(L, src)) //check if we have true line of sight
if(!(L in check_trajectory(L, src))) //check if we have true line of sight
return TURRET_NOT_TARGET
if(emagged) // If emagged not even the dead get a rest

View File

@@ -132,26 +132,42 @@
// Used to make sure projectiles will probably hit the target and not the wall or a friend.
/datum/ai_holder/proc/test_projectile_safety(atom/movable/AM)
if(holder.Adjacent(AM)) // If they're right next to us then lets just say yes. check_trajectory() tends to spaz out otherwise.
ai_log("test_projectile_safety([AM]) : Entering.", AI_LOG_TRACE)
// If they're right next to us then lets just say yes. check_trajectory() tends to spaz out otherwise.
if(holder.Adjacent(AM))
ai_log("test_projectile_safety() : Adjacent to target. Exiting with TRUE.", AI_LOG_TRACE)
return TRUE
var/mob/living/L = check_trajectory(AM, holder) // This isn't always reliable but its better than the previous method.
// world << "Checked trajectory, would hit [L]."
// This will hold a list of all mobs in a line, even those behind the target, and possibly the wall.
// By default the test projectile goes through things like glass and grilles, which is desirable as otherwise the AI won't try to shoot through windows.
var/list/hit_things = check_trajectory(AM, holder) // This isn't always reliable but its better than the previous method.
if(istype(L)) // Did we hit a mob?
// world << "Hit [L]."
if(holder.IIsAlly(L))
// world << "Would hit ally, canceling."
return FALSE // We would hit a friend!
// world << "Won't threaten ally, firing."
return TRUE // Otherwise we don't care, even if its not the intended target.
else
if(!isliving(AM)) // If the original target was an object, then let it happen if it doesn't threaten an ally.
// world << "Targeting object, ignoring and firing."
return TRUE
// world << "Not sure."
// Test to see if the primary target actually has a chance to get hit.
// We'll fire anyways if not, if we have conserve_ammo turned off.
var/would_hit_primary_target = FALSE
if(AM in hit_things)
would_hit_primary_target = TRUE
ai_log("test_projectile_safety() : Test projectile did[!would_hit_primary_target ? " NOT " : " "]hit \the [AM]", AI_LOG_DEBUG)
return !conserve_ammo // If we have infinite ammo than shooting the wall isn't so bad, but otherwise lets not.
// Make sure we don't have a chance to shoot our friends.
for(var/a in hit_things)
var/atom/A = a
ai_log("test_projectile_safety() : Evaluating \the [A] ([A.type]).", AI_LOG_TRACE)
if(isliving(A)) // Don't shoot at our friends, even if they're behind the target, as RNG can make them get hit.
var/mob/living/L = A
if(holder.IIsAlly(L))
ai_log("test_projectile_safety() : Would threaten ally, exiting with FALSE.", AI_LOG_DEBUG)
return FALSE
// Don't fire if we cannot hit the primary target, and we wish to be conservative with our projectiles.
// We make an exception for turf targets because manual commanded AIs targeting the floor are generally intending to fire blindly.
if(!would_hit_primary_target && !isturf(AM) && conserve_ammo)
ai_log("test_projectile_safety() : conserve_ammo is set, and test projectile failed to hit primary target. Exiting with FALSE.", AI_LOG_DEBUG)
return FALSE
ai_log("test_projectile_safety() : Passed other tests, exiting with TRUE.", AI_LOG_TRACE)
return TRUE
// Test if we are within range to attempt an attack, melee or ranged.
/datum/ai_holder/proc/within_range(atom/movable/AM)

View File

@@ -1,4 +1,5 @@
//Helper proc to check if you can hit them or not.
// Helper proc to check if you can hit them or not.
// Will return a list of hit mobs/objects.
/proc/check_trajectory(atom/target as mob|obj, atom/firer as mob|obj, var/pass_flags=PASSTABLE|PASSGLASS|PASSGRILLE, flags=null)
if(!istype(target) || !istype(firer))
return 0