When patrolling, look for targets slightly out of range.
Fixes patrolling VTOLs flying past targets before deciding to shoot.master
parent
f1dc0f29e2
commit
e69482f473
52
src/ai.cpp
52
src/ai.cpp
|
@ -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)
|
||||
{
|
||||
|
|
2
src/ai.h
2
src/ai.h
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue