2024-02-19 23:02:10 +01:00
# include "patches.h"
# include "transform_ids.h"
2024-03-11 05:13:32 +01:00
# include "overlays/actors/ovl_Object_Kankyo/z_object_kankyo.h"
2024-04-01 05:12:22 +02:00
# include "overlays/actors/ovl_Eff_Stk/z_eff_stk.h"
2024-04-24 20:56:23 +02:00
# include "overlays/actors/ovl_En_Clear_Tag/z_en_clear_tag.h"
2024-03-14 00:26:29 +01:00
# include "z64effect.h"
2024-02-19 23:02:10 +01:00
2024-03-11 05:13:32 +01:00
extern f32 D_808DE5B0 ;
extern Gfx gEffDust5Tex [ ] ;
extern Gfx gEffDustDL [ ] ;
// Use an unused byte in the particle's struct to track whether its interpolation should be skipped this frame.
# define particle_skipped(particle) \
( ( & ( particle ) . unk_1C ) [ 1 ] )
// @recomp Patched to record when a particle is moved to skip interpolation.
void func_808DC454 ( ObjectKankyo * this , PlayState * play ) {
s16 i ;
s32 pad1 ;
f32 phi_f20 ;
f32 spD0 ;
f32 spCC ;
f32 spC8 ;
f32 spC4 ;
f32 spC0 ;
f32 spBC ;
f32 temp_f0_4 ;
f32 temp_f22 ;
f32 temp_f24 ;
f32 temp_f28 ;
f32 x = play - > view . at . x - play - > view . eye . x ;
f32 y = play - > view . at . y - play - > view . eye . y ;
f32 z = play - > view . at . z - play - > view . eye . z ;
f32 magnitude = sqrtf ( SQ ( x ) + SQ ( y ) + SQ ( z ) ) ;
f32 temp_120 = 120.0f ;
f32 temp_f30 ;
Vec3f sp88 ;
s32 pad ;
spD0 = x / magnitude ;
spCC = y / magnitude ;
spC8 = z / magnitude ;
for ( i = 0 ; i < play - > envCtx . precipitation [ PRECIP_SNOW_CUR ] ; i + + ) {
switch ( this - > unk_14C [ i ] . unk_1C ) {
case 0 :
this - > unk_14C [ i ] . unk_00 = play - > view . eye . x + ( spD0 * 120.0f ) ;
this - > unk_14C [ i ] . unk_04 = play - > view . eye . y + ( spCC * 120.0f ) ;
this - > unk_14C [ i ] . unk_08 = play - > view . eye . z + ( spC8 * 120.0f ) ;
this - > unk_14C [ i ] . unk_0C = ( Rand_ZeroOne ( ) - 0.5f ) * ( 2.0f * temp_120 ) ;
temp_f22 = ( Camera_GetCamDirPitch ( GET_ACTIVE_CAM ( play ) ) * 0.004f ) + 60.0f ;
if ( temp_f22 < 20.0f ) {
temp_f22 = 20.0f ;
}
if ( this - > unk_114E = = 0 ) {
this - > unk_14C [ i ] . unk_10 = temp_f22 ;
} else {
this - > unk_14C [ i ] . unk_10 + = temp_f22 ;
if ( play - > envCtx . precipitation [ PRECIP_SNOW_CUR ] = = ( ( u32 ) i + 1 ) ) {
this - > unk_114E = 0 ;
}
}
this - > unk_14C [ i ] . unk_14 = ( Rand_ZeroOne ( ) - 0.5f ) * ( 2.0f * temp_120 ) ;
if ( play - > envCtx . precipitation [ PRECIP_SOS_MAX ] = = 0 ) {
this - > unk_14C [ i ] . unk_18 = ( Rand_ZeroOne ( ) * 3.0f ) + 1.0f ;
} else {
this - > unk_14C [ i ] . unk_18 = ( Rand_ZeroOne ( ) * 3.0f ) + 8.0f ;
}
particle_skipped ( this - > unk_14C [ i ] ) = true ;
this - > unk_14C [ i ] . unk_1C + + ;
break ;
case 1 :
temp_f24 = play - > view . eye . x + ( spD0 * 120.0f ) ;
temp_f28 = play - > view . eye . y + ( spCC * 120.0f ) ;
temp_f30 = play - > view . eye . z + ( spC8 * 120.0f ) ;
magnitude = sqrtf ( ( f32 ) SQ ( play - > envCtx . windDirection . x ) + SQ ( play - > envCtx . windDirection . y ) +
SQ ( play - > envCtx . windDirection . z ) ) ;
if ( magnitude = = 0.0f ) {
magnitude = 0.001f ;
}
spC4 = - play - > envCtx . windDirection . x / magnitude ;
spC0 = - play - > envCtx . windDirection . y / magnitude ;
spBC = - play - > envCtx . windDirection . z / magnitude ;
if ( i = = 0 ) {
this - > unk_144 + = 0.049999997f * Rand_ZeroOne ( ) ;
this - > unk_148 + = 0.049999997f * Rand_ZeroOne ( ) ;
}
phi_f20 = play - > envCtx . windSpeed / 120.0f ;
phi_f20 = CLAMP ( phi_f20 , 0.0f , 1.0f ) ;
this - > unk_14C [ i ] . unk_0C + = sinf ( ( this - > unk_144 + ( i * 100.0f ) ) * 0.01f ) + ( spC4 * 10.0f * phi_f20 ) ;
this - > unk_14C [ i ] . unk_14 + = cosf ( ( this - > unk_148 + ( i * 100.0f ) ) * 0.01f ) + ( spBC * 10.0f * phi_f20 ) ;
this - > unk_14C [ i ] . unk_10 - = this - > unk_14C [ i ] . unk_18 - ( spC0 * 3.0f * ( play - > envCtx . windSpeed / 100.0f ) ) ;
temp_f22 = ( - Camera_GetCamDirPitch ( GET_ACTIVE_CAM ( play ) ) * 0.012f ) + 40.0f ;
if ( temp_f22 < - 40.0f ) {
temp_f22 = - 40.0f ;
}
if ( ( ( this - > unk_14C [ i ] . unk_00 + this - > unk_14C [ i ] . unk_0C ) - temp_f24 ) > temp_120 ) {
this - > unk_14C [ i ] . unk_00 = temp_f24 - temp_120 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
if ( ( ( this - > unk_14C [ i ] . unk_00 + this - > unk_14C [ i ] . unk_0C ) - temp_f24 ) < - temp_120 ) {
this - > unk_14C [ i ] . unk_00 = temp_f24 + temp_120 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
sp88 . x = this - > unk_14C [ i ] . unk_00 + this - > unk_14C [ i ] . unk_0C ;
sp88 . y = this - > unk_14C [ i ] . unk_04 + this - > unk_14C [ i ] . unk_10 ;
sp88 . z = this - > unk_14C [ i ] . unk_08 + this - > unk_14C [ i ] . unk_14 ;
phi_f20 = Math_Vec3f_DistXZ ( & sp88 , & play - > view . eye ) / 200.0f ;
phi_f20 = CLAMP ( phi_f20 , 0.0f , 1.0f ) ;
temp_f0_4 = 100.0f + phi_f20 + 60.0f ;
if ( temp_f0_4 < ( this - > unk_14C [ i ] . unk_04 + ( this - > unk_14C [ i ] . unk_10 ) - temp_f28 ) ) {
this - > unk_14C [ i ] . unk_04 = temp_f28 - temp_f0_4 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
if ( ( ( this - > unk_14C [ i ] . unk_04 + this - > unk_14C [ i ] . unk_10 ) - temp_f28 ) < - temp_f0_4 ) {
this - > unk_14C [ i ] . unk_04 = temp_f28 + temp_f0_4 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
if ( ( ( this - > unk_14C [ i ] . unk_08 + this - > unk_14C [ i ] . unk_14 ) - temp_f30 ) > temp_120 ) {
this - > unk_14C [ i ] . unk_08 = temp_f30 - temp_120 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
if ( ( ( this - > unk_14C [ i ] . unk_08 + this - > unk_14C [ i ] . unk_14 ) - temp_f30 ) < - temp_120 ) {
this - > unk_14C [ i ] . unk_08 = temp_f30 + temp_120 ;
// @recomp Skip interpolation.
particle_skipped ( this - > unk_14C [ i ] ) = true ;
}
if ( ( this - > unk_14C [ i ] . unk_04 + this - > unk_14C [ i ] . unk_10 ) < ( ( play - > view . eye . y - temp_f22 ) - 40.0f ) ) {
this - > unk_14C [ i ] . unk_1C = 0 ;
}
break ;
}
}
}
void func_808DD3C8 ( Actor * thisx , PlayState * play2 ) {
PlayState * play = play2 ;
ObjectKankyo * this = ( ObjectKankyo * ) thisx ;
Vec3f worldPos ;
Vec3f screenPos ;
s16 i ;
u8 pad2 ;
u8 spB4 ;
f32 temp_f0 ;
u8 sp68 ;
s32 pad ;
f32 temp_f2 ;
f32 tempf ;
if ( ( play - > cameraPtrs [ CAM_ID_MAIN ] - > stateFlags & CAM_STATE_UNDERWATER ) | | ( ( u8 ) play - > envCtx . stormState = = 0 ) ) {
return ;
}
OPEN_DISPS ( play - > state . gfxCtx ) ;
spB4 = false ;
if ( this - > actor . params = = 3 ) {
// @recomp Manual relocation, TODO remove when the recompiler handles this automatically.
f32 * D_808DE5B0_ptr = actor_relocate ( thisx , & D_808DE5B0 ) ;
temp_f0 = func_80173B48 ( & play - > state ) / 1.4e7 f ;
temp_f0 = CLAMP ( temp_f0 , 0.0f , 1.0f ) ;
Math_SmoothStepToF ( D_808DE5B0_ptr , temp_f0 , 0.2f , 0.1f , 0.001f ) ;
sp68 = play - > envCtx . precipitation [ PRECIP_SNOW_CUR ] ;
sp68 * = * D_808DE5B0_ptr ;
if ( ( play - > envCtx . precipitation [ PRECIP_SNOW_CUR ] > = 32 ) & & ( sp68 < 32 ) ) {
sp68 = 32 ;
}
} else {
sp68 = play - > envCtx . precipitation [ PRECIP_SNOW_CUR ] ;
}
for ( i = 0 ; i < sp68 ; i + + ) {
worldPos . x = this - > unk_14C [ i ] . unk_00 + this - > unk_14C [ i ] . unk_0C ;
worldPos . y = this - > unk_14C [ i ] . unk_04 + this - > unk_14C [ i ] . unk_10 ;
worldPos . z = this - > unk_14C [ i ] . unk_08 + this - > unk_14C [ i ] . unk_14 ;
Play_GetScreenPos ( play , & worldPos , & screenPos ) ;
// @recomp Render particles beyond the screen bounds.
if ( true ) {
// if ((screenPos.x >= 0.0f) && (screenPos.x < SCREEN_WIDTH) && (screenPos.y >= 0.0f) &&
// (screenPos.y < SCREEN_HEIGHT)) {
if ( ! spB4 ) {
spB4 = true ;
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , 255 , 255 , 255 , 255 ) ;
gSPClearGeometryMode ( POLY_XLU_DISP + + , G_LIGHTING ) ;
POLY_XLU_DISP = Gfx_SetupDL ( POLY_XLU_DISP , SETUPDL_0 ) ;
gDPSetRenderMode ( POLY_XLU_DISP + + , G_RM_FOG_SHADE_A , G_RM_ZB_CLD_SURF2 ) ;
gSPSetGeometryMode ( POLY_XLU_DISP + + , G_FOG ) ;
gSPSegment ( POLY_XLU_DISP + + , 0x08 , Lib_SegmentedToVirtual ( gEffDust5Tex ) ) ;
}
Matrix_Translate ( worldPos . x , worldPos . y , worldPos . z , MTXMODE_NEW ) ;
tempf = ( i & 7 ) * 0.008f ;
Matrix_Scale ( 0.05f + tempf , 0.05f + tempf , 0.05f + tempf , MTXMODE_APPLY ) ;
temp_f2 = Math_Vec3f_DistXYZ ( & worldPos , & play - > view . eye ) / 300.0f ;
temp_f2 = ( ( 1.0f < temp_f2 ) ? 0.0f : ( ( ( 1.0f - temp_f2 ) > 1.0f ) ? 1.0f : 1.0f - temp_f2 ) ) ;
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 255 , 255 , 255 , ( u8 ) ( 160.0f * temp_f2 ) ) ;
Matrix_Mult ( & play - > billboardMtxF , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( play - > state . gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Check if the particle's interpolation should be skipped this frame.
if ( particle_skipped ( this - > unk_14C [ i ] ) ) {
// @recomp Tag the particle's transform to skip interpolation.
2024-04-01 05:12:22 +02:00
gEXMatrixGroupDecomposedSkipPosRot ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
2024-03-11 05:13:32 +01:00
}
else {
// @recomp Tag the particle's matrix to interpolate normally.
2024-03-29 01:36:16 +01:00
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_ALLOW ) ;
2024-03-11 05:13:32 +01:00
}
gSPDisplayList ( POLY_XLU_DISP + + , gEffDustDL ) ;
// @recomp Pop the particle transform tag.
2024-03-29 01:36:16 +01:00
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
2024-03-11 05:13:32 +01:00
}
// @recomp Reset the particle's skip flag.
particle_skipped ( this - > unk_14C [ i ] ) = false ;
}
CLOSE_DISPS ( play - > state . gfxCtx ) ;
}
2024-03-14 00:26:29 +01:00
# define SPARK_COUNT 3
# define BLURE_COUNT 25
# define SHIELD_PARTICLE_COUNT 3
# define TIRE_MARK_COUNT 15
# define TOTAL_EFFECT_COUNT SPARK_COUNT + BLURE_COUNT + SHIELD_PARTICLE_COUNT + TIRE_MARK_COUNT
typedef struct EffectStatus {
/* 0x0 */ u8 active ;
/* 0x1 */ u8 unk1 ;
/* 0x2 */ u8 unk2 ;
} EffectStatus ; // size = 0x3
typedef struct EffectContext {
/* 0x0000 */ struct PlayState * play ;
struct {
EffectStatus status ;
EffectSpark effect ;
} /* 0x0004 */ sparks [ SPARK_COUNT ] ;
struct {
EffectStatus status ;
EffectBlure effect ;
} /* 0x0E5C */ blures [ BLURE_COUNT ] ;
struct {
EffectStatus status ;
EffectShieldParticle effect ;
} /* 0x388C */ shieldParticles [ SHIELD_PARTICLE_COUNT ] ;
struct {
EffectStatus status ;
EffectTireMark effect ;
} /* 0x3DF0 */ tireMarks [ TIRE_MARK_COUNT ] ;
} EffectContext ; // size = 0x98E0
typedef struct EffectInfo {
/* 0x00 */ u32 size ;
/* 0x04 */ void ( * init ) ( void * effect , void * initParams ) ;
/* 0x08 */ void ( * destroy ) ( void * effect ) ;
/* 0x0C */ s32 ( * update ) ( void * effect ) ;
/* 0x10 */ void ( * draw ) ( void * effect , struct GraphicsContext * gfxCtx ) ;
} EffectInfo ; // size = 0x14
extern EffectContext sEffectContext ;
extern EffectInfo sEffectInfoTable [ ] ;
static inline void tag_interpolate_effect ( GraphicsContext * gfxCtx , u32 id ) {
OPEN_DISPS ( gfxCtx ) ;
2024-03-29 01:36:16 +01:00
gEXMatrixGroupDecomposedNormal ( POLY_OPA_DISP + + , id , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_ALLOW ) ;
2024-03-14 00:26:29 +01:00
2024-03-29 01:36:16 +01:00
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , id + EFFECT_TRANSFORM_ID_COUNT , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_ALLOW ) ;
2024-03-14 00:26:29 +01:00
CLOSE_DISPS ( ) ;
}
static inline void tag_skip_effect ( GraphicsContext * gfxCtx , u32 id ) {
OPEN_DISPS ( gfxCtx ) ;
gEXMatrixGroupSimple ( POLY_OPA_DISP + + , id , G_EX_PUSH , G_MTX_MODELVIEW ,
G_EX_COMPONENT_SKIP , G_EX_COMPONENT_SKIP , G_EX_COMPONENT_SKIP ,
2024-03-29 01:36:16 +01:00
G_EX_COMPONENT_SKIP , G_EX_COMPONENT_INTERPOLATE , G_EX_ORDER_LINEAR , G_EX_EDIT_NONE ) ;
2024-03-14 00:26:29 +01:00
gEXMatrixGroupSimple ( POLY_XLU_DISP + + , id + EFFECT_TRANSFORM_ID_COUNT , G_EX_PUSH , G_MTX_MODELVIEW ,
G_EX_COMPONENT_SKIP , G_EX_COMPONENT_SKIP , G_EX_COMPONENT_SKIP ,
2024-03-29 01:36:16 +01:00
G_EX_COMPONENT_SKIP , G_EX_COMPONENT_INTERPOLATE , G_EX_ORDER_LINEAR , G_EX_EDIT_NONE ) ;
2024-03-14 00:26:29 +01:00
CLOSE_DISPS ( ) ;
}
static inline void pop_effect_tag ( GraphicsContext * gfxCtx ) {
OPEN_DISPS ( gfxCtx ) ;
2024-03-29 01:36:16 +01:00
gEXPopMatrixGroup ( POLY_OPA_DISP + + , G_MTX_MODELVIEW ) ;
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
2024-03-14 00:26:29 +01:00
CLOSE_DISPS ( ) ;
}
// @recomp Patched to tag effects.
void Effect_DrawAll ( GraphicsContext * gfxCtx ) {
s32 i ;
for ( i = 0 ; i < SPARK_COUNT ; i + + ) {
if ( ! sEffectContext . sparks [ i ] . status . active ) {
continue ;
}
// @recomp Tag transform.
tag_interpolate_effect ( gfxCtx , EFFECT_SPARK_TRANSFORM_ID_START + i ) ;
sEffectInfoTable [ EFFECT_SPARK ] . draw ( & sEffectContext . sparks [ i ] . effect , gfxCtx ) ;
// @recomp Pop tag.
pop_effect_tag ( gfxCtx ) ;
}
for ( i = 0 ; i < BLURE_COUNT ; i + + ) {
if ( ! sEffectContext . blures [ i ] . status . active ) {
continue ;
}
// @recomp Tag transform to skip interpolation as this effect doesn't work well with it.
tag_skip_effect ( gfxCtx , EFFECT_BLURE_TRANSFORM_ID_START + i ) ;
sEffectInfoTable [ EFFECT_BLURE1 ] . draw ( & sEffectContext . blures [ i ] . effect , gfxCtx ) ;
// @recomp Pop tag.
pop_effect_tag ( gfxCtx ) ;
}
for ( i = 0 ; i < SHIELD_PARTICLE_COUNT ; i + + ) {
if ( ! sEffectContext . shieldParticles [ i ] . status . active ) {
continue ;
}
// @recomp Tag transform.
tag_interpolate_effect ( gfxCtx , EFFECT_SHIELD_PARTICLE_TRANSFORM_ID_START + i ) ;
sEffectInfoTable [ EFFECT_SHIELD_PARTICLE ] . draw ( & sEffectContext . shieldParticles [ i ] . effect , gfxCtx ) ;
// @recomp Pop tag.
pop_effect_tag ( gfxCtx ) ;
}
for ( i = 0 ; i < TIRE_MARK_COUNT ; i + + ) {
if ( ! sEffectContext . tireMarks [ i ] . status . active ) {
continue ;
}
// @recomp Tag transform to skip interpolation as this effect doesn't work well with it.
tag_skip_effect ( gfxCtx , EFFECT_TIRE_MARK_TRANSFORM_ID_START + i ) ;
sEffectInfoTable [ EFFECT_TIRE_MARK ] . draw ( & sEffectContext . tireMarks [ i ] . effect , gfxCtx ) ;
// @recomp Pop tag.
pop_effect_tag ( gfxCtx ) ;
}
}
2024-04-01 05:12:22 +02:00
extern Gfx object_stk2_DL_008920 [ ] ;
extern Gfx object_stk2_DL_008A38 [ ] ;
extern AnimatedMaterial object_stk2_Matanimheader_009F60 [ ] ;
void EffStk_Draw ( Actor * thisx , PlayState * play ) {
EffStk * this = ( EffStk * ) thisx ;
s32 pad ;
Camera * activeCam = GET_ACTIVE_CAM ( play ) ;
Vec3f eye = activeCam - > eye ;
Vec3f quakeOffset ;
quakeOffset = Camera_GetQuakeOffset ( activeCam ) ;
OPEN_DISPS ( play - > state . gfxCtx ) ;
Gfx_SetupDL25_Xlu ( play - > state . gfxCtx ) ;
Matrix_Translate ( eye . x + quakeOffset . x , eye . y + quakeOffset . y , eye . z + quakeOffset . z , MTXMODE_NEW ) ;
Matrix_Scale ( 0.2f , 0.2f , 0.2f , MTXMODE_APPLY ) ;
Matrix_ReplaceRotation ( & play - > billboardMtxF ) ;
Matrix_Translate ( 0.0f , 0.0f , this - > unk148 , MTXMODE_APPLY ) ;
Mtx * mtx = Matrix_NewMtx ( play - > state . gfxCtx ) ;
// @recomp Tag the transform. Do not allow edits as this will get edited by the billboard detection and we'll want to skip position during a camera cut too.
if ( camera_was_skipped ( ) ) {
gEXMatrixGroupDecomposedSkipPosRot ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
}
else {
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
}
gSPMatrix ( POLY_XLU_DISP + + , mtx , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
AnimatedMat_DrawAlphaStep ( play , Lib_SegmentedToVirtual ( object_stk2_Matanimheader_009F60 ) , 1.0f , this - > unk144 ) ;
gDPSetColorDither ( POLY_XLU_DISP + + , G_CD_NOISE ) ;
gDPSetAlphaDither ( POLY_XLU_DISP + + , G_AD_NOISE ) ;
gSPDisplayList ( POLY_XLU_DISP + + , object_stk2_DL_008920 ) ;
gSPDisplayList ( POLY_XLU_DISP + + , object_stk2_DL_008A38 ) ;
2024-04-01 09:19:16 +02:00
// @recomp Pop the transform tag.
2024-04-01 05:12:22 +02:00
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
CLOSE_DISPS ( play - > state . gfxCtx ) ;
}
2024-04-24 20:56:23 +02:00
typedef enum {
/* 0x00 */ CLEAR_TAG_EFFECT_AVAILABLE ,
/* 0x01 */ CLEAR_TAG_EFFECT_DEBRIS ,
/* 0x02 */ CLEAR_TAG_EFFECT_FIRE , // never set to, remnant of OoT
/* 0x03 */ CLEAR_TAG_EFFECT_SMOKE ,
/* 0x04 */ CLEAR_TAG_EFFECT_FLASH ,
/* 0x05 */ CLEAR_TAG_EFFECT_LIGHT_RAYS ,
/* 0x06 */ CLEAR_TAG_EFFECT_SHOCKWAVE ,
/* 0x07 */ CLEAR_TAG_EFFECT_SPLASH ,
/* 0x08 */ CLEAR_TAG_EFFECT_ISOLATED_SMOKE
} ClearTagEffectType ;
extern Gfx gClearTagDebrisEffectMaterialDL [ ] ;
extern Gfx gClearTagDebrisEffectDL [ ] ;
extern Gfx gEffShockwaveDL [ ] ;
extern Gfx gClearTagFlashEffectGroundDL [ ] ;
extern Gfx gClearTagFireEffectMaterialDL [ ] ;
extern Gfx gClearTagFireEffectDL [ ] ;
extern Gfx gClearTagFireEffectMaterialDL [ ] ;
extern Gfx gClearTagFireEffectDL [ ] ;
extern Gfx gClearTagFlashEffectDL [ ] ;
extern Gfx gClearTagLightRayEffectMaterialDL [ ] ;
extern Gfx gClearTagLightRayEffectDL [ ] ;
extern Gfx gEffWaterSplashDL [ ] ;
extern u64 gEffWaterSplash1Tex [ ] ;
extern u64 gEffWaterSplash2Tex [ ] ;
extern u64 gEffWaterSplash3Tex [ ] ;
extern u64 gEffWaterSplash4Tex [ ] ;
extern u64 gEffWaterSplash5Tex [ ] ;
extern u64 gEffWaterSplash6Tex [ ] ;
extern u64 gEffWaterSplash7Tex [ ] ;
extern u64 gEffWaterSplash8Tex [ ] ;
static TexturePtr sWaterSplashTextures [ ] = {
gEffWaterSplash1Tex ,
gEffWaterSplash2Tex ,
gEffWaterSplash3Tex ,
gEffWaterSplash4Tex ,
gEffWaterSplash5Tex ,
gEffWaterSplash6Tex ,
gEffWaterSplash7Tex ,
gEffWaterSplash8Tex ,
NULL ,
NULL ,
NULL ,
} ;
/**
* Draws all effects .
* Each effect type is drawn before the next . The function will apply a material that
* applies to all effects of that type while drawing the first effect of that type .
*/
// @recomp Patched to tag matrices.
void EnClearTag_DrawEffects ( Actor * thisx , PlayState * play ) {
u8 isMaterialApplied = false ;
s16 i ;
s16 j ;
Vec3f vec ;
WaterBox * waterBox ;
f32 ySurface ;
MtxF mtxF ;
GraphicsContext * gfxCtx = play - > state . gfxCtx ;
EnClearTag * this = ( EnClearTag * ) thisx ;
EnClearTagEffect * effect = this - > effect ;
EnClearTagEffect * firstEffect = this - > effect ;
OPEN_DISPS ( gfxCtx ) ;
Gfx_SetupDL25_Opa ( play - > state . gfxCtx ) ;
Gfx_SetupDL25_Xlu ( play - > state . gfxCtx ) ;
// Draw all Debris effects.
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_DEBRIS ) {
// Apply the debris effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
isMaterialApplied + + ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_OPA_DISP + + , actor_relocate ( thisx , gClearTagDebrisEffectMaterialDL ) ) ;
}
// Draw the debris effect.
Matrix_Translate ( effect - > pos . x , effect - > pos . y , effect - > pos . z , MTXMODE_NEW ) ;
Matrix_Scale ( effect - > scale , effect - > scale , effect - > scale , MTXMODE_APPLY ) ;
Matrix_RotateYF ( effect - > rotationY , MTXMODE_APPLY ) ;
Matrix_RotateXFApply ( effect - > rotationX ) ;
gSPMatrix ( POLY_OPA_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_OPA_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_OPA_DISP + + , actor_relocate ( thisx , gClearTagDebrisEffectDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_OPA_DISP + + , G_MTX_MODELVIEW ) ;
}
}
// Draw all Shockwave effects.
effect = firstEffect ;
if ( this - > actor . floorPoly ! = NULL ) {
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_SHOCKWAVE ) {
// Draw the shockwave effect.
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , 255 , 255 , 255 , ( s8 ) effect - > primColor . a ) ;
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 255 , 255 , 255 , ( s8 ) effect - > primColor . a ) ;
func_800C0094 ( this - > actor . floorPoly , effect - > pos . x , effect - > pos . y , effect - > pos . z , & mtxF ) ;
Matrix_Put ( & mtxF ) ;
Matrix_Scale ( effect - > scale , 1.0f , effect - > scale , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
gSPDisplayList ( POLY_XLU_DISP + + , gEffShockwaveDL ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
}
// Draw all ground flash effects.
effect = firstEffect ;
isMaterialApplied = false ;
if ( this - > actor . floorPoly ! = NULL ) {
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_FLASH ) {
// Apply the flash ground effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , 255 , 255 , 200 , 0 ) ;
isMaterialApplied + + ;
}
// Draw the ground flash effect.
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 255 , 255 , 200 , ( s8 ) ( effect - > primColor . a * 0.7f ) ) ;
func_800C0094 ( this - > actor . floorPoly , effect - > pos . x , this - > actor . floorHeight , effect - > pos . z , & mtxF ) ;
Matrix_Put ( & mtxF ) ;
Matrix_Scale ( effect - > scale * 3.0f , 1.0f , effect - > scale * 3.0f , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFlashEffectGroundDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
}
// Draw all smoke effects.
effect = firstEffect ;
isMaterialApplied = false ;
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( ( effect - > type = = CLEAR_TAG_EFFECT_SMOKE ) | | ( effect - > type = = CLEAR_TAG_EFFECT_ISOLATED_SMOKE ) ) {
// Apply the smoke effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFireEffectMaterialDL ) ) ;
isMaterialApplied + + ;
}
// Draw the smoke effect.
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , ( s8 ) effect - > envColor . r , ( s8 ) effect - > envColor . g , ( s8 ) effect - > envColor . b ,
128 ) ;
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , ( s8 ) effect - > primColor . r , ( s8 ) effect - > primColor . g ,
( s8 ) effect - > primColor . b , ( s8 ) effect - > primColor . a ) ;
gSPSegment ( POLY_XLU_DISP + + , 0x08 ,
Gfx_TwoTexScroll ( play - > state . gfxCtx , 0 , 0 , - effect - > actionTimer * 5 , 32 , 64 , 1 , 0 , 0 , 32 , 32 ) ) ;
Matrix_Translate ( effect - > pos . x , effect - > pos . y , effect - > pos . z , MTXMODE_NEW ) ;
Matrix_ReplaceRotation ( & play - > billboardMtxF ) ;
Matrix_Scale ( effect - > smokeScaleX * effect - > scale , effect - > smokeScaleY * effect - > scale , 1.0f , MTXMODE_APPLY ) ;
Matrix_Translate ( 0.0f , 20.0f , 0.0f , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFireEffectDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
// Draw all fire effects.
effect = firstEffect ;
isMaterialApplied = false ;
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_FIRE ) {
// Apply the fire effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFireEffectMaterialDL ) ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , 255 , 215 , 255 , 128 ) ;
isMaterialApplied + + ;
}
// Draw the fire effect.
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 200 , 20 , 0 , ( s8 ) effect - > primColor . a ) ;
gSPSegment ( POLY_XLU_DISP + + , 0x08 ,
Gfx_TwoTexScroll ( play - > state . gfxCtx , 0 , 0 , - effect - > actionTimer * 15 , 32 , 64 , 1 , 0 , 0 , 32 , 32 ) ) ;
Matrix_Translate ( effect - > pos . x , effect - > pos . y , effect - > pos . z , MTXMODE_NEW ) ;
Matrix_ReplaceRotation ( & play - > billboardMtxF ) ;
Matrix_Scale ( effect - > scale , effect - > scale , 1.0f , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFireEffectDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
// Draw all flash billboard effects.
effect = firstEffect ;
isMaterialApplied = false ;
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_FLASH ) {
// Apply the flash billboard effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , this - > flashEnvColor . r , this - > flashEnvColor . g , this - > flashEnvColor . b , 0 ) ;
isMaterialApplied + + ;
}
// Draw the flash billboard effect.
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 255 , 255 , 200 , ( s8 ) effect - > primColor . a ) ;
Matrix_Translate ( effect - > pos . x , effect - > pos . y , effect - > pos . z , MTXMODE_NEW ) ;
Matrix_ReplaceRotation ( & play - > billboardMtxF ) ;
Matrix_Scale ( 2.0f * effect - > scale , 2.0f * effect - > scale , 1.0f , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagFlashEffectDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
// Draw all light ray effects.
effect = firstEffect ;
isMaterialApplied = false ;
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_LIGHT_RAYS ) {
// Apply the light ray effect material if it has not already been applied.
if ( ! isMaterialApplied ) {
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , ( u8 ) effect - > envColor . r , ( u8 ) effect - > envColor . g , ( u8 ) effect - > envColor . b ,
0 ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagLightRayEffectMaterialDL ) ) ;
isMaterialApplied + + ;
}
// Draw the light ray effect.
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , ( u8 ) effect - > primColor . r , ( u8 ) effect - > primColor . g ,
( u8 ) effect - > primColor . b , ( u8 ) effect - > primColor . a ) ;
Matrix_Translate ( effect - > pos . x , effect - > pos . y , effect - > pos . z , MTXMODE_NEW ) ;
Matrix_RotateYF ( effect - > rotationY , MTXMODE_APPLY ) ;
Matrix_RotateXFApply ( effect - > rotationX ) ;
Matrix_RotateZF ( effect - > rotationZ , MTXMODE_APPLY ) ;
Matrix_Scale ( effect - > scale * 0.5f , effect - > scale * 0.5f , effect - > maxScale * effect - > scale , MTXMODE_APPLY ) ;
Matrix_RotateXFApply ( M_PI / 2 ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp Tag the matrix.
gEXMatrixGroupDecomposedNormal ( POLY_XLU_DISP + + , actor_transform_id ( thisx ) + i , G_EX_PUSH , G_MTX_MODELVIEW , G_EX_EDIT_NONE ) ;
// @recomp Manual relocation, TODO remove when automated.
gSPDisplayList ( POLY_XLU_DISP + + , actor_relocate ( thisx , gClearTagLightRayEffectDL ) ) ;
// @recomp Pop the matrix tag.
gEXPopMatrixGroup ( POLY_XLU_DISP + + , G_MTX_MODELVIEW ) ;
}
}
// Draw all splash effects.
effect = firstEffect ;
for ( i = 0 ; i < ARRAY_COUNT ( this - > effect ) ; i + + , effect + + ) {
if ( effect - > type = = CLEAR_TAG_EFFECT_SPLASH ) {
gDPPipeSync ( POLY_XLU_DISP + + ) ;
gDPSetEnvColor ( POLY_XLU_DISP + + , 255 , 255 , 255 , 200 ) ;
gDPSetPrimColor ( POLY_XLU_DISP + + , 0 , 0 , 255 , 255 , 255 , 200 ) ;
gSPSegment ( POLY_XLU_DISP + + , 0x08 , Lib_SegmentedToVirtual ( sWaterSplashTextures [ effect - > actionTimer ] ) ) ;
Gfx_SetupDL61_Xlu ( gfxCtx ) ;
gSPClearGeometryMode ( POLY_XLU_DISP + + , G_CULL_BACK ) ;
isMaterialApplied + + ;
// Apply material 16 times along a circle to give the appearance of a splash
for ( j = 0 ; j < 16 ; j + + ) {
Matrix_RotateYF ( 2.0f * ( j * M_PI ) * ( 1.0f / 16.0f ) , MTXMODE_NEW ) ;
Matrix_MultVecZ ( effect - > maxScale , & vec ) ;
/**
* Get the water surface at point ( ` x ` , ` ySurface ` , ` z ` ) . ` ySurface ` doubles as position y input
* returns true if point is within the xz boundaries of an active water box , else false
* ` ySurface ` returns the water box ' s surface , while ` outWaterBox ` returns a pointer to the WaterBox
*/
ySurface = effect - > pos . y ;
if ( WaterBox_GetSurface1 ( play , & play - > colCtx , effect - > pos . x + vec . x , effect - > pos . z + vec . z , & ySurface ,
& waterBox ) ) {
if ( ( effect - > pos . y - ySurface ) < 200.0f ) {
// Draw the splash effect.
Matrix_Translate ( effect - > pos . x + vec . x , ySurface , effect - > pos . z + vec . z , MTXMODE_NEW ) ;
Matrix_RotateYF ( 2.0f * ( j * M_PI ) * ( 1.0f / 16.0f ) , MTXMODE_APPLY ) ;
Matrix_RotateXFApply ( effect - > rotationX ) ;
Matrix_Scale ( effect - > scale , effect - > scale , effect - > scale , MTXMODE_APPLY ) ;
gSPMatrix ( POLY_XLU_DISP + + , Matrix_NewMtx ( gfxCtx ) , G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW ) ;
// @recomp TODO figure out a way to tag these without increasing the allocated IDs per actor.
gSPDisplayList ( POLY_XLU_DISP + + , gEffWaterSplashDL ) ;
}
}
}
}
}
CLOSE_DISPS ( play - > state . gfxCtx ) ;
}