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-861f7616d084master
parent
ee5f151162
commit
2d02726753
24
src/combat.c
24
src/combat.c
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue