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
parent
f18f984522
commit
48f0020455
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
16
src/map.h
16
src/map.h
|
@ -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)
|
||||
{
|
||||
|
|
19
src/move.cpp
19
src/move.cpp
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue