Merge branch 'bugfixes'

Conflicts:
	src/ai.cpp
	src/combat.cpp
	src/mapgrid.cpp
	src/mapgrid.h
	src/projectile.cpp
	src/qtscriptfuncs.cpp
master
Cyp 2013-02-10 13:46:55 +01:00
commit c1cb8e4343
11 changed files with 114 additions and 111 deletions

View File

@ -619,11 +619,11 @@ static bool actionRemoveDroidsFromBuildPos(unsigned player, Vector2i pos, uint16
Vector2i structureCentre = world_coord(b.map) + world_coord(b.size)/2;
unsigned structureMaxRadius = iHypot(world_coord(b.size)/2) + 1; // +1 since iHypot rounds down.
gridStartIterate(structureCentre.x, structureCentre.y, structureMaxRadius);
BASE_OBJECT *psObj;
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(structureCentre.x, structureCentre.y, structureMaxRadius);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
DROID *droid = castDroid(psObj);
DROID *droid = castDroid(*gi);
if (droid == NULL)
{
continue; // Only looking for droids.

View File

@ -518,7 +518,7 @@ static SDWORD targetAttackWeight(BASE_OBJECT *psTarget, BASE_OBJECT *psAttacker,
int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, int extraRange)
{
SDWORD bestMod = 0,newMod, failure = -1;
BASE_OBJECT *psTarget = NULL, *friendlyObj, *bestTarget = NULL, *iter, *targetInQuestion, *tempTarget;
BASE_OBJECT *psTarget = NULL, *bestTarget = NULL, *tempTarget;
bool electronic = false;
STRUCTURE *targetStructure;
WEAPON_EFFECT weaponEffect;
@ -552,11 +552,12 @@ int aiBestNearestTarget(DROID *psDroid, BASE_OBJECT **ppsObj, int weapon_slot, i
// Range was previously 9*TILE_UNITS. Increasing this doesn't seem to help much, though. Not sure why.
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())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, droidRange);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
friendlyObj = NULL;
targetInQuestion = iter;
BASE_OBJECT *friendlyObj = NULL;
BASE_OBJECT *targetInQuestion = *gi;
/* This is a friendly unit, check if we can reuse its target */
if(aiCheckAlliances(targetInQuestion->player,psDroid->player))
@ -892,9 +893,11 @@ bool aiChooseTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget, int weapon_slot
srange = objSensorRange(psObj);
}
gridStartIterate(psObj->pos.x, psObj->pos.y, srange);
for (BASE_OBJECT *psCurr = gridIterate(); psCurr != NULL; psCurr = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psObj->pos.x, psObj->pos.y, srange);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psCurr = *gi;
/* Check that it is a valid target */
if (psCurr->type != OBJ_FEATURE && !psCurr->died
&& !aiCheckAlliances(psCurr->player, psObj->player)
@ -970,13 +973,14 @@ bool aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget)
}
else // structure
{
BASE_OBJECT *psCurr, *psTemp = NULL;
BASE_OBJECT * psTemp = NULL;
int tarDist = SDWORD_MAX;
gridStartIterate(psObj->pos.x, psObj->pos.y, objSensorRange(psObj));
psCurr = gridIterate();
while (psCurr != NULL)
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psObj->pos.x, psObj->pos.y, objSensorRange(psObj));
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psCurr = *gi;
// Don't target features or doomed/dead objects
if (psCurr->type != OBJ_FEATURE && !psCurr->died)
{
@ -994,7 +998,6 @@ bool aiChooseSensorTarget(BASE_OBJECT *psObj, BASE_OBJECT **ppsTarget)
}
}
}
psCurr = gridIterate();
}
if (psTemp)

View File

@ -304,8 +304,6 @@ bool combFire(WEAPON *psWeap, BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget, in
if any support a counter battery sensor*/
void counterBatteryFire(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget)
{
BASE_OBJECT *psViewer;
/*if a null target is passed in ignore - this will be the case when a 'miss'
projectile is sent - we may have to cater for these at some point*/
// also ignore cases where you attack your own player
@ -319,7 +317,7 @@ void counterBatteryFire(BASE_OBJECT *psAttacker, BASE_OBJECT *psTarget)
CHECK_OBJECT(psTarget);
for (psViewer = apsSensorList[0]; psViewer; psViewer = psViewer->psNextFunc)
for (BASE_OBJECT *psViewer = apsSensorList[0]; psViewer; psViewer = psViewer->psNextFunc)
{
if (aiCheckAlliances(psTarget->player, psViewer->player))
{

View File

@ -31,12 +31,10 @@
#include "mapgrid.h"
#include "pointtree.h"
// the current state of the iterator
void **gridIterator;
PointTree *gridPointTree = NULL; // A quad-tree-like object.
PointTree::Filter *gridFiltersUnseen;
PointTree::Filter *gridFiltersDroidsByPlayer;
static PointTree *gridPointTree = NULL; // A quad-tree-like object.
static PointTree::Filter *gridFiltersUnseen;
static PointTree::Filter *gridFiltersDroidsByPlayer;
// initialise the grid system
bool gridInitialise(void)
@ -102,7 +100,7 @@ static bool isInRadius(int32_t x, int32_t y, uint32_t radius)
// initialise the grid system to start iterating through units that
// could affect a location (x,y in world coords)
template<class Condition>
static void gridStartIterateFiltered(int32_t x, int32_t y, uint32_t radius, PointTree::Filter *filter, Condition const &condition)
static GridList const &gridStartIterateFiltered(int32_t x, int32_t y, uint32_t radius, PointTree::Filter *filter, Condition const &condition)
{
if (filter == NULL)
{
@ -127,20 +125,31 @@ static void gridStartIterateFiltered(int32_t x, int32_t y, uint32_t radius, Poin
}
}
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.
debug(LOG_WARNING, "gridStartIterateFiltered(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size() - 1);
debug(LOG_WARNING, "gridStartIterateFiltered(%d, %d, %u) found %u objects", x, y, radius, (unsigned)gridPointTree->lastQueryResults.size());
*/
static GridList gridList;
gridList.resize(gridPointTree->lastQueryResults.size());
for (unsigned n = 0; n < gridList.size(); ++n)
{
gridList[n] = (BASE_OBJECT *)gridPointTree->lastQueryResults[n];
}
return gridList;
}
template<class Condition>
static void gridStartIterateFilteredArea(int32_t x, int32_t y, int32_t x2, int32_t y2, Condition const &condition)
static GridList const &gridStartIterateFilteredArea(int32_t x, int32_t y, int32_t x2, int32_t y2, Condition const &condition)
{
gridPointTree->query(x, y, x2, y2);
gridPointTree->lastQueryResults.push_back(NULL); // NULL-terminate the result.
gridIterator = &gridPointTree->lastQueryResults[0];
static GridList gridList;
gridList.resize(gridPointTree->lastQueryResults.size());
for (unsigned n = 0; n < gridList.size(); ++n)
{
gridList[n] = (BASE_OBJECT *)gridPointTree->lastQueryResults[n];
}
return gridList;
}
struct ConditionTrue
@ -151,14 +160,14 @@ struct ConditionTrue
}
};
void gridStartIterate(int32_t x, int32_t y, uint32_t radius)
GridList const &gridStartIterate(int32_t x, int32_t y, uint32_t radius)
{
gridStartIterateFiltered(x, y, radius, NULL, ConditionTrue());
return gridStartIterateFiltered(x, y, radius, NULL, ConditionTrue());
}
void gridStartIterateArea(int32_t x, int32_t y, uint32_t x2, uint32_t y2)
GridList const &gridStartIterateArea(int32_t x, int32_t y, uint32_t x2, uint32_t y2)
{
gridStartIterateFilteredArea(x, y, x2, y2, ConditionTrue());
return gridStartIterateFilteredArea(x, y, x2, y2, ConditionTrue());
}
struct ConditionDroidsByPlayer
@ -171,9 +180,9 @@ struct ConditionDroidsByPlayer
int player;
};
void gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player)
GridList const &gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player)
{
gridStartIterateFiltered(x, y, radius, &gridFiltersDroidsByPlayer[player], ConditionDroidsByPlayer(player));
return gridStartIterateFiltered(x, y, radius, &gridFiltersDroidsByPlayer[player], ConditionDroidsByPlayer(player));
}
struct ConditionUnseen
@ -186,9 +195,9 @@ struct ConditionUnseen
int player;
};
void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player)
GridList const &gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player)
{
gridStartIterateFiltered(x, y, radius, &gridFiltersUnseen[player], ConditionUnseen(player));
return gridStartIterateFiltered(x, y, radius, &gridFiltersUnseen[player], ConditionUnseen(player));
}
BASE_OBJECT **gridIterateDup(void)

View File

@ -24,7 +24,9 @@
#ifndef __INCLUDED_SRC_MAPGRID_H__
#define __INCLUDED_SRC_MAPGRID_H__
extern void **gridIterator; ///< The iterator.
typedef std::vector<BASE_OBJECT *> GridList;
typedef GridList::const_iterator GridIterator;
// initialise the grid system
@ -37,43 +39,18 @@ extern void gridShutDown(void);
// Resets seenThisTick[] to false.
extern void gridReset(void);
/// Find all objects within radius. Call gridIterate() to get the search results.
extern void gridStartIterate(int32_t x, int32_t y, uint32_t radius);
/// Find all objects within radius.
GridList const &gridStartIterate(int32_t x, int32_t y, uint32_t radius);
/// Find all objects within radius. Call gridIterate() to get the search results.
extern void gridStartIterateArea(int32_t x, int32_t y, uint32_t x2, uint32_t y2);
/// Find all objects within radius.
GridList const &gridStartIterateArea(int32_t x, int32_t y, uint32_t x2, uint32_t y2);
// Isn't, but could be used by some cluster system. Don't really understand what cluster.c is for.
/// Find all objects within radius where object->type == OBJ_DROID && object->player == player. Call gridIterate() to get the search results.
extern void gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player);
/// Find all objects within radius where object->type == OBJ_DROID && object->player == player.
GridList const &gridStartIterateDroidsByPlayer(int32_t x, int32_t y, uint32_t radius, int player);
// Used for visibility.
/// Find all objects within radius where object->seenThisTick[player] != 255. Call gridIterate() to get the search results.
extern void gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player);
/// Get the next search result from gridStartIterate, or NULL if finished.
static inline BASE_OBJECT *gridIterate()
{
BASE_OBJECT *ret = (BASE_OBJECT *)*gridIterator++;
if (ret == NULL)
{
gridIterator = NULL; // Detect (by crashing in a reproducible way) if calling gridIterate() again before gridStartIterate().
}
return ret;
}
/// Saves the list returned by gridIterate(), so that future gridStartIterate() calls will not overwrite the list.
static inline void gridGetIterateList(std::vector<BASE_OBJECT *> *list)
{
list->clear();
for (BASE_OBJECT *psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
{
list->push_back(psObj);
}
}
// Isn't, but could be used by some weird recursive calls in cluster.c.
/// Make a copy of the list. Free with free().
BASE_OBJECT **gridIterateDup(void);
/// Find all objects within radius where object->seenThisTick[player] != 255.
GridList const &gridStartIterateUnseen(int32_t x, int32_t y, uint32_t radius, int player);
#endif // __INCLUDED_SRC_MAPGRID_H__

View File

@ -300,10 +300,11 @@ static void moveShuffleDroid(DROID *psDroid, Vector2i s)
}
// find any droids that could block the shuffle
gridStartIterate(psDroid->pos.x, psDroid->pos.y, SHUFFLE_DIST);
for (BASE_OBJECT *psCurr_ = gridIterate(); psCurr_ != NULL; psCurr_ = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, SHUFFLE_DIST);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
DROID *psCurr = castDroid(psCurr_);
DROID *psCurr = castDroid(*gi);
if (psCurr == NULL || psCurr->died || psCurr == psDroid)
{
continue;
@ -615,14 +616,15 @@ static SDWORD moveObjRadius(const BASE_OBJECT* psObj)
static void moveCheckSquished(DROID *psDroid, int32_t emx, int32_t emy)
{
int32_t rad, radSq, objR, xdiff, ydiff, distSq;
BASE_OBJECT *psObj;
const int32_t droidR = moveObjRadius((BASE_OBJECT *)psDroid);
const int32_t mx = gameTimeAdjustedAverage(emx, EXTRA_PRECISION);
const int32_t my = gameTimeAdjustedAverage(emy, EXTRA_PRECISION);
gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
for (psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
if (psObj->type != OBJ_DROID || ((DROID *)psObj)->droidType != DROID_PERSON)
{
// ignore everything but people
@ -1062,10 +1064,9 @@ static void moveCalcDroidSlide(DROID *psDroid, int *pmx, int *pmy)
droidR = moveObjRadius((BASE_OBJECT *)psDroid);
BASE_OBJECT *psObst = NULL;
gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
static std::vector<BASE_OBJECT *> list; // static to avoid allocations.
gridGetIterateList(&list);
for (std::vector<BASE_OBJECT *>::const_iterator gi = list.begin(); gi != list.end(); ++gi)
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, OBJ_MAXRADIUS);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
if (psObj->died)
@ -1180,15 +1181,16 @@ static Vector2i moveGetObstacleVector(DROID *psDroid, Vector2i dest)
}
// scan the neighbours for obstacles
gridStartIterate(psDroid->pos.x, psDroid->pos.y, AVOID_DIST);
for (BASE_OBJECT *psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, AVOID_DIST);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
if (psObj == psDroid)
if (*gi == psDroid)
{
continue; // Don't try to avoid ourselves.
}
DROID *psObstacle = castDroid(psObj);
DROID *psObstacle = castDroid(*gi);
if (psObstacle == NULL)
{
// Object wrong type to worry about.
@ -2247,9 +2249,11 @@ static void checkLocalFeatures(DROID *psDroid)
// scan the neighbours
#define DROIDDIST ((TILE_UNITS*5)/2)
gridStartIterate(psDroid->pos.x, psDroid->pos.y, DROIDDIST);
for (BASE_OBJECT *psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psDroid->pos.x, psDroid->pos.y, DROIDDIST);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
bool pickedUp = false;
if (psObj->type == OBJ_FEATURE && !psObj->died)

View File

@ -842,9 +842,11 @@ static void proj_InFlightFunc(PROJECTILE *psProj)
closestCollisionSpacetime.time = 0xFFFFFFFF;
/* Check nearby objects for possible collisions */
gridStartIterate(psProj->pos.x, psProj->pos.y, PROJ_NEIGHBOUR_RANGE);
for (BASE_OBJECT *psTempObj = gridIterate(); psTempObj != NULL; psTempObj = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psProj->pos.x, psProj->pos.y, PROJ_NEIGHBOUR_RANGE);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psTempObj = *gi;
CHECK_OBJECT(psTempObj);
if (std::find(psProj->psDamaged.begin(), psProj->psDamaged.end(), psTempObj) != psProj->psDamaged.end())
@ -1214,9 +1216,11 @@ static void proj_ImpactFunc( PROJECTILE *psObj )
/* Note when it exploded for the explosion effect */
psObj->born = gameTime;
gridStartIterate(psObj->pos.x, psObj->pos.y, psStats->radius);
for (BASE_OBJECT *psCurr = gridIterate(); psCurr != NULL; psCurr = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psObj->pos.x, psObj->pos.y, psStats->radius);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psCurr = *gi;
if (psCurr->died)
{
continue; // Do not damage dead objects further.
@ -1398,9 +1402,11 @@ static void proj_checkPeriodicalDamage(PROJECTILE *psProj)
WEAPON_STATS *psStats = psProj->psWStats;
gridStartIterate(psProj->pos.x, psProj->pos.y, psStats->periodicalDamageRadius);
for (BASE_OBJECT *psCurr = gridIterate(); psCurr != NULL; psCurr = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psProj->pos.x, psProj->pos.y, psStats->periodicalDamageRadius);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psCurr = *gi;
if (psCurr->died)
{
continue; // Do not damage dead objects further.

View File

@ -346,7 +346,7 @@ QScriptValue convStructure(STRUCTURE *psStruct, QScriptEngine *engine)
value.setProperty("isRadarDetector", objRadarDetector(psStruct), QScriptValue::ReadOnly);
value.setProperty("range", range, QScriptValue::ReadOnly);
value.setProperty("status", (int)psStruct->status, QScriptValue::ReadOnly);
value.setProperty("health", 100 * structureBody(psStruct) / MAX(1, psStruct->body), QScriptValue::ReadOnly);
value.setProperty("health", 100 * psStruct->body / MAX(1, structureBody(psStruct)), QScriptValue::ReadOnly);
value.setProperty("cost", psStruct->pStructureType->powerToBuild, QScriptValue::ReadOnly);
switch (psStruct->pStructureType->type) // don't bleed our source insanities into the scripting world
{
@ -3241,10 +3241,12 @@ static QScriptValue js_enumRange(QScriptContext *context, QScriptEngine *engine)
{
seen = context->argument(4).toBool();
}
gridStartIterate(x, y, range);
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(x, y, range);
QList<BASE_OBJECT *> list;
for (BASE_OBJECT *psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
if ((psObj->visible[player] || !seen) && !psObj->died)
{
if ((filter >= 0 && psObj->player == filter) || filter == ALL_PLAYERS
@ -3304,10 +3306,12 @@ static QScriptValue js_enumArea(QScriptContext *context, QScriptEngine *engine)
{
seen = context->argument(nextparam - 1).toBool();
}
gridStartIterateArea(x1, y1, x2, y2);
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterateArea(x1, y1, x2, y2);
QList<BASE_OBJECT *> list;
for (BASE_OBJECT *psObj = gridIterate(); psObj != NULL; psObj = gridIterate())
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
if ((psObj->visible[player] || !seen) && !psObj->died)
{
if ((filter >= 0 && psObj->player == filter) || filter == ALL_PLAYERS

View File

@ -3894,7 +3894,6 @@ bool scrMyResponsibility(void)
bool scrStructureBuiltInRange(void)
{
SDWORD player, index, x, y, range;
BASE_OBJECT *psCurr;
STRUCTURE *psStruct = NULL;
STRUCTURE_STATS *psTarget;
@ -3912,9 +3911,11 @@ bool scrStructureBuiltInRange(void)
// Now look through the players list of structures to see if this type exists within range
psTarget = &asStructureStats[index];
gridStartIterate(x, y, range);
for (psCurr = gridIterate(); psCurr; psCurr = gridIterate())
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(x, y, range);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psCurr = *gi;
if (psCurr->type == OBJ_STRUCTURE)
{
psStruct = (STRUCTURE *)psCurr;

View File

@ -3681,12 +3681,12 @@ void structureUpdate(STRUCTURE *psBuilding, bool mission)
if (psBuilding->state == SAS_OPEN && psBuilding->lastStateTime + SAS_STAY_OPEN_TIME < gameTime)
{
bool found = false;
BASE_OBJECT *psObj;
gridStartIterate(psBuilding->pos.x, psBuilding->pos.y, TILE_UNITS);
while (!found && (psObj = gridIterate()))
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterate(psBuilding->pos.x, psBuilding->pos.y, TILE_UNITS);
for (GridIterator gi = gridList.begin(); !found && gi != gridList.end(); ++gi)
{
found = (psObj->type == OBJ_DROID);
found = isDroid(*gi);
}
if (!found) // no droids on our tile, safe to close

View File

@ -538,8 +538,6 @@ static void processVisibilitySelf(BASE_OBJECT *psObj)
// Calculate which objects we can see. Better to call after processVisibilitySelf, since that check is cheaper.
static void processVisibilityVision(BASE_OBJECT *psViewer)
{
BASE_OBJECT *psObj;
if (psViewer->type == OBJ_FEATURE)
{
return;
@ -547,9 +545,12 @@ static void processVisibilityVision(BASE_OBJECT *psViewer)
// get all the objects from the grid the droid is in
// Will give inconsistent results if hasSharedVision is not an equivalence relation.
gridStartIterateUnseen(psViewer->pos.x, psViewer->pos.y, psViewer->sensorRange, psViewer->player);
while (psObj = gridIterate(), psObj != NULL)
static GridList gridList; // static to avoid allocations.
gridList = gridStartIterateUnseen(psViewer->pos.x, psViewer->pos.y, psViewer->sensorRange, psViewer->player);
for (GridIterator gi = gridList.begin(); gi != gridList.end(); ++gi)
{
BASE_OBJECT *psObj = *gi;
int val = visibleObject(psViewer, psObj, false);
// If we've got ranged line of sight...