diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/event_object_movement.c | 2 | ||||
-rwxr-xr-x | src/faraway_island.c | 191 |
2 files changed, 107 insertions, 86 deletions
diff --git a/src/event_object_movement.c b/src/event_object_movement.c index ad839e006..de5536240 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -8124,7 +8124,7 @@ static void DoFlaggedGroundEffects(struct ObjectEvent *objEvent, struct Sprite * { u8 i; - if (ObjectEventIsFarawayIslandMew(objEvent) == TRUE && !sub_81D4A58(objEvent)) + if (ObjectEventIsFarawayIslandMew(objEvent) == TRUE && !ShouldMewShakeGrass(objEvent)) return; for (i = 0; i < ARRAY_COUNT(sGroundEffectFuncs); i++, flags >>= 1) diff --git a/src/faraway_island.c b/src/faraway_island.c index 06e47cd21..57d31057f 100755 --- a/src/faraway_island.c +++ b/src/faraway_island.c @@ -9,15 +9,15 @@ #include "constants/maps.h" #include "constants/metatile_behaviors.h" -static u8 sub_81D4890(u8); -static bool8 sub_81D4C14(struct ObjectEvent*, u8); -static u8 sub_81D4C9C(struct ObjectEvent*, u8); -static u8 sub_81D4C58(struct ObjectEvent*, u8); -static u8 sub_81D4CE0(struct ObjectEvent*, u8); -static u8 sub_81D4D24(u8); -static bool8 CanMewWalkToCoords(s16, s16); +static u8 GetValidMewMoveDirection(u8); +static bool8 ShouldMewMoveNorth(struct ObjectEvent*, u8); +static bool8 ShouldMewMoveSouth(struct ObjectEvent*, u8); +static bool8 ShouldMewMoveEast(struct ObjectEvent*, u8); +static bool8 ShouldMewMoveWest(struct ObjectEvent*, u8); +static u8 GetRandomMewDirectionCandidate(u8); +static bool8 CanMewMoveToCoords(s16, s16); -static EWRAM_DATA u8 sUnknown_0203CF50 = 0; +static EWRAM_DATA u8 sGrassSpriteId = 0; static s16 sPlayerToMewDeltaX; static s16 sPlayerToMewDeltaY; @@ -28,10 +28,10 @@ extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[]; static const s16 sFarawayIslandRockCoords[4][2] = { - {21, 16}, - {25, 16}, - {16, 17}, - {20, 20}, + {14 + 7, 9 + 7}, + {18 + 7, 9 + 7}, + { 9 + 7, 10 + 7}, + {13 + 7, 13 + 7}, }; static u8 GetMewObjectEventId(void) @@ -41,10 +41,12 @@ static u8 GetMewObjectEventId(void) return objectEventId; } +// When the player enters Faraway Island interior it begins a "hide and seek" minigame where Mew disappears into the grass +// This function returns the direction Mew will take a step, and is run every time the player takes a step u32 GetMewMoveDirection(void) { u8 i; - int skip; + int mewSafeFromTrap; struct ObjectEvent *mew = &gObjectEvents[GetMewObjectEventId()]; sPlayerToMewDeltaX = gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x - mew->currentCoords.x; @@ -52,43 +54,47 @@ u32 GetMewMoveDirection(void) for (i = 0; i < ARRAY_COUNT(sMewDirectionCandidates); i++) sMewDirectionCandidates[i] = DIR_NONE; + // Player hasn't moved (just facing new direction), don't move if (gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x == gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x && gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y == gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y) { return DIR_NONE; } + // Mew is invisible except for every 8th step if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 8 == 0) - mew->invisible = 0; + mew->invisible = FALSE; else - mew->invisible = 1; + mew->invisible = TRUE; + // Mew will stay in place for 1 step after its visible if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 9 == 0) return DIR_NONE; + // Below loop is for Mew to try to avoid getting trapped between the player and a rock for (i = 0; i < ARRAY_COUNT(sFarawayIslandRockCoords); i++) { if (gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x == sFarawayIslandRockCoords[i][0]) { - skip = 0; + mewSafeFromTrap = FALSE; if (gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y < sFarawayIslandRockCoords[i][1]) { if (mew->currentCoords.y <= sFarawayIslandRockCoords[i][1]) - skip = 1; + mewSafeFromTrap = TRUE; } else { if (mew->currentCoords.y >= sFarawayIslandRockCoords[i][1]) - skip = 1; + mewSafeFromTrap = TRUE; } - if (!skip) + if (!mewSafeFromTrap) { if (sPlayerToMewDeltaX > 0) { if (mew->currentCoords.x + 1 == gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x) { - if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) return DIR_EAST; } } @@ -96,7 +102,7 @@ u32 GetMewMoveDirection(void) { if (mew->currentCoords.x - 1 == gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x) { - if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) return DIR_WEST; } } @@ -105,12 +111,12 @@ u32 GetMewMoveDirection(void) { if (sPlayerToMewDeltaY > 0) { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) return DIR_NORTH; } else { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) return DIR_SOUTH; } } @@ -119,25 +125,25 @@ u32 GetMewMoveDirection(void) if (gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y == sFarawayIslandRockCoords[i][1]) { - skip = 0; + mewSafeFromTrap = FALSE; if (gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.x < sFarawayIslandRockCoords[i][0]) { if (mew->currentCoords.x <= sFarawayIslandRockCoords[i][0]) - skip = 1; + mewSafeFromTrap = TRUE; } else { if (mew->currentCoords.x >= sFarawayIslandRockCoords[i][0]) - skip = 1; + mewSafeFromTrap = TRUE; } - if (!skip) + if (!mewSafeFromTrap) { if (sPlayerToMewDeltaY > 0) { if (mew->currentCoords.y + 1 == gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y) { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) return DIR_SOUTH; } } @@ -145,7 +151,7 @@ u32 GetMewMoveDirection(void) { if (mew->currentCoords.y - 1 == gObjectEvents[gPlayerAvatar.objectEventId].previousCoords.y) { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) return DIR_NORTH; } } @@ -154,12 +160,12 @@ u32 GetMewMoveDirection(void) { if (sPlayerToMewDeltaX > 0) { - if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) return DIR_WEST; } else { - if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) return DIR_EAST; } } @@ -167,92 +173,101 @@ u32 GetMewMoveDirection(void) } } - if (sub_81D4C14(mew, 0)) + // Check if Mew can move in any direction without getting closer to the player + // If so load into sMewDirectionCandidates + // If Mew can move in two of the checked directions, choose one randomly + if (ShouldMewMoveNorth(mew, 0)) { - if (sub_81D4C58(mew, 1)) - return sub_81D4D24(2); - else if (sub_81D4CE0(mew, 1)) - return sub_81D4D24(2); + if (ShouldMewMoveEast(mew, 1)) + return GetRandomMewDirectionCandidate(2); + else if (ShouldMewMoveWest(mew, 1)) + return GetRandomMewDirectionCandidate(2); else return DIR_NORTH; } - if (sub_81D4C9C(mew, 0)) + if (ShouldMewMoveSouth(mew, 0)) { - if (sub_81D4C58(mew, 1)) - return sub_81D4D24(2); - else if (sub_81D4CE0(mew, 1)) - return sub_81D4D24(2); + if (ShouldMewMoveEast(mew, 1)) + return GetRandomMewDirectionCandidate(2); + else if (ShouldMewMoveWest(mew, 1)) + return GetRandomMewDirectionCandidate(2); else return DIR_SOUTH; } - if (sub_81D4C58(mew, 0)) + if (ShouldMewMoveEast(mew, 0)) { - if (sub_81D4C14(mew, 1)) - return sub_81D4D24(2); - else if (sub_81D4C9C(mew, 1)) - return sub_81D4D24(2); + if (ShouldMewMoveNorth(mew, 1)) + return GetRandomMewDirectionCandidate(2); + else if (ShouldMewMoveSouth(mew, 1)) + return GetRandomMewDirectionCandidate(2); else return DIR_EAST; } - if (sub_81D4CE0(mew, 0)) + if (ShouldMewMoveWest(mew, 0)) { - if (sub_81D4C14(mew, 1)) - return sub_81D4D24(2); - else if (sub_81D4C9C(mew, 1)) - return sub_81D4D24(2); + if (ShouldMewMoveNorth(mew, 1)) + return GetRandomMewDirectionCandidate(2); + else if (ShouldMewMoveSouth(mew, 1)) + return GetRandomMewDirectionCandidate(2); else return DIR_WEST; } + // If this point is reached, Mew cannot move without getting closer to the player + + // Avoid player on same Y, try move North/South if (sPlayerToMewDeltaY == 0) { if (gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y > mew->currentCoords.y) { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) return DIR_NORTH; } if (gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y < mew->currentCoords.y) { - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) return DIR_SOUTH; } - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) return DIR_NORTH; - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) return DIR_SOUTH; } + // Avoid player on same X, try move West/East if (sPlayerToMewDeltaX == 0) { if (gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x > mew->currentCoords.x) { - if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) return DIR_WEST; } if (gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x < mew->currentCoords.x) { - if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) return DIR_EAST; } - if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) return DIR_EAST; - if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + if (CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) return DIR_WEST; } - return sub_81D4890(DIR_NONE); + // Can't avoid player on axis, move any valid direction + return GetValidMewMoveDirection(DIR_NONE); } -static bool8 CanMewWalkToCoords(s16 x, s16 y) +// Mew can move to any Tall/Long Grass metatile the player isn't currently on +static bool8 CanMewMoveToCoords(s16 x, s16 y) { if (gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.x == x && gObjectEvents[gPlayerAvatar.objectEventId].currentCoords.y == y) @@ -263,7 +278,8 @@ static bool8 CanMewWalkToCoords(s16 x, s16 y) return MetatileBehavior_IsPokeGrass(MapGridGetMetatileBehaviorAt(x, y)); } -static u8 sub_81D4890(u8 ignoredDir) +// Last ditch effort to move, clear move candidates and try all directions again +static u8 GetValidMewMoveDirection(u8 ignoredDir) { u8 i; u8 count = 0; @@ -272,25 +288,25 @@ static u8 sub_81D4890(u8 ignoredDir) for (i = 0; i < ARRAY_COUNT(sMewDirectionCandidates); i++) sMewDirectionCandidates[i] = DIR_NONE; - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1) == TRUE && ignoredDir != DIR_NORTH) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1) == TRUE && ignoredDir != DIR_NORTH) { sMewDirectionCandidates[count] = DIR_NORTH; count++; } - if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y) == TRUE && ignoredDir != DIR_EAST) + if (CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y) == TRUE && ignoredDir != DIR_EAST) { sMewDirectionCandidates[count] = DIR_EAST; count++; } - if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1) == TRUE && ignoredDir != DIR_SOUTH) + if (CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1) == TRUE && ignoredDir != DIR_SOUTH) { sMewDirectionCandidates[count] = DIR_SOUTH; count++; } - if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y) == TRUE && ignoredDir != DIR_WEST) + if (CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y) == TRUE && ignoredDir != DIR_WEST) { sMewDirectionCandidates[count] = DIR_WEST; count++; @@ -340,7 +356,9 @@ bool8 IsMewPlayingHideAndSeek(void) return FALSE; } -bool8 sub_81D4A58(struct ObjectEvent *objectEvent) +// Every 4th step Mew will shake the grass it steps into +// Otherwise its movement leaves grass undisturbed +bool8 ShouldMewShakeGrass(struct ObjectEvent *objectEvent) { if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) != 0xFFFF && VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 4 == 0) @@ -349,22 +367,25 @@ bool8 sub_81D4A58(struct ObjectEvent *objectEvent) return FALSE; } -void sub_81D4A90(void) +void SetMewAboveGrass(void) { s16 x; s16 y; u8 spriteId; struct ObjectEvent *mew = &gObjectEvents[GetMewObjectEventId()]; - mew->invisible = 0; + mew->invisible = FALSE; if (gSpecialVar_0x8004 == 1) { + // For after battle where Mew should still be present (e.g. if ran from battle) mew->fixedPriority = 1; gSprites[mew->spriteId].subspriteMode = SUBSPRITES_IGNORE_PRIORITY; gSprites[mew->spriteId].subpriority = 1; } else { + // Mew emerging from grass when found + // Also do field effect for grass shaking as it emerges VarSet(VAR_FARAWAY_ISLAND_STEP_COUNTER, 0xFFFF); mew->fixedPriority = 1; gSprites[mew->spriteId].subspriteMode = SUBSPRITES_IGNORE_PRIORITY; @@ -377,10 +398,10 @@ void sub_81D4A90(void) x = mew->currentCoords.x; y = mew->currentCoords.y; SetSpritePosToOffsetMapCoords(&x, &y, 8, 8); - sUnknown_0203CF50 = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[15], x, y, gSprites[mew->spriteId].subpriority - 1); - if (sUnknown_0203CF50 != MAX_SPRITES) + sGrassSpriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[15], x, y, gSprites[mew->spriteId].subpriority - 1); + if (sGrassSpriteId != MAX_SPRITES) { - struct Sprite *sprite = &gSprites[sUnknown_0203CF50]; + struct Sprite *sprite = &gSprites[sGrassSpriteId]; sprite->coordOffsetEnabled = 1; sprite->oam.priority = 2; sprite->callback = SpriteCallbackDummy; @@ -388,15 +409,15 @@ void sub_81D4A90(void) } } -void sub_81D4BEC(void) +void DestroyMewEmergingGrassSprite(void) { - if (sUnknown_0203CF50 != MAX_SPRITES) - DestroySprite(&gSprites[sUnknown_0203CF50]); + if (sGrassSpriteId != MAX_SPRITES) + DestroySprite(&gSprites[sGrassSpriteId]); } -static bool8 sub_81D4C14(struct ObjectEvent *mew, u8 index) +static bool8 ShouldMewMoveNorth(struct ObjectEvent *mew, u8 index) { - if (sPlayerToMewDeltaY > 0 && CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + if (sPlayerToMewDeltaY > 0 && CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) { sMewDirectionCandidates[index] = DIR_NORTH; return TRUE; @@ -405,9 +426,9 @@ static bool8 sub_81D4C14(struct ObjectEvent *mew, u8 index) return FALSE; } -static u8 sub_81D4C58(struct ObjectEvent *mew, u8 index) +static bool8 ShouldMewMoveEast(struct ObjectEvent *mew, u8 index) { - if (sPlayerToMewDeltaX < 0 && CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + if (sPlayerToMewDeltaX < 0 && CanMewMoveToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) { sMewDirectionCandidates[index] = DIR_EAST; return TRUE; @@ -416,9 +437,9 @@ static u8 sub_81D4C58(struct ObjectEvent *mew, u8 index) return FALSE; } -static u8 sub_81D4C9C(struct ObjectEvent *mew, u8 index) +static bool8 ShouldMewMoveSouth(struct ObjectEvent *mew, u8 index) { - if (sPlayerToMewDeltaY < 0 && CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + if (sPlayerToMewDeltaY < 0 && CanMewMoveToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) { sMewDirectionCandidates[index] = DIR_SOUTH; return TRUE; @@ -427,9 +448,9 @@ static u8 sub_81D4C9C(struct ObjectEvent *mew, u8 index) return FALSE; } -static u8 sub_81D4CE0(struct ObjectEvent *mew, u8 index) +static bool8 ShouldMewMoveWest(struct ObjectEvent *mew, u8 index) { - if (sPlayerToMewDeltaX > 0 && CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + if (sPlayerToMewDeltaX > 0 && CanMewMoveToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) { sMewDirectionCandidates[index] = DIR_WEST; return TRUE; @@ -438,7 +459,7 @@ static u8 sub_81D4CE0(struct ObjectEvent *mew, u8 index) return FALSE; } -static u8 sub_81D4D24(u8 mod) +static u8 GetRandomMewDirectionCandidate(u8 numDirections) { - return sMewDirectionCandidates[VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % mod]; + return sMewDirectionCandidates[VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % numDirections]; } |