diff options
Diffstat (limited to 'src/field_effect_helpers.c')
-rwxr-xr-x | src/field_effect_helpers.c | 1774 |
1 files changed, 1774 insertions, 0 deletions
diff --git a/src/field_effect_helpers.c b/src/field_effect_helpers.c new file mode 100755 index 000000000..304f7a6f9 --- /dev/null +++ b/src/field_effect_helpers.c @@ -0,0 +1,1774 @@ +#include "global.h" +#include "sprite.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "sound.h" +#include "event_object_movement.h" +#include "field_camera.h" +#include "field_weather.h" +#include "field_effect.h" +#include "field_effect_helpers.h" +#include "constants/songs.h" +#include "gpu_regs.h" +#include "trig.h" + +void objc_reflection_maybe(struct Sprite *); +void npc_pal_op(struct EventObject *eventObject, struct Sprite *sprite); +void npc_pal_op_A(struct EventObject *, u8); +void npc_pal_op_B(struct EventObject *, u8); +void sub_81561FC(struct Sprite *, u8, u8); +void sub_8154C7C(struct Sprite *); +void sub_8154CA0(struct Sprite *); +void sub_8154FB4(struct Sprite *); +void sub_815547C(struct Sprite *); +void sub_81554AC(struct Sprite *); +void sub_815550C(struct Sprite *); +void sub_81556B0(struct EventObject *, struct Sprite *); +void sub_81556E8(struct EventObject *, struct Sprite *); +void sub_815577C(struct EventObject *, struct Sprite *, struct Sprite *); +void sub_8155850(struct Sprite *); +u32 ShowDisguiseFieldEffect(u8, u8, u8); + +void SetUpReflection(struct EventObject *eventObject, struct Sprite *sprite, bool8 stillReflection) +{ + struct Sprite *reflectionSprite; + + reflectionSprite = &gSprites[CreateCopySpriteAt(sprite, sprite->pos1.x, sprite->pos1.y, 0x98)]; + reflectionSprite->callback = objc_reflection_maybe; + 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] = eventObject->localId; + reflectionSprite->data[7] = stillReflection; + npc_pal_op(eventObject, reflectionSprite); + + if (!stillReflection) + reflectionSprite->oam.affineMode = ST_OAM_AFFINE_NORMAL; +} + +s16 sub_8153F98(struct EventObject *eventObject) +{ + return GetEventObjectGraphicsInfo(eventObject->graphicsId)->height - 2; +} + +void npc_pal_op(struct EventObject *eventObject, struct Sprite *sprite) +{ + u8 bridgeType; + u16 bridgeReflectionVerticalOffsets[] = { 12, 28, 44 }; + sprite->data[2] = 0; + if (!GetEventObjectGraphicsInfo(eventObject->graphicsId)->disableReflectionPaletteLoad && ((bridgeType = MetatileBehavior_GetBridgeSth(eventObject->previousMetatileBehavior)) || (bridgeType = MetatileBehavior_GetBridgeSth(eventObject->currentMetatileBehavior)))) + { + sprite->data[2] = bridgeReflectionVerticalOffsets[bridgeType - 1]; + npc_pal_op_A(eventObject, sprite->oam.paletteNum); + } + else + { + npc_pal_op_B(eventObject, sprite->oam.paletteNum); + } +} + +void npc_pal_op_B(struct EventObject *eventObject, u8 paletteIndex) +{ + const struct EventObjectGraphicsInfo *graphicsInfo; + + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + if (graphicsInfo->paletteTag2 != 0x11ff) + { + 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. +void npc_pal_op_A(struct EventObject *eventObject, u8 paletteNum) +{ + const struct EventObjectGraphicsInfo *graphicsInfo; + + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + if (graphicsInfo->paletteTag2 != 0x11ff) + { + PatchObjectPalette(graphicsInfo->paletteTag2, paletteNum); + UpdateSpritePaletteWithWeather(paletteNum); + } +} + +void objc_reflection_maybe(struct Sprite *reflectionSprite) +{ + struct EventObject *eventObject; + struct Sprite *mainSprite; + + eventObject = &gEventObjects[reflectionSprite->data[0]]; + mainSprite = &gSprites[eventObject->spriteId]; + if (!eventObject->active || !eventObject->hasReflection || eventObject->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 | 0x10; + 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 + sub_8153F98(eventObject) + 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 (eventObject->unk3_3 == 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 & 0x8) + reflectionSprite->oam.matrixNum = 1; + } + } +} + +extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[]; + +u8 sub_8154228(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 objid_set_invisible(u8 spriteId) +{ + gSprites[spriteId].invisible = TRUE; +} + +void sub_8154298(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) + { + sub_8093038(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 oei_shadow(void) +{ + u8 eventObjectId; + const struct EventObjectGraphicsInfo *graphicsInfo; + u8 spriteId; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + graphicsInfo = GetEventObjectGraphicsInfo(gEventObjects[eventObjectId].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 oamc_shadow(struct Sprite *sprite) +{ + u8 eventObjectId; + struct EventObject *eventObject; + struct Sprite *linkedSprite; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + else + { + eventObject = &gEventObjects[eventObjectId]; + linkedSprite = &gSprites[eventObject->spriteId]; + sprite->oam.priority = linkedSprite->oam.priority; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + sprite->data[3]; + if (!eventObject->active || !eventObject->hasShadow + || MetatileBehavior_IsPokeGrass(eventObject->currentMetatileBehavior) + || MetatileBehavior_IsSurfableWaterOrUnderwater(eventObject->currentMetatileBehavior) + || MetatileBehavior_IsSurfableWaterOrUnderwater(eventObject->previousMetatileBehavior) + || MetatileBehavior_IsReflective(eventObject->currentMetatileBehavior) + || MetatileBehavior_IsReflective(eventObject->previousMetatileBehavior)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + } +} + +u32 oei_grass_normal(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_80930E0(&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 unc_grass_normal(struct Sprite *sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 eventObjectId; + struct EventObject *eventObject; + + 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 (TryGetEventObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &eventObjectId) || !MetatileBehavior_IsTallGrass(metatileBehavior) || (sprite->data[7] && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_TALL_GRASS); + } + else + { + eventObject = &gEventObjects[eventObjectId]; + if ((eventObject->currentCoords.x != sprite->data[1] || eventObject->currentCoords.y != sprite->data[2]) && (eventObject->previousCoords.x != sprite->data[1] || eventObject->previousCoords.y != sprite->data[2])) + sprite->data[7] = TRUE; + + metatileBehavior = 0; + if (sprite->animCmdIndex == 0) + metatileBehavior = 4; + + UpdateEventObjectSpriteVisibility(sprite, 0); + sub_81561FC(sprite, sprite->data[0], metatileBehavior); + } +} + +u32 sub_8154658(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_81546C8(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 == unc_grass_normal && (x == sprite->data[1] && y == sprite->data[2]) && (localId == (u8)(sprite->data[3] >> 8) && mapNum == (sprite->data[3] & 0xFF) && mapGroup == sprite->data[4])) + return i; + } + } + + return MAX_SPRITES; +} + +u32 sub_8154758(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_80930E0(&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 unc_grass_tall(struct Sprite *sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 eventObjectId; + struct EventObject *eventObject; + + 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 (TryGetEventObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &eventObjectId) || !MetatileBehavior_IsLongGrass(metatileBehavior) || (sprite->data[7] && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_LONG_GRASS); + } + else + { + eventObject = &gEventObjects[eventObjectId]; + if ((eventObject->currentCoords.x != sprite->data[1] || eventObject->currentCoords.y != sprite->data[2]) && (eventObject->previousCoords.x != sprite->data[1] || eventObject->previousCoords.y != sprite->data[2])) + { + sprite->data[7] = TRUE; + } + UpdateEventObjectSpriteVisibility(sprite, 0); + sub_81561FC(sprite, sprite->data[0], 0); + } +} + +u32 sub_81548FC(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_815496C(void) +{ + u8 eventObjectId; + struct EventObject *eventObject; + u8 spriteId; + struct Sprite *sprite; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + eventObject = &gEventObjects[eventObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[30], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &(gSprites[spriteId]); + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[eventObject->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[eventObject->spriteId].pos1.x; + sprite->data[4] = gSprites[eventObject->spriteId].pos1.y; + } + return 0; +} + +void sub_8154A10(struct Sprite *sprite) +{ + u8 eventObjectId; + s16 x; + s16 y; + const struct EventObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId) || !gEventObjects[eventObjectId].inShortGrass) + { + FieldEffectStop(sprite, FLDEFF_SHORT_GRASS); + } + else + { + graphicsInfo = GetEventObjectGraphicsInfo(gEventObjects[eventObjectId].graphicsId); + linkedSprite = &gSprites[gEventObjects[eventObjectId].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; + UpdateEventObjectSpriteVisibility(sprite, linkedSprite->invisible); + } +} + +u32 sub_8154B04(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8154B78(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8154BEC(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 *) = { + sub_8154C7C, + sub_8154CA0 +}; + +void sub_8154C60(struct Sprite *sprite) +{ + gFadeFootprintsTireTracksFuncs[sprite->data[0]](sprite); +} + +void sub_8154C7C(struct Sprite *sprite) +{ + // Wait 40 frames before the flickering starts. + if (++sprite->data[1] > 40) + sprite->data[0] = 1; + + UpdateEventObjectSpriteVisibility(sprite, FALSE); +} + +void sub_8154CA0(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + sprite->data[1]++; + UpdateEventObjectSpriteVisibility(sprite, sprite->invisible); + if (sprite->data[1] > 56) + { + FieldEffectStop(sprite, sprite->data[7]); + } +} + +u32 sub_8154CEC(void) +{ + u8 eventObjectId; + struct EventObject *eventObject; + u8 spriteId; + struct Sprite *sprite; + const struct EventObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + eventObject = &gEventObjects[eventObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + linkedSprite = &gSprites[eventObject->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 sub_8154D90(struct Sprite *sprite) +{ + u8 eventObjectId; + + if (sprite->animEnded || TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId)) + { + FieldEffectStop(sprite, FLDEFF_SPLASH); + } + else + { + sprite->pos1.x = gSprites[gEventObjects[eventObjectId].spriteId].pos1.x; + sprite->pos1.y = gSprites[gEventObjects[eventObjectId].spriteId].pos1.y; + UpdateEventObjectSpriteVisibility(sprite, FALSE); + } +} + +u32 sub_8154E1C(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 oei_water_drop_tall(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8154EFC(void) +{ + u8 eventObjectId; + struct EventObject *eventObject; + u8 spriteId; + struct Sprite *sprite; + const struct EventObjectGraphicsInfo *graphicsInfo; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + eventObject = &gEventObjects[eventObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->callback = sub_8154FB4; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[eventObject->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; +} + +void sub_8154FB4(struct Sprite *sprite) +{ + u8 eventObjectId; + struct Sprite *linkedSprite; + struct EventObject *eventObject; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId) || !gEventObjects[eventObjectId].inShallowFlowingWater) + { + FieldEffectStop(sprite, FLDEFF_FEET_IN_FLOWING_WATER); + } + else + { + eventObject = &gEventObjects[eventObjectId]; + linkedSprite = &gSprites[eventObject->spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y; + sprite->subpriority = linkedSprite->subpriority; + UpdateEventObjectSpriteVisibility(sprite, FALSE); + if (eventObject->currentCoords.x != sprite->data[3] || eventObject->currentCoords.y != sprite->data[4]) + { + sprite->data[3] = eventObject->currentCoords.x; + sprite->data[4] = eventObject->currentCoords.y; + if (!sprite->invisible) + { + PlaySE(SE_MIZU); + } + } + } +} + +u32 oei_ripples(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 sub_81550B4(void) +{ + u8 eventObjectId; + struct EventObject *eventObject; + u8 spriteId; + struct Sprite *sprite; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + eventObject = &gEventObjects[eventObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[31], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[eventObject->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[eventObject->spriteId].pos1.x; + sprite->data[4] = gSprites[eventObject->spriteId].pos1.y; + } + return 0; +} + +void sub_8155158(struct Sprite *sprite) +{ + u8 eventObjectId; + const struct EventObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId) || !gEventObjects[eventObjectId].inHotSprings) + { + FieldEffectStop(sprite, FLDEFF_HOT_SPRINGS_WATER); + } + else + { + graphicsInfo = GetEventObjectGraphicsInfo(gEventObjects[eventObjectId].graphicsId); + linkedSprite = &gSprites[gEventObjects[eventObjectId].spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = (graphicsInfo->height >> 1) + linkedSprite->pos1.y - 8; + sprite->subpriority = linkedSprite->subpriority - 1; + UpdateEventObjectSpriteVisibility(sprite, FALSE); + } +} + +u32 sub_81551F0(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_815525C(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_81552C8(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8155334(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 ash(s16 x, s16 y, u16 c, s16 d) +{ + gFieldEffectArguments[0] = x; + gFieldEffectArguments[1] = y; + gFieldEffectArguments[2] = 0x52; + gFieldEffectArguments[3] = 1; + gFieldEffectArguments[4] = c; + gFieldEffectArguments[5] = d; + FieldEffectStart(FLDEFF_ASH); +} + +u32 oei_ash(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_80930E0(&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 *) = { + sub_815547C, + sub_81554AC, + sub_815550C +}; + +void sub_8155460(struct Sprite *sprite) +{ + gAshFieldEffectFuncs[sprite->data[0]](sprite); +} + +void sub_815547C(struct Sprite *sprite) +{ + sprite->invisible = TRUE; + sprite->animPaused = TRUE; + if (--sprite->data[4] == 0) + sprite->data[0] = 1; +} + +void sub_81554AC(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]); + gEventObjects[gPlayerAvatar.eventObjectId].triggerGroundEffectsOnMove = TRUE; + sprite->data[0] = 2; +} + +void sub_815550C(struct Sprite *sprite) +{ + UpdateEventObjectSpriteVisibility(sprite, FALSE); + if (sprite->animEnded) + FieldEffectStop(sprite, FLDEFF_ASH); +} + +u32 sub_8155534(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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] = -1; + sprite->data[6] = -1; + sprite->data[7] = -1; + } + FieldEffectActiveListRemove(FLDEFF_SURF_BLOB); + return spriteId; +} + +void sub_81555AC(u8 spriteId, u8 value) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF) | (value & 0xF); +} + +void sub_81555D8(u8 spriteId, u8 value) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF0) | ((value & 0xF) << 4); +} + +void sub_8155604(u8 spriteId, u8 value, s16 data1) +{ + gSprites[spriteId].data[0] = (gSprites[spriteId].data[0] & ~0xF00) | ((value & 0xF) << 8); + gSprites[spriteId].data[1] = data1; +} + +u8 sub_8155638(struct Sprite *sprite) +{ + return sprite->data[0] & 0xF; +} + +u8 sub_8155640(struct Sprite *sprite) +{ + return (sprite->data[0] & 0xF0) >> 4; +} + +u8 sub_815564C(struct Sprite *sprite) +{ + return (sprite->data[0] & 0xF00) >> 8; +} + +void sub_8155658(struct Sprite *sprite) +{ + struct EventObject *eventObject; + struct Sprite *linkedSprite; + + eventObject = &gEventObjects[sprite->data[2]]; + linkedSprite = &gSprites[eventObject->spriteId]; + sub_81556B0(eventObject, sprite); + sub_81556E8(eventObject, sprite); + sub_815577C(eventObject, linkedSprite, sprite); + sprite->oam.priority = linkedSprite->oam.priority; +} + +void sub_81556B0(struct EventObject *eventObject, struct Sprite *sprite) +{ + u8 surfBlobDirectionAnims[] = { + 0, // DIR_NONE + 0, // DIR_SOUTH + 1, // DIR_NORTH + 2, // DIR_WEST + 3, // DIR_EAST + 0, + 0, + 1, + 1, + }; + + if (sub_8155640(sprite) == 0) + StartSpriteAnimIfDifferent(sprite, surfBlobDirectionAnims[eventObject->movementDirection]); +} + +#ifdef NONMATCHING +void sub_81556E8(struct EventObject *eventObject, struct Sprite *sprite) +{ + s16 x; + s16 y; + u8 i; + + x = eventObject->currentCoords.x; + y = eventObject->currentCoords.y; + if (sprite->pos2.y == 0 && (x != sprite->data[6] || y != sprite->data[7])) + { + sprite->data[5] = sprite->pos2.y; + for (sprite->data[6] = x, sprite->data[7] = y, 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; + } + } + } +} +#else +NAKED void sub_81556E8(struct EventObject *eventObject, struct Sprite *sprite) +{ + asm_unified("push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + sub sp, 0x4\n\ + adds r4, r1, 0\n\ + ldrh r2, [r0, 0x10]\n\ + mov r1, sp\n\ + strh r2, [r1]\n\ + ldrh r1, [r0, 0x12]\n\ + mov r0, sp\n\ + adds r0, 0x2\n\ + strh r1, [r0]\n\ + movs r2, 0x26\n\ + ldrsh r3, [r4, r2]\n\ + mov r8, r0\n\ + cmp r3, 0\n\ + bne _08155770\n\ + mov r0, sp\n\ + movs r5, 0\n\ + ldrsh r2, [r0, r5]\n\ + movs r5, 0x3A\n\ + ldrsh r0, [r4, r5]\n\ + cmp r2, r0\n\ + bne _08155724\n\ + lsls r0, r1, 16\n\ + asrs r0, 16\n\ + movs r5, 0x3C\n\ + ldrsh r1, [r4, r5]\n\ + cmp r0, r1\n\ + beq _08155770\n\ +_08155724:\n\ + strh r3, [r4, 0x38]\n\ + strh r2, [r4, 0x3A]\n\ + mov r1, r8\n\ + movs r2, 0\n\ + ldrsh r0, [r1, r2]\n\ + strh r0, [r4, 0x3C]\n\ + movs r5, 0x1\n\ + mov r7, r8\n\ + mov r6, sp\n\ +_08155736:\n\ + adds r0, r5, 0\n\ + mov r1, sp\n\ + adds r2, r7, 0\n\ + bl MoveCoords\n\ + movs r1, 0\n\ + ldrsh r0, [r6, r1]\n\ + movs r2, 0\n\ + ldrsh r1, [r7, r2]\n\ + bl MapGridGetZCoordAt\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x3\n\ + bne _0815575C\n\ + ldrh r0, [r4, 0x38]\n\ + adds r0, 0x1\n\ + strh r0, [r4, 0x38]\n\ + b _08155770\n\ +_0815575C:\n\ + adds r0, r5, 0x1\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + ldrh r0, [r4, 0x3A]\n\ + strh r0, [r6]\n\ + ldrh r0, [r4, 0x3C]\n\ + mov r1, r8\n\ + strh r0, [r1]\n\ + cmp r5, 0x4\n\ + bls _08155736\n\ +_08155770:\n\ + add sp, 0x4\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0"); +} +#endif + +void sub_815577C(struct EventObject *eventObject, struct Sprite *linkedSprite, struct Sprite *sprite) +{ + u16 unk_085CDC6A[] = {3, 7}; + u8 v0 = sub_8155638(sprite); + if (v0 != 0) + { + if (((u16)(++ sprite->data[4]) & unk_085CDC6A[sprite->data[5]]) == 0) + { + sprite->pos2.y += sprite->data[3]; + } + if ((sprite->data[4] & 0x0F) == 0) + { + sprite->data[3] = -sprite->data[3]; + } + if (v0 != 2) + { + if (sub_815564C(sprite) == 0) + linkedSprite->pos2.y = sprite->pos2.y; + else + linkedSprite->pos2.y = sprite->data[1] + sprite->pos2.y; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + 8; + } + } +} + +u8 sub_8155800(u8 oldSpriteId) +{ + u8 spriteId; + struct Sprite *sprite; + + spriteId = CreateSpriteAtEnd(&gDummySpriteTemplate, 0, 0, -1); + sprite = &gSprites[spriteId]; + sprite->callback = sub_8155850; + sprite->invisible = TRUE; + sprite->data[0] = oldSpriteId; + sprite->data[1] = 1; + return spriteId; +} + +void sub_8155850(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 sub_8155890(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8155900(void) +{ + u8 eventObjectId; + struct EventObject *eventObject; + u8 spriteId; + struct Sprite *sprite; + const struct EventObjectGraphicsInfo *graphicsInfo; + + eventObjectId = GetEventObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + eventObject = &gEventObjects[eventObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[29], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[eventObject->spriteId].oam.priority; + sprite->data[0] = gFieldEffectArguments[0]; + sprite->data[1] = gFieldEffectArguments[1]; + sprite->data[2] = gFieldEffectArguments[2]; + sprite->data[3] = gSprites[eventObject->spriteId].pos1.x; + sprite->data[4] = gSprites[eventObject->spriteId].pos1.y; + sprite->pos2.y = (graphicsInfo->height >> 1) - 2; + SeekSpriteAnim(sprite, 2); + } + return 0; +} + +void sub_81559BC(struct Sprite *sprite) +{ + u8 eventObjectId; + s16 x; + s16 y; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[0], sprite->data[1], sprite->data[2], &eventObjectId) || !gEventObjects[eventObjectId].inSandPile) + { + FieldEffectStop(sprite, FLDEFF_SAND_PILE); + } + else + { + y = gSprites[gEventObjects[eventObjectId].spriteId].pos1.y; + x = gSprites[gEventObjects[eventObjectId].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[gEventObjects[eventObjectId].spriteId].subpriority; + UpdateEventObjectSpriteVisibility(sprite, FALSE); + } +} + +u32 sub_8155A88(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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 sub_8155AEC(struct Sprite *sprite) +{ + sprite->data[0] += 0x80; + sprite->data[0] &= 0x100; + sprite->pos1.y -= sprite->data[0] >> 8; + UpdateEventObjectSpriteVisibility(sprite, FALSE); + if (sprite->invisible || sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_BUBBLES); + } +} + +u32 sub_8155B2C(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_80930E0((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); +} + +u32 ShowDisguiseFieldEffect(u8 fldEff, u8 templateIdx, u8 paletteNum) +{ + u8 spriteId; + struct Sprite *sprite; + + if (TryGetEventObjectIdByLocalIdAndMap(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 sub_8155C88(struct Sprite *sprite) +{ + u8 eventObjectId; + const struct EventObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetEventObjectIdByLocalIdAndMap(sprite->data[2], sprite->data[3], sprite->data[4], &eventObjectId)) + { + FieldEffectStop(sprite, sprite->data[1]); + } + + graphicsInfo = GetEventObjectGraphicsInfo(gEventObjects[eventObjectId].graphicsId); + linkedSprite = &gSprites[gEventObjects[eventObjectId].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_8155D78(struct EventObject *eventObject) +{ + if (eventObject->directionSequenceIndex == 1) + { + gSprites[eventObject->fieldEffectSpriteId].data[0]++; + } +} + +bool8 sub_8155DA0(struct EventObject *eventObject) +{ + struct Sprite *sprite; + + if (eventObject->directionSequenceIndex == 2) + { + return TRUE; + } + if (eventObject->directionSequenceIndex == 0) + { + return TRUE; + } + sprite = &gSprites[eventObject->fieldEffectSpriteId]; + if (sprite->data[7]) + { + eventObject->directionSequenceIndex = 2; + sprite->data[0]++; + return TRUE; + } + return FALSE; +} + +u32 sub_8155DDC(void) +{ + u8 spriteId; + + gFieldEffectArguments[0] += 7; + gFieldEffectArguments[1] += 7; + sub_80930E0((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 sub_8155E50(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_8155EA0(struct Sprite *sprite) +{ + sprite->data[6] = 0; + sprite->data[7] = 0; +} + +bool8 sub_8155EA8(struct Sprite *sprite) +{ + bool8 returnBool = FALSE; + + switch (sprite->data[7]) + { + case 0: + sprite->pos2.x += sub_809773C(sprite->data[6]); + sprite->pos2.y += sub_8097728(sprite->data[6]); + break; + case 1: + sprite->pos2.x -= sub_809773C(0x47 - sprite->data[6]); + sprite->pos2.y += sub_8097728(0x47 - sprite->data[6]); + break; + case 2: + sprite->pos2.x -= sub_809773C(sprite->data[6]); + sprite->pos2.y += sub_8097728(sprite->data[6]); + break; + case 3: + sprite->pos2.x += sub_809773C(0x47 - sprite->data[6]); + sprite->pos2.y += sub_8097728(0x47 - sprite->data[6]); + break; + } + + SetGpuReg(REG_OFFSET_BG0HOFS, -sprite->pos2.x); + if (++sprite->data[6] == 72) + { + sprite->data[6] = 0; + sprite->data[7]++; + } + if (sprite->data[7] == 4) + { + sprite->pos2.y = 0; + sprite->pos2.x = 0; + returnBool = TRUE; + } + + return returnBool; +} + +void sub_8155F80(struct Sprite *sprite) +{ + u8 i, j; + + switch (sprite->data[2]) + { + case 0: + SetGpuReg(REG_OFFSET_BG0VOFS, 0x78 - (sprite->data[0] / 3)); + if (sprite->data[0] == 0x60) + { + for (i = 0; i < 3; i++) + { + for (j = 12; j < 18; j++) + { + ((u16*)(VRAM + 0xF800))[i * 32 + j] = 0xBFF4 + i * 6 + j + 1; + } + } + } + if (sprite->data[0] > 0x137) + { + sprite->data[2] = 1; + sprite->data[0] = 0; + } + break; + case 1: + sprite->pos1.y = (gSineTable[sprite->data[0] / 3] >> 2) + sprite->data[4]; + if (sprite->data[0] == 0xBD) + { + sprite->data[2] = 2; + sprite->data[5] = 0; + sprite->data[0] = 0; + } + break; + case 2: + if (sprite->data[0] == 0x3C) + { + sprite->data[5]++; + sprite->data[0] = 0; + } + if (sprite->data[5] == 7) + { + sprite->data[5] = 0; + sprite->data[2] = 3; + } + break; + case 3: + if (sprite->pos2.y == 0) + { + sprite->data[0] = 0; + sprite->data[2]++; + } + if (sprite->data[0] == 5) + { + sprite->data[0] = 0; + if (sprite->pos2.y > 0) + sprite->pos2.y--; + else + sprite->pos2.y++; + } + break; + case 4: + if (sprite->data[0] == 0x3C) + { + sprite->data[2] = 5; + sprite->data[0] = 0; + sprite->data[5] = 0; + } + break; + case 5: + sub_8155EA0(sprite); + sprite->data[2] = 6; + sprite->data[0] = 0; + break; + case 6: + if (sub_8155EA8(sprite)) + { + sprite->data[0] = 0; + if (++sprite->data[5] <= 2) + { + sub_8155EA0(sprite); + } + else + { + sprite->data[5] = 0; + sprite->data[2] = 7; + } + } + break; + case 7: + if (sprite->data[0] == 0x1E) + { + sprite->data[2] = 8; + sprite->data[0] = 0; + } + break; + case 8: + for (i = 0; i < 15; i++) + { + for (j = 12; j < 18; j++) + { + ((u16*)(VRAM + 0xF800))[i * 32 + j] = 0; + } + } + SetGpuReg(REG_OFFSET_BG0VOFS, 0); + FieldEffectStop(sprite, FLDEFF_64); + break; + } + + if (sprite->data[2] == 1) + { + if ((sprite->data[1] & 7) == 0) + sprite->pos2.y += sprite->data[3]; + if ((sprite->data[1] & 15) == 0) + sprite->data[3] = -sprite->data[3]; + sprite->data[1]++; + } + + sprite->data[0]++; +} + +void sub_8156194(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, sprite->data[1]); + } + else + { + UpdateEventObjectSpriteVisibility(sprite, FALSE); + SetObjectSubpriorityByZCoord(sprite->data[0], sprite, 0); + } +} + +void sub_81561D0(struct Sprite *sprite) +{ + if (sprite->animEnded) + FieldEffectStop(sprite, sprite->data[0]); + else + UpdateEventObjectSpriteVisibility(sprite, FALSE); +} + +#ifdef NONMATCHING +void sub_81561FC(struct Sprite *sprite /*r6*/, u8 z, u8 offset) +{ + u8 i; + s16 xlo; + s16 xhi; + s16 lx; + s16 lyhi; + s16 ly; + s16 ylo; + s16 yhi; + struct EventObject *eventObject; // r4 + const struct EventObjectGraphicsInfo *graphicsInfo; // destroyed + struct Sprite *linkedSprite; // r5 + + SetObjectSubpriorityByZCoord(z, sprite, offset); + for (i = 0; i < 16; i ++) + { + eventObject = &gEventObjects[i]; + if (eventObject->active) + { + graphicsInfo = GetEventObjectGraphicsInfo(eventObject->graphicsId); + linkedSprite = &gSprites[eventObject->spriteId]; + xhi = sprite->pos1.x + sprite->centerToCornerVecX; + xlo = sprite->pos1.x - sprite->centerToCornerVecX; + lx = linkedSprite->pos1.x; + if (xhi < lx && xlo > lx) + { + lyhi = linkedSprite->pos1.y + linkedSprite->centerToCornerVecY; + ly = linkedSprite->pos1.y; + ylo = sprite->pos1.y - sprite->centerToCornerVecY; + yhi = ylo + linkedSprite->centerToCornerVecY; + if ((lyhi < yhi || lyhi < ylo) && ly > yhi) + { + if (sprite->subpriority <= linkedSprite->subpriority) + { + sprite->subpriority = linkedSprite->subpriority + 2; + break; + } + } + } + } + } +} +#else +NAKED void sub_81561FC(struct Sprite *sprite /*r6*/, u8 z, u8 offset) +{ + asm_unified("push {r4-r7,lr}\n\ + adds r6, r0, 0\n\ + adds r0, r1, 0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + adds r1, r6, 0\n\ + bl SetObjectSubpriorityByZCoord\n\ + movs r7, 0\n\ +_08156212:\n\ + lsls r0, r7, 3\n\ + adds r0, r7\n\ + lsls r0, 2\n\ + ldr r1, =gEventObjects\n\ + adds r4, r0, r1\n\ + ldrb r0, [r4]\n\ + lsls r0, 31\n\ + cmp r0, 0\n\ + beq _081562B4\n\ + ldrb r0, [r4, 0x5]\n\ + bl GetEventObjectGraphicsInfo\n\ + ldrb r1, [r4, 0x4]\n\ + lsls r0, r1, 4\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + ldr r1, =gSprites\n\ + adds r5, r0, r1\n\ + adds r0, r6, 0\n\ + adds r0, 0x28\n\ + movs r2, 0\n\ + ldrsb r2, [r0, r2]\n\ + ldrh r0, [r6, 0x20]\n\ + adds r1, r0, r2\n\ + subs r0, r2\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + movs r0, 0x20\n\ + ldrsh r2, [r5, r0]\n\ + cmp r1, r2\n\ + bge _081562B4\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + cmp r0, r2\n\ + ble _081562B4\n\ + adds r0, r5, 0\n\ + adds r0, 0x29\n\ + movs r3, 0\n\ + ldrsb r3, [r0, r3]\n\ + ldrh r2, [r5, 0x22]\n\ + adds r2, r3\n\ + ldrh r4, [r5, 0x22]\n\ + adds r0, r6, 0\n\ + adds r0, 0x29\n\ + movs r1, 0\n\ + ldrsb r1, [r0, r1]\n\ + ldrh r0, [r6, 0x22]\n\ + subs r0, r1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + adds r3, r0, r3\n\ + lsls r2, 16\n\ + asrs r2, 16\n\ + lsls r3, 16\n\ + asrs r3, 16\n\ + cmp r2, r3\n\ + blt _0815628C\n\ + cmp r2, r0\n\ + bge _081562B4\n\ +_0815628C:\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + cmp r0, r3\n\ + ble _081562B4\n\ + adds r2, r6, 0\n\ + adds r2, 0x43\n\ + adds r0, r5, 0\n\ + adds r0, 0x43\n\ + ldrb r1, [r0]\n\ + ldrb r0, [r2]\n\ + cmp r0, r1\n\ + bhi _081562B4\n\ + adds r0, r1, 0x2\n\ + strb r0, [r2]\n\ + b _081562BE\n\ + .pool\n\ +_081562B4:\n\ + adds r0, r7, 0x1\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + cmp r7, 0xF\n\ + bls _08156212\n\ +_081562BE:\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0"); +} +#endif |