From d2e807834832ca4bd9036775f57af480bedb5bdb Mon Sep 17 00:00:00 2001 From: Anewbe Date: Mon, 11 Feb 2019 22:06:11 -0600 Subject: [PATCH] Fixes turrets, AI shooting, and makes mob AI shooting a little smarter. --- code/game/machinery/portable_turret.dm | 2 +- code/modules/ai/ai_holder_combat.dm | 48 +++++++++++++------- code/modules/projectiles/projectile/trace.dm | 3 +- 3 files changed, 35 insertions(+), 18 deletions(-) diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm index 086ab1e182..210e9c50e4 100644 --- a/code/game/machinery/portable_turret.dm +++ b/code/game/machinery/portable_turret.dm @@ -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 diff --git a/code/modules/ai/ai_holder_combat.dm b/code/modules/ai/ai_holder_combat.dm index 2bb224e801..12cf9e2436 100644 --- a/code/modules/ai/ai_holder_combat.dm +++ b/code/modules/ai/ai_holder_combat.dm @@ -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) diff --git a/code/modules/projectiles/projectile/trace.dm b/code/modules/projectiles/projectile/trace.dm index 3052d11ab7..aaf7b9a7b6 100644 --- a/code/modules/projectiles/projectile/trace.dm +++ b/code/modules/projectiles/projectile/trace.dm @@ -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