When patrolling, look for targets slightly out of range.

Fixes patrolling VTOLs flying past targets before deciding to shoot.
master
Cyp 2011-02-03 20:35:19 +01:00
parent f1dc0f29e2
commit e69482f473
4 changed files with 39 additions and 32 deletions

View File

@ -74,6 +74,27 @@ PlayerMask alliancebits[MAX_PLAYER_SLOTS];
/// A bitfield for the satellite uplink
PlayerMask satuplinkbits;
static int aiObjRange(DROID *psDroid, int weapon_slot)
{
int32_t longRange;
if (psDroid->droidType == DROID_SENSOR)
{
longRange = psDroid->sensorRange;
}
else if (psDroid->numWeaps == 0 || psDroid->asWeaps[0].nStat == 0)
{
// Can't attack without a weapon
return 0;
}
else
{
WEAPON_STATS *psWStats = psDroid->asWeaps[weapon_slot].nStat + asWeaponStats;
longRange = proj_GetLongRange(psWStats);
}
return longRange;
}
// see if a structure has the range to fire on a target
static bool aiStructHasRange(STRUCTURE *psStruct, BASE_OBJECT *psTarget, int weapon_slot)
{
@ -85,32 +106,15 @@ static bool aiStructHasRange(STRUCTURE *psStruct, BASE_OBJECT *psTarget, int wea
WEAPON_STATS *psWStats = psStruct->asWeaps[weapon_slot].nStat + asWeaponStats;
Vector2i diff = removeZ(psStruct->pos - psTarget->pos);
int longRange = proj_GetLongRange(psWStats);
return diff*diff < longRange*longRange && lineOfFire(psStruct, psTarget, weapon_slot, true);
return objPosDiffSq(psStruct, psTarget) < longRange*longRange && lineOfFire(psStruct, psTarget, weapon_slot, true);
}
static bool aiDroidHasRange(DROID *psDroid, BASE_OBJECT *psTarget, int weapon_slot)
{
int32_t longRange;
int32_t longRange = aiObjRange(psDroid, weapon_slot);
if (psDroid->droidType == DROID_SENSOR)
{
longRange = psDroid->sensorRange;
}
else if (psDroid->numWeaps == 0 || psDroid->asWeaps[0].nStat == 0)
{
// Can't attack without a weapon
return false;
}
else
{
WEAPON_STATS *psWStats = psDroid->asWeaps[weapon_slot].nStat + asWeaponStats;
longRange = proj_GetLongRange(psWStats);
}
Vector2i diff = removeZ(psDroid->pos - psTarget->pos);
return diff*diff < longRange*longRange;
return objPosDiffSq(psDroid, psTarget) < longRange*longRange;
}
static bool aiObjHasRange(BASE_OBJECT *psObj, BASE_OBJECT *psTarget, int weapon_slot)
@ -476,7 +480,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker,
// Find the best nearest target for a droid
// Returns integer representing target priority, -1 if failed
SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin)
SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin, int extraRange)
{
SDWORD bestMod = 0,newMod, failure = -1;
BASE_OBJECT *psTarget = NULL, *friendlyObj, *bestTarget = NULL, *iter, *targetInQuestion, *tempTarget;
@ -517,7 +521,9 @@ SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot
electronic = electronicDroid(psDroid);
// Range was previously 9*TILE_UNITS. Increasing this doesn't seem to help much, though. Not sure why.
gridStartIterate(psDroid->pos.x, psDroid->pos.y, psDroid->sensorRange + 6*TILE_UNITS);
int droidRange = std::min(aiObjRange(psDroid, weapon_slot) + extraRange, psDroid->sensorRange + 6*TILE_UNITS);
gridStartIterate(psDroid->pos.x, psDroid->pos.y, droidRange);
for (iter = gridIterate(); iter != NULL; iter = gridIterate())
{
friendlyObj = NULL;
@ -568,7 +574,7 @@ SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot
&& targetInQuestion->visible[psDroid->player] == UBYTE_MAX
&& !aiCheckAlliances(targetInQuestion->player,psDroid->player)
&& validTarget(psDroid, targetInQuestion, weapon_slot)
&& aiDroidHasRange(psDroid, targetInQuestion, weapon_slot))
&& objPosDiffSq(psDroid, targetInQuestion) < droidRange*droidRange)
{
if (targetInQuestion->type == OBJ_DROID)
{

View File

@ -58,7 +58,7 @@ void aiUpdateDroid(DROID *psDroid);
// Find the nearest best target for a droid
// returns integer representing quality of choice, -1 if failed
SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin);
int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin, int extraRange = 0);
// Are there a lot of bullets heading towards the structure?
BOOL aiObjectIsProbablyDoomed(BASE_OBJECT *psObject);

View File

@ -137,11 +137,14 @@ static inline bool isDead(const BASE_OBJECT* psObj)
static inline int objPosDiffSq(Position pos1, Position pos2)
{
const int xdiff = pos1.x - pos2.x;
const int ydiff = pos1.y - pos2.y;
return (xdiff * xdiff + ydiff * ydiff);
const Vector2i diff = removeZ(pos1 - pos2);
return diff*diff;
}
static inline int objPosDiffSq(SIMPLE_OBJECT const *pos1, SIMPLE_OBJECT const *pos2)
{
return objPosDiffSq(pos1->pos, pos2->pos);
}
// True iff object is a droid, structure or feature (not a projectile). Will incorrectly return true if passed a nonsense object of type OBJ_TARGET or OBJ_NUM_TYPES.
static inline bool isBaseObject(SIMPLE_OBJECT const *psObject) { return psObject->type != OBJ_PROJECTILE; }

View File

@ -509,7 +509,7 @@ void orderUpdateDroid(DROID *psDroid)
{
// true if in condition to set actionDroid to attack/observe
bool attack = secondaryGetState(psDroid, DSO_ATTACK_LEVEL) == DSS_ALEV_ALWAYS &&
aiBestNearestTarget(psDroid, &psObj, 0, NULL) >= 0;
aiBestNearestTarget(psDroid, &psObj, 0, NULL, SCOUT_ATTACK_DIST) >= 0;
switch (psDroid->droidType)
{
case DROID_CONSTRUCT:
@ -595,10 +595,8 @@ void orderUpdateDroid(DROID *psDroid)
(psDroid->action == DACTION_OBSERVE) ||
(psDroid->action == DACTION_MOVETOOBSERVE))
{
// attacking something - see if the droid has gone too far
xdiff = (SDWORD)psDroid->pos.x - (SDWORD)psDroid->actionX;
ydiff = (SDWORD)psDroid->pos.y - (SDWORD)psDroid->actionY;
if (xdiff*xdiff + ydiff*ydiff > SCOUT_ATTACK_DIST*SCOUT_ATTACK_DIST)
// attacking something - see if the droid has gone too far, go up to twice the distance we want to go, so that we don't repeatedly turn back when the target is almost in range.
if (objPosDiffSq(psDroid->pos, Vector3i(psDroid->actionX, psDroid->actionY, 0)) > (SCOUT_ATTACK_DIST*2 * SCOUT_ATTACK_DIST*2))
{
actionDroid(psDroid, DACTION_RETURNTOPOS, psDroid->actionX,psDroid->actionY);
}