mirror of
https://github.com/pret/pokefirered.git
synced 2026-04-25 07:19:36 -05:00
Merge pull request #140 from MiyazakiTheFalse/codex/add-chase-overworld-subsystem-for-chaser-events-eoy8ez
Add overworld chaser visuals and chase_overworld module; integrate with chase stamina
This commit is contained in:
commit
e9ff05c45c
|
|
@ -10,17 +10,30 @@
|
|||
#define CHASE_OVERWORLD_MAX_CHASERS 2
|
||||
#define CHASE_OVERWORLD_LOCAL_ID_BASE 230
|
||||
#define CHASE_OVERWORLD_GFX_ID OBJ_EVENT_GFX_MEOWTH
|
||||
#define CHASE_OVERWORLD_MAX_STALLED_FRAMES 30
|
||||
|
||||
static const u8 sAllMoveDirections[] =
|
||||
{
|
||||
DIR_NORTH,
|
||||
DIR_SOUTH,
|
||||
DIR_WEST,
|
||||
DIR_EAST,
|
||||
};
|
||||
|
||||
static EWRAM_DATA bool8 sChasersSpawned = FALSE;
|
||||
static EWRAM_DATA u8 sSpawnedMapGroup = MAP_GROUP(MAP_UNDEFINED);
|
||||
static EWRAM_DATA u8 sSpawnedMapNum = MAP_NUM(MAP_UNDEFINED);
|
||||
static EWRAM_DATA u8 sChaserStalledFrames[CHASE_OVERWORLD_MAX_CHASERS];
|
||||
|
||||
static void DespawnChasers(void)
|
||||
{
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < CHASE_OVERWORLD_MAX_CHASERS; i++)
|
||||
{
|
||||
RemoveObjectEventByLocalIdAndMap(CHASE_OVERWORLD_LOCAL_ID_BASE + i, sSpawnedMapNum, sSpawnedMapGroup);
|
||||
sChaserStalledFrames[i] = 0;
|
||||
}
|
||||
|
||||
sChasersSpawned = FALSE;
|
||||
sSpawnedMapGroup = MAP_GROUP(MAP_UNDEFINED);
|
||||
|
|
@ -34,89 +47,88 @@ static bool8 IsSpawnContextValid(void)
|
|||
&& sSpawnedMapNum == gSaveBlock1Ptr->location.mapNum;
|
||||
}
|
||||
|
||||
static u8 GetMoveDirectionTowardTarget(s16 fromX, s16 fromY, s16 toX, s16 toY, u8 preferredDir)
|
||||
static u16 GetDistanceScore(s16 fromX, s16 fromY, s16 toX, s16 toY, u8 direction)
|
||||
{
|
||||
if (fromX < toX)
|
||||
return DIR_EAST;
|
||||
if (fromX > toX)
|
||||
return DIR_WEST;
|
||||
if (fromY < toY)
|
||||
return DIR_SOUTH;
|
||||
if (fromY > toY)
|
||||
return DIR_NORTH;
|
||||
s16 testX = fromX;
|
||||
s16 testY = fromY;
|
||||
s16 dx;
|
||||
s16 dy;
|
||||
|
||||
return preferredDir;
|
||||
MoveCoords(direction, &testX, &testY);
|
||||
dx = testX - toX;
|
||||
if (dx < 0)
|
||||
dx = -dx;
|
||||
dy = testY - toY;
|
||||
if (dy < 0)
|
||||
dy = -dy;
|
||||
|
||||
return dx + dy;
|
||||
}
|
||||
|
||||
static bool8 TryQueueChaserStep(struct ObjectEvent *objectEvent, s16 targetX, s16 targetY)
|
||||
{
|
||||
s16 dx;
|
||||
s16 dy;
|
||||
u8 i;
|
||||
u8 primaryDir;
|
||||
u8 secondaryDir;
|
||||
u8 fallbackDirs[4];
|
||||
u8 dirOrder[ARRAY_COUNT(sAllMoveDirections)];
|
||||
|
||||
primaryDir = DIR_NONE;
|
||||
secondaryDir = DIR_NONE;
|
||||
dx = objectEvent->currentCoords.x - targetX;
|
||||
if (dx < 0)
|
||||
dx = -dx;
|
||||
dy = objectEvent->currentCoords.y - targetY;
|
||||
if (dy < 0)
|
||||
dy = -dy;
|
||||
for (i = 0; i < ARRAY_COUNT(dirOrder); i++)
|
||||
dirOrder[i] = sAllMoveDirections[i];
|
||||
|
||||
if (dx >= dy)
|
||||
for (i = 0; i < ARRAY_COUNT(dirOrder); i++)
|
||||
{
|
||||
if (objectEvent->currentCoords.x < targetX)
|
||||
primaryDir = DIR_EAST;
|
||||
else if (objectEvent->currentCoords.x > targetX)
|
||||
primaryDir = DIR_WEST;
|
||||
u8 j;
|
||||
|
||||
if (objectEvent->currentCoords.y < targetY)
|
||||
secondaryDir = DIR_SOUTH;
|
||||
else if (objectEvent->currentCoords.y > targetY)
|
||||
secondaryDir = DIR_NORTH;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (objectEvent->currentCoords.y < targetY)
|
||||
primaryDir = DIR_SOUTH;
|
||||
else if (objectEvent->currentCoords.y > targetY)
|
||||
primaryDir = DIR_NORTH;
|
||||
|
||||
if (objectEvent->currentCoords.x < targetX)
|
||||
secondaryDir = DIR_EAST;
|
||||
else if (objectEvent->currentCoords.x > targetX)
|
||||
secondaryDir = DIR_WEST;
|
||||
for (j = i + 1; j < ARRAY_COUNT(dirOrder); j++)
|
||||
{
|
||||
if (GetDistanceScore(objectEvent->currentCoords.x, objectEvent->currentCoords.y, targetX, targetY, dirOrder[j])
|
||||
< GetDistanceScore(objectEvent->currentCoords.x, objectEvent->currentCoords.y, targetX, targetY, dirOrder[i]))
|
||||
{
|
||||
u8 tmp = dirOrder[i];
|
||||
dirOrder[i] = dirOrder[j];
|
||||
dirOrder[j] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (primaryDir == DIR_NONE)
|
||||
primaryDir = GetMoveDirectionTowardTarget(objectEvent->currentCoords.x, objectEvent->currentCoords.y, targetX, targetY, objectEvent->facingDirection);
|
||||
|
||||
fallbackDirs[0] = primaryDir;
|
||||
fallbackDirs[1] = secondaryDir;
|
||||
fallbackDirs[2] = objectEvent->facingDirection;
|
||||
fallbackDirs[3] = GetOppositeDirection(objectEvent->facingDirection);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(fallbackDirs); i++)
|
||||
for (i = 0; i < ARRAY_COUNT(dirOrder); i++)
|
||||
{
|
||||
u8 direction = fallbackDirs[i];
|
||||
u8 direction = dirOrder[i];
|
||||
s16 testX = objectEvent->currentCoords.x;
|
||||
s16 testY = objectEvent->currentCoords.y;
|
||||
|
||||
if (direction == DIR_NONE)
|
||||
continue;
|
||||
|
||||
MoveCoords(direction, &testX, &testY);
|
||||
if (GetCollisionAtCoords(objectEvent, testX, testY, direction) == COLLISION_NONE)
|
||||
return ObjectEventSetHeldMovement(objectEvent, GetWalkNormalMovementAction(direction));
|
||||
}
|
||||
|
||||
ObjectEventTurn(objectEvent, GetMoveDirectionTowardTarget(objectEvent->currentCoords.x, objectEvent->currentCoords.y, targetX, targetY, objectEvent->facingDirection));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void PlaceChaserNearPlayer(u8 localId, u8 objectEventId, s16 playerX, s16 playerY)
|
||||
{
|
||||
static const s8 sRespawnOffsets[][2] =
|
||||
{
|
||||
{-2, 0},
|
||||
{2, 0},
|
||||
{0, -2},
|
||||
{0, 2},
|
||||
{-2, 2},
|
||||
{2, 2},
|
||||
};
|
||||
|
||||
u8 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sRespawnOffsets); i++)
|
||||
{
|
||||
s16 candidateX = playerX + sRespawnOffsets[i][0];
|
||||
s16 candidateY = playerY + sRespawnOffsets[i][1];
|
||||
|
||||
TryMoveObjectEventToMapCoords(localId, sSpawnedMapNum, sSpawnedMapGroup, candidateX, candidateY);
|
||||
if (gObjectEvents[objectEventId].currentCoords.x == candidateX
|
||||
&& gObjectEvents[objectEventId].currentCoords.y == candidateY)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void SpawnOrSyncChasers(void)
|
||||
{
|
||||
u8 i;
|
||||
|
|
@ -149,6 +161,7 @@ static void SpawnOrSyncChasers(void)
|
|||
if (i >= activeChasers)
|
||||
{
|
||||
RemoveObjectEventByLocalIdAndMap(localId, sSpawnedMapNum, sSpawnedMapGroup);
|
||||
sChaserStalledFrames[i] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -161,6 +174,7 @@ static void SpawnOrSyncChasers(void)
|
|||
SpawnSpecialObjectEventParameterized(CHASE_OVERWORLD_GFX_ID, MOVEMENT_TYPE_FACE_DOWN, localId, spawnX + MAP_OFFSET, spawnY + MAP_OFFSET, elevation);
|
||||
if (!TryGetObjectEventIdByLocalIdAndMap(localId, sSpawnedMapNum, sSpawnedMapGroup, &objectEventId))
|
||||
continue;
|
||||
sChaserStalledFrames[i] = 0;
|
||||
}
|
||||
|
||||
if (ObjectEventIsHeldMovementActive(&gObjectEvents[objectEventId]))
|
||||
|
|
@ -169,7 +183,21 @@ static void SpawnOrSyncChasers(void)
|
|||
continue;
|
||||
}
|
||||
|
||||
TryQueueChaserStep(&gObjectEvents[objectEventId], playerX, playerY);
|
||||
if (TryQueueChaserStep(&gObjectEvents[objectEventId], playerX, playerY))
|
||||
{
|
||||
sChaserStalledFrames[i] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sChaserStalledFrames[i] < 0xFF)
|
||||
sChaserStalledFrames[i]++;
|
||||
|
||||
if (sChaserStalledFrames[i] >= CHASE_OVERWORLD_MAX_STALLED_FRAMES)
|
||||
{
|
||||
PlaceChaserNearPlayer(localId, objectEventId, playerX, playerY);
|
||||
sChaserStalledFrames[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user