#include "common.h" #include "sprite.h" #include "effects.h" #include "battle/battle.h" #include "sprite/npc/BattleWatt.h" enum StandardPalettes { STANDARD_PAL_POISON = 1, STANDARD_PAL_DIZZY = 2, STANDARD_PAL_STATIC = 3, }; // lerp from A to B as alpha does from 0 to 255 #define LERP_COMPONENT(a, b, alpha) ((a) * (255 - (alpha)) + (b) * (alpha)) / 255; #define PAL_ANIM_END 0xFF enum PalSwapState { PAL_SWAP_HOLD_A = 0, PAL_SWAP_A_TO_B = 1, PAL_SWAP_HOLD_B = 2, PAL_SWAP_B_TO_A = 3, }; // palette types for static palette animation enum { STATIC_DEFAULT = 0, STATIC_BRIGHT = 1, STATIC_DARK = 2, }; // animated palettes for electrified sprites // each pair gives { mode, duration } u8 StaticPalettesAnim[] = { STATIC_DEFAULT, 32, STATIC_BRIGHT, 4, STATIC_DARK, 2, STATIC_DEFAULT, 16, STATIC_BRIGHT, 2, STATIC_DEFAULT, 64, STATIC_BRIGHT, 2, STATIC_DARK, 2, STATIC_DEFAULT, 28, STATIC_BRIGHT, 2, STATIC_DEFAULT, 18, STATIC_BRIGHT, 4, STATIC_DEFAULT, 16, STATIC_BRIGHT, 2, STATIC_DEFAULT, 80, STATIC_BRIGHT, 2, STATIC_DEFAULT, 16, STATIC_DARK, 2, STATIC_BRIGHT, 2, STATIC_DEFAULT, 32, STATIC_BRIGHT, 2, STATIC_DEFAULT, 14, STATIC_BRIGHT, 2, STATIC_DARK, 2, PAL_ANIM_END }; s16 FearPaletteAnimXOffsets[] = { -2, 2, 0, 0, -2, 2, 0, 0, 0, 0, -2, 2, 0, 0, 0, 0, 0, 0, PAL_ANIM_END }; s16 ParalyzePaletteAnimXOffsets[] = { -2, 2, 0, 0, -2, 2, 0, 0, 0, 0, -2, 2, 0, 0, 0, 0, 0, 0, PAL_ANIM_END }; // palette types for watt palette animations enum { WATT_DEFAULT = 0, WATT_BRIGHTEST = 1, WATT_BRIGHTER = 2, }; // animated palettes for Watt // each pair gives { mode, duration } u8 bWattIdlePalettesAnim[] = { WATT_BRIGHTEST, 2, WATT_DEFAULT, 52, WATT_BRIGHTEST, 4, WATT_DEFAULT, 54, WATT_DEFAULT, 54, WATT_BRIGHTEST, 2, WATT_DEFAULT, 28, WATT_BRIGHTEST, 2, WATT_DEFAULT, 6, WATT_BRIGHTEST, 2, WATT_DEFAULT, 44, WATT_BRIGHTEST, 2, WATT_DEFAULT, 44, PAL_ANIM_END }; u8 WattAttackPalettesAnim[] = { WATT_BRIGHTEST, 2, WATT_DEFAULT, 10, WATT_BRIGHTER, 4, WATT_DEFAULT, 14, WATT_BRIGHTEST, 2, WATT_DEFAULT, 10, WATT_BRIGHTER, 4, WATT_DEFAULT, 4, PAL_ANIM_END }; s16 SparkleSpawnIntervals[] = { -1, 15, 10, 7, 5, 3, 2, 1 }; void update_player_actor_shadow(void); void appendGfx_npc_actor(s32 isPartner, s32 actorIndex); void create_status_chill_out(s32 iconID); void enable_status_static(s32 iconID); void enable_status_chill_out(s32 iconID); void enable_status_debuff(s16); void enable_status_transparent(s16); void enable_status_icon_boost_jump(s32 iconID); void enable_status_icon_boost_hammer(s32 iconID); s32 get_npc_anim_for_status(u32*, s32); void set_actor_pal_adjustment(Actor* actor, s32 arg1); void create_status_icon_boost_hammer(s32 iconID); void create_status_icon_boost_jump(s32 iconID); void create_status_icon_peril(s32 iconID); void create_status_icon_danger(s32 iconID); void set_status_icons_offset(s32 iconID, s32 offsetY, s32 arg2); void set_status_icons_properties(s32 iconID, f32 x, f32 y, f32 z, s32 arg, s32 arg2, s32 radius, s32 offsetY); void appendGfx_npc_actor_reflection(s32, Actor*); void make_flash_palettes(ActorPart*); void func_unkA_draw_npc(ActorPart*, s32, Matrix4f); void func_unkB_draw_npc(ActorPart*, s32, Matrix4f); void func_unkA_draw_player(ActorPart*, s32, Matrix4f); void func_unkB_draw_player(ActorPart*, s32, Matrix4f); void part_glow_on(b32 arg0, ActorPart* part, s32 yaw, b32 arg3); void part_flash_on(b32 arg0, ActorPart* part, s32 yaw, b32 arg3); void add_part_decor_none(ActorPart*, s32); void add_part_decor_golden_flames(ActorPart*, s32); void add_part_decor_sweat(ActorPart*, s32); void add_part_decor_seeing_stars(ActorPart*, s32); void add_part_decor_red_flames(ActorPart*, s32); void add_part_decor_smoky_trail(ActorPart*, s32); void add_part_decor_fiery_trail(ActorPart*, s32); void add_part_decor_whirlwind(ActorPart*, s32); void add_part_decor_steam(ActorPart*, s32); void add_part_decor_sparkles(ActorPart*, s32); void add_part_decor_bowser_aura(ActorPart*, s32); void add_part_decor_radiating_stars(ActorPart*, s32); void render_without_adjusted_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_sleep_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_static_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_fear_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_poison_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_paralyze_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_berserk_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_watt_idle_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_watt_attack_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); void render_with_player_debuff_palettes(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation, s32 isPoison); void render_with_pal_blending(b32 arg0, ActorPart* part, s32 yaw, s32 arg3, Matrix4f mtx, s32 skipAnimation); void render_with_palset_blending(b32 arg0, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation); s32 update_part_glow(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection); s32 update_part_flash(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection); s32 get_player_anim_for_status(s32 animID); void clear_part_flash_mode(ActorPart* part); // thresholds slightly lower than in GetDamageIntensity s32 get_flash_damage_intensity(ActorPart* part) { s32 ret; if (gBattleStatus.lastAttackDamage < 3) { ret = DAMAGE_INTENSITY_LIGHT; } else if (gBattleStatus.lastAttackDamage < 5) { ret = DAMAGE_INTENSITY_MEDIUM; } else if (gBattleStatus.lastAttackDamage < 9) { ret = DAMAGE_INTENSITY_HEAVY; } else { ret = DAMAGE_INTENSITY_EXTREME; } return ret; } void mtx_mirror_y(Matrix4f mtx) { guMtxIdentF(mtx); mtx[0][0] = 1.0f; mtx[1][1] = -1.0f; mtx[2][2] = 1.0f; mtx[3][3] = 1.0f; } void enable_actor_blur(Actor* actor) { ActorPart* partsTable = actor->partsTable; DecorationTable* decorations = partsTable->decorationTable; s32 i, j; s32 numParts; decorations->blurDisableDelay = 0; decorations->blurEnableCount++; actor->flags |= ACTOR_FLAG_BLUR_ENABLED; partsTable = actor->partsTable; numParts = actor->numParts; for (i = 0; i < numParts; i++) { if (partsTable->idleAnimations != NULL && !(partsTable->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { decorations = partsTable->decorationTable; decorations->blurUnused = 0; decorations->blurBufferPos = 0; for (j = 0; j < ARRAY_COUNT(decorations->posX); j++) { decorations->posX[j] = partsTable->curPos.x; decorations->posY[j] = partsTable->curPos.y; decorations->posZ[j] = partsTable->curPos.z; decorations->yaw[j] = actor->yaw; decorations->rotPivotOffsetX[j] = (s32)(actor->rotPivotOffset.x * actor->scalingFactor); decorations->rotPivotOffsetY[j] = (s32)(actor->rotPivotOffset.y * actor->scalingFactor); decorations->rotX[j] = clamp_angle(actor->rot.x) * 0.5f; decorations->rotY[j] = clamp_angle(actor->rot.y) * 0.5f; decorations->rotZ[j] = clamp_angle(actor->rot.z) * 0.5f; } } partsTable = partsTable->nextPart; } } void disable_actor_blur(Actor* actor) { ActorPart* actorPart = actor->partsTable; if ((actorPart->idleAnimations != NULL) && !(actorPart->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { DecorationTable* decorations = actorPart->decorationTable; if (decorations->blurEnableCount != 0) { decorations->blurEnableCount--; if (decorations->blurEnableCount == 0) { decorations->blurDisableDelay = 20; } } } } void reset_actor_blur(Actor* actor) { ActorPart* actorPart = actor->partsTable; if ((actorPart->idleAnimations != NULL) && !(actorPart->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { DecorationTable* decorations = actorPart->decorationTable; if (decorations->blurEnableCount != 0) { decorations->blurEnableCount--; if (decorations->blurEnableCount == 0) { actor->flags &= ~ACTOR_FLAG_BLUR_ENABLED; decorations->blurDisableDelay = 1; } } } } void force_disable_actor_blur(Actor* actor) { ActorPart* actorPart = actor->partsTable; if (actorPart->idleAnimations != NULL && !(actorPart->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { DecorationTable* decorations = actorPart->decorationTable; decorations->blurEnableCount = 0; decorations->blurDisableDelay = 20; } } void enable_partner_blur(void) { enable_actor_blur(gBattleStatus.partnerActor); } void disable_partner_blur(void) { disable_actor_blur(gBattleStatus.partnerActor); } void reset_partner_blur(void) { reset_actor_blur(gBattleStatus.partnerActor); } void force_disable_partner_blur(void) { force_disable_actor_blur(gBattleStatus.partnerActor); } void enable_player_blur(void) { Actor* playerActor = gBattleStatus.playerActor; ActorPart* partsTable = playerActor->partsTable; DecorationTable* decorations = partsTable->decorationTable; s32 i; decorations->blurDisableDelay = 0; decorations->blurEnableCount++; playerActor->flags |= ACTOR_FLAG_BLUR_ENABLED; decorations->blurUnused = 0; decorations->blurBufferPos = 0; for (i = 0; i < ARRAY_COUNT(decorations->posX); i++) { decorations->posX[i] = partsTable->curPos.x; decorations->posY[i] = partsTable->curPos.y; decorations->posZ[i] = partsTable->curPos.z; decorations->yaw[i] = playerActor->yaw; decorations->rotPivotOffsetX[i] = playerActor->rotPivotOffset.x * playerActor->scalingFactor; decorations->rotPivotOffsetY[i] = playerActor->rotPivotOffset.y * playerActor->scalingFactor; decorations->rotX[i] = clamp_angle(playerActor->rot.x) * 0.5f; decorations->rotY[i] = clamp_angle(playerActor->rot.y) * 0.5f; decorations->rotZ[i] = clamp_angle(playerActor->rot.z) * 0.5f; } } void disable_player_blur(void) { Actor* playerActor = gBattleStatus.playerActor; ActorPart* partsTable = playerActor->partsTable; DecorationTable* decorations = partsTable->decorationTable; if (decorations->blurEnableCount != 0) { decorations->blurEnableCount--; if (decorations->blurEnableCount == 0) { decorations->blurDisableDelay = 20; } } } void reset_player_blur(void) { Actor* playerActor = gBattleStatus.playerActor; ActorPart* partsTable = playerActor->partsTable; DecorationTable* decorations = partsTable->decorationTable; if (decorations->blurEnableCount != 0) { decorations->blurEnableCount--; if (decorations->blurEnableCount == 0) { playerActor->flags &= ~ACTOR_FLAG_BLUR_ENABLED; decorations->blurDisableDelay = 1; } } } void force_disable_player_blur(void) { Actor* playerActor = gBattleStatus.playerActor; ActorPart* partsTable = playerActor->partsTable; DecorationTable* decorations = partsTable->decorationTable; decorations->blurEnableCount = 0; decorations->blurDisableDelay = 20; } void force_disable_player_blur_immediately(void) { Actor* playerActor = gBattleStatus.playerActor; ActorPart* partsTable = playerActor->partsTable; DecorationTable* decorations = partsTable->decorationTable; playerActor->flags &= ~ACTOR_FLAG_BLUR_ENABLED; decorations->blurEnableCount = 0; decorations->blurDisableDelay = 1; } void update_player_actor_blur_history(Actor* actor) { ActorPart* partsTable = actor->partsTable; DecorationTable* decorations = partsTable->decorationTable; if (!(partsTable->flags & ACTOR_PART_FLAG_INVISIBLE) && partsTable->idleAnimations != NULL) { s32 i = decorations->blurBufferPos; decorations->posX[i] = partsTable->curPos.x; decorations->posY[i] = partsTable->curPos.y; decorations->posZ[i] = partsTable->curPos.z; decorations->yaw[i] = actor->yaw; decorations->rotPivotOffsetX[i] = actor->rotPivotOffset.x * actor->scalingFactor; decorations->rotPivotOffsetY[i] = actor->rotPivotOffset.y * actor->scalingFactor; decorations->rotX[i] = clamp_angle(actor->rot.x) * 0.5f; decorations->rotY[i] = clamp_angle(actor->rot.y) * 0.5f; decorations->rotZ[i] = clamp_angle(actor->rot.z) * 0.5f; i++; if (i >= ARRAY_COUNT(decorations->posX)) { i = 0; } decorations->blurBufferPos = i; } } void appendGfx_player_actor_blur(Actor* actor) { Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation; Matrix4f mtxScale; Matrix4f mtxPivotOn, mtxPivotOff, mtxTranslate; Matrix4f mtxTransform, mtxTemp; s32 strideIdx; s32 drawIdx; s32 yaw; ActorPart* partTable; DecorationTable* decorations; f32 rotX, rotY, rotZ; s32 prevOpacity; s32 opacity; s32 pivotOffsetX; s32 pivotOffsetY; s32 bufPos; s32 blurOpacityBase; s32 opacityLossIncrement; f32 x, y, z; partTable = actor->partsTable; decorations = partTable->decorationTable; if (decorations->blurDisableDelay != 0) { decorations->blurDisableDelay--; if (decorations->blurDisableDelay == 0) { actor->flags &= ~ACTOR_FLAG_BLUR_ENABLED; return; } } if (!(partTable->flags & ACTOR_PART_FLAG_INVISIBLE) && partTable->idleAnimations != NULL) { bufPos = decorations->blurBufferPos; strideIdx = 0; drawIdx = 0; while (TRUE) { bufPos--; strideIdx++; if (bufPos < 0) { bufPos = ARRAY_COUNT(decorations->posX) - 1; } if (bufPos == decorations->blurBufferPos) { break; } // only draw every third blur frame if (strideIdx < 3) { continue; } strideIdx = 0; drawIdx++; if (decorations->blurDrawCount < drawIdx) { break; } opacity = partTable->opacity; x = decorations->posX[bufPos]; y = decorations->posY[bufPos]; z = decorations->posZ[bufPos]; yaw = decorations->yaw[bufPos]; pivotOffsetX = decorations->rotPivotOffsetX[bufPos]; pivotOffsetY = decorations->rotPivotOffsetY[bufPos]; rotX = decorations->rotX[bufPos] * 2; rotY = decorations->rotY[bufPos] * 2; rotZ = decorations->rotZ[bufPos] * 2; blurOpacityBase = 120; opacityLossIncrement = 20; if (opacity < 50) { blurOpacityBase = 50; opacityLossIncrement = 8; } else if (opacity < 100) { blurOpacityBase = 70; opacityLossIncrement = 10; } else if (opacity < 150) { blurOpacityBase = 100; opacityLossIncrement = 15; } guTranslateF(mtxTranslate, x, y, z); guTranslateF(mtxPivotOn, -pivotOffsetX, -pivotOffsetY, 0.0f); guTranslateF(mtxPivotOff, pivotOffsetX, pivotOffsetY, 0.0f); guRotateF(mtxRotX, rotX, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, rotY, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, rotZ, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotX, mtxRotY, mtxTransform); guMtxCatF(mtxTransform, mtxRotZ, mtxRotation); guScaleF(mtxScale, actor->scale.x * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.y * SPRITE_WORLD_SCALE_D * actor->scalingFactor * partTable->verticalStretch, actor->scale.z * SPRITE_WORLD_SCALE_D); guMtxCatF(mtxScale, mtxPivotOn, mtxTemp); guMtxCatF(mtxTemp, mtxRotation, mtxTransform); guMtxCatF(mtxTransform, mtxPivotOff, mtxTemp); guMtxCatF(mtxTemp, mtxTranslate, mtxTransform); prevOpacity = partTable->opacity; partTable->opacity = blurOpacityBase - (drawIdx * opacityLossIncrement); render_with_adjusted_palettes(SPRITE_MODE_PLAYER, partTable, clamp_angle(yaw + 180), mtxTransform, 1); partTable->opacity = prevOpacity; } } } void update_nonplayer_actor_blur_history(b32 isPartner, Actor* actor) { s32 numParts = actor->numParts; ActorPart* partsTable = actor->partsTable; DecorationTable* decorations; s32 i, j; for (i = 0; i < numParts; i++) { if (partsTable->flags & ACTOR_PART_FLAG_INVISIBLE || partsTable->idleAnimations == NULL || partsTable->flags & ACTOR_PART_FLAG_NO_DECORATIONS) { partsTable = partsTable->nextPart; } else { decorations = partsTable->decorationTable; j = decorations->blurBufferPos; decorations->posX[j] = partsTable->curPos.x; decorations->posY[j] = partsTable->curPos.y; decorations->posZ[j] = partsTable->curPos.z; decorations->yaw[j] = actor->yaw; decorations->rotPivotOffsetX[j] = actor->rotPivotOffset.x; decorations->rotPivotOffsetY[j] = actor->rotPivotOffset.y; decorations->rotX[j] = clamp_angle(actor->rot.x) * 0.5f; decorations->rotY[j] = clamp_angle(actor->rot.y) * 0.5f; decorations->rotZ[j] = clamp_angle(actor->rot.z) * 0.5f; j++; if (j >= ARRAY_COUNT(decorations->posX)) { j = 0; } decorations->blurBufferPos = j; } } } void appendGfx_nonplayer_actor_blur(b32 isPartner, Actor* actor) { DecorationTable* decorations; ActorPart* partTable; Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation; Matrix4f mtxScale, mtxTranslate; Matrix4f mtxTemp, mtxTransform; Matrix4f mtxPivotOn, mtxPivotOff; Matrix4f mtxActor, mtxPartScale; s32 numParts; s32 i, bufPos, strideIdx, drawIdx; f32 x, y, z; f32 rotX, rotY, rotZ; s32 yaw; s32 opacity; s32 pivotX; s32 pivotY; s32 blurOpacityBase; s32 opacityLossIncrement; s32 blurOpacity; s32 flags; guRotateF(mtxRotX, actor->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, actor->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, actor->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotX, mtxRotY, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, actor->scale.x * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.y * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.z * SPRITE_WORLD_SCALE_D); guMtxCatF(mtxScale, mtxRotation, mtxActor); numParts = actor->numParts; partTable = actor->partsTable; for (i = 0; i < numParts; i++) { if ((partTable->idleAnimations == NULL) || (partTable->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { partTable = partTable->nextPart; continue; } decorations = partTable->decorationTable; if (decorations->blurDisableDelay != 0) { decorations->blurDisableDelay--; if (decorations->blurDisableDelay == 0) { actor->flags &= ~ACTOR_FLAG_BLUR_ENABLED; partTable = partTable->nextPart; continue; } } if (partTable->flags & ACTOR_PART_FLAG_INVISIBLE) { partTable = partTable->nextPart; continue; } if (partTable->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION) { guScaleF(mtxPartScale, actor->scale.x * SPRITE_WORLD_SCALE_D, actor->scale.y * SPRITE_WORLD_SCALE_D, actor->scale.z * SPRITE_WORLD_SCALE_D); } bufPos = decorations->blurBufferPos; strideIdx = 0; drawIdx = 0; while (TRUE) { bufPos--; strideIdx++; if (bufPos < 0) { bufPos = ACTOR_BLUR_FRAMES - 1; } if (bufPos == decorations->blurBufferPos) { break; } // only draw every third blur frame if (strideIdx < 3) { continue; } strideIdx = 0; drawIdx++; if (decorations->blurDrawCount < drawIdx) { break; } opacity = partTable->opacity; x = decorations->posX[bufPos]; y = decorations->posY[bufPos]; z = decorations->posZ[bufPos]; yaw = decorations->yaw[bufPos]; pivotX = decorations->rotPivotOffsetX[bufPos]; pivotY = decorations->rotPivotOffsetY[bufPos]; rotX = decorations->rotX[bufPos] * 2; rotY = decorations->rotY[bufPos] * 2; rotZ = decorations->rotZ[bufPos] * 2; blurOpacityBase = 120; opacityLossIncrement = 20; if (opacity < 50) { blurOpacityBase = 50; opacityLossIncrement = 8; } else if (opacity < 100) { blurOpacityBase = 70; opacityLossIncrement = 10; } else if (opacity < 150) { blurOpacityBase = 100; opacityLossIncrement = 15; } if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { guTranslateF(mtxPivotOn, -pivotX, -pivotY, 0.0f); guTranslateF(mtxPivotOff, pivotX, pivotY, 0.0f); } else { guTranslateF(mtxPivotOn, -pivotX, pivotY, 0.0f); guTranslateF(mtxPivotOff, pivotX, -pivotY, 0.0f); } guTranslateF(mtxTranslate, x, y, z); guRotateF(mtxRotX, rotX, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, rotY, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, rotZ, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, partTable->scale.x, partTable->scale.y * partTable->verticalStretch, partTable->scale.z); guMtxCatF(mtxScale, mtxPivotOn, mtxTransform); guMtxCatF(mtxTransform, mtxRotation, mtxTemp); guMtxCatF(mtxTemp, mtxPivotOff, mtxTransform); if (!(partTable->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { guMtxCatF(mtxTransform, mtxActor, mtxTemp); } else { guMtxCatF(mtxTransform, mtxPartScale, mtxTemp); } guMtxCatF(mtxTemp, mtxTranslate, mtxTransform); flags = DRAW_SPRITE_OVERRIDE_ALPHA; blurOpacity = blurOpacityBase - drawIdx * opacityLossIncrement; if (!isPartner) { spr_draw_npc_sprite(partTable->spriteInstanceID | flags, yaw, blurOpacity, 0, mtxTransform); } else { spr_draw_npc_sprite(partTable->spriteInstanceID | flags, clamp_angle(yaw + 180), blurOpacity, 0, mtxTransform); } } } } void update_enemy_actor_blur_history(Actor* actor) { update_nonplayer_actor_blur_history(FALSE, actor); } void appendGfx_enemy_actor_blur(void* data) { Actor* actor = data; appendGfx_nonplayer_actor_blur(FALSE, actor); } void update_partner_actor_blur_history(Actor* actor) { update_nonplayer_actor_blur_history(TRUE, actor); } void appendGfx_partner_actor_blur(void* data) { Actor* actor = data; appendGfx_nonplayer_actor_blur(TRUE, actor); } void update_nonplayer_actor_shadow(b32 isPartner, Actor* actor) { Camera* camera = &gCameras[CAM_BATTLE]; ActorPart* actorPart; Shadow* shadow; s32 numParts; f32 x1, y1, z1; f32 x2, y2, z2; f32 dist; s32 spriteID; f32 yaw; s32 i; if (actor != NULL) { shadow = get_shadow_by_index(actor->shadow.id); shadow->flags |= ENTITY_FLAG_HIDDEN; if (!(actor->flags & ACTOR_FLAG_INVISIBLE)) { if (actor->flags & ACTOR_FLAG_BLUR_ENABLED) { if (!isPartner) { update_enemy_actor_blur_history(actor); } else { update_partner_actor_blur_history(actor); } } actor->renderMode = RENDER_MODE_ALPHATEST; x1 = actor->curPos.x + actor->headOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { y1 = actor->curPos.y + actor->headOffset.y; } else { y1 = actor->curPos.y - actor->headOffset.y; } z1 = actor->curPos.z + actor->headOffset.z; numParts = actor->numParts; actorPart = actor->partsTable; for (i = 0; i < numParts; i++) { if (!(actorPart->flags & ACTOR_PART_FLAG_INVISIBLE) && actorPart->idleAnimations != NULL) { spriteID = actorPart->spriteInstanceID; if (spriteID >= 0) { spr_update_sprite(spriteID, actorPart->curAnimation, actorPart->animationRate); actorPart->animNotifyValue = spr_get_notify_value(actorPart->spriteInstanceID); } if (!(actorPart->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { x2 = x1 + actorPart->partOffset.x + actorPart->visualOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { y2 = y1 + actorPart->partOffset.y + actorPart->visualOffset.y; } else { y2 = y1 - actorPart->partOffset.y - actorPart->visualOffset.y; } z2 = z1 + actorPart->partOffset.z + actorPart->visualOffset.z; yaw = actorPart->yaw = actor->yaw; } else { x2 = actorPart->absolutePos.x + actorPart->visualOffset.x; y2 = actorPart->absolutePos.y + actorPart->visualOffset.y; z2 = actorPart->absolutePos.z + actorPart->visualOffset.z; yaw = actorPart->yaw; } actorPart->curPos.x = x2; actorPart->curPos.y = y2; actorPart->curPos.z = z2; if (!(actorPart->flags & ACTOR_PART_FLAG_NO_SHADOW)) { shadow = get_shadow_by_index(actorPart->shadowIndex); shadow->flags &= ~ENTITY_FLAG_HIDDEN; x1 = actorPart->curPos.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { y1 = actorPart->curPos.y + 12.0; } else { y1 = actorPart->curPos.y - 12.0; } z1 = actorPart->curPos.z; dist = 32767.0f; npc_raycast_down_sides(0, &x1, &y1, &z1, &dist); if (200.0f < dist) { shadow->flags |= ENTITY_FLAG_HIDDEN; } shadow->pos.x = x1; shadow->pos.y = y1; shadow->pos.z = z1; shadow->rot.y = clamp_angle(yaw - camera->curYaw); set_standard_shadow_scale(shadow, dist); shadow->scale.x *= actorPart->shadowScale; } if (actorPart->opacity < 255 || actorPart->flags & ACTOR_PART_FLAG_TRANSPARENT) { actor->renderMode = RENDER_MODE_SURFACE_XLU_LAYER3; } } actorPart = actorPart->nextPart; } shadow = get_shadow_by_index(actor->shadow.id); if (!(actor->flags & ACTOR_FLAG_NO_SHADOW)) { shadow->flags &= ~ENTITY_FLAG_HIDDEN; } x1 = actor->curPos.x + actor->headOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { y1 = actor->curPos.y + actor->headOffset.y + 12.0; } else { y1 = actor->curPos.y - actor->headOffset.y + 12.0; } z1 = actor->curPos.z + actor->headOffset.z; dist = 32767.0f; npc_raycast_down_sides(0, &x1, &y1, &z1, &dist); if (200.0f < dist) { shadow->flags |= ENTITY_FLAG_HIDDEN; } shadow->pos.x = x1; shadow->pos.y = y1; shadow->pos.z = z1 + bActorOffsets[actor->actorType].shadow; shadow->rot.y = clamp_angle(actor->yaw - camera->curYaw); set_standard_shadow_scale(shadow, dist); shadow->scale.x *= actor->shadowScale * actor->scalingFactor; } } } void update_enemy_shadows(void) { BattleStatus* battleStatus = &gBattleStatus; s32 i; for (i = 0; i < ARRAY_COUNT(battleStatus->enemyActors); i++) { update_nonplayer_actor_shadow(FALSE, battleStatus->enemyActors[i]); } } void update_hero_shadows(void) { update_nonplayer_actor_shadow(TRUE, gBattleStatus.partnerActor); update_player_actor_shadow(); } void func_80255FD8(void) { } void appendGfx_npc_actor(b32 isPartner, s32 actorIndex) { BattleStatus* battleStatus = &gBattleStatus; Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation; Matrix4f mtxScale, mtxScaleMod; Matrix4f mtxPivotOn, mtxPivotOff, mtxTranslate; Matrix4f mtxTemp, mtxActor, mtxTransform, mtxPartScale; Actor* actor; ActorPart* part; EffectInstance* effect; s32 numParts; f32 actorPosX, actorPosY, actorPosZ; f32 partPosX, partPosY, partPosZ, partYaw; u32 lastAnim; s32 animChanged; s32 palChanged; s32 decorChanged; s32 i; if (!isPartner) { actor = battleStatus->enemyActors[actorIndex]; } else { actor = battleStatus->partnerActor; } actorPosX = actor->curPos.x + actor->headOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { actorPosY = actor->curPos.y + actor->headOffset.y + actor->verticalRenderOffset; } else { actorPosY = actor->curPos.y - actor->headOffset.y + actor->verticalRenderOffset; } actorPosZ = actor->curPos.z + actor->headOffset.z; actor->disableEffect->data.disableX->pos.x = actorPosX + (actor->actorBlueprint->statusIconOffset.x + actor->statusIconOffset.x) * actor->scalingFactor; actor->disableEffect->data.disableX->pos.y = actorPosY + (actor->actorBlueprint->statusIconOffset.y + actor->statusIconOffset.y) * actor->scalingFactor; actor->disableEffect->data.disableX->pos.z = actorPosZ; if (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (actor->flags & ACTOR_FLAG_SHOW_STATUS_ICONS)) { if (actor->disableDismissTimer != 0) { actor->disableDismissTimer--; actor->disableEffect->data.disableX->pos.y = NPC_DISPOSE_POS_Y; } else { actor->disableEffect->data.disableX->scale = (actor->scalingFactor * 0.75); } } else { actor->disableEffect->data.disableX->pos.y = NPC_DISPOSE_POS_Y; actor->disableDismissTimer = 10; } if (actor->debuff == STATUS_KEY_FROZEN) { effect = actor->icePillarEffect; if (actor->icePillarEffect != NULL) { if ((gBattleStatus.flags1 & BS_FLAGS1_SHOW_PLAYER_DECORATIONS) || (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (actor->flags & ACTOR_FLAG_SHOW_STATUS_ICONS))) { effect->data.icePillar->pos.x = actorPosX; effect->data.icePillar->pos.y = actorPosY; effect->data.icePillar->pos.z = actorPosZ; effect->data.icePillar->scale = actor->size.y / 24.0; } else { effect->data.icePillar->pos.x = NPC_DISPOSE_POS_X; effect->data.icePillar->pos.y = NPC_DISPOSE_POS_Y; effect->data.icePillar->pos.z = NPC_DISPOSE_POS_Z; } } } else { effect = actor->icePillarEffect; if (effect != NULL) { effect->flags |= FX_INSTANCE_FLAG_DISMISS; actor->icePillarEffect = NULL; } } set_status_icons_properties(actor->hudElementDataIndex, actorPosX, actorPosY, actorPosZ, (actor->actorBlueprint->statusIconOffset.x + actor->statusIconOffset.x) * actor->scalingFactor, (actor->actorBlueprint->statusIconOffset.y + actor->statusIconOffset.y) * actor->scalingFactor, (actor->actorBlueprint->statusTextOffset.x + actor->statusTextOffset.x) * actor->scalingFactor, (actor->actorBlueprint->statusTextOffset.y + actor->statusTextOffset.y) * actor->scalingFactor); if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { set_status_icons_offset(actor->hudElementDataIndex, actor->size.y * actor->scalingFactor, actor->size.x * actor->scalingFactor); } else { set_status_icons_offset(actor->hudElementDataIndex, -actor->size.y * actor->scalingFactor, actor->size.x * actor->scalingFactor); } do { if (actor->debuff == STATUS_KEY_SHRINK) { actor->scalingFactor += ((0.4 - actor->scalingFactor) / 6.0); } else { actor->scalingFactor += ((1.0 - actor->scalingFactor) / 6.0); } } while (0); // required to match if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { guTranslateF(mtxPivotOn, -actor->rotPivotOffset.x * actor->scalingFactor, -actor->rotPivotOffset.y * actor->scalingFactor, -actor->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, actor->rotPivotOffset.x * actor->scalingFactor, actor->rotPivotOffset.y * actor->scalingFactor, actor->rotPivotOffset.z * actor->scalingFactor); } else { guTranslateF(mtxPivotOn, -actor->rotPivotOffset.x * actor->scalingFactor, actor->rotPivotOffset.y * actor->scalingFactor, -actor->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, actor->rotPivotOffset.x * actor->scalingFactor, -actor->rotPivotOffset.y * actor->scalingFactor, actor->rotPivotOffset.z * actor->scalingFactor); } guRotateF(mtxRotX, actor->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, actor->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, actor->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, actor->scale.x * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.y * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.z * SPRITE_WORLD_SCALE_D); guScaleF(mtxScaleMod, actor->scaleModifier.x, actor->scaleModifier.y, actor->scaleModifier.z); guMtxCatF(mtxPivotOn, mtxScale, mtxTemp); guMtxCatF(mtxTemp, mtxScaleMod, mtxScale); guMtxCatF(mtxScale, mtxRotation, mtxTransform); guMtxCatF(mtxTransform, mtxPivotOff, mtxActor); part = actor->partsTable; numParts = actor->numParts; for (i = 0; i < numParts; i++) { if (!(part->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { partPosX = actorPosX + part->partOffset.x + part->visualOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { partPosY = actorPosY + part->partOffset.y + part->visualOffset.y; } else { partPosY = (actorPosY - part->partOffset.y) - part->visualOffset.y; } partPosZ = actorPosZ + part->partOffset.z + part->visualOffset.z; partYaw = part->yaw = actor->yaw; } else { partPosX = part->absolutePos.x + part->visualOffset.x; partPosY = part->absolutePos.y + part->visualOffset.y; partPosZ = part->absolutePos.z + part->visualOffset.z; guScaleF(mtxPartScale, actor->scale.x * SPRITE_WORLD_SCALE_D, actor->scale.y * SPRITE_WORLD_SCALE_D, actor->scale.z * SPRITE_WORLD_SCALE_D); partYaw = part->yaw; } part->curPos.x = partPosX; part->curPos.y = partPosY; part->curPos.z = partPosZ; if (part->flags & ACTOR_PART_FLAG_INVISIBLE) { part = part->nextPart; continue; } if (part->idleAnimations == NULL) { part = part->nextPart; continue; } if (actor->transparentStatus == STATUS_KEY_TRANSPARENT) { part->flags |= ACTOR_PART_FLAG_TRANSPARENT; } else { part->flags &= ~ACTOR_PART_FLAG_TRANSPARENT; } do { lastAnim = part->curAnimation; animChanged = FALSE; palChanged = FALSE; decorChanged = FALSE; } while (0); // required to match if (isPartner) { if (!(gBattleStatus.flags2 & (BS_FLAGS2_OVERRIDE_INACTIVE_PARTNER)) && (gBattleStatus.flags2 & BS_FLAGS2_PARTNER_TURN_USED) ) { do { if (actor->koStatus == 0) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_INACTIVE); spr_update_sprite(part->spriteInstanceID, part->curAnimation, part->animationRate); animChanged = TRUE; } } while (0); // required to match set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_PLAYER_DEBUFF); palChanged = TRUE; set_actor_glow_pal(actor, GLOW_PAL_OFF); decorChanged = TRUE; } if (isPartner && (gPlayerData.curPartner == PARTNER_WATT)) { if (!palChanged) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_WATT_IDLE); } palChanged = TRUE; } } if (actor->isGlowing) { if (!decorChanged) { set_actor_glow_pal(actor, GLOW_PAL_ON); } decorChanged = TRUE; } if (actor->debuff == STATUS_KEY_POISON) { if (!palChanged) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_POISON); } palChanged = TRUE; } if (actor->debuff == STATUS_KEY_PARALYZE) { if (!palChanged) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_PARALYZE); } palChanged = TRUE; } if (actor->debuff == STATUS_KEY_FEAR) { if (!palChanged) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_FEAR); } palChanged = TRUE; } if (actor->staticStatus == STATUS_KEY_STATIC) { if (!palChanged) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_STATIC); } palChanged = TRUE; } if (!palChanged && !(part->flags & ACTOR_PART_FLAG_HAS_PAL_EFFECT)) { set_actor_pal_adjustment(actor, ACTOR_PAL_ADJUST_NONE); } if (!decorChanged && !(part->flags & ACTOR_PART_FLAG_HAS_PAL_EFFECT)) { set_actor_glow_pal(actor, GLOW_PAL_OFF); } // adjust idle animation for status if (actor->flags & ACTOR_FLAG_USING_IDLE_ANIM) { if (!(part->flags & ACTOR_PART_FLAG_NO_STATUS_ANIMS)) { if (actor->debuff == STATUS_KEY_FROZEN) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_FROZEN); animChanged = TRUE; } } else if (actor->debuff != STATUS_KEY_SHRINK) { if (actor->debuff == STATUS_KEY_POISON) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_POISON); animChanged = TRUE; } } else if (actor->debuff == STATUS_KEY_DIZZY) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_DIZZY); animChanged = TRUE; } } else if (actor->debuff == STATUS_KEY_FEAR) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_FEAR); animChanged = TRUE; } } else if (actor->debuff == STATUS_KEY_SLEEP) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_SLEEP); animChanged = TRUE; } } else if (actor->debuff == STATUS_KEY_PARALYZE) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_PARALYZE); animChanged = TRUE; } } } if (actor->staticStatus == STATUS_KEY_STATIC) { if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_STATIC); animChanged = TRUE; } do {} while (0); // required to match } if (!animChanged) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, 1); } if (isPartner) { if (actor->koStatus == STATUS_KEY_DAZE) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_DAZE); animChanged = TRUE; } else { s32 temp = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_NORMAL); do { if (temp == get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_DAZE)) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_NORMAL); } } while (0); // required to match } } if (actor->debuff == STATUS_KEY_STOP) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_STOP); create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_STOP); } else if (!animChanged) { s32 temp = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_NORMAL); do { if (temp == get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_STOP)) { part->curAnimation = get_npc_anim_for_status(part->idleAnimations, STATUS_KEY_NORMAL); } } while (0); // required to match } } } if (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (actor->flags & ACTOR_FLAG_SHOW_STATUS_ICONS)) { do { if (actor->debuff == STATUS_KEY_POISON) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_POISON); } else if (actor->debuff == STATUS_KEY_DIZZY) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_DIZZY); } else if (actor->debuff == STATUS_KEY_SLEEP) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_SLEEP); } else if (actor->debuff == STATUS_KEY_PARALYZE) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_PARALYZE); } else if (actor->debuff == STATUS_KEY_SHRINK) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_SHRINK); } else if (actor->debuff == STATUS_KEY_FROZEN) { create_status_debuff(actor->hudElementDataIndex, STATUS_KEY_FROZEN); } } while (0); // required to match if (actor->staticStatus == STATUS_KEY_STATIC) { create_status_static(actor->hudElementDataIndex, STATUS_KEY_STATIC); } if ((actor->transparentStatus == STATUS_KEY_TRANSPARENT) || (part->flags & ACTOR_PART_FLAG_TRANSPARENT)) { create_status_transparent(actor->hudElementDataIndex, STATUS_KEY_TRANSPARENT); } if (actor->chillOutAmount != 0) { create_status_chill_out(actor->hudElementDataIndex); } } else { enable_status_debuff(actor->hudElementDataIndex); enable_status_static(actor->hudElementDataIndex); enable_status_transparent(actor->hudElementDataIndex); enable_status_chill_out(actor->hudElementDataIndex); } if (part->spriteInstanceID >= 0) { if (lastAnim != part->curAnimation) { spr_update_sprite(part->spriteInstanceID, part->curAnimation, part->animationRate); part->animNotifyValue = spr_get_notify_value(part->spriteInstanceID); } } if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { guTranslateF(mtxPivotOn, -part->rotPivotOffset.x * actor->scalingFactor, -part->rotPivotOffset.y * actor->scalingFactor, -part->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, part->rotPivotOffset.x * actor->scalingFactor, part->rotPivotOffset.y * actor->scalingFactor, part->rotPivotOffset.z * actor->scalingFactor); } else { guTranslateF(mtxPivotOn, -part->rotPivotOffset.x * actor->scalingFactor, part->rotPivotOffset.y * actor->scalingFactor, -part->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, part->rotPivotOffset.x * actor->scalingFactor, -part->rotPivotOffset.y * actor->scalingFactor, part->rotPivotOffset.z * actor->scalingFactor); } guTranslateF(mtxTranslate, partPosX + part->palAnimPosOffset[0], partPosY + part->palAnimPosOffset[1], partPosZ); guRotateF(mtxRotX, part->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, part->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, part->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, part->scale.x, part->scale.y * part->verticalStretch, part->scale.z); guMtxCatF(mtxScale, mtxPivotOn, mtxTransform); guMtxCatF(mtxTransform, mtxRotation, mtxTemp); guMtxCatF(mtxTemp, mtxPivotOff, mtxTransform); if (!(part->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { guMtxCatF(mtxTransform, mtxActor, mtxTemp); } else { guMtxCatF(mtxTransform, mtxPartScale, mtxTemp); } guMtxCatF(mtxTemp, mtxTranslate, mtxTransform); part->curPos.x = partPosX + part->palAnimPosOffset[0]; part->curPos.y = partPosY + part->palAnimPosOffset[1]; part->curPos.z = partPosZ; if (part->spriteInstanceID >= 0) { if (!isPartner) { update_part_glow(TRUE, part, partYaw, FALSE); update_part_flash(TRUE, part, partYaw, FALSE); render_with_adjusted_palettes(SPRITE_MODE_NPC, part, partYaw, mtxTransform, 0); } else { update_part_glow(TRUE, part, clamp_angle(180.0f - partYaw), FALSE); update_part_flash(TRUE, part, clamp_angle(180.0f - partYaw), FALSE); render_with_adjusted_palettes(SPRITE_MODE_NPC, part, clamp_angle(180.0f - partYaw), mtxTransform, 0); } _add_part_decoration(part); } part = part->nextPart; } } void appendGfx_npc_actor_reflection(s32 flipYaw, Actor* actor) { Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation, mtxScale; Matrix4f mtxPivotOn, mtxPivotOff, mtxTranslate; Matrix4f mtxTemp, mtxTransform, mtxMirror; Matrix4f mtxActor, mtxPartScale; ActorPart* part; f32 actorPosX, actorPosY, actorPosZ; f32 partPosX, partPosY, partPosZ; f32 partYaw; s32 numParts; s32 i; actorPosX = actor->curPos.x + actor->headOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { actorPosY = actor->curPos.y + actor->headOffset.y; } else { actorPosY = actor->curPos.y - actor->headOffset.y; } actorPosZ = actor->curPos.z + actor->headOffset.z - 5.0f; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { guTranslateF(mtxPivotOn, -actor->rotPivotOffset.x * actor->scalingFactor, -actor->rotPivotOffset.y * actor->scalingFactor, -actor->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, actor->rotPivotOffset.x * actor->scalingFactor, actor->rotPivotOffset.y * actor->scalingFactor, actor->rotPivotOffset.z * actor->scalingFactor); } else { guTranslateF(mtxPivotOn, -actor->rotPivotOffset.x * actor->scalingFactor, actor->rotPivotOffset.y * actor->scalingFactor, -actor->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, actor->rotPivotOffset.x * actor->scalingFactor, -actor->rotPivotOffset.y * actor->scalingFactor, actor->rotPivotOffset.z * actor->scalingFactor); } guRotateF(mtxRotX, actor->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, actor->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, actor->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, actor->scale.x * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.y * SPRITE_WORLD_SCALE_D * actor->scalingFactor, actor->scale.z * SPRITE_WORLD_SCALE_D); guMtxCatF(mtxPivotOn, mtxScale, mtxTemp); guMtxCatF(mtxTemp, mtxRotation, mtxTransform); guMtxCatF(mtxTransform, mtxPivotOff, mtxActor); part = actor->partsTable; numParts = actor->numParts; for (i = 0; i < numParts; i++) { // determine part position if (!(part->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { partPosX = actorPosX + part->partOffset.x + part->visualOffset.x; if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { partPosY = actorPosY + part->partOffset.y + part->visualOffset.y; } else { partPosY = actorPosY - part->partOffset.y - part->visualOffset.y; } partPosZ = actorPosZ + part->partOffset.z + part->visualOffset.z; partYaw = part->yaw = actor->yaw; } else { partPosX = part->absolutePos.x + part->visualOffset.x; partPosY = part->absolutePos.y + part->visualOffset.y; partPosZ = part->absolutePos.z + part->visualOffset.z; guScaleF(mtxPartScale, actor->scale.x * SPRITE_WORLD_SCALE_D, actor->scale.y * SPRITE_WORLD_SCALE_D, actor->scale.z * SPRITE_WORLD_SCALE_D); partYaw = part->yaw; } if (part->flags & ACTOR_PART_FLAG_INVISIBLE) { part = part->nextPart; continue; } if (part->idleAnimations == NULL) { part = part->nextPart; continue; } if (!(actor->flags & ACTOR_FLAG_UPSIDE_DOWN)) { guTranslateF(mtxPivotOn, -part->rotPivotOffset.x * actor->scalingFactor, -part->rotPivotOffset.y * actor->scalingFactor, -part->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, part->rotPivotOffset.x * actor->scalingFactor, part->rotPivotOffset.y * actor->scalingFactor, part->rotPivotOffset.z * actor->scalingFactor); } else { guTranslateF(mtxPivotOn, -part->rotPivotOffset.x * actor->scalingFactor, part->rotPivotOffset.y * actor->scalingFactor, -part->rotPivotOffset.z * actor->scalingFactor); guTranslateF(mtxPivotOff, part->rotPivotOffset.x * actor->scalingFactor, -part->rotPivotOffset.y * actor->scalingFactor, part->rotPivotOffset.z * actor->scalingFactor); } guTranslateF(mtxTranslate, partPosX + part->palAnimPosOffset[0], partPosY + part->palAnimPosOffset[1], partPosZ - 1.0f); guRotateF(mtxRotX, part->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, part->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, part->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, part->scale.x, part->scale.y * part->verticalStretch, part->scale.z); mtx_mirror_y(mtxMirror); guMtxCatF(mtxScale, mtxPivotOn, mtxTemp); guMtxCatF(mtxTemp, mtxRotation, mtxTransform); guMtxCatF(mtxTransform, mtxPivotOff, mtxTemp); if (!(part->flags & ACTOR_PART_FLAG_USE_ABSOLUTE_POSITION)) { guMtxCatF(mtxTemp, mtxActor, mtxTransform); } else { guMtxCatF(mtxTemp, mtxPartScale, mtxTransform); } guMtxCatF(mtxTransform, mtxTranslate, mtxTemp); guMtxCatF(mtxTemp, mtxMirror, mtxTransform); if (flipYaw == 0) { update_part_glow(TRUE, part, partYaw, TRUE); update_part_flash(TRUE, part, partYaw, TRUE); render_with_adjusted_palettes(SPRITE_MODE_NPC, part, partYaw, mtxTransform, 1); } else { update_part_glow(TRUE, part, clamp_angle(partYaw + 180.0f), TRUE); update_part_flash(TRUE, part, clamp_angle(partYaw + 180.0f), TRUE); render_with_adjusted_palettes(SPRITE_MODE_NPC, part, clamp_angle(partYaw + 180.0f), mtxTransform, 1); } part = part->nextPart; } } void appendGfx_enemy_actor(void* data) { appendGfx_npc_actor(FALSE, (s32) data); } void appendGfx_partner_actor(void* data) { appendGfx_npc_actor(TRUE, (s32) data); } void appendGfx_enemy_actor_reflection(void* data) { Actor* actor = data; appendGfx_npc_actor_reflection(0, actor); } void appendGfx_partner_actor_reflection(void* data) { appendGfx_npc_actor_reflection(1, gBattleStatus.partnerActor); } void update_player_actor_shadow(void) { BattleStatus* battleStatus = &gBattleStatus; Camera* camera = &gCameras[CAM_BATTLE]; Actor* player = battleStatus->playerActor; ActorPart* parts = player->partsTable; Shadow* shadow; f32 x, y, z, distance; parts->animNotifyValue = spr_update_player_sprite(PLAYER_SPRITE_MAIN, parts->curAnimation, parts->animationRate); if (player->flags & ACTOR_FLAG_BLUR_ENABLED) { update_player_actor_blur_history(player); } shadow = get_shadow_by_index(player->shadow.id); shadow->flags &= ~ENTITY_FLAG_HIDDEN; if (!battleStatus->outtaSightActive) { shadow->alpha = 128; } else { shadow->alpha = 40; } distance = 32767.0f; x = player->curPos.x + player->headOffset.x; z = player->curPos.z + player->headOffset.z; y = player->curPos.y + player->headOffset.y + 12.0; npc_raycast_down_sides(0, &x, &y, &z, &distance); if (distance > 200.0f) { shadow->flags |= ENTITY_FLAG_HIDDEN; } shadow->pos.x = x; shadow->pos.y = y; shadow->pos.z = z; shadow->rot.y = clamp_angle(player->yaw - camera->curYaw); set_standard_shadow_scale(shadow, distance); shadow->scale.x *= player->shadowScale * player->scalingFactor; if (parts->opacity >= 255 && !(parts->flags & ACTOR_PART_FLAG_TRANSPARENT)) { player->renderMode = RENDER_MODE_ALPHATEST; } else { player->renderMode = RENDER_MODE_SURFACE_XLU_LAYER3; } } void appendGfx_player_actor(void* arg0) { BattleStatus* battleStatus = &gBattleStatus; PlayerData* playerData = &gPlayerData; Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation; Matrix4f mtxScale; Matrix4f mtxPivotOn, mtxPivotOff, mtxTranslate; Matrix4f mtxTemp, mtxTransform; Actor* partner; Actor* player; ActorPart* playerParts; EffectInstance* effect; f32 playerPosX, playerPosY, playerPosZ, playerYaw; s32 animChanged, palChanged, decorChanged, cond4; u32 lastAnim; player = battleStatus->playerActor; partner = battleStatus->partnerActor; playerParts = player->partsTable; playerPosX = player->curPos.x + player->headOffset.x; playerPosY = player->curPos.y + player->headOffset.y + player->verticalRenderOffset; playerPosZ = player->curPos.z + player->headOffset.z; playerYaw = playerParts->yaw = player->yaw; player->disableEffect->data.disableX->pos.x = playerPosX + (player->actorBlueprint->statusIconOffset.x + player->statusIconOffset.x) * player->scalingFactor; player->disableEffect->data.disableX->pos.y = playerPosY + (player->actorBlueprint->statusIconOffset.y + player->statusIconOffset.y) * player->scalingFactor; player->disableEffect->data.disableX->pos.z = playerPosZ; if (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS)) { if (player->disableDismissTimer != 0) { player->disableDismissTimer--; player->disableEffect->data.disableX->pos.y = NPC_DISPOSE_POS_Y; } else { player->disableEffect->data.disableX->scale = player->scalingFactor * 0.75; } } else { player->disableEffect->data.disableX->pos.y = NPC_DISPOSE_POS_Y; player->disableDismissTimer = 10; } if (battleStatus->waterBlockTurnsLeft != 0) { if ((gBattleStatus.flags1 & BS_FLAGS1_SHOW_PLAYER_DECORATIONS) || (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS))) { effect = battleStatus->waterBlockEffect; effect->data.waterBlock->pos.x = playerPosX; effect->data.waterBlock->pos.y = playerPosY; effect->data.waterBlock->pos.z = playerPosZ; } else { effect = battleStatus->waterBlockEffect; effect->data.waterBlock->pos.x = playerPosX; effect->data.waterBlock->pos.y = NPC_DISPOSE_POS_Y; effect->data.waterBlock->pos.z = playerPosZ; } } if (battleStatus->cloudNineTurnsLeft != 0) { if ((gBattleStatus.flags1 & BS_FLAGS1_SHOW_PLAYER_DECORATIONS) || (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS))) { effect = battleStatus->cloudNineEffect; effect->data.endingDecals->pos.x = playerPosX; effect->data.endingDecals->pos.y = playerPosY; effect->data.endingDecals->pos.z = playerPosZ; effect->data.endingDecals->scale = player->scalingFactor; } else { effect = battleStatus->cloudNineEffect; effect->data.endingDecals->pos.x = playerPosX; effect->data.endingDecals->pos.y = NPC_DISPOSE_POS_Y; effect->data.endingDecals->pos.z = playerPosZ; } } if (player->debuff == STATUS_KEY_FROZEN) { effect = player->icePillarEffect; if (player->icePillarEffect != NULL) { if ((gBattleStatus.flags1 & BS_FLAGS1_SHOW_PLAYER_DECORATIONS) || (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS))) { effect->data.icePillar->pos.x = playerPosX - 8.0f; effect->data.icePillar->pos.y = playerPosY; effect->data.icePillar->pos.z = playerPosZ; effect->data.icePillar->scale = player->size.y / 24.0; } else { effect->data.icePillar->pos.x = NPC_DISPOSE_POS_X; effect->data.icePillar->pos.y = NPC_DISPOSE_POS_Y; effect->data.icePillar->pos.z = NPC_DISPOSE_POS_Z; } } else { effect->data.icePillar->pos.x = NPC_DISPOSE_POS_X; effect->data.icePillar->pos.y = NPC_DISPOSE_POS_Y; effect->data.icePillar->pos.z = NPC_DISPOSE_POS_Z; } } else { effect = player->icePillarEffect; if (effect != NULL) { effect->flags |= FX_INSTANCE_FLAG_DISMISS; player->icePillarEffect = NULL; } } if (!(gBattleStatus.flags2 & BS_FLAGS2_HIDE_BUFF_COUNTERS) && !(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS) ) { battleStatus->buffEffect->data.partnerBuff->visible = TRUE; } else { battleStatus->buffEffect->data.partnerBuff->visible = FALSE; } do { if (player->debuff == STATUS_KEY_SHRINK) { player->scalingFactor += (0.4 - player->scalingFactor) / 6.0; } else { player->scalingFactor += (1.0 - player->scalingFactor) / 6.0; } } while (0); // required to match if (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS) { if (battleStatus->hammerCharge > 0) { create_status_icon_boost_hammer(player->hudElementDataIndex); remove_status_icon_boost_jump(player->hudElementDataIndex); } else { remove_status_icon_boost_hammer(player->hudElementDataIndex); } if (battleStatus->jumpCharge > 0) { create_status_icon_boost_jump(player->hudElementDataIndex); remove_status_icon_boost_hammer(player->hudElementDataIndex); } else { remove_status_icon_boost_jump(player->hudElementDataIndex); } } else { enable_status_icon_boost_jump(player->hudElementDataIndex); enable_status_icon_boost_hammer(player->hudElementDataIndex); } if ((player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS) && !(gBattleStatus.flags2 & BS_FLAGS2_PEACH_BATTLE)) { if (playerData->curHP > PERIL_THRESHOLD) { remove_status_icon_peril(player->hudElementDataIndex); do { if (playerData->curHP <= DANGER_THRESHOLD) { create_status_icon_danger(player->hudElementDataIndex); remove_status_icon_peril(player->hudElementDataIndex); } else { remove_status_icon_danger(player->hudElementDataIndex); } } while (0); // required to match } else { create_status_icon_peril(player->hudElementDataIndex); remove_status_icon_danger(player->hudElementDataIndex); } } else { remove_status_icon_peril(player->hudElementDataIndex); remove_status_icon_danger(player->hudElementDataIndex); } if (player->transparentStatus == STATUS_KEY_TRANSPARENT) { playerParts->flags |= ACTOR_PART_FLAG_TRANSPARENT; if (FALSE) { // TODO required to match - also whyyyyyy compiler, whyyyyy back: playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_STOP); create_status_debuff(player->hudElementDataIndex, STATUS_KEY_STOP); goto end; } } else { playerParts->flags &= ~ACTOR_PART_FLAG_TRANSPARENT; } do { animChanged = FALSE; palChanged = FALSE; decorChanged = FALSE; cond4 = FALSE; lastAnim = playerParts->curAnimation; } while (0); // required to match if ((((!(gBattleStatus.flags2 & BS_FLAGS2_OVERRIDE_INACTIVE_PLAYER) && (gBattleStatus.flags2 & BS_FLAGS2_PLAYER_TURN_USED)) && (partner != NULL)) || (battleStatus->outtaSightActive > 0)) && !(player->flags & ACTOR_FLAG_NO_INACTIVE_ANIM) && !((partner != NULL) && (partner->flags & ACTOR_FLAG_NO_ATTACK)) ) { if (!(gBattleStatus.flags2 & BS_FLAGS2_NO_PLAYER_PAL_ADJUST)) { if ((player->debuff != STATUS_KEY_FEAR) && (player->debuff != STATUS_KEY_PARALYZE) && (player->debuff != STATUS_KEY_FROZEN) && (player->debuff != STATUS_KEY_STOP) ) { if ((player->transparentStatus != STATUS_KEY_TRANSPARENT) && (player->stoneStatus != STATUS_KEY_STONE) && ((battleStatus->outtaSightActive > 0) || (gBattleStatus.flags2 & BS_FLAGS2_PLAYER_TURN_USED))) { if (is_ability_active(ABILITY_BERSERKER)) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_INACTIVE_BERSERK); } else if (player->debuff == STATUS_KEY_SLEEP) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_INACTIVE_SLEEP); } else if (player->debuff == STATUS_KEY_DIZZY) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_INACTIVE_DIZZY); } else { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_INACTIVE); } spr_update_player_sprite(PLAYER_SPRITE_MAIN, playerParts->curAnimation, playerParts->animationRate); animChanged = TRUE; } } if (player->debuff != STATUS_KEY_POISON) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_PLAYER_DEBUFF); } else { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_PLAYER_POISON); } palChanged = TRUE; set_actor_glow_pal(player, GLOW_PAL_OFF); decorChanged = TRUE; } } if (player->stoneStatus == STATUS_KEY_STONE) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_STONE); spr_update_player_sprite(PLAYER_SPRITE_MAIN, playerParts->curAnimation, playerParts->animationRate); animChanged = TRUE; if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_NONE); } set_actor_glow_pal(player, GLOW_PAL_OFF); palChanged = TRUE; enable_status_debuff(player->hudElementDataIndex); decorChanged = TRUE; enable_status_static(player->hudElementDataIndex); cond4 = TRUE; enable_status_transparent(player->hudElementDataIndex); enable_status_chill_out(player->hudElementDataIndex); } if ((player->flags & ACTOR_FLAG_USING_IDLE_ANIM) && !animChanged) { s32 temp = playerParts->curAnimation; if (temp == get_player_anim_for_status(STATUS_KEY_STONE)) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_NORMAL); } } if (is_ability_active(ABILITY_BERSERKER)) { if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_BERSERK); } palChanged = TRUE; } if (player->debuff == STATUS_KEY_POISON) { if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_POISON); } palChanged = TRUE; } if (player->debuff == STATUS_KEY_PARALYZE) { if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_PARALYZE); } palChanged = TRUE; } if (player->staticStatus == STATUS_KEY_STATIC) { if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_STATIC); } palChanged = TRUE; } if (battleStatus->turboChargeTurnsLeft != 0) { if (!decorChanged) { set_actor_glow_pal(player, GLOW_PAL_ON); } decorChanged = TRUE; } if (is_ability_active(ABILITY_ZAP_TAP)) { if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_STATIC); } palChanged = TRUE; } if (!palChanged) { set_actor_pal_adjustment(player, ACTOR_PAL_ADJUST_NONE); } if (!decorChanged) { set_actor_glow_pal(player, GLOW_PAL_OFF); } if (player->flags & ACTOR_FLAG_USING_IDLE_ANIM) { if (battleStatus->hustleTurns != 0) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_HUSTLE); animChanged = TRUE; } else if (!animChanged) { s32 temp = get_player_anim_for_status(STATUS_KEY_NORMAL); do { if (temp == get_player_anim_for_status(STATUS_KEY_HUSTLE)) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_NORMAL); } } while (0); // required to match } do { if (player->debuff == STATUS_KEY_FROZEN) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_FROZEN); animChanged = TRUE; } } else if (player->debuff != STATUS_KEY_SHRINK) { if (player->debuff == STATUS_KEY_POISON) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_POISON); animChanged = TRUE; } } else if (player->debuff == STATUS_KEY_DIZZY) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_DIZZY); animChanged = TRUE; } } else if (player->debuff == STATUS_KEY_SLEEP) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_SLEEP); animChanged = TRUE; } } else if (player->debuff == STATUS_KEY_PARALYZE) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_PARALYZE); animChanged = TRUE; } } else { if (player_team_is_ability_active(player, ABILITY_BERSERKER)) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_BERSERK); animChanged = TRUE; } } } } if (is_ability_active(ABILITY_ZAP_TAP)) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_STATIC); animChanged = TRUE; } player->staticStatus = STATUS_KEY_STATIC; player->staticDuration = 127; } else if ((player->staticStatus == STATUS_KEY_STATIC) && !animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_STATIC); animChanged = TRUE; } if ((player->transparentStatus == STATUS_KEY_TRANSPARENT) || (playerParts->flags & ACTOR_PART_FLAG_TRANSPARENT)) { if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_TRANSPARENT); animChanged = TRUE; } create_status_transparent(player->hudElementDataIndex, STATUS_KEY_TRANSPARENT); } if (!animChanged) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_NORMAL); } } while (0); // needed to match } if (!(gBattleStatus.flags1 & BS_FLAGS1_TATTLE_OPEN) && (player->flags & ACTOR_FLAG_SHOW_STATUS_ICONS)) { if (!cond4) { do { if (player->debuff == STATUS_KEY_POISON) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_POISON); } else if (player->debuff == STATUS_KEY_SLEEP) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_SLEEP); } else if (player->debuff == STATUS_KEY_PARALYZE) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_PARALYZE); } else if (player->debuff == STATUS_KEY_DIZZY) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_DIZZY); } else if (player->debuff == STATUS_KEY_SHRINK) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_SHRINK); } else if (player->debuff == STATUS_KEY_FROZEN) { create_status_debuff(player->hudElementDataIndex, STATUS_KEY_FROZEN); } } while (0); // required to match if (!cond4 && (is_ability_active(ABILITY_ZAP_TAP) || (player->staticStatus == STATUS_KEY_STATIC))) { create_status_static(player->hudElementDataIndex, STATUS_KEY_STATIC); } } if ((player->transparentStatus == STATUS_KEY_TRANSPARENT) || (playerParts->flags & ACTOR_PART_FLAG_TRANSPARENT)) { create_status_transparent(player->hudElementDataIndex, STATUS_KEY_TRANSPARENT); } } else { enable_status_debuff(player->hudElementDataIndex); enable_status_static(player->hudElementDataIndex); enable_status_transparent(player->hudElementDataIndex); enable_status_chill_out(player->hudElementDataIndex); } if (player->debuff != STATUS_KEY_STOP) { if (!animChanged) { s32 temp = playerParts->curAnimation; if (temp == get_player_anim_for_status(STATUS_KEY_STOP)) { playerParts->curAnimation = get_player_anim_for_status(STATUS_KEY_NORMAL); } } } else { goto back; } end: set_status_icons_properties(player->hudElementDataIndex, playerPosX, playerPosY, playerPosZ, player->actorBlueprint->statusIconOffset.x * player->scalingFactor, player->actorBlueprint->statusIconOffset.y * player->scalingFactor, player->actorBlueprint->statusTextOffset.x * player->scalingFactor, player->actorBlueprint->statusTextOffset.y * player->scalingFactor); set_status_icons_offset(player->hudElementDataIndex, player->size.y * player->scalingFactor, player->size.x * player->scalingFactor); playerPosX += playerParts->palAnimPosOffset[0]; playerPosY += playerParts->palAnimPosOffset[1]; playerParts->curPos.x = playerPosX; playerParts->curPos.y = playerPosY; playerParts->curPos.z = playerPosZ; guTranslateF(mtxTranslate, playerPosX, playerPosY, playerPosZ); guTranslateF(mtxPivotOn, -player->rotPivotOffset.x * player->scalingFactor, -player->rotPivotOffset.y * player->scalingFactor, -player->rotPivotOffset.z * player->scalingFactor); guTranslateF(mtxPivotOff, player->rotPivotOffset.x * player->scalingFactor, player->rotPivotOffset.y * player->scalingFactor, player->rotPivotOffset.z * player->scalingFactor); guRotateF(mtxRotX, player->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, player->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, player->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, player->scale.x * SPRITE_WORLD_SCALE_D * player->scalingFactor, player->scale.y * SPRITE_WORLD_SCALE_D * player->scalingFactor * playerParts->verticalStretch, player->scale.z * SPRITE_WORLD_SCALE_D); guMtxCatF(mtxScale, mtxPivotOn, mtxTemp); guMtxCatF(mtxTemp, mtxRotation, mtxTransform); guMtxCatF(mtxTransform, mtxPivotOff, mtxTemp); guMtxCatF(mtxTemp, mtxTranslate, mtxTransform); if (lastAnim != playerParts->curAnimation) { spr_update_player_sprite(PLAYER_SPRITE_MAIN, playerParts->curAnimation, playerParts->animationRate); } update_part_glow(FALSE, playerParts, clamp_angle(playerYaw + 180.0f), FALSE); update_part_flash(FALSE, playerParts, clamp_angle(playerYaw + 180.0f), FALSE); render_with_adjusted_palettes(SPRITE_MODE_PLAYER, playerParts, clamp_angle(playerYaw + 180.0f), mtxTransform, 0); _add_part_decoration(playerParts); } void appendGfx_player_actor_reflection(void* arg0) { Matrix4f mtxRotX, mtxRotY, mtxRotZ, mtxRotation, mtxScale; Matrix4f mtxPivotOn, mtxPivotOff, mtxTranslate; Matrix4f mtxTemp, mtxTransform, mtxMirror; Actor* player = gBattleStatus.playerActor; ActorPart* part = &player->partsTable[0]; f32 playerYaw = player->yaw; f32 dx, dy, dz; dx = player->curPos.x + player->headOffset.x; dx += part->palAnimPosOffset[0]; dy = player->curPos.y + player->headOffset.y; dy += part->palAnimPosOffset[1]; dz = player->curPos.z + player->headOffset.z - 5.0f; part->yaw = playerYaw; guTranslateF(mtxTranslate, dx, dy, dz - 1.0f); guTranslateF(mtxPivotOn, -player->rotPivotOffset.x * player->scalingFactor, -player->rotPivotOffset.y * player->scalingFactor, -player->rotPivotOffset.z * player->scalingFactor); guTranslateF(mtxPivotOff, player->rotPivotOffset.x * player->scalingFactor, player->rotPivotOffset.y * player->scalingFactor, player->rotPivotOffset.z * player->scalingFactor); guRotateF(mtxRotX, player->rot.x, 1.0f, 0.0f, 0.0f); guRotateF(mtxRotY, player->rot.y, 0.0f, 1.0f, 0.0f); guRotateF(mtxRotZ, player->rot.z, 0.0f, 0.0f, 1.0f); guMtxCatF(mtxRotY, mtxRotX, mtxTemp); guMtxCatF(mtxTemp, mtxRotZ, mtxRotation); guScaleF(mtxScale, player->scale.x * SPRITE_WORLD_SCALE_D * player->scalingFactor, player->scale.y * SPRITE_WORLD_SCALE_D * player->scalingFactor * part->verticalStretch, player->scale.z * SPRITE_WORLD_SCALE_D); mtx_mirror_y(mtxMirror); guMtxCatF(mtxScale, mtxPivotOn, mtxTemp); guMtxCatF(mtxTemp, mtxRotation, mtxTemp); guMtxCatF(mtxTemp, mtxPivotOff, mtxTemp); guMtxCatF(mtxTemp, mtxTranslate, mtxTransform); guMtxCatF(mtxTransform, mtxMirror, mtxTransform); update_part_glow(FALSE, part, clamp_angle(playerYaw + 180.0f), TRUE); update_part_flash(FALSE, part, clamp_angle(playerYaw + 180.0f), TRUE); render_with_adjusted_palettes(SPRITE_MODE_PLAYER, part, clamp_angle(playerYaw + 180.0f), mtxTransform, TRUE); } s32 render_with_adjusted_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { s32 opacity; s32 sprDrawOpts; if (part->flags & ACTOR_PART_FLAG_NO_DECORATIONS) { opacity = 255; sprDrawOpts = 0; if (part->opacity < 255) { sprDrawOpts = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { sprDrawOpts = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = opacity * 120 / 255; } if (isNpcSprite == SPRITE_MODE_PLAYER) { if (opacity == 255) { spr_draw_player_sprite(PLAYER_SPRITE_MAIN, yaw, 0, NULL, mtx); } else { spr_draw_player_sprite(PLAYER_SPRITE_MAIN | sprDrawOpts, yaw, opacity, NULL, mtx); } } else { if (opacity == 255) { spr_draw_npc_sprite(part->spriteInstanceID, yaw, 0, NULL, mtx); } else { spr_draw_npc_sprite(part->spriteInstanceID | sprDrawOpts, yaw, opacity, NULL, mtx); } } return 0; } switch (part->decorationTable->paletteAdjustment) { case ACTOR_PAL_ADJUST_NONE: render_without_adjusted_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_SLEEP: render_with_sleep_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_STATIC: render_with_static_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_FEAR: render_with_fear_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_POISON: render_with_poison_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_PARALYZE: render_with_paralyze_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_BERSERK: render_with_berserk_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_WATT_IDLE: render_with_watt_idle_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_WATT_ATTACK: render_with_watt_attack_palettes(isNpcSprite, part, yaw, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_PLAYER_DEBUFF: render_with_player_debuff_palettes(isNpcSprite, part, yaw, mtx, skipAnimation, FALSE); break; case ACTOR_PAL_ADJUST_PLAYER_POISON: render_with_player_debuff_palettes(isNpcSprite, part, yaw, mtx, skipAnimation, TRUE); break; case ACTOR_PAL_ADJUST_BLEND_PALETTES_UNIFORM_INTERVALS: render_with_pal_blending(isNpcSprite, part, yaw, FALSE, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_BLEND_PALETTES_VARYING_INTERVALS: render_with_pal_blending(isNpcSprite, part, yaw, TRUE, mtx, skipAnimation); break; case ACTOR_PAL_ADJUST_BLEND_PALSETS: render_with_palset_blending(isNpcSprite, part, yaw, mtx, skipAnimation); break; default: break; } return 0; } void make_flash_palettes(ActorPart* part) { DecorationTable* decorations = part->decorationTable; PAL_PTR src; PAL_PTR dest; s32 i, j; for (i = 0; i < decorations->originalPalettesCount; i++) { if (decorations->adjustedPalettes[i] != NULL) { src = decorations->adjustedPalettes[i]; dest = decorations->copiedPalettes[1][i]; for (j = 0; j < SPR_PAL_SIZE; j++) { *dest = *src | 0xFFFE; // pure white, not affecting alpha bit src++; dest++; } decorations->flashPalettes[i] = decorations->copiedPalettes[1][i]; } } } void func_unkA_draw_npc(ActorPart* part, s32 yaw, Matrix4f mtx) { DecorationTable* decorations = part->decorationTable; s32 opacity = 255; s32 idMask = 0; PAL_PTR dest; PAL_PTR src; s32 i, j; if (part->opacity < 255) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = (opacity * 120) / 255; } if (decorations->flashEnabled != FLASH_PAL_OFF) { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 0x10); decorations->originalPalettesCount = 0; while (decorations->originalPalettesList[decorations->originalPalettesCount] != (PAL_PTR) -1) { decorations->originalPalettesCount++; } for (i = 0; i < decorations->originalPalettesCount; i++) { src = decorations->originalPalettesList[i]; dest = decorations->copiedPalettes[0][i]; if (src != NULL) { for (j = 0; j < ARRAY_COUNT(decorations->copiedPalettes[0][i]); j++) { *dest = *src; src++; dest++; } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } func_unkB_draw_npc(part, yaw, mtx); } else { spr_draw_npc_sprite(part->spriteInstanceID | idMask, yaw, opacity, NULL, mtx); } } void func_unkB_draw_npc(ActorPart* part, s32 yaw, Matrix4f mtx) { DecorationTable* decorations = part->decorationTable; s32 opacity = 255; s32 idMask = 0; if (part->opacity < 255) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = (opacity * 120) / 255; } if (decorations->flashEnabled != FLASH_PAL_OFF) { make_flash_palettes(part); spr_draw_npc_sprite(part->spriteInstanceID | DRAW_SPRITE_OVERRIDE_PALETTES | idMask, yaw, opacity, decorations->flashPalettes, mtx); } else { spr_draw_npc_sprite(part->spriteInstanceID | DRAW_SPRITE_OVERRIDE_PALETTES | idMask, yaw, opacity, decorations->adjustedPalettes, mtx); } } void func_unkA_draw_player(ActorPart* part, s32 yaw, Matrix4f mtx) { DecorationTable* decorations = part->decorationTable; s32 opacity = 255; s32 idMask = 0; PAL_PTR src; PAL_PTR dest; s32 i, j; if (part->opacity < 255) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = (opacity * 120) / 255; } if (decorations->flashEnabled != FLASH_PAL_OFF) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while (decorations->originalPalettesList[decorations->originalPalettesCount] != (PAL_PTR) -1) { decorations->originalPalettesCount++; } for (i = 0; i < decorations->originalPalettesCount; i++) { src = decorations->originalPalettesList[i]; dest = decorations->copiedPalettes[0][i]; if (decorations->originalPalettesList[i] != NULL) { for (j = 0; j < ARRAY_COUNT(decorations->copiedPalettes[0][i]); j++) { *dest = *src; dest++; src++; } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } func_unkB_draw_player(part, yaw, mtx); } else { spr_draw_player_sprite(PLAYER_SPRITE_MAIN | idMask, yaw, opacity, NULL, mtx); } } void func_unkB_draw_player(ActorPart* part, s32 yaw, Matrix4f mtx) { DecorationTable* decorations = part->decorationTable; s32 opacity = 255; s32 idMask = 0; if (part->opacity < 255) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { idMask = DRAW_SPRITE_OVERRIDE_ALPHA; opacity = (opacity * 120) / 255; } if (decorations->flashEnabled != FLASH_PAL_OFF) { make_flash_palettes(part); idMask |= DRAW_SPRITE_OVERRIDE_PALETTES; spr_draw_player_sprite(PLAYER_SPRITE_MAIN | idMask, yaw, opacity, decorations->flashPalettes, mtx); } else { idMask |= DRAW_SPRITE_OVERRIDE_PALETTES; spr_draw_player_sprite(PLAYER_SPRITE_MAIN | idMask, yaw, opacity, decorations->adjustedPalettes, mtx); } } void render_without_adjusted_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; if (decorations->resetPalAdjust) { part->verticalStretch = 1; part->palAnimPosOffset[0] = 0; part->palAnimPosOffset[1] = 0; decorations->resetPalAdjust = FALSE; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkA_draw_player(part, yaw, mtx); } else { func_unkA_draw_npc(part, yaw, mtx); } } void render_with_sleep_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; s32 i, j; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } decorations->palAnimState = 0; decorations->resetPalAdjust = FALSE; } for (i = 0; i < decorations->originalPalettesCount; i++) { PAL_PTR palIn = decorations->originalPalettesList[i]; PAL_PTR palOut = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = palOut; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r = UNPACK_PAL_R(*palIn); u8 g = UNPACK_PAL_G(*palIn); u8 b = UNPACK_PAL_B(*palIn); u8 a = UNPACK_PAL_A(*palIn); palIn++; // make colors darker and bluer r *= 0.2; g *= 0.4; b *= 0.7; *palOut++ = PACK_PAL_RGBA(r, g, b, a); } } } switch (decorations->palAnimState) { case 0: case 1: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } break; } } void render_with_static_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; s32 paletteType; s32 staticPalIdx; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = SPR_PLAYER_COLOR_VARIATIONS; } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } decorations->palAnimState = -2; decorations->palBlendAlpha = 0; decorations->resetPalAdjust = FALSE; decorations->nextPalTime = 0; } if (!skipAnimation) { if (decorations->nextPalTime == 0) { decorations->palAnimState += 2; if (StaticPalettesAnim[decorations->palAnimState] == PAL_ANIM_END) { decorations->palAnimState = 0; } decorations->nextPalTime = StaticPalettesAnim[decorations->palAnimState + 1] / 2; } paletteType = StaticPalettesAnim[decorations->palAnimState]; decorations->nextPalTime--; } else { paletteType = StaticPalettesAnim[decorations->palAnimState]; } switch (paletteType) { case STATIC_DEFAULT: // no change for (i = 0; i < decorations->spriteColorVariations; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case STATIC_BRIGHT: // bright yellow for (i = 0; i < decorations->spriteColorVariations; i++) { staticPalIdx = decorations->spriteColorVariations * STANDARD_PAL_STATIC + i; palIn = decorations->originalPalettesList[staticPalIdx]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case STATIC_DARK: // darkened via code for (i = 0; i < decorations->spriteColorVariations; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r = UNPACK_PAL_R(*palIn); u8 g = UNPACK_PAL_G(*palIn); u8 b = UNPACK_PAL_B(*palIn); u8 a = UNPACK_PAL_A(*palIn); palIn++; r *= 0.1; g *= 0.1; b *= 0.1; *palOut++ = PACK_PAL_RGBA(r, g, b, a); } } } break; } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } if (!skipAnimation) { decorations->palBlendAlpha--; } } void render_with_fear_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; s32 temp; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 2; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } decorations->palAnimState = 0; decorations->palBlendAlpha = 0; decorations->nextPalTime = 0; decorations->resetPalAdjust = FALSE; } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = palOut; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r = UNPACK_PAL_R(*palIn); u8 g = UNPACK_PAL_G(*palIn); u8 b = UNPACK_PAL_B(*palIn); u8 a = UNPACK_PAL_A(*palIn); palIn++; // darken the color r /= 2; g /= 2; b /= 2; *palOut++ = PACK_PAL_RGBA(r, g, b, a); } } } if (decorations->nextPalTime <= 0) { part->palAnimPosOffset[0] = FearPaletteAnimXOffsets[abs(decorations->nextPalTime)]; if (part->palAnimPosOffset[0] == PAL_ANIM_END) { part->palAnimPosOffset[0] = 0; // 30-90 decorations->nextPalTime = rand_int(60) + 30; } } if (!skipAnimation) { decorations->nextPalTime--; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } } void render_with_poison_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = SPR_PLAYER_COLOR_VARIATIONS; } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } decorations->palAnimState = 0; decorations->palBlendAlpha = 0; decorations->resetPalAdjust = FALSE; } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } for (i = 0; i < decorations->spriteColorVariations; i++) { palIn = decorations->originalPalettesList[decorations->spriteColorVariations + i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } } void render_with_paralyze_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } decorations->palAnimState = 0; decorations->nextPalTime = 0; decorations->palBlendAlpha = 10; decorations->resetPalAdjust = FALSE; } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r = UNPACK_PAL_R(*palIn); u8 g = UNPACK_PAL_G(*palIn); u8 b = UNPACK_PAL_B(*palIn); u8 a = UNPACK_PAL_A(*palIn); palIn++; r += 4; if (r > 31) { r = 31; } g += 4; if (g > 31) { g = 31; } b += 4; if (b > 31) { b = 31; } *palOut++ = PACK_PAL_RGBA(r, g, b, a); } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } switch (decorations->palAnimState) { case 0: case 1: if (decorations->nextPalTime <= 0) { part->palAnimPosOffset[1] = ParalyzePaletteAnimXOffsets[abs(decorations->nextPalTime)]; if (part->palAnimPosOffset[1] == PAL_ANIM_END) { part->palAnimPosOffset[1] = 0; decorations->nextPalTime = rand_int(60) + 30; // 30-90 } } if (!skipAnimation) { decorations->nextPalTime--; } switch (decorations->palBlendAlpha) { case 10: case 12: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } break; case 13: decorations->palBlendAlpha = 0; // fallthrough default: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkA_draw_player(part, yaw, mtx); } else { func_unkA_draw_npc(part, yaw, mtx); } break; } if (!skipAnimation) { decorations->palBlendAlpha++; } break; } } void render_with_berserk_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; s32 i, j; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->palAnimState = 0; } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->palAnimState = 0; } decorations->palBlendAlpha = 0; decorations->palAnimState = 0; decorations->resetPalAdjust = FALSE; } // adjust each palette for (i = 0; i < decorations->originalPalettesCount; i++) { PAL_PTR palIn = decorations->originalPalettesList[i]; PAL_PTR palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r = UNPACK_PAL_R(*palIn); u8 g = UNPACK_PAL_G(*palIn); u8 b = UNPACK_PAL_B(*palIn); u8 a = UNPACK_PAL_A(*palIn); palIn++; // make each color darker and redder r *= 0.8; g *= 0.6; b *= 0.1; *palOut++ = PACK_PAL_RGBA(r, g, b, a); } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } } void render_with_watt_idle_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; s32 palIdx; s32 brightnessLevel; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = SPR_PLAYER_COLOR_VARIATIONS; } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } decorations->palAnimState = -2; decorations->palBlendAlpha = 0; decorations->resetPalAdjust = FALSE; decorations->nextPalTime = 0; } if (!skipAnimation) { if (decorations->nextPalTime == 0) { decorations->palAnimState += 2; if (bWattIdlePalettesAnim[decorations->palAnimState] == PAL_ANIM_END) { decorations->palAnimState = 0; } decorations->nextPalTime = bWattIdlePalettesAnim[decorations->palAnimState + 1] / 2; } brightnessLevel = bWattIdlePalettesAnim[decorations->palAnimState]; decorations->nextPalTime--; } else { //@bug if only called with skipAnimation set, palAnimPos will always be -2 and the array access is OOB brightnessLevel = bWattIdlePalettesAnim[decorations->palAnimState]; } switch (brightnessLevel) { case WATT_DEFAULT: for (i = 0; i < decorations->spriteColorVariations; i++) { // use watt's base palettes palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case WATT_BRIGHTEST: for (i = 0; i < decorations->spriteColorVariations; i++) { // use watt's Brightest palettes palIdx = decorations->spriteColorVariations * SPR_PAL_BattleWatt_Brightest + i; palIn = decorations->originalPalettesList[palIdx]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case WATT_BRIGHTER: for (i = 0; i < decorations->spriteColorVariations; i++) { // use watt's Brighter palettes palIdx = decorations->spriteColorVariations * SPR_PAL_BattleWatt_Brighter + i; palIn = decorations->originalPalettesList[palIdx]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } if (!skipAnimation) { decorations->palBlendAlpha--; } } void render_with_watt_attack_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR palIn; PAL_PTR palOut; s32 i, j; s32 palIdx; s32 brightness; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = SPR_PLAYER_COLOR_VARIATIONS; } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } for (i = 0; i < decorations->originalPalettesCount; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } decorations->palAnimState = -2; decorations->palBlendAlpha = 0; decorations->resetPalAdjust = FALSE; decorations->nextPalTime = 0; } if (!skipAnimation) { if (decorations->nextPalTime == 0) { decorations->palAnimState += 2; if (WattAttackPalettesAnim[decorations->palAnimState] == PAL_ANIM_END) { decorations->palAnimState = 0; } decorations->nextPalTime = WattAttackPalettesAnim[decorations->palAnimState + 1] / 2; } brightness = WattAttackPalettesAnim[decorations->palAnimState]; decorations->nextPalTime--; } else { //@bug if only called with skipAnimation set, palAnimPos will always be -2 and the array access is OOB brightness = WattAttackPalettesAnim[decorations->palAnimState]; } switch (brightness) { case WATT_DEFAULT: for (i = 0; i < decorations->spriteColorVariations; i++) { palIn = decorations->originalPalettesList[i]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case WATT_BRIGHTEST: for (i = 0; i < decorations->spriteColorVariations; i++) { // use watt's Brightest palettes palIdx = decorations->spriteColorVariations * SPR_PAL_BattleWatt_Brightest + i; palIn = decorations->originalPalettesList[palIdx]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; case WATT_BRIGHTER: for (i = 0; i < decorations->spriteColorVariations; i++) { // use watt's Brighter palettes palIdx = decorations->spriteColorVariations * SPR_PAL_BattleWatt_Brighter + i; palIn = decorations->originalPalettesList[palIdx]; palOut = decorations->copiedPalettes[0][i]; if (palIn != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *palIn++; } } } break; } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } if (!skipAnimation) { decorations->palBlendAlpha--; } } void render_with_player_debuff_palettes(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation, b32 isPoison) { DecorationTable* decorations = part->decorationTable; PAL_PTR color2; PAL_PTR color1; PAL_PTR palOut; s32 i, j; u8 blendAlpha; if (decorations->resetPalAdjust) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } if (gBattleStatus.flags2 & BS_FLAGS2_PEACH_BATTLE) { decorations->spriteColorVariations = SPR_PEACH_BTL_PAL_STRIDE; } else { decorations->spriteColorVariations = SPR_PLAYER_COLOR_VARIATIONS; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } if (decorations->resetPalAdjust == TRUE) { decorations->palAnimState = 0; decorations->palBlendAlpha = 0; } else { decorations->palAnimState = 0; decorations->palBlendAlpha = 255; } for (i = 0; i < decorations->originalPalettesCount; i++) { color2 = decorations->originalPalettesList[i]; color1 = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = color1; if (color2 != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *color1++ = *color2++; } } } if (isPoison) { for (i = 0; i < decorations->spriteColorVariations; i++) { color2 = decorations->originalPalettesList[decorations->spriteColorVariations + i]; palOut = decorations->copiedPalettes[0][i]; for (j = 0; j < SPR_PAL_SIZE; j++) { *palOut++ = *color2++; } } } decorations->nextPalTime = 10; decorations->palBlendAlpha = 0; decorations->palAnimState = 0; decorations->resetPalAdjust = FALSE; } if (decorations->palAnimState == 0) { if (!skipAnimation && decorations->nextPalTime != 0) { decorations->nextPalTime--; } else { if (!skipAnimation) { decorations->palBlendAlpha += 2560; if (decorations->palBlendAlpha > 255 * 100) { decorations->palBlendAlpha = 255 * 100; } } blendAlpha = decorations->palBlendAlpha / 100; for (i = 0; i < decorations->spriteColorVariations; i++) { if (!isPoison) { color2 = decorations->originalPalettesList[i]; } else { color2 = decorations->originalPalettesList[decorations->spriteColorVariations * STANDARD_PAL_POISON + i]; } color1 = decorations->originalPalettesList[decorations->spriteColorVariations * STANDARD_PAL_DIZZY + i]; palOut = decorations->copiedPalettes[0][i]; for (j = 0; j < SPR_PAL_SIZE; j++) { u8 r2 = UNPACK_PAL_R(*color2); u8 g2 = UNPACK_PAL_G(*color2); u8 b2 = UNPACK_PAL_B(*color2); u8 r1 = UNPACK_PAL_R(*color1); u8 g1 = UNPACK_PAL_G(*color1); u8 b1 = UNPACK_PAL_B(*color1); u8 a1 = UNPACK_PAL_A(*color1); color2++; color1++; r1 = LERP_COMPONENT(r2, r1, blendAlpha); g1 = LERP_COMPONENT(g2, g1, blendAlpha); b1 = LERP_COMPONENT(b2, b1, blendAlpha); *palOut++ = PACK_PAL_RGBA(r1, g1, b1, a1); } } if (blendAlpha == 255) { decorations->palAnimState = 1; } } } for (i = 0; i < decorations->originalPalettesCount; i++) { decorations->adjustedPalettes[i] = decorations->copiedPalettes[0][i]; } switch (decorations->palAnimState) { case 0: case 1: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } break; } } void render_with_pal_blending(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 hasDifferentIntervals, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR color1; PAL_PTR color2; PAL_PTR outColor; s32 i, j; u8 blendAlpha; u8 r2, g2, b2, a1; u8 r1, g1, b1; if (decorations->resetPalAdjust != 0) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while ((s32)decorations->originalPalettesList[decorations->originalPalettesCount] != -1) { decorations->originalPalettesCount++; } } if (decorations->resetPalAdjust == 1) { decorations->palAnimState = 0; decorations->palBlendAlpha = 0; } else { decorations->palAnimState = 0; decorations->palBlendAlpha = 255; } for (i = 0; i < decorations->originalPalettesCount; i++) { color2 = decorations->originalPalettesList[i]; color1 = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = color1; if (color2 != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *color1++ = *color2++; } } } if (!hasDifferentIntervals) { decorations->palswapTimeAtoB = decorations->palswapTimeHoldA; decorations->palswapTimeHoldB = decorations->palswapTimeAtoB; decorations->palswapTimeBtoA = decorations->palswapTimeAtoB; decorations->palswapTimeHoldA = 0; } decorations->nextPalTime = decorations->palswapTimeHoldA; decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->resetPalAdjust = FALSE; } // blending from A -> B switch (decorations->palAnimState) { case PAL_SWAP_HOLD_A: if (skipAnimation) { break; } if (decorations->nextPalTime != 0) { decorations->nextPalTime--; break; } decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_A_TO_B; // fallthrough case PAL_SWAP_A_TO_B: if (!skipAnimation) { decorations->palBlendAlpha += 25600 / decorations->palswapTimeAtoB; if (decorations->palBlendAlpha > 255 * 100) { decorations->palBlendAlpha = 255 * 100; } } blendAlpha = decorations->palBlendAlpha / 100; // blend two palettes color2 = decorations->originalPalettesList[decorations->blendPalA]; color1 = decorations->originalPalettesList[decorations->blendPalB]; outColor = decorations->adjustedPalettes[0] = decorations->copiedPalettes[0][0]; for (j = 0; j < SPR_PAL_SIZE; j++) { r2 = UNPACK_PAL_R(*color2); g2 = UNPACK_PAL_G(*color2); b2 = UNPACK_PAL_B(*color2); r1 = UNPACK_PAL_R(*color1); g1 = UNPACK_PAL_G(*color1); b1 = UNPACK_PAL_B(*color1); a1 = UNPACK_PAL_A(*color1); color2++; color1++; r1 = LERP_COMPONENT(r2, r1, blendAlpha); g1 = LERP_COMPONENT(g2, g1, blendAlpha); b1 = LERP_COMPONENT(b2, b1, blendAlpha); *outColor++ = PACK_PAL_RGBA(r1, g1, b1, a1); } if (blendAlpha == 255) { decorations->palAnimState = PAL_SWAP_HOLD_B; decorations->nextPalTime = decorations->palswapTimeHoldB; } break; } // blending from B -> A switch (decorations->palAnimState) { case PAL_SWAP_HOLD_B: if (skipAnimation) { break; } if (decorations->nextPalTime != 0) { decorations->nextPalTime--; break; } decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_B_TO_A; // fallthrough case PAL_SWAP_B_TO_A: if (!skipAnimation) { decorations->palBlendAlpha += 25600 / decorations->palswapTimeBtoA; if (decorations->palBlendAlpha > 255 * 100) { decorations->palBlendAlpha = 255 * 100; } } blendAlpha = decorations->palBlendAlpha / 100; // blend two palettes color2 = decorations->originalPalettesList[decorations->blendPalB]; color1 = decorations->originalPalettesList[decorations->blendPalA]; outColor = decorations->copiedPalettes[0][0]; decorations->adjustedPalettes[0] = outColor; for (j = 0; j < SPR_PAL_SIZE; j++) { r2 = UNPACK_PAL_R(*color2); g2 = UNPACK_PAL_G(*color2); b2 = UNPACK_PAL_B(*color2); r1 = UNPACK_PAL_R(*color1); g1 = UNPACK_PAL_G(*color1); b1 = UNPACK_PAL_B(*color1); a1 = UNPACK_PAL_A(*color1); color2++; color1++; r1 = LERP_COMPONENT(r2, r1, blendAlpha); g1 = LERP_COMPONENT(g2, g1, blendAlpha); b1 = LERP_COMPONENT(b2, b1, blendAlpha); *outColor++ = PACK_PAL_RGBA(r1, g1, b1, a1); } if (blendAlpha == 255) { decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->nextPalTime = decorations->palswapTimeHoldA; } break; } switch (decorations->palAnimState) { case PAL_SWAP_HOLD_A: case PAL_SWAP_A_TO_B: case PAL_SWAP_HOLD_B: case PAL_SWAP_B_TO_A: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } break; } } void render_with_palset_blending(b32 isNpcSprite, ActorPart* part, s32 yaw, Matrix4f mtx, b32 skipAnimation) { DecorationTable* decorations = part->decorationTable; PAL_PTR color1; PAL_PTR color2; PAL_PTR outColor; s32 i, j; u8 blendAlpha; u8 r2, g2, b2, a1; u8 r1, g1, b1; // copy palettes from sprite data if (decorations->resetPalAdjust != 0) { if (isNpcSprite == SPRITE_MODE_PLAYER) { decorations->originalPalettesList = spr_get_player_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while (decorations->originalPalettesList[decorations->originalPalettesCount] != (PAL_PTR) -1) { decorations->originalPalettesCount++; } } else { decorations->originalPalettesList = spr_get_npc_palettes(part->curAnimation >> 16); decorations->originalPalettesCount = 0; while (decorations->originalPalettesList[decorations->originalPalettesCount] != (PAL_PTR) -1) { decorations->originalPalettesCount++; } decorations->spriteColorVariations = spr_get_npc_color_variations(part->curAnimation >> 16); } if (decorations->resetPalAdjust == 1) { decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->palBlendAlpha = 0; } else { decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->palBlendAlpha = 255; } for (i = 0; i < decorations->originalPalettesCount; i++) { color2 = decorations->originalPalettesList[i]; color1 = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = color1; if (color2 != NULL) { for (j = 0; j < SPR_PAL_SIZE; j++) { *color1++ = *color2++; } } } decorations->nextPalTime = decorations->palswapTimeHoldA; decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->resetPalAdjust = FALSE; } // blending from A -> B switch (decorations->palAnimState) { case PAL_SWAP_HOLD_A: if (skipAnimation) { break; } if (decorations->nextPalTime != 0) { decorations->nextPalTime--; break; } decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_A_TO_B; // fallthrough case PAL_SWAP_A_TO_B: if (!skipAnimation) { decorations->palBlendAlpha += 25600 / decorations->palswapTimeAtoB; if (decorations->palBlendAlpha > 255 * 100) { decorations->palBlendAlpha = 255 * 100; } } blendAlpha = decorations->palBlendAlpha / 100; // blend all palettes from two palette sets for (i = 0; i < decorations->spriteColorVariations; i++) { color2 = decorations->originalPalettesList[decorations->blendPalA * decorations->spriteColorVariations + i]; color1 = decorations->originalPalettesList[decorations->blendPalB * decorations->spriteColorVariations + i]; outColor = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = outColor; for (j = 0; j < SPR_PAL_SIZE; j++) { r2 = UNPACK_PAL_R(*color2); g2 = UNPACK_PAL_G(*color2); b2 = UNPACK_PAL_B(*color2); r1 = UNPACK_PAL_R(*color1); g1 = UNPACK_PAL_G(*color1); b1 = UNPACK_PAL_B(*color1); a1 = UNPACK_PAL_A(*color1); color2++; color1++; r1 = LERP_COMPONENT(r2, r1, blendAlpha); g1 = LERP_COMPONENT(g2, g1, blendAlpha); b1 = LERP_COMPONENT(b2, b1, blendAlpha); *outColor++ = PACK_PAL_RGBA(r1, g1, b1, a1); } } if (blendAlpha == 255) { decorations->palAnimState = PAL_SWAP_HOLD_B; decorations->nextPalTime = decorations->palswapTimeHoldB; } break; } switch (decorations->palAnimState) { case PAL_SWAP_HOLD_B: if (skipAnimation) { break; } if (decorations->nextPalTime != 0) { decorations->nextPalTime--; break; } decorations->palBlendAlpha = 0; decorations->palAnimState = PAL_SWAP_B_TO_A; // fallthrough case PAL_SWAP_B_TO_A: if (!skipAnimation) { decorations->palBlendAlpha += 25600 / decorations->palswapTimeBtoA; if (decorations->palBlendAlpha > 255 * 100) { decorations->palBlendAlpha = 255 * 100; } } blendAlpha = decorations->palBlendAlpha / 100; // blend all palettes from two palette sets for (i = 0; i < decorations->spriteColorVariations; i++) { color2 = decorations->originalPalettesList[decorations->blendPalA * decorations->spriteColorVariations + i]; color1 = decorations->originalPalettesList[decorations->blendPalB * decorations->spriteColorVariations + i]; outColor = decorations->copiedPalettes[0][i]; decorations->adjustedPalettes[i] = outColor; for (j = 0; j < SPR_PAL_SIZE; j++) { r2 = UNPACK_PAL_R(*color2); g2 = UNPACK_PAL_G(*color2); b2 = UNPACK_PAL_B(*color2); r1 = UNPACK_PAL_R(*color1); g1 = UNPACK_PAL_G(*color1); b1 = UNPACK_PAL_B(*color1); a1 = UNPACK_PAL_A(*color1); color2++; color1++; r1 = LERP_COMPONENT(r2, r1, blendAlpha); g1 = LERP_COMPONENT(g2, g1, blendAlpha); b1 = LERP_COMPONENT(b2, b1, blendAlpha); *outColor++ = PACK_PAL_RGBA(r1, g1, b1, a1); } } if (blendAlpha == 255) { decorations->palAnimState = PAL_SWAP_HOLD_A; decorations->nextPalTime = decorations->palswapTimeHoldA; } break; } switch (decorations->palAnimState) { case PAL_SWAP_HOLD_A: case PAL_SWAP_A_TO_B: case PAL_SWAP_HOLD_B: case PAL_SWAP_B_TO_A: if (isNpcSprite == SPRITE_MODE_PLAYER) { func_unkB_draw_player(part, yaw, mtx); } else { func_unkB_draw_npc(part, yaw, mtx); } break; } } s32 update_part_glow(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { if (!(part->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { switch (part->decorationTable->glowState) { case GLOW_PAL_OFF: part_glow_off(isNpcSprite, part, yaw, isReflection); return 0; case GLOW_PAL_ON: part_glow_on(isNpcSprite, part, yaw, isReflection); break; } } return 0; } void part_glow_off(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { if (part->decorationTable->glowStateChanged) { part->decorationTable->glowStateChanged = FALSE; if (isNpcSprite == SPRITE_MODE_PLAYER) { set_player_imgfx_all(PLAYER_SPRITE_MAIN, IMGFX_CLEAR, 0, 0, 0, 0, 0); } else { set_npc_imgfx_all(part->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, 0); } } } void part_glow_on(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { DecorationTable* decorations = part->decorationTable; u8 rbuf[20]; u8 gbuf[20]; u8 bbuf[20]; s32 color; s32 alpha; s32 i; if (decorations->glowStateChanged) { decorations->glowUnk1 = -2; decorations->glowUnk3 = 0; decorations->glowStateChanged = FALSE; decorations->glowUnk2 = 0; if (isNpcSprite == SPRITE_MODE_PLAYER) { set_player_imgfx_all(PLAYER_SPRITE_MAIN, IMGFX_ALLOC_COLOR_BUF, 20, 0, 0, 255, 0); } else { set_npc_imgfx_all(part->spriteInstanceID, IMGFX_ALLOC_COLOR_BUF, 20, 0, 0, 255, 0); } } decorations->glowPhase += 7; if (decorations->glowPhase >= 360) { decorations->glowPhase %= 360; } for (i = 0; i < ARRAY_COUNT(rbuf); i++) { rbuf[i] = (cosine(decorations->glowPhase + (25 * i)) + 1.0) * 112.0; gbuf[i] = (cosine(decorations->glowPhase + (25 * i) + 45) + 1.0) * 112.0; bbuf[i] = (cosine(decorations->glowPhase + (25 * i) + 90) + 1.0) * 112.0; } alpha = 255; if (part->opacity < 255) { alpha = part->opacity; } if (part->flags & ACTOR_PART_FLAG_TRANSPARENT) { alpha = (alpha * 120) / 255; } for (i = 0; i < ARRAY_COUNT(rbuf); i++) { color = (rbuf[i] << 0x18) | (gbuf[i] << 0x10) | (bbuf[i] << 8) | alpha; if (isNpcSprite == SPRITE_MODE_PLAYER) { set_player_imgfx_all(PLAYER_SPRITE_MAIN, IMGFX_COLOR_BUF_SET_MODULATE, i, color, 0, 255, 0); } else { set_npc_imgfx_all(part->spriteInstanceID, IMGFX_COLOR_BUF_SET_MODULATE, i, color, 0, 255, 0); } } if (!isReflection) { decorations->glowUnk3 -= 1; } } s32 update_part_flash(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { if (!(part->flags & ACTOR_PART_FLAG_NO_DECORATIONS)) { switch (part->decorationTable->flashState) { case 0: part_flash_off(isNpcSprite, part, yaw, isReflection); return 0; case 1: part_flash_on(isNpcSprite, part, yaw, isReflection); return 0; } } return 0; } void part_flash_off(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { DecorationTable* decorations = part->decorationTable; if (decorations->flashStateChanged) { decorations->flashStateChanged = FALSE; } decorations->flashEnabled = FLASH_PAL_OFF; } void part_flash_on(b32 isNpcSprite, ActorPart* part, s32 yaw, b32 isReflection) { DecorationTable* decorations = part->decorationTable; if (decorations->flashStateChanged) { switch (get_flash_damage_intensity(part)) { case DAMAGE_INTENSITY_LIGHT: decorations->flashFramesLeft = 1; decorations->flashMode = FLASH_MODE_LIGHT; break; case DAMAGE_INTENSITY_MEDIUM: decorations->flashFramesLeft = 8; decorations->flashMode = FLASH_MODE_MEDIUM; break; case DAMAGE_INTENSITY_HEAVY: default: decorations->flashFramesLeft = 14; decorations->flashMode = FLASH_MODE_HEAVY; break; } decorations->flashEnabled = FLASH_PAL_OFF; decorations->flashStateChanged = FALSE; } if (decorations->flashMode == FLASH_MODE_DISPOSE) { decorations->flashEnabled = FLASH_PAL_OFF; clear_part_flash_mode(part); } switch (decorations->flashMode) { case FLASH_MODE_LIGHT: switch (decorations->flashFramesLeft) { case 0: decorations->flashEnabled = FLASH_PAL_ON; decorations->flashMode = FLASH_MODE_DISPOSE; break; default: decorations->flashEnabled = FLASH_PAL_OFF; if (!isReflection) { decorations->flashFramesLeft--; } break; } break; case FLASH_MODE_MEDIUM: switch (decorations->flashFramesLeft) { case 1: case 2: case 5: case 6: decorations->flashEnabled = FLASH_PAL_ON; break; case 3: case 4: case 7: case 8: decorations->flashEnabled = FLASH_PAL_OFF; break; case 0: decorations->flashMode = FLASH_MODE_DISPOSE; break; } if (!isReflection) { decorations->flashFramesLeft--; } break; case FLASH_MODE_HEAVY: switch (decorations->flashFramesLeft) { case 1: case 2: case 5: case 6: case 9: case 10: case 13: case 14: decorations->flashEnabled = FLASH_PAL_OFF; break; case 3: case 4: case 7: case 8: case 11: case 12: decorations->flashEnabled = FLASH_PAL_ON; break; case 0: decorations->flashMode = FLASH_MODE_DISPOSE; break; } if (!isReflection) { decorations->flashFramesLeft--; } break; } } void _add_part_decoration(ActorPart* actorPart) { DecorationTable* decorations; s32 i; if (actorPart->flags & ACTOR_PART_FLAG_NO_DECORATIONS) { return; } decorations = actorPart->decorationTable; for (i = 0; i < ARRAY_COUNT(decorations->type); i++) { switch (decorations->type[i]) { case ACTOR_DECORATION_NONE: add_part_decor_none(actorPart, i); break; case ACTOR_DECORATION_GOLDEN_FLAMES: add_part_decor_golden_flames(actorPart, i); break; case ACTOR_DECORATION_SWEAT: add_part_decor_sweat(actorPart, i); break; case ACTOR_DECORATION_SEEING_STARS: add_part_decor_seeing_stars(actorPart, i); break; case ACTOR_DECORATION_RED_FLAMES: add_part_decor_red_flames(actorPart, i); break; case ACTOR_DECORATION_GREY_SMOKE_TRAIL: add_part_decor_smoky_trail(actorPart, i); break; case ACTOR_DECORATION_FIRE_SMOKE_TRAIL: add_part_decor_fiery_trail(actorPart, i); break; case ACTOR_DECORATION_WHIRLWIND: add_part_decor_whirlwind(actorPart, i); break; case ACTOR_DECORATION_STEAM_EMITTER: add_part_decor_steam(actorPart, i); break; case ACTOR_DECORATION_SPARKLES: add_part_decor_sparkles(actorPart, i); break; case ACTOR_DECORATION_BOWSER_AURA: add_part_decor_bowser_aura(actorPart, i); break; case ACTOR_DECORATION_RADIAL_STAR_EMITTER: add_part_decor_radiating_stars(actorPart, i); break; } } } void _remove_part_decoration(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; switch (decorations->type[idx]) { case ACTOR_DECORATION_NONE: remove_part_decor_none(part, idx); break; case ACTOR_DECORATION_GOLDEN_FLAMES: remove_part_decor_golden_flames(part, idx); break; case ACTOR_DECORATION_SWEAT: remove_part_decor_sweat(part, idx); break; case ACTOR_DECORATION_SEEING_STARS: remove_part_decor_seeing_stars(part, idx); break; case ACTOR_DECORATION_RED_FLAMES: remove_part_decor_red_flames(part, idx); break; case ACTOR_DECORATION_GREY_SMOKE_TRAIL: remove_part_decor_smoky_trail(part, idx); break; case ACTOR_DECORATION_FIRE_SMOKE_TRAIL: remove_part_decor_fiery_trail(part, idx); break; case ACTOR_DECORATION_WHIRLWIND: remove_part_decor_whirlwind(part, idx); break; case ACTOR_DECORATION_STEAM_EMITTER: remove_part_decor_steam(part, idx); break; case ACTOR_DECORATION_SPARKLES: remove_part_decor_sparkles(part, idx); break; case ACTOR_DECORATION_BOWSER_AURA: remove_part_decor_bowser_aura(part, idx); break; case ACTOR_DECORATION_RADIAL_STAR_EMITTER: remove_part_decor_radiating_stars(part, idx); break; } decorations->type[idx] = ACTOR_DECORATION_NONE; } void add_part_decor_none(ActorPart* actorPart, s32 i) { } void remove_part_decor_none(ActorPart* part, s32 idx) { } void add_part_decor_golden_flames(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; AuraFXData* data; f32 scale; switch (decorations->state[idx]) { case 0: fx_aura(FX_AURA_GOLD, part->curPos.x, part->curPos.y, part->curPos.z, 0.4f, &decorations->effect[idx]); decorations->state[idx] = 1; decorations->decorData[idx].goldenFlames.scaleX = 40; decorations->decorData[idx].goldenFlames.scaleY = 40; decorations->decorData[idx].goldenFlames.offsetX = 0; break; case 1: effect = decorations->effect[idx]; data = effect->data.aura; data->posA.x = part->curPos.x + decorations->decorData[idx].goldenFlames.offsetX; data->posA.y = part->curPos.y; data->posA.z = part->curPos.z; scale = decorations->decorData[idx].goldenFlames.scaleX; scale /= 100.0f; effect->data.aura->scale.x = scale; scale = decorations->decorData[idx].goldenFlames.scaleY; scale /= 100.0f; effect->data.aura->scale.y = scale; break; } } void remove_part_decor_golden_flames(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->data.aura->fadeTime = 5; } void add_part_decor_sweat(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; switch (decorations->state[idx]) { case 0: if (part->yaw > 90.0f) { fx_sweat(0, part->curPos.x, part->curPos.y + part->size.y, part->curPos.z, 5.0f, 45.0f, 20); } else { fx_sweat(0, part->curPos.x, part->curPos.y + part->size.y, part->curPos.z, 5.0f, -45.0f, 20); } decorations->stateResetTimer[idx] = 10; decorations->state[idx] = TRUE; break; case 1: if (decorations->stateResetTimer[idx] != 0) { decorations->stateResetTimer[idx]--; } else { decorations->state[idx] = FALSE; } break; } } void remove_part_decor_sweat(ActorPart* part, s32 idx) { } void add_part_decor_seeing_stars(ActorPart* part, s32 idx) { DecorationTable* decorations; StarsOrbitingFXData* data; decorations = part->decorationTable; switch (decorations->state[idx]) { case 0: fx_stars_orbiting(0, part->curPos.x, part->curPos.y + part->size.y, part->curPos.z, 20.0f, 3, &decorations->effect[idx]); decorations->state[idx] = 1; break; case 1: data = decorations->effect[idx]->data.starsOrbiting; data->pos.x = part->curPos.x; data->pos.y = part->curPos.y + part->size.y; data->pos.z = part->curPos.z; break; } } void remove_part_decor_seeing_stars(ActorPart* part, s32 idx) { remove_effect(part->decorationTable->effect[idx]); } void add_part_decor_red_flames(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; AuraFXData* data; f32 scale; switch (decorations->state[idx]) { case 0: fx_aura(FX_AURA_RED, part->curPos.x, part->curPos.y, part->curPos.z, 0.4f, &decorations->effect[idx]); decorations->state[idx] = 1; decorations->decorData[idx].redFlames.scaleX = 40; decorations->decorData[idx].redFlames.scaleY = 40; decorations->decorData[idx].redFlames.alpha = 255; decorations->decorData[idx].redFlames.offsetZ = 0; decorations->decorData[idx].redFlames.unused1 = 255; decorations->decorData[idx].redFlames.unused2 = 0; decorations->decorData[idx].redFlames.unused3 = 0; // fallthrough case 1: effect = decorations->effect[idx]; data = effect->data.aura; data->posA.x = part->curPos.x; data->posA.y = part->curPos.y; data->posA.z = part->curPos.z + decorations->decorData[idx].redFlames.offsetZ; scale = decorations->decorData[idx].redFlames.scaleX; scale /= 100.0f; effect->data.aura->scale.x = scale; scale = decorations->decorData[idx].redFlames.scaleY; scale /= 100.0f; effect->data.aura->scale.y = scale; effect->data.aura->primA = decorations->decorData[idx].redFlames.alpha; break; } } void remove_part_decor_red_flames(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->data.aura->fadeTime = 5; } void add_part_decor_smoky_trail(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; switch (decorations->state[idx]) { case 0: decorations->effect[idx] = fx_effect_65(1, part->curPos.x, part->curPos.y, part->curPos.z, 1.0f, 0); decorations->state[idx] = 1; break; case 1: effect = decorations->effect[idx]; effect->data.unk_65->pos.x = part->curPos.x; effect->data.unk_65->pos.y = part->curPos.y; effect->data.unk_65->pos.z = part->curPos.z; break; } } void remove_part_decor_smoky_trail(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->flags |= FX_INSTANCE_FLAG_DISMISS; } void add_part_decor_fiery_trail(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; switch (decorations->state[idx]) { case 0: decorations->effect[idx] = fx_effect_65(2, part->curPos.x, part->curPos.y, part->curPos.z, 1.0f, 0); decorations->decorData[idx].fireTrail.scale = 1; decorations->state[idx] = 1; break; case 1: effect = decorations->effect[idx]; effect->data.unk_65->pos.x = part->curPos.x; effect->data.unk_65->pos.y = part->curPos.y; effect->data.unk_65->pos.z = part->curPos.z; effect->data.unk_65->scale = decorations->decorData[idx].fireTrail.scale / 100.0f; break; } } void remove_part_decor_fiery_trail(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->flags |= FX_INSTANCE_FLAG_DISMISS; } void add_part_decor_whirlwind(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; switch (decorations->state[idx]) { case 0: decorations->effect[idx] = fx_whirlwind(2, part->curPos.x, part->curPos.y, part->curPos.z, 1.0f, 0); decorations->state[idx] = 1; break; case 1: effect = decorations->effect[idx]; effect->data.whirlwind->pos.x = part->curPos.x; effect->data.whirlwind->pos.y = part->curPos.y; effect->data.whirlwind->pos.z = part->curPos.z; break; } } void remove_part_decor_whirlwind(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->flags |= FX_INSTANCE_FLAG_DISMISS; } void add_part_decor_steam(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; f32 angle, sinA, cosA; switch (decorations->state[idx]) { case 0: decorations->stateResetTimer[idx] = 0; decorations->state[idx] = 1; // fallthrough case 1: decorations->stateResetTimer[idx]++; if (decorations->stateResetTimer[idx] >= 4) { decorations->stateResetTimer[idx] = 0; angle = DEG_TO_RAD(clamp_angle(-part->yaw)); sinA = sin_rad(angle); cosA = cos_rad(angle); fx_walking_dust(0, part->curPos.x + (part->size.x * sinA * 0.2f), part->curPos.y + 1.5f, part->curPos.z + (part->size.x * cosA * 0.2f), sinA, cosA); } break; } } void remove_part_decor_steam(ActorPart* part, s32 idx) { } void add_part_decor_sparkles(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; f32 x, y, z; if (SparkleSpawnIntervals[decorations->decorData[idx].sparkles.spawnInterval] >= 0) { switch (decorations->state[idx]) { case 0: decorations->stateResetTimer[idx] = 0; decorations->state[idx] = 1; // fallthrough case 1: x = part->curPos.x; y = part->curPos.y + (part->size.y / 2); z = part->curPos.z - 5.0f; /// @bug this should be % 4 if ((gGameStatusPtr->frameCounter / 4) == 0) { fx_sparkles(FX_SPARKLES_1, x, y, z, 10.0f); } decorations->stateResetTimer[idx]++; if (SparkleSpawnIntervals[decorations->decorData[idx].sparkles.spawnInterval] < decorations->stateResetTimer[idx]) { decorations->stateResetTimer[idx] = 0; fx_sparkles(FX_SPARKLES_1, x, y, z, 20.0f); } break; } } } void remove_part_decor_sparkles(ActorPart* part, s32 idx) { } void add_part_decor_bowser_aura(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EffectInstance* effect; AuraFXData* data; f32 scale; switch (decorations->state[idx]) { case 0: fx_aura(FX_AURA_BLUE, part->curPos.x, part->curPos.y, part->curPos.z, 1.2f, &decorations->effect[idx]); decorations->state[idx] = 1; decorations->decorData[idx].bowserAura.scaleX = 150; decorations->decorData[idx].bowserAura.scaleY = 150; decorations->decorData[idx].bowserAura.alpha = 255; decorations->decorData[idx].bowserAura.offsetZ = 0; // fallthrough case 1: effect = decorations->effect[idx]; data = effect->data.aura; data->posA.x = part->curPos.x; data->posA.y = part->curPos.y; data->posA.z = part->curPos.z + decorations->decorData[idx].bowserAura.offsetZ; scale = decorations->decorData[idx].bowserAura.scaleX; scale /= 100.0f; effect->data.aura->scale.x = scale; scale = decorations->decorData[idx].bowserAura.scaleY; scale /= 100.0f; effect->data.aura->scale.y = scale * (0.8 - 1e-16); // small epsilon effect->data.aura->primA = decorations->decorData[idx].bowserAura.alpha; effect->data.aura->renderYaw = part->yaw; break; } } void remove_part_decor_bowser_aura(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->data.aura->fadeTime = 5; } void add_part_decor_radiating_stars(ActorPart* part, s32 idx) { DecorationTable* decorations = part->decorationTable; EnergyInOutFXData* data; f32 scale; switch (decorations->state[idx]) { case 0: decorations->effect[idx] = fx_energy_in_out(4, part->curPos.x, part->curPos.y, part->curPos.z, 1.2f, 0); decorations->state[idx] = 1; decorations->decorData[idx].stars.scalePct = 120; decorations->decorData[idx].stars.offsetY = 0; // fallthrough case 1: data = decorations->effect[idx]->data.energyInOut; scale = decorations->decorData[idx].stars.scalePct; scale /= 100.0f; data->unk_44 = scale; data->pos.x = part->curPos.x; data->pos.y = (part->curPos.y + (scale * 41.0f)); data->pos.z = (part->curPos.z + decorations->decorData[idx].stars.offsetY); break; } } void remove_part_decor_radiating_stars(ActorPart* part, s32 idx) { part->decorationTable->effect[idx]->flags |= FX_INSTANCE_FLAG_DISMISS; }