Restrict direct fire to weapons range only instead of minimum of sensor range and

weapon range. Patch by myself and Zarel with input from the forums. From ticket #97.


git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@6182 4a71c877-e1ca-e34f-864e-861f7616d084
master
Per Inge Mathisen 2008-10-18 17:59:09 +00:00
parent ee5f151162
commit 2d02726753
3 changed files with 63 additions and 14 deletions

View File

@ -176,11 +176,18 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
return;
}
if (!psTarget->visible[psAttacker->player])
{
// Can't see it - can't hit it
objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target", psAttacker->id, psStats->pName, psTarget->id);
return;
}
/* Check we can see the target */
if (psAttacker->type == OBJ_DROID && !isVtolDroid((DROID *)psAttacker)
&& (proj_Direct(psStats) || actionInsideMinRange(psDroid, psTarget, psStats)))
{
if(!visibleObject(psAttacker, psTarget, true))
if(!lineOfFire(psAttacker, psTarget, true))
{
// Can't see the target - can't hit it with direct fire
objTrace(psAttacker->id, "combFire(%u[%s]->%u): Droid has no direct line of sight to target",
@ -193,7 +200,7 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
proj_Direct(psStats))
{
// a bunker can't shoot through walls
if (!visibleObject(psAttacker, psTarget, true))
if (!lineOfFire(psAttacker, psTarget, true))
{
// Can't see the target - can't hit it with direct fire
objTrace(psAttacker->id, "combFire(%u[%s]->%u): Structure has no direct line of sight to target",
@ -204,7 +211,7 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
else if ( proj_Direct(psStats) )
{
// VTOL or tall building
if (!visibleObject(psAttacker, psTarget, false))
if (!lineOfFire(psAttacker, psTarget, false))
{
// Can't see the target - can't hit it with direct fire
objTrace(psAttacker->id, "combFire(%u[%s]->%u): Tall object has no direct line of sight to target",
@ -212,17 +219,6 @@ void combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
return;
}
}
else
{
// Indirect fire
if (!psTarget->visible[psAttacker->player])
{
// Can't get an indirect LOS - can't hit it with the weapon
objTrace(psAttacker->id, "combFire(%u[%s]->%u): Object has no indirect sight of target",
psAttacker->id, psStats->pName, psTarget->id);
return;
}
}
// if the turret doesn't turn, check if the attacker is in alignment with the target
if (psAttacker->type == OBJ_DROID && !psStats->rotate)

View File

@ -755,3 +755,53 @@ bool scrTileIsVisible(SDWORD player, SDWORD x, SDWORD y)
return scrTileVisible[player][x][y];
}
/* Check whether psViewer can fire directly at psTarget.
* psTarget can be any type of BASE_OBJECT (e.g. a tree).
*/
bool lineOfFire(const BASE_OBJECT* psViewer, const BASE_OBJECT* psTarget, bool wallsBlock)
{
Vector3i pos, dest, diff;
int range, distSq;
ASSERT(psViewer != NULL, "Invalid shooter pointer!");
ASSERT(psTarget != NULL, "Invalid target pointer!");
if (!psViewer || !psTarget)
{
return false;
}
// FIXME HACK Needed since we got those ugly Vector3uw floating around in BASE_OBJECT...
pos = Vector3uw_To3i(psViewer->pos);
dest = Vector3uw_To3i(psTarget->pos);
diff = Vector3i_Sub(dest, pos);
range = objSensorRange(psViewer);
distSq = Vector3i_ScalarP(diff, diff);
if (distSq == 0)
{
// Should never be on top of each other, but ...
return true;
}
// initialise the callback variables
{
VisibleObjectHelp_t help = { true, wallsBlock, distSq, pos.z + visObjHeight(psViewer), { map_coord(dest.x), map_coord(dest.y) }, 0, 0, -UBYTE_MAX * GRAD_MUL * ELEVATION_SCALE, 0, { 0, 0 } };
int targetGrad, top;
// Cast a ray from the viewer to the target
rayCast(pos, diff, range, rayLOSCallback, &help);
if (gWall != NULL && gNumWalls != NULL) // Out globals are set
{
*gWall = help.wall;
*gNumWalls = help.numWalls;
}
// See if the target can be seen
top = dest.z + visObjHeight(psTarget) - help.startHeight;
targetGrad = top * GRAD_MUL / help.lastDist;
return targetGrad >= help.currGrad;
}
}

View File

@ -45,6 +45,9 @@ extern void visTilesUpdate(BASE_OBJECT *psObj, RAY_CALLBACK callback);
*/
extern bool visibleObject(const BASE_OBJECT* psViewer, const BASE_OBJECT* psTarget, bool wallsBlock);
/** Can shooter hit target with direct fire weapon? */
bool lineOfFire(const BASE_OBJECT* psViewer, const BASE_OBJECT* psTarget, bool wallsBlock);
// Find the wall that is blocking LOS to a target (if any)
extern STRUCTURE* visGetBlockingWall(const BASE_OBJECT* psViewer, const BASE_OBJECT* psTarget);