diff options
author | PikalaxALT <pikalaxalt@gmail.com> | 2020-03-02 13:34:34 -0500 |
---|---|---|
committer | PikalaxALT <pikalaxalt@gmail.com> | 2020-03-02 13:34:34 -0500 |
commit | 6363d39e99612904a0393a272bbb1748ef9dca20 (patch) | |
tree | cf9c1aefab372c383d222339f01a39f5ec7f210d /src | |
parent | 9803cb612e6ca383694527d01f05f33edcc777a2 (diff) |
port field_effect_helpers from emerald
Diffstat (limited to 'src')
-rw-r--r-- | src/field_effect.c | 24 | ||||
-rw-r--r-- | src/field_effect_helpers.c | 1410 | ||||
-rw-r--r-- | src/quest_log_objects.c | 22 | ||||
-rw-r--r-- | src/quest_log_player.c | 10 |
4 files changed, 1438 insertions, 28 deletions
diff --git a/src/field_effect.c b/src/field_effect.c index 9b2974f1f..c7dd8b4e4 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -446,7 +446,7 @@ static void FieldEffectScript_LoadFadedPal(const u8 **script) LoadSpritePalette(spritePalette); if (idx == 0xFF) sub_8083598(IndexOfSpritePaletteTag(spritePalette->tag)); - sub_807AA8C(IndexOfSpritePaletteTag(spritePalette->tag)); + UpdateSpritePaletteWithWeather(IndexOfSpritePaletteTag(spritePalette->tag)); *script += sizeof(u32); } @@ -1604,7 +1604,7 @@ static bool8 waterfall_4_wait_player_move_probably(struct Task * task, struct Ob { if (!ObjectEventClearHeldMovementIfFinished(playerObj)) return FALSE; - if (MetatileBehavior_IsWaterfall(playerObj->mapobj_unk_1E)) + if (MetatileBehavior_IsWaterfall(playerObj->currentMetatileBehavior)) { task->data[0] = 3; return TRUE; @@ -1664,7 +1664,7 @@ static bool8 dive_3_unknown(struct Task * task) PlayerGetDestCoords(&pos.x, &pos.y); if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) { - dive_warp(&pos, gObjectEvents[gPlayerAvatar.objectEventId].mapobj_unk_1E); + dive_warp(&pos, gObjectEvents[gPlayerAvatar.objectEventId].currentMetatileBehavior); DestroyTask(FindTaskIdByFunc(Task_Dive)); FieldEffectActiveListRemove(FLDEFF_USE_DIVE); } @@ -2904,7 +2904,7 @@ static void UseSurfEffect_1(struct Task * task) gPlayerAvatar.preventStep = TRUE; SetPlayerAvatarStateMask(8); PlayerGetDestCoords(&task->data[1], &task->data[2]); - MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].placeholder18, &task->data[1], &task->data[2]); + MoveCoords(gObjectEvents[gPlayerAvatar.objectEventId].movementDirection, &task->data[1], &task->data[2]); task->data[0]++; } @@ -2940,11 +2940,11 @@ static void UseSurfEffect_4(struct Task * task) objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(2)); ObjectEventClearHeldMovementIfFinished(objectEvent); - ObjectEventSetHeldMovement(objectEvent, sub_80641C0(objectEvent->placeholder18)); + ObjectEventSetHeldMovement(objectEvent, sub_80641C0(objectEvent->movementDirection)); gFieldEffectArguments[0] = task->data[1]; gFieldEffectArguments[1] = task->data[2]; gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; - objectEvent->mapobj_unk_1A = FieldEffectStart(FLDEFF_SURF_BLOB); + objectEvent->fieldEffectSpriteId = FieldEffectStart(FLDEFF_SURF_BLOB); task->data[0]++; } } @@ -2957,8 +2957,8 @@ static void UseSurfEffect_5(struct Task * task) { gPlayerAvatar.preventStep = FALSE; gPlayerAvatar.flags &= 0xdf; - ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->placeholder18)); - sub_80DC44C(objectEvent->mapobj_unk_1A, 1); + ObjectEventSetHeldMovement(objectEvent, GetFaceDirectionMovementAction(objectEvent->movementDirection)); + sub_80DC44C(objectEvent->fieldEffectSpriteId, 1); UnfreezeObjectEvents(); ScriptContext2_Disable(); FieldEffectActiveListRemove(FLDEFF_USE_SURF); @@ -3151,8 +3151,8 @@ static void UseFlyEffect_3(struct Task * task) struct ObjectEvent * objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; if (task->data[15] & 0x08) { - sub_80DC44C(objectEvent->mapobj_unk_1A, 2); - sub_80DC478(objectEvent->mapobj_unk_1A, 0); + sub_80DC44C(objectEvent->fieldEffectSpriteId, 2); + sub_80DC478(objectEvent->fieldEffectSpriteId, 0); } task->data[1] = sub_8087168(); task->data[0]++; @@ -3435,7 +3435,7 @@ static void FlyInEffect_1(struct Task * task) SetPlayerAvatarStateMask(0x01); if (task->data[15] & 0x08) { - sub_80DC44C(objectEvent->mapobj_unk_1A, 0); + sub_80DC44C(objectEvent->fieldEffectSpriteId, 0); } ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(2)); CameraObjectReset2(); @@ -3549,7 +3549,7 @@ static void FlyInEffect_7(struct Task * task) if (task->data[15] & 0x08) { state = 2; - sub_80DC44C(objectEvent->mapobj_unk_1A, 1); + sub_80DC44C(objectEvent->fieldEffectSpriteId, 1); } ObjectEventSetGraphicsId(objectEvent, GetPlayerAvatarGraphicsIdByStateId(state)); ObjectEventTurn(objectEvent, DIR_SOUTH); diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c new file mode 100644 index 000000000..b156d9029 --- /dev/null +++ b/src/field_effect_helpers.c @@ -0,0 +1,1410 @@ +#include "global.h" +#include "event_object_movement.h" +#include "field_camera.h" +#include "field_effect.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "sound.h" +#include "sprite.h" +#include "constants/field_effects.h" +#include "constants/songs.h" + +#define OBJ_EVENT_PAL_TAG_NONE 0x11FF // duplicate of define in event_object_movement.c + +static void UpdateObjectReflectionSprite(struct Sprite * sprite); +static void LoadObjectReflectionPalette(struct ObjectEvent * objectEvent, struct Sprite * sprite); +static void LoadObjectHighBridgeReflectionPalette(struct ObjectEvent * objectEvent, u8 paletteNum); +static void LoadObjectRegularReflectionPalette(struct ObjectEvent * objectEvent, u8 paletteNum); +static void sub_80DCD48(struct Sprite * sprite, u8 z, u8 offset); +static void FadeFootprintsTireTracks_Step0(struct Sprite * sprite); +static void FadeFootprintsTireTracks_Step1(struct Sprite * sprite); +static void UpdateFeetInFlowingWaterFieldEffect(struct Sprite * sprite); +static void UpdateAshFieldEffect_Step0(struct Sprite * sprite); +static void UpdateAshFieldEffect_Step1(struct Sprite * sprite); +static void UpdateAshFieldEffect_Step2(struct Sprite * sprite); +static void SynchroniseSurfAnim(struct ObjectEvent * objectEvent, struct Sprite * sprite); +static void sub_80DC588(struct ObjectEvent * objectEvent, struct Sprite * sprite); +static void CreateBobbingEffect(struct ObjectEvent * objectEvent, struct Sprite * linkedSprite, struct Sprite * sprite); +static void sub_80DC700(struct Sprite * sprite); +static u32 ShowDisguiseFieldEffect(u8 fldEff, u8 templateIdx, u8 paletteNum); + +void SetUpReflection(struct ObjectEvent * objectEvent, struct Sprite * sprite, bool8 stillReflection) +{ + struct Sprite * reflectionSprite; + + reflectionSprite = &gSprites[CreateCopySpriteAt(sprite, sprite->pos1.x, sprite->pos1.y, 0x98)]; + reflectionSprite->callback = UpdateObjectReflectionSprite; + reflectionSprite->oam.priority = 3; + reflectionSprite->oam.paletteNum = gReflectionEffectPaletteMap[reflectionSprite->oam.paletteNum]; + reflectionSprite->usingSheet = TRUE; + reflectionSprite->anims = gDummySpriteAnimTable; + StartSpriteAnim(reflectionSprite, 0); + reflectionSprite->affineAnims = gDummySpriteAffineAnimTable; + reflectionSprite->affineAnimBeginning = TRUE; + reflectionSprite->subspriteMode = SUBSPRITES_OFF; + reflectionSprite->data[0] = sprite->data[0]; + reflectionSprite->data[1] = objectEvent->localId; + reflectionSprite->data[7] = stillReflection; + LoadObjectReflectionPalette(objectEvent, reflectionSprite); + + if (!stillReflection) + reflectionSprite->oam.affineMode = ST_OAM_AFFINE_NORMAL; +} + +static s16 GetReflectionVerticalOffset(struct ObjectEvent * objectEvent) +{ + return GetObjectEventGraphicsInfo(objectEvent->graphicsId)->height - 2; +} + +static void LoadObjectReflectionPalette(struct ObjectEvent * objectEvent, struct Sprite * sprite) +{ + u8 bridgeType; + u16 bridgeReflectionVerticalOffsets[] = { 12, 28, 44 }; + sprite->data[2] = 0; + if (!GetObjectEventGraphicsInfo(objectEvent->graphicsId)->disableReflectionPaletteLoad && ((bridgeType = MetatileBehavior_GetBridgeType(objectEvent->previousMetatileBehavior)) || (bridgeType = MetatileBehavior_GetBridgeType(objectEvent->currentMetatileBehavior)))) + { + sprite->data[2] = bridgeReflectionVerticalOffsets[bridgeType - 1]; + LoadObjectHighBridgeReflectionPalette(objectEvent, sprite->oam.paletteNum); + } + else + { + LoadObjectRegularReflectionPalette(objectEvent, sprite->oam.paletteNum); + } +} + +static void LoadObjectRegularReflectionPalette(struct ObjectEvent * objectEvent, u8 paletteIndex) +{ + const struct ObjectEventGraphicsInfo * graphicsInfo; + + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + if (graphicsInfo->paletteTag2 != OBJ_EVENT_PAL_TAG_NONE) + { + if (graphicsInfo->paletteSlot == 0) + { + LoadPlayerObjectReflectionPalette(graphicsInfo->paletteTag1, paletteIndex); + } + else if (graphicsInfo->paletteSlot == 10) + { + LoadSpecialObjectReflectionPalette(graphicsInfo->paletteTag1, paletteIndex); + } + else + { + PatchObjectPalette(GetObjectPaletteTag(paletteIndex), paletteIndex); + } + UpdateSpritePaletteWithWeather(paletteIndex); + } +} + +// When walking on a bridge high above water (Route 120), the reflection is a solid dark blue color. +// This is so the sprite blends in with the dark water metatile underneath the bridge. +static void LoadObjectHighBridgeReflectionPalette(struct ObjectEvent * objectEvent, u8 paletteNum) +{ + const struct ObjectEventGraphicsInfo * graphicsInfo; + + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + if (graphicsInfo->paletteTag2 != OBJ_EVENT_PAL_TAG_NONE) + { + PatchObjectPalette(graphicsInfo->paletteTag2, paletteNum); + UpdateSpritePaletteWithWeather(paletteNum); + } +} + +static void UpdateObjectReflectionSprite(struct Sprite * reflectionSprite) +{ + struct ObjectEvent * objectEvent; + struct Sprite * mainSprite; + + objectEvent = &gObjectEvents[reflectionSprite->data[0]]; + mainSprite = &gSprites[objectEvent->spriteId]; + if (!objectEvent->active || !objectEvent->hasReflection || objectEvent->localId != reflectionSprite->data[1]) + { + reflectionSprite->inUse = FALSE; + } + else + { + reflectionSprite->oam.paletteNum = gReflectionEffectPaletteMap[mainSprite->oam.paletteNum]; + reflectionSprite->oam.shape = mainSprite->oam.shape; + reflectionSprite->oam.size = mainSprite->oam.size; + reflectionSprite->oam.matrixNum = mainSprite->oam.matrixNum | ST_OAM_VFLIP; + reflectionSprite->oam.tileNum = mainSprite->oam.tileNum; + reflectionSprite->subspriteTables = mainSprite->subspriteTables; + reflectionSprite->subspriteTableNum = mainSprite->subspriteTableNum; + reflectionSprite->invisible = mainSprite->invisible; + reflectionSprite->pos1.x = mainSprite->pos1.x; + // reflectionSprite->data[2] holds an additional vertical offset, used by the high bridges on Route 120 + reflectionSprite->pos1.y = mainSprite->pos1.y + GetReflectionVerticalOffset(objectEvent) + reflectionSprite->data[2]; + reflectionSprite->centerToCornerVecX = mainSprite->centerToCornerVecX; + reflectionSprite->centerToCornerVecY = mainSprite->centerToCornerVecY; + reflectionSprite->pos2.x = mainSprite->pos2.x; + reflectionSprite->pos2.y = -mainSprite->pos2.y; + reflectionSprite->coordOffsetEnabled = mainSprite->coordOffsetEnabled; + +/* + if (objectEvent->hideReflection == TRUE) + reflectionSprite->invisible = TRUE; +*/ + + // Check if the reflection is not still. + if (reflectionSprite->data[7] == FALSE) + { + // Sets the reflection sprite's rot/scale matrix to the appropriate + // matrix based on whether or not the main sprite is horizontally flipped. + // If the sprite is facing to the east, then it is flipped, and its matrixNum is 8. + reflectionSprite->oam.matrixNum = 0; + if (mainSprite->oam.matrixNum & ST_OAM_HFLIP) + reflectionSprite->oam.matrixNum = 1; + } + } +} + +extern const struct SpriteTemplate * const gFieldEffectObjectTemplatePointers[]; + +u8 CreateWarpArrowSprite(void) +{ + u8 spriteId; + struct Sprite * sprite; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[8], 0, 0, 0x52); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->oam.priority = 1; + sprite->coordOffsetEnabled = TRUE; + sprite->invisible = TRUE; + } + return spriteId; +} + +void SetSpriteInvisible(u8 spriteId) +{ + gSprites[spriteId].invisible = TRUE; +} + +void ShowWarpArrowSprite(u8 spriteId, u8 direction, s16 x, s16 y) +{ + s16 x2; + s16 y2; + struct Sprite * sprite; + + sprite = &gSprites[spriteId]; + if (sprite->invisible || sprite->data[0] != x || sprite->data[1] != y) + { + SetSpritePosToMapCoords(x, y, &x2, &y2); + sprite = &gSprites[spriteId]; + sprite->pos1.x = x2 + 8; + sprite->pos1.y = y2 + 8; + sprite->invisible = FALSE; + sprite->data[0] = x; + sprite->data[1] = y; + StartSpriteAnim(sprite, direction - 1); + } +} + +const u8 gShadowEffectTemplateIds[] = { + 0, + 1, + 2, + 3 +}; + +const u16 gShadowVerticalOffsets[] = { + 4, + 4, + 4, + 16 +}; + +u32 FldEff_Shadow(void) +{ + u8 objectEventId; + const struct ObjectEventGraphicsInfo * graphicsInfo; + u8 spriteId; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[objectEventId].graphicsId); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[gShadowEffectTemplateIds[graphicsInfo->shadowSize]], 0, 0, 0x94); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].coordOffsetEnabled = TRUE; + gSprites[spriteId].data[0] = gFieldEffectArguments[0]; + gSprites[spriteId].data[1] = gFieldEffectArguments[1]; + gSprites[spriteId].data[2] = gFieldEffectArguments[2]; + gSprites[spriteId].data[3] = (graphicsInfo->height >> 1) - gShadowVerticalOffsets[graphicsInfo->shadowSize]; + } + return 0; +} + +void UpdateShadowFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + struct Sprite * linkedSprite; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + else + { + objectEvent = &gObjectEvents[objectEventId]; + linkedSprite = &gSprites[objectEvent->spriteId]; + sprite->oam.priority = linkedSprite->oam.priority; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + sprite->data[3]; + if (!objectEvent->active || !objectEvent->hasShadow + || MetatileBehavior_IsTallGrass(objectEvent->currentMetatileBehavior) + || MetatileBehavior_IsSurfable(objectEvent->currentMetatileBehavior) + || MetatileBehavior_IsSurfable(objectEvent->previousMetatileBehavior) + || MetatileBehavior_IsReflective(objectEvent->currentMetatileBehavior) + || MetatileBehavior_IsReflective(objectEvent->previousMetatileBehavior)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + } +} + +u32 FldEff_TallGrass(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite * sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8063BC4(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[4], x, y, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = gFieldEffectArguments[0]; + sprite->data[2] = gFieldEffectArguments[1]; + sprite->data[3] = gFieldEffectArguments[4]; + sprite->data[4] = gFieldEffectArguments[5]; + sprite->data[5] = gFieldEffectArguments[6]; + if (gFieldEffectArguments[7]) + { + SeekSpriteAnim(sprite, 4); + } + } + return 0; +} + +void UpdateTallGrassFieldEffect(struct Sprite * sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 objectEventId; + struct ObjectEvent * objectEvent; + + mapNum = sprite->data[5] >> 8; + mapGroup = sprite->data[5]; + if (gCamera.active && (gSaveBlock1Ptr->location.mapNum != mapNum || gSaveBlock1Ptr->location.mapGroup != mapGroup)) + { + sprite->data[1] -= gCamera.x; + sprite->data[2] -= gCamera.y; + sprite->data[5] = ((u8)gSaveBlock1Ptr->location.mapNum << 8) | (u8)gSaveBlock1Ptr->location.mapGroup; + } + localId = sprite->data[3] >> 8; + mapNum = sprite->data[3]; + mapGroup = sprite->data[4]; + metatileBehavior = MapGridGetMetatileBehaviorAt(sprite->data[1], sprite->data[2]); + if (TryGetObjectEventIdByLocalIdAndMap(localId, mapNum, mapGroup, &objectEventId) || !MetatileBehavior_IsTallGrass_2(metatileBehavior) || (sprite->data[7] && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_TALL_GRASS); + } + else + { + objectEvent = &gObjectEvents[objectEventId]; + if ((objectEvent->currentCoords.x != sprite->data[1] || objectEvent->currentCoords.y != sprite->data[2]) && (objectEvent->previousCoords.x != sprite->data[1] || objectEvent->previousCoords.y != sprite->data[2])) + sprite->data[7] = TRUE; + + metatileBehavior = 0; + if (sprite->animCmdIndex == 0) + metatileBehavior = 4; + + UpdateObjectEventSpriteVisibility(sprite, 0); + sub_80DCD48(sprite, sprite->data[0], metatileBehavior); + } +} + +u32 FldEff_JumpTallGrass(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[10], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = 12; + } + return 0; +} + +u8 FindTallGrassFieldEffectSpriteId(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y) +{ + struct Sprite * sprite; + u8 i; + + for (i = 0; i < MAX_SPRITES; i ++) + { + if (gSprites[i].inUse) + { + sprite = &gSprites[i]; + if (sprite->callback == UpdateTallGrassFieldEffect && (x == sprite->data[1] && y == sprite->data[2]) && (localId == (sprite->data[3] >> 8) && mapNum == (sprite->data[3] & 0xFF) && mapGroup == sprite->data[4])) + return i; + } + } + + return MAX_SPRITES; +} + +u32 FldEff_LongGrass(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite * sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8063BC4(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[15], x, y, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = ZCoordToPriority(gFieldEffectArguments[2]); + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = gFieldEffectArguments[0]; + sprite->data[2] = gFieldEffectArguments[1]; + sprite->data[3] = gFieldEffectArguments[4]; + sprite->data[4] = gFieldEffectArguments[5]; + sprite->data[5] = gFieldEffectArguments[6]; + if (gFieldEffectArguments[7]) + { + SeekSpriteAnim(sprite, 6); + } + } + return 0; +} + +void UpdateLongGrassFieldEffect(struct Sprite * sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 objectEventId; + struct ObjectEvent * objectEvent; + + mapNum = sprite->data[5] >> 8; + mapGroup = sprite->data[5]; + if (gCamera.active && (gSaveBlock1Ptr->location.mapNum != mapNum || gSaveBlock1Ptr->location.mapGroup != mapGroup)) + { + sprite->data[1] -= gCamera.x; + sprite->data[2] -= gCamera.y; + sprite->data[5] = ((u8)gSaveBlock1Ptr->location.mapNum << 8) | (u8)gSaveBlock1Ptr->location.mapGroup; + } + localId = sprite->data[3] >> 8; + mapNum = sprite->data[3]; + mapGroup = sprite->data[4]; + metatileBehavior = MapGridGetMetatileBehaviorAt(sprite->data[1], sprite->data[2]); + if (TryGetObjectEventIdByLocalIdAndMap(localId, mapNum, mapGroup, &objectEventId) || !MetatileBehavior_IsLongGrass(metatileBehavior) || (sprite->data[7] && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_LONG_GRASS); + } + else + { + objectEvent = &gObjectEvents[objectEventId]; + if ((objectEvent->currentCoords.x != sprite->data[1] || objectEvent->currentCoords.y != sprite->data[2]) && (objectEvent->previousCoords.x != sprite->data[1] || objectEvent->previousCoords.y != sprite->data[2])) + { + sprite->data[7] = TRUE; + } + UpdateObjectEventSpriteVisibility(sprite, 0); + sub_80DCD48(sprite, sprite->data[0], 0); + } +} + +u32 FldEff_JumpLongGrass(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[16], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = 18; + } + return 0; +} + +u32 FldEff_ShortGrass(void) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + u8 spriteId; + struct Sprite * sprite; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + objectEvent = &gObjectEvents[objectEventId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[30], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &(gSprites[spriteId]); + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[objectEvent->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[objectEvent->spriteId].pos1.x; + sprite->data[4] = gSprites[objectEvent->spriteId].pos1.y; + } + return 0; +} + +void UpdateShortGrassFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + s16 x; + s16 y; + const struct ObjectEventGraphicsInfo * graphicsInfo; + struct Sprite * linkedSprite; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId) || !gObjectEvents[objectEventId].inShortGrass) + { + FieldEffectStop(sprite, FLDEFF_SHORT_GRASS); + } + else + { + graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[objectEventId].graphicsId); + linkedSprite = &gSprites[gObjectEvents[objectEventId].spriteId]; + y = linkedSprite->pos1.y; + x = linkedSprite->pos1.x; + if (x != sprite->data[3] || y != sprite->data[4]) + { + sprite->data[3] = x; + sprite->data[4] = y; + if (sprite->animEnded) + { + StartSpriteAnim(sprite, 0); + } + } + sprite->pos1.x = x; + sprite->pos1.y = y; + sprite->pos2.y = (graphicsInfo->height >> 1) - 8; + sprite->subpriority = linkedSprite->subpriority - 1; + sprite->oam.priority = linkedSprite->oam.priority; + UpdateObjectEventSpriteVisibility(sprite, linkedSprite->invisible); + } +} + +u32 FldEff_SandFootprints(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[11], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[7] = FLDEFF_SAND_FOOTPRINTS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return 0; +} + +u32 FldEff_DeepSandFootprints(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[23], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[7] = FLDEFF_DEEP_SAND_FOOTPRINTS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return spriteId; +} + +u32 FldEff_BikeTireTracks(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[27], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[7] = FLDEFF_BIKE_TIRE_TRACKS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return spriteId; +} + +void (*const gFadeFootprintsTireTracksFuncs[])(struct Sprite * sprite) = { + FadeFootprintsTireTracks_Step0, + FadeFootprintsTireTracks_Step1 +}; + +void UpdateFootprintsTireTracksFieldEffect(struct Sprite * sprite) +{ + gFadeFootprintsTireTracksFuncs[sprite->data[0]](sprite); +} + +static void FadeFootprintsTireTracks_Step0(struct Sprite * sprite) +{ + // Wait 40 frames before the flickering starts. + if (++sprite->data[1] > 40) + sprite->data[0] = 1; + + UpdateObjectEventSpriteVisibility(sprite, FALSE); +} + +static void FadeFootprintsTireTracks_Step1(struct Sprite * sprite) +{ + sprite->invisible ^= 1; + sprite->data[1]++; + UpdateObjectEventSpriteVisibility(sprite, sprite->invisible); + if (sprite->data[1] > 56) + { + FieldEffectStop(sprite, sprite->data[7]); + } +} + +u32 FldEff_Splash(void) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + u8 spriteId; + struct Sprite * sprite; + const struct ObjectEventGraphicsInfo * graphicsInfo; + struct Sprite * linkedSprite; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + objectEvent = &gObjectEvents[objectEventId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + linkedSprite = &gSprites[objectEvent->spriteId]; + sprite->oam.priority = linkedSprite->oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->pos2.y = (graphicsInfo->height >> 1) - 4; + PlaySE(SE_MIZU); + } + return 0; +} + +void UpdateSplashFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + + if (sprite->animEnded || TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId)) + { + FieldEffectStop(sprite, FLDEFF_SPLASH); + } + else + { + sprite->pos1.x = gSprites[gObjectEvents[objectEventId].spriteId].pos1.x; + sprite->pos1.y = gSprites[gObjectEvents[objectEventId].spriteId].pos1.y; + UpdateObjectEventSpriteVisibility(sprite, FALSE); + } +} + +u32 FldEff_JumpSmallSplash(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[14], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = FLDEFF_JUMP_SMALL_SPLASH; + } + return 0; +} + +u32 FldEff_JumpBigSplash(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[12], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = FLDEFF_JUMP_BIG_SPLASH; + } + return 0; +} + +u32 FldEff_FeetInFlowingWater(void) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + u8 spriteId; + struct Sprite * sprite; + const struct ObjectEventGraphicsInfo * graphicsInfo; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + objectEvent = &gObjectEvents[objectEventId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + sprite = &gSprites[spriteId]; + sprite->callback = UpdateFeetInFlowingWaterFieldEffect; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[objectEvent->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = -1; + sprite->data[4] = -1; + sprite->pos2.y = (graphicsInfo->height >> 1) - 4; + StartSpriteAnim(sprite, 1); + } + return 0; +} + +static void UpdateFeetInFlowingWaterFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + struct Sprite * linkedSprite; + struct ObjectEvent * objectEvent; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId) || !gObjectEvents[objectEventId].inShallowFlowingWater) + { + FieldEffectStop(sprite, FLDEFF_FEET_IN_FLOWING_WATER); + } + else + { + objectEvent = &gObjectEvents[objectEventId]; + linkedSprite = &gSprites[objectEvent->spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y; + sprite->subpriority = linkedSprite->subpriority; + UpdateObjectEventSpriteVisibility(sprite, FALSE); + if (objectEvent->currentCoords.x != sprite->data[3] || objectEvent->currentCoords.y != sprite->data[4]) + { + sprite->data[3] = objectEvent->currentCoords.x; + sprite->data[4] = objectEvent->currentCoords.y; + if (!sprite->invisible) + { + PlaySE(SE_MIZU); + } + } + } +} + +u32 FldEff_Ripple(void) +{ + u8 spriteId; + struct Sprite * sprite; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[5], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = FLDEFF_RIPPLE; + } + return 0; +} + +u32 FldEff_HotSpringsWater(void) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + u8 spriteId; + struct Sprite * sprite; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + objectEvent = &gObjectEvents[objectEventId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[31], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[objectEvent->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[objectEvent->spriteId].pos1.x; + sprite->data[4] = gSprites[objectEvent->spriteId].pos1.y; + } + return 0; +} + +void UpdateHotSpringsWaterFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + const struct ObjectEventGraphicsInfo * graphicsInfo; + struct Sprite * linkedSprite; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId) || !gObjectEvents[objectEventId].inHotSprings) + { + FieldEffectStop(sprite, FLDEFF_HOT_SPRINGS_WATER); + } + else + { + graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[objectEventId].graphicsId); + linkedSprite = &gSprites[gObjectEvents[objectEventId].spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = (graphicsInfo->height >> 1) + linkedSprite->pos1.y - 8; + sprite->subpriority = linkedSprite->subpriority - 1; + UpdateObjectEventSpriteVisibility(sprite, FALSE); + } +} + +u32 FldEff_Unknown19(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[17], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = FLDEFF_UNKNOWN_19; + } + return 0; +} + +u32 FldEff_Unknown20(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[18], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = FLDEFF_UNKNOWN_20; + } + return 0; +} + +u32 FldEff_Unknown21(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[19], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = FLDEFF_UNKNOWN_21; + } + return 0; +} + +u32 FldEff_Unknown22(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[20], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = FLDEFF_UNKNOWN_22; + } + return 0; +} + +void StartAshFieldEffect(s16 x, s16 y, u16 metatileId, s16 d) +{ + gFieldEffectArguments[0] = x; + gFieldEffectArguments[1] = y; + gFieldEffectArguments[2] = 0x52; + gFieldEffectArguments[3] = 1; + gFieldEffectArguments[4] = metatileId; + gFieldEffectArguments[5] = d; + FieldEffectStart(FLDEFF_ASH); +} + +u32 FldEff_Ash(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite * sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8063BC4(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[6], x, y, gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[1] = gFieldEffectArguments[0]; + sprite->data[2] = gFieldEffectArguments[1]; + sprite->data[3] = gFieldEffectArguments[4]; + sprite->data[4] = gFieldEffectArguments[5]; + } + return 0; +} + +void (*const gAshFieldEffectFuncs[])(struct Sprite * sprite) = { + UpdateAshFieldEffect_Step0, + UpdateAshFieldEffect_Step1, + UpdateAshFieldEffect_Step2 +}; + +void UpdateAshFieldEffect(struct Sprite * sprite) +{ + gAshFieldEffectFuncs[sprite->data[0]](sprite); +} + +static void UpdateAshFieldEffect_Step0(struct Sprite * sprite) +{ + sprite->invisible = TRUE; + sprite->animPaused = TRUE; + if (--sprite->data[4] == 0) + sprite->data[0] = 1; +} + +static void UpdateAshFieldEffect_Step1(struct Sprite * sprite) +{ + sprite->invisible = FALSE; + sprite->animPaused = FALSE; + MapGridSetMetatileIdAt(sprite->data[1], sprite->data[2], sprite->data[3]); + CurrentMapDrawMetatileAt(sprite->data[1], sprite->data[2]); + gObjectEvents[gPlayerAvatar.objectEventId].triggerGroundEffectsOnMove = TRUE; + sprite->data[0] = 2; +} + +static void UpdateAshFieldEffect_Step2(struct Sprite * sprite) +{ + UpdateObjectEventSpriteVisibility(sprite, FALSE); + if (sprite->animEnded) + FieldEffectStop(sprite, FLDEFF_ASH); +} + +u32 FldEff_SurfBlob(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[7], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x96); + if (spriteId !=MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.paletteNum = 0; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = 0; + sprite->data[6] = -1; + sprite->data[7] = -1; + } + FieldEffectActiveListRemove(FLDEFF_SURF_BLOB); + return spriteId; +} + +void sub_80DC44C(u8 spriteId, u8 value) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF) | (value & 0xF); +} + +void sub_80DC478(u8 spriteId, u8 value) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF0) | ((value & 0xF) << 4); +} + +void sub_80DC4A4(u8 spriteId, u8 value, s16 data1) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF00) | ((value & 0xF) << 8); + gSprites[spriteId].data[1] = data1; +} + +static u8 sub_80DC4D8(struct Sprite * sprite) +{ + return sprite->data[0] & 0xF; +} + +static u8 sub_80DC4E0(struct Sprite * sprite) +{ + return (sprite->data[0] & 0xF0) >> 4; +} + +static u8 sub_80DC4EC(struct Sprite * sprite) +{ + return (sprite->data[0] & 0xF00) >> 8; +} + +void UpdateSurfBlobFieldEffect(struct Sprite * sprite) +{ + struct ObjectEvent * objectEvent; + struct Sprite * linkedSprite; + + objectEvent = &gObjectEvents[sprite->data[2]]; + linkedSprite = &gSprites[objectEvent->spriteId]; + SynchroniseSurfAnim(objectEvent, sprite); + sub_80DC588(objectEvent, sprite); + CreateBobbingEffect(objectEvent, linkedSprite, sprite); + sprite->oam.priority = linkedSprite->oam.priority; +} + +static void SynchroniseSurfAnim(struct ObjectEvent * objectEvent, struct Sprite * sprite) +{ + u8 surfBlobDirectionAnims[] = { + [DIR_NONE] = 0, + [DIR_SOUTH] = 0, + [DIR_NORTH] = 1, + [DIR_WEST] = 2, + [DIR_EAST] = 3 + }; + + if (sub_80DC4E0(sprite) == 0) + StartSpriteAnimIfDifferent(sprite, surfBlobDirectionAnims[objectEvent->movementDirection]); +} + +void sub_80DC588(struct ObjectEvent * objectEvent, struct Sprite * sprite) +{ + u8 i; + s16 x = objectEvent->currentCoords.x; + s16 y = objectEvent->currentCoords.y; + s32 spriteY = sprite->pos2.y; + + if (spriteY == 0 && (x != sprite->data[6] || y != sprite->data[7])) + { + sprite->data[5] = spriteY; + sprite->data[6] = x; + sprite->data[7] = y; + for (i = DIR_SOUTH; i <= DIR_EAST; i++, x = sprite->data[6], y = sprite->data[7]) + { + MoveCoords(i, &x, &y); + if (MapGridGetZCoordAt(x, y) == 3) + { + sprite->data[5] ++; + break; + } + } + } +} + +static void CreateBobbingEffect(struct ObjectEvent * objectEvent, struct Sprite * linkedSprite, struct Sprite * sprite) +{ + u16 unk_83FECFA[] = {7, 15}; + u8 v0 = sub_80DC4D8(sprite); + if (v0 != 0) + { + if (((u16)(++ sprite->data[4]) & unk_83FECFA[sprite->data[5]]) == 0) + { + sprite->pos2.y += sprite->data[3]; + } + if ((sprite->data[4] & 0x1F) == 0) + { + sprite->data[3] = -sprite->data[3]; + } + if (v0 != 2) + { + if (sub_80DC4EC(sprite) == 0) + linkedSprite->pos2.y = sprite->pos2.y; + else + linkedSprite->pos2.y = sprite->data[1] + sprite->pos2.y; + if (sprite->animCmdIndex != 0) + linkedSprite->pos2.y++; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + 8; + } + } +} + +u8 sub_80DC6B0(u8 oldSpriteId) +{ + u8 spriteId; + struct Sprite * sprite; + + spriteId = CreateSpriteAtEnd(&gDummySpriteTemplate, 0, 0, -1); + sprite = &gSprites[spriteId]; + sprite->callback = sub_80DC700; + sprite->invisible = TRUE; + sprite->data[0] = oldSpriteId; + sprite->data[1] = 1; + return spriteId; +} + +static void sub_80DC700(struct Sprite * sprite) +{ + struct Sprite * oldSprite; + + oldSprite = &gSprites[sprite->data[0]]; + if (((sprite->data[2]++) & 0x03) == 0) + { + oldSprite->pos2.y += sprite->data[1]; + } + if ((sprite->data[2] & 0x0F) == 0) + { + sprite->data[1] = -sprite->data[1]; + } +} + +u32 FldEff_Dust(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[9], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data[0] = gFieldEffectArguments[2]; + sprite->data[1] = 10; + } + return 0; +} + +u32 FldEff_SandPile(void) +{ + u8 objectEventId; + struct ObjectEvent * objectEvent; + u8 spriteId; + struct Sprite * sprite; + const struct ObjectEventGraphicsInfo * graphicsInfo; + + objectEventId = GetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + objectEvent = &gObjectEvents[objectEventId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[29], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[objectEvent->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[objectEvent->spriteId].pos1.x; + sprite->data[4] = gSprites[objectEvent->spriteId].pos1.y; + sprite->pos2.y = (graphicsInfo->height >> 1) - 2; + SeekSpriteAnim(sprite, 2); + } + return 0; +} + +void UpdateSandPileFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + s16 x; + s16 y; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &objectEventId) || !gObjectEvents[objectEventId].inSandPile) + { + FieldEffectStop(sprite, FLDEFF_SAND_PILE); + } + else + { + y = gSprites[gObjectEvents[objectEventId].spriteId].pos1.y; + x = gSprites[gObjectEvents[objectEventId].spriteId].pos1.x; + if (x != sprite->data[3] || y != sprite->data[4]) + { + sprite->data[3] = x; + sprite->data[4] = y; + if (sprite->animEnded) + { + StartSpriteAnim(sprite, 0); + } + } + sprite->pos1.x = x; + sprite->pos1.y = y; + sprite->subpriority = gSprites[gObjectEvents[objectEventId].spriteId].subpriority; + UpdateObjectEventSpriteVisibility(sprite, FALSE); + } +} + +u32 FldEff_Bubbles(void) +{ + u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 0); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[34], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x52); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = 1; + } + return 0; +} + +void UpdateBubblesFieldEffect(struct Sprite * sprite) +{ + sprite->data[0] += 0x80; + sprite->data[0] &= 0x100; + sprite->pos1.y -= sprite->data[0] >> 8; + UpdateObjectEventSpriteVisibility(sprite, FALSE); + if (sprite->invisible || sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_BUBBLES); + } +} + +u32 FldEff_BerryTreeGrowthSparkle(void) +{ + /*u8 spriteId; + struct Sprite * sprite; + + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 4); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[22], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->oam.paletteNum = 5; + sprite->data[0] = FLDEFF_BERRY_TREE_GROWTH_SPARKLE; + }*/ + return 0; +} + +u32 ShowTreeDisguiseFieldEffect(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_TREE_DISGUISE, 24, 4); +} + +u32 ShowMountainDisguiseFieldEffect(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_MOUNTAIN_DISGUISE, 25, 3); +} + +u32 ShowSandDisguiseFieldEffect(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_SAND_DISGUISE, 28, 2); +} + +static u32 ShowDisguiseFieldEffect(u8 fldEff, u8 templateIdx, u8 paletteNum) +{ + u8 spriteId; + struct Sprite * sprite; + + if (TryGetObjectEventIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &spriteId)) + { + FieldEffectActiveListRemove(fldEff); + return MAX_SPRITES; + } + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[templateIdx], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled ++; + sprite->oam.paletteNum = paletteNum; + sprite->data[1] = fldEff; + sprite->data[2] = gFieldEffectArguments[0]; + sprite->data[3] = gFieldEffectArguments[1]; + sprite->data[4] = gFieldEffectArguments[2]; + } + return spriteId; +} + +void UpdateDisguiseFieldEffect(struct Sprite * sprite) +{ + u8 objectEventId; + const struct ObjectEventGraphicsInfo * graphicsInfo; + struct Sprite * linkedSprite; + + if (TryGetObjectEventIdByLocalIdAndMap(sprite->data[2], sprite->data[3], sprite->data[4], &objectEventId)) + { + FieldEffectStop(sprite, sprite->data[1]); + } + + graphicsInfo = GetObjectEventGraphicsInfo(gObjectEvents[objectEventId].graphicsId); + linkedSprite = &gSprites[gObjectEvents[objectEventId].spriteId]; + sprite->invisible = linkedSprite->invisible; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = (graphicsInfo->height >> 1) + linkedSprite->pos1.y - 16; + sprite->subpriority = linkedSprite->subpriority - 1; + if (sprite->data[0] == 1) + { + sprite->data[0] ++; + StartSpriteAnim(sprite, 1); + } + if (sprite->data[0] == 2 && sprite->animEnded) + { + sprite->data[7] = 1; + } + if (sprite->data[0] == 3) + { + FieldEffectStop(sprite, sprite->data[1]); + } +} + +void sub_80DCBB8(struct ObjectEvent * objectEvent) +{ + if (objectEvent->directionSequenceIndex == 1) + { + gSprites[objectEvent->fieldEffectSpriteId].data[0]++; + } +} + +bool8 sub_80DCBE0(struct ObjectEvent * objectEvent) +{ + struct Sprite * sprite; + + if (objectEvent->directionSequenceIndex == 2) + { + return TRUE; + } + if (objectEvent->directionSequenceIndex == 0) + { + return TRUE; + } + sprite = &gSprites[objectEvent->fieldEffectSpriteId]; + if (sprite->data[7]) + { + objectEvent->directionSequenceIndex = 2; + sprite->data[0]++; + return TRUE; + } + return FALSE; +} + +u32 FldEff_Sparkle(void) +{ + u8 spriteId; + + gFieldEffectArguments[0] += 7; + gFieldEffectArguments[1] += 7; + sub_8063BC4((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[35], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x52); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].oam.priority = gFieldEffectArguments[2]; + gSprites[spriteId].coordOffsetEnabled = TRUE; + } + return 0; +} + +void UpdateSparkleFieldEffect(struct Sprite * sprite) +{ + if (sprite->data[0] == 0) + { + if (sprite->animEnded) + { + sprite->invisible = TRUE; + sprite->data[0]++; + } + + if (sprite->data[0] == 0) + return; + } + + if (++sprite->data[1] > 34) + FieldEffectStop(sprite, FLDEFF_SPARKLE); +} + +void sub_80DCCE0(struct Sprite * sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, sprite->data[1]); + } + else + { + UpdateObjectEventSpriteVisibility(sprite, FALSE); + SetObjectSubpriorityByZCoord(sprite->data[0], sprite, 0); + } +} + +void WaitFieldEffectSpriteAnim(struct Sprite * sprite) +{ + if (sprite->animEnded) + FieldEffectStop(sprite, sprite->data[0]); + else + UpdateObjectEventSpriteVisibility(sprite, FALSE); +} + +static void sub_80DCD48(struct Sprite * sprite, u8 z, u8 offset) +{ + u8 i; + s16 var, xhi, lyhi, yhi, ylo; + const struct ObjectEventGraphicsInfo * graphicsInfo; // Unused Variable + struct Sprite * linkedSprite; + + SetObjectSubpriorityByZCoord(z, sprite, offset); + for (i = 0; i < OBJECT_EVENTS_COUNT; i ++) + { + struct ObjectEvent * objectEvent = &gObjectEvents[i]; + if (objectEvent->active) + { + graphicsInfo = GetObjectEventGraphicsInfo(objectEvent->graphicsId); + linkedSprite = &gSprites[objectEvent->spriteId]; + xhi = sprite->pos1.x + sprite->centerToCornerVecX; + var = sprite->pos1.x - sprite->centerToCornerVecX; + if (xhi < linkedSprite->pos1.x && var > linkedSprite->pos1.x) + { + lyhi = linkedSprite->pos1.y + linkedSprite->centerToCornerVecY; + var = linkedSprite->pos1.y; + ylo = sprite->pos1.y - sprite->centerToCornerVecY; + yhi = ylo + linkedSprite->centerToCornerVecY; + if ((lyhi < yhi || lyhi < ylo) && var > yhi && sprite->subpriority <= linkedSprite->subpriority) + { + sprite->subpriority = linkedSprite->subpriority + 2; + break; + } + } + } + } +} diff --git a/src/quest_log_objects.c b/src/quest_log_objects.c index 5676c20fc..7d8300cd7 100644 --- a/src/quest_log_objects.c +++ b/src/quest_log_objects.c @@ -39,8 +39,8 @@ void SetQuestLogObjectEventsData(struct QuestLog * questLog) questLog->unk_008[i].x = gObjectEvents[i].currentCoords.x; questLog->unk_008[i].y = gObjectEvents[i].currentCoords.y; questLog->unk_008[i].trainerRange_berryTreeId = gObjectEvents[i].trainerRange_berryTreeId; - questLog->unk_008[i].mapobj_unk_1F = gObjectEvents[i].mapobj_unk_1F; - questLog->unk_008[i].mapobj_unk_21 = gObjectEvents[i].mapobj_unk_21; + questLog->unk_008[i].previousMetatileBehavior = gObjectEvents[i].previousMetatileBehavior; + questLog->unk_008[i].directionSequenceIndex = gObjectEvents[i].directionSequenceIndex; questLog->unk_008[i].animId = gObjectEvents[i].animId; } } @@ -83,8 +83,8 @@ void sub_815A1F8(const struct QuestLog * questLog, const struct ObjectEventTempl gObjectEvents[i].currentCoords.x = questLogObjectEvents[i].x; gObjectEvents[i].currentCoords.y = questLogObjectEvents[i].y; gObjectEvents[i].trainerRange_berryTreeId = questLogObjectEvents[i].trainerRange_berryTreeId; - gObjectEvents[i].mapobj_unk_1F = questLogObjectEvents[i].mapobj_unk_1F; - gObjectEvents[i].mapobj_unk_21 = questLogObjectEvents[i].mapobj_unk_21; + gObjectEvents[i].previousMetatileBehavior = questLogObjectEvents[i].previousMetatileBehavior; + gObjectEvents[i].directionSequenceIndex = questLogObjectEvents[i].directionSequenceIndex; gObjectEvents[i].animId = questLogObjectEvents[i].animId; for (j = 0; j < 0x40; j++) @@ -98,28 +98,28 @@ void sub_815A1F8(const struct QuestLog * questLog, const struct ObjectEventTempl } } - gObjectEvents[i].mapobj_unk_1E = MapGridGetMetatileBehaviorAt(gObjectEvents[i].currentCoords.x, gObjectEvents[i].currentCoords.y); - if (gObjectEvents[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y))) + gObjectEvents[i].currentMetatileBehavior = MapGridGetMetatileBehaviorAt(gObjectEvents[i].currentCoords.x, gObjectEvents[i].currentCoords.y); + if (gObjectEvents[i].previousMetatileBehavior == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y))) { gObjectEvents[i].previousCoords.x = gObjectEvents[i].currentCoords.x; gObjectEvents[i].previousCoords.y = gObjectEvents[i].currentCoords.y; } - else if (gObjectEvents[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x - 1), (s16)(gObjectEvents[i].currentCoords.y))) + else if (gObjectEvents[i].previousMetatileBehavior == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x - 1), (s16)(gObjectEvents[i].currentCoords.y))) { gObjectEvents[i].previousCoords.x = gObjectEvents[i].currentCoords.x - 1; gObjectEvents[i].previousCoords.y = gObjectEvents[i].currentCoords.y; } - else if (gObjectEvents[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x + 1), (s16)(gObjectEvents[i].currentCoords.y))) + else if (gObjectEvents[i].previousMetatileBehavior == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x + 1), (s16)(gObjectEvents[i].currentCoords.y))) { gObjectEvents[i].previousCoords.x = gObjectEvents[i].currentCoords.x + 1; gObjectEvents[i].previousCoords.y = gObjectEvents[i].currentCoords.y; } - else if (gObjectEvents[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y - 1))) + else if (gObjectEvents[i].previousMetatileBehavior == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y - 1))) { gObjectEvents[i].previousCoords.x = gObjectEvents[i].currentCoords.x; gObjectEvents[i].previousCoords.y = gObjectEvents[i].currentCoords.y - 1; } - else if (gObjectEvents[i].mapobj_unk_1F == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y + 1))) + else if (gObjectEvents[i].previousMetatileBehavior == MapGridGetMetatileBehaviorAt((s16)(gObjectEvents[i].currentCoords.x), (s16)(gObjectEvents[i].currentCoords.y + 1))) { gObjectEvents[i].previousCoords.x = gObjectEvents[i].currentCoords.x; gObjectEvents[i].previousCoords.y = gObjectEvents[i].currentCoords.y + 1; @@ -140,7 +140,7 @@ void sub_815A540(void) { struct ObjectEvent * objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; SetPlayerAvatarTransitionFlags(0x01); - DestroySprite(&gSprites[objectEvent->mapobj_unk_1A]); + DestroySprite(&gSprites[objectEvent->fieldEffectSpriteId]); } } } diff --git a/src/quest_log_player.c b/src/quest_log_player.c index ccf0565fb..b57e3930c 100644 --- a/src/quest_log_player.c +++ b/src/quest_log_player.c @@ -58,7 +58,7 @@ static void sub_81504A8(void) { struct ObjectEvent *objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; sub_81507BC(objectEvent, GetPlayerAvatarGraphicsIdByStateId(0)); - ObjectEventTurn(objectEvent, objectEvent->placeholder18); + ObjectEventTurn(objectEvent, objectEvent->movementDirection); SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_ON_FOOT); } @@ -66,7 +66,7 @@ static void sub_81504E8(void) { struct ObjectEvent *objectEvent = &gObjectEvents[gPlayerAvatar.objectEventId]; sub_81507BC(objectEvent, GetPlayerAvatarGraphicsIdByStateId(1)); - ObjectEventTurn(objectEvent, objectEvent->placeholder18); + ObjectEventTurn(objectEvent, objectEvent->movementDirection); SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_MACH_BIKE); sub_80BD620(0, 0); } @@ -125,7 +125,7 @@ static void sub_81505C4(u8 taskId) sub_81507BC(objectEvent, GetPlayerAvatarGraphicsIdByStateId(0)); else sub_81507BC(objectEvent, GetPlayerAvatarGraphicsIdByStateId(2)); - ObjectEventTurn(objectEvent, objectEvent->placeholder18); + ObjectEventTurn(objectEvent, objectEvent->movementDirection); sprite->pos2.x = 0; sprite->pos2.y = 0; ScriptContext2_Disable(); @@ -143,13 +143,13 @@ static void sub_8150708(void) if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING)) { sub_81507BC(objectEvent, GetPlayerAvatarGraphicsIdByStateId(2)); - ObjectEventTurn(objectEvent, objectEvent->placeholder18); + ObjectEventTurn(objectEvent, objectEvent->movementDirection); SetPlayerAvatarStateMask(PLAYER_AVATAR_FLAG_SURFING); gFieldEffectArguments[0] = objectEvent->currentCoords.x; gFieldEffectArguments[1] = objectEvent->currentCoords.y; gFieldEffectArguments[2] = gPlayerAvatar.objectEventId; fieldEffectId = FieldEffectStart(FLDEFF_SURF_BLOB); - objectEvent->mapobj_unk_1A = fieldEffectId; + objectEvent->fieldEffectSpriteId = fieldEffectId; sub_80DC44C(fieldEffectId, 1); } } |