diff options
Diffstat (limited to 'src/faraway_island.c')
-rwxr-xr-x | src/faraway_island.c | 446 |
1 files changed, 446 insertions, 0 deletions
diff --git a/src/faraway_island.c b/src/faraway_island.c new file mode 100755 index 000000000..6a835a02b --- /dev/null +++ b/src/faraway_island.c @@ -0,0 +1,446 @@ +#include "global.h" +#include "event_data.h" +#include "event_object_movement.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "sprite.h" +#include "constants/event_objects.h" +#include "constants/flags.h" +#include "constants/maps.h" +#include "constants/metatile_behaviors.h" +#include "constants/vars.h" + +static u8 sub_81D4890(u8); +static bool8 sub_81D4C14(struct EventObject*, u8); +static u8 sub_81D4C9C(struct EventObject*, u8); +static u8 sub_81D4C58(struct EventObject*, u8); +static u8 sub_81D4CE0(struct EventObject*, u8); +static u8 sub_81D4D24(u8); +static bool8 CanMewWalkToCoords(s16, s16); + +static EWRAM_DATA u8 sUnknown_0203CF50 = 0; + +static s16 sPlayerToMewDeltaX; +static s16 sPlayerToMewDeltaY; +static u8 sMewDirectionCandidates[4]; + +extern const struct SpritePalette gFieldEffectObjectPaletteInfo1; +extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[]; + +static const s16 sFarawayIslandRockCoords[4][2] = +{ + {21, 16}, + {25, 16}, + {16, 17}, + {20, 20}, +}; + +static u8 GetMewEventObjectId(void) +{ + u8 eventObjectId; + TryGetEventObjectIdByLocalIdAndMap(1, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, &eventObjectId); + return eventObjectId; +} + +u32 GetMewMoveDirection(void) +{ + u8 i; + int skip; + struct EventObject *mew = &gEventObjects[GetMewEventObjectId()]; + + sPlayerToMewDeltaX = gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x - mew->currentCoords.x; + sPlayerToMewDeltaY = gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y - mew->currentCoords.y; + for (i = 0; i < ARRAY_COUNT(sMewDirectionCandidates); i++) + sMewDirectionCandidates[i] = DIR_NONE; + + if (gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x == gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.x + && gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y == gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.y) + { + return DIR_NONE; + } + + if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 8 == 0) + mew->invisible = 0; + else + mew->invisible = 1; + + if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 9 == 0) + return DIR_NONE; + + for (i = 0; i < ARRAY_COUNT(sFarawayIslandRockCoords); i++) + { + if (gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x == sFarawayIslandRockCoords[i][0]) + { + skip = 0; + if (gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y < sFarawayIslandRockCoords[i][1]) + { + if (mew->currentCoords.y <= sFarawayIslandRockCoords[i][1]) + skip = 1; + } + else + { + if (mew->currentCoords.y >= sFarawayIslandRockCoords[i][1]) + skip = 1; + } + + if (!skip) + { + if (sPlayerToMewDeltaX > 0) + { + if (mew->currentCoords.x + 1 == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x) + { + if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + return DIR_EAST; + } + } + else if (sPlayerToMewDeltaX < 0) + { + if (mew->currentCoords.x - 1 == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x) + { + if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + return DIR_WEST; + } + } + + if (mew->currentCoords.x == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x) + { + if (sPlayerToMewDeltaY > 0) + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + return DIR_NORTH; + } + else + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + return DIR_SOUTH; + } + } + } + } + + if (gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y == sFarawayIslandRockCoords[i][1]) + { + skip = 0; + if (gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.x < sFarawayIslandRockCoords[i][0]) + { + if (mew->currentCoords.x <= sFarawayIslandRockCoords[i][0]) + skip = 1; + } + else + { + if (mew->currentCoords.x >= sFarawayIslandRockCoords[i][0]) + skip = 1; + } + + if (!skip) + { + if (sPlayerToMewDeltaY > 0) + { + if (mew->currentCoords.y + 1 == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y) + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + return DIR_SOUTH; + } + } + else if (sPlayerToMewDeltaY < 0) + { + if (mew->currentCoords.y - 1 == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y) + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + return DIR_NORTH; + } + } + + if (mew->currentCoords.y == gEventObjects[gPlayerAvatar.eventObjectId].previousCoords.y) + { + if (sPlayerToMewDeltaX > 0) + { + if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + return DIR_WEST; + } + else + { + if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + return DIR_EAST; + } + } + } + } + } + + if (sub_81D4C14(mew, 0)) + { + if (sub_81D4C58(mew, 1)) + return sub_81D4D24(2); + else if (sub_81D4CE0(mew, 1)) + return sub_81D4D24(2); + else + return DIR_NORTH; + } + + if (sub_81D4C9C(mew, 0)) + { + if (sub_81D4C58(mew, 1)) + return sub_81D4D24(2); + else if (sub_81D4CE0(mew, 1)) + return sub_81D4D24(2); + else + return DIR_SOUTH; + } + + if (sub_81D4C58(mew, 0)) + { + if (sub_81D4C14(mew, 1)) + return sub_81D4D24(2); + else if (sub_81D4C9C(mew, 1)) + return sub_81D4D24(2); + else + return DIR_EAST; + } + + if (sub_81D4CE0(mew, 0)) + { + if (sub_81D4C14(mew, 1)) + return sub_81D4D24(2); + else if (sub_81D4C9C(mew, 1)) + return sub_81D4D24(2); + else + return DIR_WEST; + } + + if (sPlayerToMewDeltaY == 0) + { + if (gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.y > mew->currentCoords.y) + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + return DIR_NORTH; + } + + if (gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.y < mew->currentCoords.y) + { + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + return DIR_SOUTH; + } + + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + return DIR_NORTH; + + if (CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + return DIR_SOUTH; + } + + if (sPlayerToMewDeltaX == 0) + { + if (gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.x > mew->currentCoords.x) + { + if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + return DIR_WEST; + } + + if (gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.x < mew->currentCoords.x) + { + if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + return DIR_EAST; + } + + if (CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + return DIR_EAST; + + if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + return DIR_WEST; + } + + return sub_81D4890(DIR_NONE); +} + +static bool8 CanMewWalkToCoords(s16 x, s16 y) +{ + if (gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.x == x + && gEventObjects[gPlayerAvatar.eventObjectId].currentCoords.y == y) + { + return FALSE; + } + + return MetatileBehavior_IsPokeGrass(MapGridGetMetatileBehaviorAt(x, y)); +} + +static u8 sub_81D4890(u8 ignoredDir) +{ + u8 i; + u8 count = 0; + struct EventObject *mew = &gEventObjects[GetMewEventObjectId()]; + + 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) + { + sMewDirectionCandidates[count] = DIR_NORTH; + count++; + } + + if (CanMewWalkToCoords(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) + { + sMewDirectionCandidates[count] = DIR_SOUTH; + count++; + } + + if (CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y) == TRUE && ignoredDir != DIR_WEST) + { + sMewDirectionCandidates[count] = DIR_WEST; + count++; + } + + if (count > 1) + return sMewDirectionCandidates[VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % count]; + else + return sMewDirectionCandidates[0]; +} + +void UpdateFarawayIslandStepCounter(void) +{ + u16 steps = VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER); + if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(FARAWAY_ISLAND_INTERIOR) + && gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FARAWAY_ISLAND_INTERIOR)) + { + steps++; + if (steps >= 9999) + VarSet(VAR_FARAWAY_ISLAND_STEP_COUNTER, 0); + else + VarSet(VAR_FARAWAY_ISLAND_STEP_COUNTER, steps); + } +} + +bool8 EventObjectIsFarawayIslandMew(struct EventObject *eventObject) +{ + if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(FARAWAY_ISLAND_INTERIOR) + && gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FARAWAY_ISLAND_INTERIOR)) + { + if (eventObject->graphicsId == EVENT_OBJ_GFX_MEW) + return TRUE; + } + + return FALSE; +} + +bool8 IsMewPlayingHideAndSeek(void) +{ + if (gSaveBlock1Ptr->location.mapNum == MAP_NUM(FARAWAY_ISLAND_INTERIOR) + && gSaveBlock1Ptr->location.mapGroup == MAP_GROUP(FARAWAY_ISLAND_INTERIOR)) + { + if (FlagGet(FLAG_CAUGHT_MEW) != TRUE && FlagGet(FLAG_HIDE_MEW) != TRUE) + return TRUE; + } + + return FALSE; +} + +bool8 sub_81D4A58(struct EventObject *eventObject) +{ + if (VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) != 0xFFFF + && VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % 4 == 0) + return TRUE; + + return FALSE; +} + +void sub_81D4A90(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct EventObject *mew = &gEventObjects[GetMewEventObjectId()]; + + mew->invisible = 0; + if (gSpecialVar_0x8004 == 1) + { + mew->fixedPriority = 1; + gSprites[mew->spriteId].subspriteMode = SUBSPRITES_IGNORE_PRIORITY; + gSprites[mew->spriteId].subpriority = 1; + } + else + { + VarSet(VAR_FARAWAY_ISLAND_STEP_COUNTER, 0xFFFF); + mew->fixedPriority = 1; + gSprites[mew->spriteId].subspriteMode = SUBSPRITES_IGNORE_PRIORITY; + if (gSpecialVar_Facing != DIR_NORTH) + gSprites[mew->spriteId].subpriority = 1; + + LoadSpritePalette(&gFieldEffectObjectPaletteInfo1); + UpdateSpritePaletteWithWeather(IndexOfSpritePaletteTag(gFieldEffectObjectPaletteInfo1.tag)); + + x = mew->currentCoords.x; + y = mew->currentCoords.y; + sub_80930E0(&x, &y, 8, 8); + sUnknown_0203CF50 = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[15], x, y, gSprites[mew->spriteId].subpriority - 1); + if (sUnknown_0203CF50 != MAX_SPRITES) + { + struct Sprite *sprite = &gSprites[sUnknown_0203CF50]; + sprite->coordOffsetEnabled = 1; + sprite->oam.priority = 2; + sprite->callback = SpriteCallbackDummy; + } + } +} + +void sub_81D4BEC(void) +{ + if (sUnknown_0203CF50 != MAX_SPRITES) + DestroySprite(&gSprites[sUnknown_0203CF50]); +} + +static bool8 sub_81D4C14(struct EventObject *mew, u8 index) +{ + if (sPlayerToMewDeltaY > 0 && CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y - 1)) + { + sMewDirectionCandidates[index] = DIR_NORTH; + return TRUE; + } + + return FALSE; +} + +static u8 sub_81D4C58(struct EventObject *mew, u8 index) +{ + if (sPlayerToMewDeltaX < 0 && CanMewWalkToCoords(mew->currentCoords.x + 1, mew->currentCoords.y)) + { + sMewDirectionCandidates[index] = DIR_EAST; + return TRUE; + } + + return FALSE; +} + +static u8 sub_81D4C9C(struct EventObject *mew, u8 index) +{ + if (sPlayerToMewDeltaY < 0 && CanMewWalkToCoords(mew->currentCoords.x, mew->currentCoords.y + 1)) + { + sMewDirectionCandidates[index] = DIR_SOUTH; + return TRUE; + } + + return FALSE; +} + +static u8 sub_81D4CE0(struct EventObject *mew, u8 index) +{ + if (sPlayerToMewDeltaX > 0 && CanMewWalkToCoords(mew->currentCoords.x - 1, mew->currentCoords.y)) + { + sMewDirectionCandidates[index] = DIR_WEST; + return TRUE; + } + + return FALSE; +} + +static u8 sub_81D4D24(u8 mod) +{ + return sMewDirectionCandidates[VarGet(VAR_FARAWAY_ISLAND_STEP_COUNTER) % mod]; +} |