Fix gates.

It is now possible to go through gates when, and only when, they are open, and friendly gates are always ignored by pathfinding.

Fixes ticket:2486.
master
Cyp 2011-02-28 22:58:19 +01:00
parent f18f984522
commit 48f0020455
7 changed files with 94 additions and 25 deletions

View File

@ -2571,11 +2571,11 @@ static BOOL renderWallSection(STRUCTURE *psStructure)
}
else if (psStructure->pStructureType->type == REF_GATE && psStructure->state == SAS_OPENING)
{
dv.y -= (height * (gameTime - psStructure->lastStateTime)) / SAS_OPEN_SPEED;
dv.y -= (height * std::max<int>(graphicsTime + GAME_TICKS_PER_UPDATE - psStructure->lastStateTime, 0)) / SAS_OPEN_SPEED;
}
else if (psStructure->pStructureType->type == REF_GATE && psStructure->state == SAS_CLOSING)
{
dv.y -= height - (height * (gameTime - psStructure->lastStateTime)) / SAS_OPEN_SPEED;
dv.y -= height - (height * std::max<int>(graphicsTime - psStructure->lastStateTime, 0)) / SAS_OPEN_SPEED;
}
/* Push the indentity matrix */

View File

@ -267,6 +267,7 @@ BOOL fpathBaseBlockingTile(SDWORD x, SDWORD y, PROPULSION_TYPE propulsion, int m
if ((unitbits & FEATURE_BLOCKED)
&& ((moveType == FMT_MOVE && (aux & AUXBITS_ANY_BUILDING)) // do not wish to shoot our way through enemy buildings
|| (moveType == FMT_BLOCK && (aux & AUXBITS_CLOSED_GATE)) // Do not wish to tunnel through closed gates.
|| (aux & AUXBITS_OUR_BUILDING))) // move blocked by friendly building, assuming we do not want to shoot it up en route
{
return true; // move blocked by building, and we cannot or do not want to shoot our way through anything
@ -284,7 +285,7 @@ BOOL fpathDroidBlockingTile(DROID *psDroid, int x, int y, FPATH_MOVETYPE moveTyp
// Check if the map tile at a location blocks a droid
BOOL fpathBlockingTile(SDWORD x, SDWORD y, PROPULSION_TYPE propulsion)
{
return fpathBaseBlockingTile(x, y, propulsion, 0, FMT_MOVE); // with FMT_MOVE, it is irrelevant which player is passed in
return fpathBaseBlockingTile(x, y, propulsion, 0, FMT_BLOCK); // with FMT_BLOCK, it is irrelevant which player is passed in
}

View File

@ -36,6 +36,7 @@ enum FPATH_MOVETYPE
{
FMT_MOVE, ///< Move around all obstacles
FMT_ATTACK, ///< Assume that we will destroy enemy obstacles
FMT_BLOCK, ///< Don't go through obstacles, not even gates.
};
struct PathBlockingMap;

View File

@ -124,7 +124,7 @@ extern char *tileset;
#define WATER_BLOCKED 0x04 ///< Units that cannot pass water are blocked by this tile
#define LAND_BLOCKED 0x08 ///< The inverse of the above -- for propeller driven crafts
#define AUXBITS_UNUSED 0x01 ///< Unused for now
#define AUXBITS_CLOSED_GATE 0x01 ///< There is a gate which is not open.
#define AUXBITS_OUR_BUILDING 0x02 ///< Do we or our allies have a building at this tile
#define AUXBITS_ANY_BUILDING 0x04 ///< Is there any building that might be blocking here?
#define AUXBITS_TEMPORARY 0x08 ///< Temporary bit used in calculations
@ -206,6 +206,20 @@ WZ_DECL_ALWAYS_INLINE static inline void auxSetAllied(int x, int y, int player,
}
}
/// Set aux bits. Always set identically for all players. States not set are retained.
WZ_DECL_ALWAYS_INLINE static inline void auxSetEnemy(int x, int y, int player, int state)
{
int i;
for (i = 0; i < MAX_PLAYERS; i++)
{
if (!(alliancebits[player] & (1 << i)))
{
psAuxMap[i][x + y * mapWidth] |= state;
}
}
}
/// Clear aux bits. Always set identically for all players. States not cleared are retained.
WZ_DECL_ALWAYS_INLINE static inline void auxClear(int x, int y, int player, int state)
{

View File

@ -872,26 +872,13 @@ static void moveCalcBlockingSlide(DROID *psDroid, int32_t *pmx, int32_t *pmy, ui
psTile = mapTile(ntx, nty);
}
if (!isFlying(psDroid) && psTile && psTile->psObject && psTile->psObject->type == OBJ_STRUCTURE
&& aiCheckAlliances(psTile->psObject->player, psDroid->player)
&& ((STRUCTURE *)psTile->psObject)->status == SS_BUILT
&& ((STRUCTURE *)psTile->psObject)->pStructureType->type == REF_GATE)
&& aiCheckAlliances(psTile->psObject->player, psDroid->player))
{
STRUCTURE *psStruct = (STRUCTURE *)psTile->psObject;
if (psStruct->state == SAS_NORMAL)
{
psStruct->lastStateTime = gameTime;
psStruct->state = SAS_OPENING;
psDroid->sMove.Status = MOVEPAUSE;
psDroid->sMove.pauseTime = SAS_OPEN_SPEED;
psDroid->sMove.bumpTime = gameTime;
psDroid->sMove.lastBump = 0;
return; // wait for it to open
}
requestOpenGate((STRUCTURE *)psTile->psObject); // If it's a friendly gate, open it. (It would be impolite to open an enemy gate.)
}
// is the new tile blocking?
if (!fpathBaseBlockingTile(ntx, nty, propulsion, psDroid->player, FMT_MOVE))
if (!fpathBlockingTile(ntx, nty, propulsion))
{
// not blocking, don't change the move vector
return;

View File

@ -211,7 +211,7 @@ static void auxStructureNonblocking(STRUCTURE *psStructure)
{
for (int j = 0; j < size.y; j++)
{
auxClearAll(map.x + i, map.y + j, AUXBITS_ANY_BUILDING | AUXBITS_OUR_BUILDING);
auxClearAll(map.x + i, map.y + j, AUXBITS_ANY_BUILDING | AUXBITS_OUR_BUILDING | AUXBITS_CLOSED_GATE);
}
}
}
@ -231,6 +231,35 @@ static void auxStructureBlocking(STRUCTURE *psStructure)
}
}
static void auxStructureOpenGate(STRUCTURE *psStructure)
{
Vector2i size = getStructureSize(psStructure);
Vector2i map = map_coord(removeZ(psStructure->pos)) - size/2;
for (int i = 0; i < size.x; i++)
{
for (int j = 0; j < size.y; j++)
{
auxClearAll(map.x + i, map.y + j, AUXBITS_CLOSED_GATE);
}
}
}
static void auxStructureClosedGate(STRUCTURE *psStructure)
{
Vector2i size = getStructureSize(psStructure);
Vector2i map = map_coord(removeZ(psStructure->pos)) - size/2;
for (int i = 0; i < size.x; i++)
{
for (int j = 0; j < size.y; j++)
{
auxSetEnemy(map.x + i, map.y + j, psStructure->player, AUXBITS_ANY_BUILDING);
auxSetAll(map.x + i, map.y + j, AUXBITS_CLOSED_GATE);
}
}
}
BOOL IsStatExpansionModule(STRUCTURE_STATS *psStats)
{
// If the stat is any of the 3 expansion types ... then return true
@ -1505,9 +1534,16 @@ STRUCTURE* buildStructureDir(STRUCTURE_STATS *pStructureType, UDWORD x, UDWORD y
}
}
if (pStructureType->type != REF_REARM_PAD && pStructureType->type != REF_GATE)
switch (pStructureType->type)
{
auxStructureBlocking(psBuilding);
case REF_REARM_PAD:
break; // Not blocking.
case REF_GATE:
auxStructureClosedGate(psBuilding); // Don't block for the sake of allied pathfinding.
break;
default:
auxStructureBlocking(psBuilding);
break;
}
//set up the rest of the data
@ -3605,6 +3641,34 @@ void _syncDebugStructure(const char *function, STRUCTURE const *psStruct, char c
getPrecisePower(psStruct->player));
}
int requestOpenGate(STRUCTURE *psStructure)
{
if (psStructure->status != SS_BUILT || psStructure->pStructureType->type != REF_GATE)
{
return 0; // Can't open.
}
switch (psStructure->state)
{
case SAS_NORMAL:
psStructure->lastStateTime = gameTime;
psStructure->state = SAS_OPENING;
break;
case SAS_OPEN:
psStructure->lastStateTime = gameTime;
return 0; // Already open.
case SAS_OPENING:
break;
case SAS_CLOSING:
psStructure->lastStateTime = 2*gameTime - psStructure->lastStateTime - SAS_OPEN_SPEED;
psStructure->state = SAS_OPENING;
default:
return 0; // Unknown state...
}
return psStructure->lastStateTime + SAS_OPEN_SPEED - gameTime;
}
/* The main update routine for all Structures */
void structureUpdate(STRUCTURE *psBuilding, bool mission)
{
@ -3631,14 +3695,14 @@ void structureUpdate(STRUCTURE *psBuilding, bool mission)
if (!found) // no droids on our tile, safe to close
{
psBuilding->state = SAS_CLOSING;
auxStructureBlocking(psBuilding); // closed
auxStructureClosedGate(psBuilding); // closed
psBuilding->lastStateTime = gameTime; // reset timer
}
}
else if (psBuilding->state == SAS_OPENING && psBuilding->lastStateTime + SAS_OPEN_SPEED < gameTime)
{
psBuilding->state = SAS_OPEN;
auxStructureNonblocking(psBuilding); // opened
auxStructureOpenGate(psBuilding); // opened
psBuilding->lastStateTime = gameTime; // reset timer
}
else if (psBuilding->state == SAS_CLOSING && psBuilding->lastStateTime + SAS_OPEN_SPEED < gameTime)

View File

@ -110,6 +110,8 @@ extern BOOL loadStructureStrengthModifiers(const char *pStrengthModData, UDWORD
extern BOOL structureStatsShutDown(void);
int requestOpenGate(STRUCTURE *psStructure);
int32_t structureDamage(STRUCTURE *psStructure, UDWORD damage, WEAPON_CLASS weaponClass, WEAPON_SUBCLASS weaponSubClass, HIT_SIDE impactSide);
extern void structureBuild(STRUCTURE *psStructure, DROID *psDroid, int buildPoints);
extern void structureDemolish(STRUCTURE *psStructure, DROID *psDroid, int buildPoints);