Permalink
Browse files

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.
  • Loading branch information...
Cyp committed Feb 28, 2011
1 parent f18f984 commit 48f00204553b976f60b198bb5583a5889c1b12f3
Showing with 94 additions and 25 deletions.
  1. +2 −2 src/display3d.cpp
  2. +2 −1 src/fpath.cpp
  3. +1 −0 src/fpath.h
  4. +15 −1 src/map.h
  5. +3 −16 src/move.cpp
  6. +69 −5 src/structure.cpp
  7. +2 −0 src/structure.h
View
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);

0 comments on commit 48f0020

Please sign in to comment.