pointtree: Remove "naybor" from droids.

git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@9262 4a71c877-e1ca-e34f-864e-861f7616d084
master
Cyp 2010-01-16 22:51:26 +00:00 committed by Git SVN Gateway
parent d6d0070530
commit 78389d6bb2
9 changed files with 85 additions and 218 deletions

View File

@ -247,9 +247,8 @@ BASE_OBJECT *aiSearchSensorTargets(BASE_OBJECT *psObj, int weapon_slot, WEAPON_S
// Returns integer representing target priority, -1 if failed
SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, UWORD *targetOrigin)
{
UDWORD i;
SDWORD bestMod = 0,newMod, failure = -1;
BASE_OBJECT *psTarget = NULL, *friendlyObj, *bestTarget = NULL, *targetInQuestion, *tempTarget;
BASE_OBJECT *psTarget = NULL, *friendlyObj, *bestTarget = NULL, *iter, *targetInQuestion, *tempTarget;
BOOL electronic = false;
STRUCTURE *targetStructure;
WEAPON_EFFECT weaponEffect;
@ -281,15 +280,17 @@ SDWORD aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot
bestTarget = aiSearchSensorTargets((BASE_OBJECT *)psDroid, weapon_slot, psWStats, &tmpOrigin);
bestMod = targetAttackWeight(bestTarget, (BASE_OBJECT *)psDroid, weapon_slot);
}
droidGetNaybors(psDroid);
weaponEffect = ((WEAPON_STATS *)(asWeaponStats + psDroid->asWeaps[weapon_slot].nStat))->weaponEffect;
electronic = electronicDroid(psDroid);
for (i=0; i< numNaybors; i++)
// 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);
for (iter = gridIterate(); iter != NULL; iter = gridIterate())
{
friendlyObj = NULL;
targetInQuestion = asDroidNaybors[i].psObj;
targetInQuestion = iter;
/* This is a friendly unit, check if we can reuse its target */
if(aiCheckAlliances(targetInQuestion->player,psDroid->player))
@ -862,7 +863,7 @@ BOOL aiChooseTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget, int weapon_slot
{
BASE_OBJECT *psCurr;
gridStartIterate((SDWORD)psObj->pos.x, (SDWORD)psObj->pos.y);
gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS);
psCurr = gridIterate();
while (psCurr != NULL)
{
@ -922,7 +923,7 @@ BOOL aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget)
BASE_OBJECT *psCurr, *psTemp = NULL;
int tarDist = SDWORD_MAX;
gridStartIterate((SDWORD)psObj->pos.x, (SDWORD)psObj->pos.y);
gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS);
psCurr = gridIterate();
while (psCurr != NULL)
{
@ -984,7 +985,7 @@ BOOL aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget)
BASE_OBJECT *psCurr, *psTemp = NULL;
int tarDist = SDWORD_MAX;
gridStartIterate((SDWORD)psObj->pos.x, (SDWORD)psObj->pos.y);
gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS);
psCurr = gridIterate();
while (psCurr != NULL)
{

View File

@ -445,7 +445,7 @@ void counterBatteryFire(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget)
CHECK_OBJECT(psTarget);
gridStartIterate((SDWORD)psTarget->pos.x, (SDWORD)psTarget->pos.y);
gridStartIterate(psTarget->pos.x, psTarget->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS);
for (psViewer = gridIterate(); psViewer != NULL; psViewer = gridIterate())
{
STRUCTURE *psStruct;

View File

@ -103,14 +103,9 @@ UDWORD selectedCommander = UBYTE_MAX;
/** Height the transporter hovers at above the terrain. */
#define TRANSPORTER_HOVER_HEIGHT 10
/** How far round a repair droid looks for a damaged droid. */
#define REPAIR_DIST (TILE_UNITS * 4)//8)
/* Store for the objects near the droid currently being updated
/* Sorry, Keith.
* NAYBOR = neighbour - thanks to Keith for a great abreviation
*/
NAYBOR_INFO asDroidNaybors[MAX_NAYBORS];
UDWORD numNaybors=0;
// the structure that was last hit
DROID *psLastDroidHit;
@ -677,109 +672,6 @@ void droidBurn(DROID *psDroid)
orderDroid( psDroid, DORDER_RUNBURN );
}
/* Add a new object to the naybor list */
static void addNaybor(BASE_OBJECT *psObj, UDWORD distSqr)
{
UDWORD pos;
if (numNaybors == 0)
{
// No objects in the list
asDroidNaybors[0].psObj = psObj;
asDroidNaybors[0].distSqr = distSqr;
numNaybors++;
}
else if (distSqr >= asDroidNaybors[numNaybors-1].distSqr)
{
// Simple case - this is the most distant object
asDroidNaybors[numNaybors].psObj = psObj;
asDroidNaybors[numNaybors].distSqr = distSqr;
numNaybors++;
}
else
{
// Move all the objects further away up the list
for (pos = numNaybors; pos && asDroidNaybors[pos - 1].distSqr > distSqr; pos--)
{
memcpy(asDroidNaybors + pos, asDroidNaybors + (pos - 1), sizeof(NAYBOR_INFO));
}
// Insert the object at the correct position
asDroidNaybors[pos].psObj = psObj;
asDroidNaybors[pos].distSqr = distSqr;
numNaybors++;
}
}
static DROID *CurrentNaybors = NULL;
static UDWORD nayborTime = 0;
/* Find all the objects close to the droid */
void droidGetNaybors(DROID *psDroid)
{
SDWORD xdiff, ydiff;
UDWORD dx,dy, distSqr;
BASE_OBJECT *psObj;
CHECK_DROID(psDroid);
// Ensure only called max of once per droid per game cycle.
if (CurrentNaybors == psDroid && nayborTime == gameTime)
{
return;
}
CurrentNaybors = psDroid;
nayborTime = gameTime;
// reset the naybor array
numNaybors = 0;
// search for naybor objects
dx = psDroid->pos.x;
dy = psDroid->pos.y;
gridStartIterate((SDWORD)dx, (SDWORD)dy);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
if (psObj != (BASE_OBJECT *)psDroid && !psObj->died)
{
xdiff = dx - (SDWORD)psObj->pos.x;
if (xdiff < 0)
{
xdiff = -xdiff;
}
if (xdiff > NAYBOR_RANGE)
{
continue;
}
ydiff = dy - (SDWORD)psObj->pos.y;
if (ydiff < 0)
{
ydiff = -ydiff;
}
if (ydiff > NAYBOR_RANGE)
{
continue;
}
distSqr = xdiff*xdiff + ydiff*ydiff;
if (distSqr > NAYBOR_RANGE*NAYBOR_RANGE)
{
continue;
}
addNaybor(psObj, distSqr);
if (numNaybors >= MAX_NAYBORS)
{
break;
}
}
}
}
/* The main update routine for all droids */
void droidUpdate(DROID *psDroid)
{

View File

@ -89,11 +89,6 @@ typedef enum
HALF_FREE_TILE
} PICKTILE;
/* Store for the objects near the droid currently being updated */
#define MAX_NAYBORS 120
extern NAYBOR_INFO asDroidNaybors[MAX_NAYBORS];
extern UDWORD numNaybors;
// the structure that was last hit
extern DROID *psLastDroidHit;
@ -105,10 +100,6 @@ extern BOOL droidInit(void);
extern void removeDroidBase(DROID *psDel);
// refresh the naybor list
// this only does anything if the naybor list is out of date
extern void droidGetNaybors(DROID *psDroid);
extern BOOL loadDroidTemplates(const char *pDroidData, UDWORD bufferSize);
extern BOOL loadDroidWeapons(const char *pWeaponData, UDWORD bufferSize);

View File

@ -102,19 +102,32 @@ void gridRemoveObject(BASE_OBJECT *psObj)
//gridCalcCoverage(psObj, (SDWORD)psObj->pos.x, (SDWORD)psObj->pos.y, GRID_REMOVEOBJECT);
}
static bool isInRadius(int32_t x, int32_t y, uint32_t radius)
{
return x*x + y*y <= radius*radius;
}
// initialise the grid system to start iterating through units that
// could affect a location (x,y in world coords)
void gridStartIterate(SDWORD x, SDWORD y/*, uint32_t radius*/)
void gridStartIterate(int32_t x, int32_t y, uint32_t radius)
{
uint32_t radius = 20*TILE_UNITS;
gridIterator = pointTreeQuery(gridPointTree, x, y, radius); // Use the C interface, for NULL termination.
gridPointTree->query(x, y, radius);
PointTree::ResultVector::iterator w = gridPointTree->lastQueryResults.begin(), i;
for (i = gridPointTree->lastQueryResults.begin(); i != gridPointTree->lastQueryResults.end(); ++i)
{
BASE_OBJECT *obj = static_cast<BASE_OBJECT *>(*i);
if (isInRadius(obj->pos.x - x, obj->pos.y - y, radius)) // Check that search result is less than radius (since they can be up to a factor of sqrt(2) more).
{
*w = *i;
++w;
}
}
gridPointTree->lastQueryResults.erase(w, i); // Erase all points that were a bit too far.
gridPointTree->lastQueryResults.push_back(NULL); // NULL-terminate the result.
gridIterator = &gridPointTree->lastQueryResults[0];
/*
// In case you are curious.
int len = 0;
for(void **x = gridIterator; *x != NULL; ++x)
++len;
debug(LOG_WARNING, "gridStartIterate found %d objects", len);
debug(LOG_WARNING, "gridStartIterate(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
*/
}

View File

@ -58,8 +58,9 @@ extern void gridGarbageCollect(void);
// TODO This function doesn't do anything, should probably be deleted.
extern void gridDisplayCoverage(BASE_OBJECT *psObj);
/// Find all objects within radius r = 20*TILE_UNITS. Call gridIterate() to get the search results.
extern void gridStartIterate(int32_t x, int32_t y/*, uint32_t radius*/);
#define PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS (20*TILE_UNITS)
/// Find all objects within radius. Call gridIterate() to get the search results.
extern void gridStartIterate(int32_t x, int32_t y, uint32_t radius);
/// Get the next search result from gridStartIterate, or NULL if finished.
static inline BASE_OBJECT *gridIterate(void)

View File

@ -903,51 +903,41 @@ static SDWORD moveObjRadius(const BASE_OBJECT* psObj)
// see if a Droid has run over a person
static void moveCheckSquished(DROID *psDroid, float mx,float my)
{
SDWORD i, droidR, rad, radSq;
SDWORD droidR, rad, radSq;
SDWORD objR;
SDWORD xdiff,ydiff, distSq;
NAYBOR_INFO *psInfo;
SDWORD xdiff, ydiff, distSq;
BASE_OBJECT *psObj;
droidR = moveObjRadius((BASE_OBJECT *)psDroid);
for(i=0; i<(SDWORD)numNaybors; i++)
gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
psInfo = asDroidNaybors + i;
if (psInfo->psObj->type != OBJ_DROID ||
((DROID *)psInfo->psObj)->droidType != DROID_PERSON)
if (psObj->type != OBJ_DROID || ((DROID *)psObj)->droidType != DROID_PERSON)
{
// ignore everything but people
continue;
}
ASSERT( psInfo->psObj->type == OBJ_DROID &&
((DROID *)psInfo->psObj)->droidType == DROID_PERSON,
"squished - eerk" );
ASSERT(psObj->type == OBJ_DROID && ((DROID *)psObj)->droidType == DROID_PERSON, "squished - eerk");
objR = moveObjRadius(psInfo->psObj);
objR = moveObjRadius(psObj);
rad = droidR + objR;
radSq = rad*rad;
xdiff = (SDWORD)psDroid->pos.x + mx - psInfo->psObj->pos.x;
ydiff = (SDWORD)psDroid->pos.y + my - psInfo->psObj->pos.y;
xdiff = psDroid->pos.x + mx - psObj->pos.x;
ydiff = psDroid->pos.y + my - psObj->pos.y;
distSq = xdiff*xdiff + ydiff*ydiff;
if (((2*radSq)/3) > distSq)
{
if ( (psDroid->player != psInfo->psObj->player) &&
!aiCheckAlliances(psDroid->player, psInfo->psObj->player) )
if ((psDroid->player != psObj->player) && !aiCheckAlliances(psDroid->player, psObj->player))
{
// run over a bloke - kill him
destroyDroid((DROID*)psInfo->psObj);
destroyDroid((DROID *)psObj);
scoreUpdateVar(WD_BARBARIANS_MOWED_DOWN);
continue;
}
}
else if (psInfo->distSqr > OBJ_MAXRADIUS*OBJ_MAXRADIUS)
{
// object is too far away to be hit
break;
}
}
}
@ -1351,11 +1341,10 @@ static void moveCalcBlockingSlide(DROID *psDroid, float *pmx, float *pmy, SDWORD
// Only consider stationery droids
static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
{
SDWORD i, droidR, rad, radSq;
SDWORD droidR, rad, radSq;
SDWORD objR;
SDWORD xdiff,ydiff, distSq;
NAYBOR_INFO *psInfo;
BASE_OBJECT *psObst;
SDWORD xdiff, ydiff, distSq;
BASE_OBJECT *psObj, *psObst;
BOOL bLegs;
CHECK_DROID(psDroid);
@ -1368,26 +1357,24 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
droidR = moveObjRadius((BASE_OBJECT *)psDroid);
psObst = NULL;
for(i=0; i<(SDWORD)numNaybors; i++)
gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
psInfo = asDroidNaybors + i;
if (psInfo->psObj->type == OBJ_DROID)
if (psObj->type == OBJ_DROID)
{
if ( ((DROID *)psInfo->psObj)->droidType == DROID_TRANSPORTER )
if (((DROID *)psObj)->droidType == DROID_TRANSPORTER)
{
// ignore transporters
continue;
}
if (bLegs
&& ((DROID *)psInfo->psObj)->droidType != DROID_PERSON
&& !cyborgDroid((DROID *)psInfo->psObj))
if (bLegs && ((DROID *)psObj)->droidType != DROID_PERSON
&& !cyborgDroid((DROID *)psObj))
{
// cyborgs/people only avoid other cyborgs/people
continue;
}
if (!bLegs &&
(((DROID *)psInfo->psObj)->droidType == DROID_PERSON))
if (!bLegs && ((DROID *)psObj)->droidType == DROID_PERSON)
{
// everything else doesn't avoid people
continue;
@ -1399,12 +1386,12 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
continue;
}
objR = moveObjRadius(psInfo->psObj);
objR = moveObjRadius(psObj);
rad = droidR + objR;
radSq = rad*rad;
xdiff = psDroid->sMove.fx + *pmx - psInfo->psObj->pos.x;
ydiff = psDroid->sMove.fy + *pmy - psInfo->psObj->pos.y;
xdiff = psDroid->sMove.fx + *pmx - psObj->pos.x;
ydiff = psDroid->sMove.fy + *pmy - psObj->pos.y;
distSq = xdiff * xdiff + ydiff * ydiff;
if ((float)xdiff * *pmx + (float)ydiff * *pmy >= 0)
{
@ -1414,7 +1401,7 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
if (radSq > distSq)
{
if (psObst != NULL || !aiCheckAlliances(psInfo->psObj->player, psDroid->player))
if (psObst != NULL || !aiCheckAlliances(psObj->player, psDroid->player))
{
// hit more than one droid - stop
*pmx = (float)0;
@ -1424,7 +1411,7 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
}
else
{
psObst = psInfo->psObj;
psObst = psObj;
// note the bump time and position if necessary
if (psDroid->sMove.bumpTime == 0)
@ -1466,11 +1453,6 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
}
}
}
else if (psInfo->distSqr > OBJ_MAXRADIUS*OBJ_MAXRADIUS)
{
// object is too far away to be hit
break;
}
}
if (psObst != NULL)
@ -1484,7 +1466,7 @@ static void moveCalcDroidSlide(DROID *psDroid, float *pmx, float *pmy)
// get an obstacle avoidance vector
static void moveGetObstacleVector(DROID *psDroid, float *pX, float *pY)
{
SDWORD i, xdiff, ydiff, absx, absy, dist;
SDWORD xdiff, ydiff, absx, absy, dist;
BASE_OBJECT *psObj;
SDWORD numObst = 0, distTot = 0;
float dirX = 0, dirY = 0;
@ -1495,16 +1477,13 @@ static void moveGetObstacleVector(DROID *psDroid, float *pX, float *pY)
ASSERT(psPropStats, "invalid propulsion stats pointer");
droidGetNaybors(psDroid);
// scan the neighbours for obstacles
for(i = 0; i < (SDWORD)numNaybors; i++)
gridStartIterate(psDroid->pos.x, psDroid->pos.y, AVOID_DIST);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
psObj = asDroidNaybors[i].psObj;
if (psObj->type != OBJ_DROID ||
asDroidNaybors[i].distSqr >= AVOID_DIST*AVOID_DIST)
if (psObj->type != OBJ_DROID)
{
// object too far away to worry about
// Object wrong type to worry about.
continue;
}
@ -2220,8 +2199,7 @@ static void moveUpdateGroundModel(DROID *psDroid, SDWORD speed, SDWORD direction
return;
}
// update the naybors list
droidGetNaybors(psDroid);
// Used to update some kind of weird neighbour list here.
moveCheckFinalWaypoint( psDroid, &speed );
@ -2300,8 +2278,7 @@ static void moveUpdatePersonModel(DROID *psDroid, SDWORD speed, SDWORD direction
return;
}
// update the naybors list
droidGetNaybors(psDroid);
// Used to update some kind of weird neighbour list here.
moveUpdateDroidDirection( psDroid, &speed, direction, PERSON_SPIN_ANGLE,
PERSON_SPIN_SPEED, PERSON_TURN_SPEED, &iDroidDir, &fSpeed );
@ -2425,8 +2402,7 @@ static void moveUpdateVtolModel(DROID *psDroid, SDWORD speed, SDWORD direction)
return;
}
// update the naybors list
droidGetNaybors(psDroid);
// Used to update some kind of weird neighbour list here.
moveCheckFinalWaypoint( psDroid, &speed );
@ -2534,8 +2510,7 @@ static void moveUpdateJumpCyborgModel(DROID *psDroid, SDWORD speed, SDWORD direc
return;
}
// update the naybors list
droidGetNaybors(psDroid);
// Used to update some kind of weird neighbour list here.
moveUpdateDroidDirection( psDroid, &speed, direction, VTOL_SPIN_ANGLE,
psDroid->baseSpeed, psDroid->baseSpeed/3, &iDroidDir, &fSpeed );
@ -2874,7 +2849,6 @@ static void movePlayAudio( DROID *psDroid, BOOL bStarted, BOOL bStoppedBefore, S
// use to pick up oil, etc..
static void checkLocalFeatures(DROID *psDroid)
{
SDWORD i;
BASE_OBJECT *psObj;
static int oilTimer = 0;
static bool GenerateDrum = false;
@ -2882,24 +2856,19 @@ static void checkLocalFeatures(DROID *psDroid)
// NOTE: Why not do this for AI units also?
// only do for players droids.
if (psDroid->player != selectedPlayer)
if (psDroid->player != selectedPlayer || isVtolDroid(psDroid)) // VTOLs can't pick up features!
{
return;
}
droidGetNaybors(psDroid);// update naybor list.
ASSERT( numNaybors <= MAX_NAYBORS, "numNaybors is %d, out of range of %d!", numNaybors, MAX_NAYBORS);
// scan the neighbours
for(i=0; i<(SDWORD)numNaybors; i++)
#define DROIDDIST ((TILE_UNITS*5)/2)
gridStartIterate(psDroid->pos.x, psDroid->pos.y, DROIDDIST);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
#define DROIDDIST (((TILE_UNITS*5)/2) * ((TILE_UNITS*5)/2))
psObj = asDroidNaybors[i].psObj;
if ( psObj->type != OBJ_FEATURE
|| ((FEATURE *)psObj)->psStats->subType != FEAT_OIL_DRUM
|| asDroidNaybors[i].distSqr >= DROIDDIST
|| isVtolDroid(psDroid)) // VTOLs can't pick up features!
if (psObj->type != OBJ_FEATURE || ((FEATURE *)psObj)->psStats->subType != FEAT_OIL_DRUM || psObj->died)
{
// object too far away to worry about
// Object is not a living oil drum.
continue;
}

View File

@ -75,6 +75,7 @@ typedef struct _interval
// used to create a specific ID for projectile objects to facilitate tracking them.
static const UDWORD ProjectileTrackerID = 0xdead0000;
// Watermelon:neighbour global info ripped from droid.c
#define MAX_NAYBORS 120
static PROJ_NAYBOR_INFO asProjNaybors[MAX_NAYBORS];
static UDWORD numProjNaybors = 0;
@ -1933,7 +1934,7 @@ static void projGetNaybors(PROJECTILE *psObj)
// reset the naybor array
numProjNaybors = 0;
gridStartIterate(psObj->pos.x, psObj->pos.y);
gridStartIterate(psObj->pos.x, psObj->pos.y, PROJ_NAYBOR_RANGE);
while ((psTempObj = gridIterate()) != NULL)
{
if (psTempObj != (BASE_OBJECT *)psObj && !psTempObj->died)

View File

@ -564,9 +564,6 @@ void processVisibility(BASE_OBJECT *psObj)
memcpy(currVis, prevVis, sizeof(*prevVis) * MAX_PLAYERS);
}
// get all the objects from the grid the droid is in
gridStartIterate(psObj->pos.x, psObj->pos.y);
// Make sure allies can see us
if (bMultiPlayer && game.alliance == ALLIANCES_TEAMS)
{
@ -604,6 +601,8 @@ void processVisibility(BASE_OBJECT *psObj)
}
else
{
// get all the objects from the grid the droid is in
gridStartIterate(psObj->pos.x, psObj->pos.y, PREVIOUS_DEFAULT_GRID_SEARCH_RADIUS);
while (psViewer = gridIterate(), psViewer != NULL)
{
int val;