mirror of https://github.com/zeldaret/mm.git
Demo_Kankyo (Lost Woods Sparkles) (#380)
* Demo_Kankyo * DemoKankyo: docs * DemoKankyo: documenting this is a pain... * found bug * DemoKankyo: docs * DemoKankyo: function renamed * DemoKankyo: docs * DemoKankyo: more docks * DemoKankyo: more docks * DemoKankyo: docs and format * DemoKankyo: requested changes * DemoKankyo: bug documented * PR feedback via docs * DemoKankyo: minor documentation and format * DemoKankyo: requested changes * DemoKankyo: removed some old comments Co-authored-by: Maide <eeeedddccc@hotmail.co.uk> Co-authored-by: isghj8 <isghj8@gmail.com> Co-authored-by: engineer124 <engineer124engineer124@gmail.com>
This commit is contained in:
parent
fcbd524b5d
commit
60b9cd789e
|
@ -4034,7 +4034,7 @@ extern Gfx D_04075B30[];
|
||||||
extern Gfx D_04076BC0[];
|
extern Gfx D_04076BC0[];
|
||||||
extern Gfx D_04077480[];
|
extern Gfx D_04077480[];
|
||||||
extern UNK_TYPE D_04079B10;
|
extern UNK_TYPE D_04079B10;
|
||||||
extern Gfx D_0407AB10[];
|
extern Gfx D_0407AB10[]; // sun (sparkles when small) displaylist
|
||||||
extern Gfx D_0407AB58[];
|
extern Gfx D_0407AB58[];
|
||||||
extern UNK_TYPE D_0407AFB0;
|
extern UNK_TYPE D_0407AFB0;
|
||||||
extern Gfx D_0407D590[];
|
extern Gfx D_0407D590[];
|
||||||
|
|
|
@ -942,7 +942,7 @@ typedef struct {
|
||||||
/* 0xEC */ u8 unk_EC;
|
/* 0xEC */ u8 unk_EC;
|
||||||
/* 0xED */ u8 unk_ED;
|
/* 0xED */ u8 unk_ED;
|
||||||
/* 0xEE */ u8 unk_EE[4];
|
/* 0xEE */ u8 unk_EE[4];
|
||||||
/* 0xF2 */ u8 unk_F2[8];
|
/* 0xF2 */ u8 unk_F2[8]; // [3] is used by both DemoKankyo and ObjectKankyo particle count
|
||||||
/* 0xFA */ u8 unk_FA[4];
|
/* 0xFA */ u8 unk_FA[4];
|
||||||
} EnvironmentContext; // size = 0x100
|
} EnvironmentContext; // size = 0x100
|
||||||
|
|
||||||
|
|
3
spec
3
spec
|
@ -1156,8 +1156,7 @@ beginseg
|
||||||
name "ovl_Demo_Kankyo"
|
name "ovl_Demo_Kankyo"
|
||||||
compress
|
compress
|
||||||
include "build/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.o"
|
include "build/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.o"
|
||||||
include "build/data/ovl_Demo_Kankyo/ovl_Demo_Kankyo.data.o"
|
include "build/src/overlays/actors/ovl_Demo_Kankyo/ovl_Demo_Kankyo_reloc.o"
|
||||||
include "build/data/ovl_Demo_Kankyo/ovl_Demo_Kankyo.reloc.o"
|
|
||||||
endseg
|
endseg
|
||||||
|
|
||||||
beginseg
|
beginseg
|
||||||
|
|
|
@ -15,12 +15,15 @@ void DemoKankyo_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||||
void DemoKankyo_Update(Actor* thisx, GlobalContext* globalCtx);
|
void DemoKankyo_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||||
void DemoKankyo_Draw(Actor* thisx, GlobalContext* globalCtx);
|
void DemoKankyo_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||||
|
|
||||||
void func_808CF06C(DemoKankyo* this, GlobalContext* globalCtx);
|
void DemoKakyo_MoonSparklesActionFunc(DemoKankyo* this, GlobalContext* globalCtx);
|
||||||
void func_808CF0CC(DemoKankyo* this, GlobalContext* globalCtx);
|
|
||||||
|
|
||||||
void DemoKankyo_SetupAction(DemoKankyo* this, DemoKankyoActionFunc actionFunc);
|
extern Gfx D_0407AB58[];
|
||||||
|
extern Gfx D_06001000[]; // the bubble display list used by shabom in giants type
|
||||||
|
extern Gfx D_04023428[];
|
||||||
|
|
||||||
|
static u8 sLostWoodsSparklesMutex = false; // make sure only one can exist at once
|
||||||
|
static s16 sLostWoodsSkyFishParticleNum = 0;
|
||||||
|
|
||||||
#if 0
|
|
||||||
const ActorInit Demo_Kankyo_InitVars = {
|
const ActorInit Demo_Kankyo_InitVars = {
|
||||||
ACTOR_DEMO_KANKYO,
|
ACTOR_DEMO_KANKYO,
|
||||||
ACTORCAT_ITEMACTION,
|
ACTORCAT_ITEMACTION,
|
||||||
|
@ -33,24 +36,659 @@ const ActorInit Demo_Kankyo_InitVars = {
|
||||||
(ActorFunc)DemoKankyo_Draw,
|
(ActorFunc)DemoKankyo_Draw,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
static s32 sObjectBubbleIndex = OBJECT_BUBBLE | 0x10000;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/DemoKankyo_SetupAction.s")
|
void DemoKankyo_SetupAction(DemoKankyo* this, DemoKankyoActionFunc actionFunc) {
|
||||||
|
this->actionFunc = actionFunc;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/func_808CE45C.s")
|
void DemoKakyo_LostWoodsSparkleActionFunc(DemoKankyo* this, GlobalContext* globalCtx) {
|
||||||
|
s32 pad;
|
||||||
|
s32 i;
|
||||||
|
f32 randSkyfishParticleNum;
|
||||||
|
f32 repositionLimit; // Distance from posCenter when particles are relocated. Always set to 130.0f
|
||||||
|
f32 eyeToAtNormX;
|
||||||
|
f32 eyeToAtNormY;
|
||||||
|
f32 eyeToAtNormZ;
|
||||||
|
f32 eyeToAtMag;
|
||||||
|
f32 posCenterX;
|
||||||
|
f32 posCenterY;
|
||||||
|
f32 posCenterZ;
|
||||||
|
Vec3f eyeToAt;
|
||||||
|
Player* player = GET_PLAYER(globalCtx);
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/func_808CF06C.s")
|
if (globalCtx->roomCtx.unk7A[1] != 0) {
|
||||||
|
if (globalCtx->envCtx.unk_F2[3] != 0) {
|
||||||
|
globalCtx->envCtx.unk_F2[3]--;
|
||||||
|
} else {
|
||||||
|
Actor_MarkForDeath(&this->actor);
|
||||||
|
}
|
||||||
|
} else if (globalCtx->envCtx.unk_F2[3] < DEMOKANKYO_PARTICLE_COUNT) {
|
||||||
|
globalCtx->envCtx.unk_F2[3] += 16;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/func_808CF0CC.s")
|
// note: DemoKankyo can crash if placed in an area that snows (ObjectKankyo)
|
||||||
|
// because they both use unk_F2 as a particle counter,
|
||||||
|
// causing DemoKankyo to write beyond its particle array boundry
|
||||||
|
// this crash can occur if the two actors are in different scenes connected by an exit
|
||||||
|
// e.g. if you add DemoKankyo to GoronShrine, you will crash entering/leaving through door
|
||||||
|
for (i = 0; i < globalCtx->envCtx.unk_F2[3]; i++) {
|
||||||
|
repositionLimit = 130.0f;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/DemoKankyo_Init.s")
|
eyeToAt.x = globalCtx->view.at.x - globalCtx->view.eye.x;
|
||||||
|
eyeToAt.y = globalCtx->view.at.y - globalCtx->view.eye.y;
|
||||||
|
eyeToAt.z = globalCtx->view.at.z - globalCtx->view.eye.z;
|
||||||
|
eyeToAtMag = sqrtf(SQXYZ(eyeToAt));
|
||||||
|
eyeToAtNormX = eyeToAt.x / eyeToAtMag;
|
||||||
|
eyeToAtNormY = eyeToAt.y / eyeToAtMag;
|
||||||
|
eyeToAtNormZ = eyeToAt.z / eyeToAtMag;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/DemoKankyo_Destroy.s")
|
switch (this->particles[i].state) {
|
||||||
|
case DEMO_KANKYO_STATE_INIT:
|
||||||
|
this->particles[i].posBase.x = globalCtx->view.eye.x + (eyeToAtNormX * 80.0f);
|
||||||
|
this->particles[i].posBase.y = globalCtx->view.eye.y + (eyeToAtNormY * 80.0f);
|
||||||
|
this->particles[i].posBase.z = globalCtx->view.eye.z + (eyeToAtNormZ * 80.0f);
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/DemoKankyo_Update.s")
|
this->particles[i].posOffset.x = (Rand_ZeroOne() - 0.5f) * 160.0f;
|
||||||
|
this->particles[i].posOffset.y = 30.0f;
|
||||||
|
this->particles[i].posOffset.z = (Rand_ZeroOne() - 0.5f) * 160.0f;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/func_808CF970.s")
|
this->particles[i].speedTarget = (Rand_ZeroOne() * 1.6f) + 0.5f;
|
||||||
|
this->particles[i].alpha = 0;
|
||||||
|
this->particles[i].alphaClock = Rand_ZeroOne() * 65535; // random 0 to max of u16
|
||||||
|
this->particles[i].scale = 0.1f;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/func_808CFE04.s")
|
// speedClock is angles in radians,
|
||||||
|
// should have used Rand_ZeroOne() * 2 * M_PI
|
||||||
|
// however, due to properties of sine waves, this is effectively still random
|
||||||
|
this->particles[i].speedClock.x = Rand_ZeroOne() * 360.0f;
|
||||||
|
this->particles[i].speedClock.y = Rand_ZeroOne() * 360.0f;
|
||||||
|
this->particles[i].speedClock.z = Rand_ZeroOne() * 360.0f;
|
||||||
|
this->particles[i].pad50 = 0;
|
||||||
|
this->particles[i].state += DEMO_KANKYO_STATE_SINGLE;
|
||||||
|
break;
|
||||||
|
|
||||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Demo_Kankyo/DemoKankyo_Draw.s")
|
case DEMO_KANKYO_STATE_SINGLE:
|
||||||
|
case DEMO_KANKYO_STATE_SKYFISH:
|
||||||
|
this->particles[i].alphaClock++;
|
||||||
|
posCenterX = globalCtx->view.eye.x + (eyeToAtNormX * 80.0f);
|
||||||
|
posCenterY = globalCtx->view.eye.y + (eyeToAtNormY * 80.0f);
|
||||||
|
posCenterZ = globalCtx->view.eye.z + (eyeToAtNormZ * 80.0f);
|
||||||
|
this->particles[i].posOffsetPrev.x = this->particles[i].posOffset.x;
|
||||||
|
this->particles[i].posOffsetPrev.y = this->particles[i].posOffset.y;
|
||||||
|
this->particles[i].posOffsetPrev.z = this->particles[i].posOffset.z;
|
||||||
|
|
||||||
|
if (this->particles[i].state == DEMO_KANKYO_STATE_SINGLE) {
|
||||||
|
|
||||||
|
// The first 32 particles will become skyfish particles
|
||||||
|
// This block is also init code and only runs once
|
||||||
|
if (i < 32) {
|
||||||
|
if (Rand_ZeroOne() < 0.5f) {
|
||||||
|
this->particles[i].LostWoodsSkyFishSpeedXZ = (s16)(Rand_ZeroOne() * 200.0f) + 200;
|
||||||
|
} else {
|
||||||
|
this->particles[i].LostWoodsSkyFishSpeedXZ = -200 - (s16)(Rand_ZeroOne() * 200.0f);
|
||||||
|
}
|
||||||
|
this->particles[i].LostWoodsSkyFishPosOffsetMax = (s16)(Rand_ZeroOne() * 50.0f) + 15;
|
||||||
|
this->particles[i].LostWoodsSkyFishSpeedY = ((Rand_ZeroOne() * 10.0f) + 10.0f) * 0.01f;
|
||||||
|
|
||||||
|
// Only the 31st particle matters as sLostWoodsSkyFishParticleNum will be overwritten
|
||||||
|
// every particle until the last skyfish particle is initialized
|
||||||
|
randSkyfishParticleNum = Rand_ZeroOne();
|
||||||
|
if (randSkyfishParticleNum < 0.2f) {
|
||||||
|
sLostWoodsSkyFishParticleNum = 1;
|
||||||
|
} else if (randSkyfishParticleNum < 0.2f) {
|
||||||
|
// This case is never taken as the else-if conditional is identical to the previous one
|
||||||
|
sLostWoodsSkyFishParticleNum = 3;
|
||||||
|
} else if (randSkyfishParticleNum < 0.4f) {
|
||||||
|
sLostWoodsSkyFishParticleNum = 7;
|
||||||
|
} else {
|
||||||
|
sLostWoodsSkyFishParticleNum = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((i & sLostWoodsSkyFishParticleNum) == 0) {
|
||||||
|
// Head particle
|
||||||
|
this->particles[i].posOffset.y = 0.0f;
|
||||||
|
}
|
||||||
|
this->particles[i].state = DEMO_KANKYO_STATE_SKYFISH;
|
||||||
|
this->particles[i].speedTarget = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Math_SmoothStepToF(&this->particles[i].scale, 0.1, 0.1f, 0.001f, 0.00001f);
|
||||||
|
Math_SmoothStepToF(&this->particles[i].speed, this->particles[i].speedTarget, 0.5f, 0.2f, 0.02f);
|
||||||
|
this->particles[i].posOffset.x +=
|
||||||
|
__sinf(this->particles[i].speedClock.x) * this->particles[i].speed;
|
||||||
|
this->particles[i].posOffset.y +=
|
||||||
|
__sinf(this->particles[i].speedClock.y) * this->particles[i].speed;
|
||||||
|
this->particles[i].posOffset.z +=
|
||||||
|
__sinf(this->particles[i].speedClock.z) * this->particles[i].speed;
|
||||||
|
|
||||||
|
switch ((i >> 1) & 3) {
|
||||||
|
case 0:
|
||||||
|
this->particles[i].speedClock.x += 0.008f;
|
||||||
|
this->particles[i].speedClock.y += 0.05f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.015f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.05f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.005f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.4f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.004f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.08f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.05f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (this->particles[i].state == DEMO_KANKYO_STATE_SKYFISH) {
|
||||||
|
if ((i & sLostWoodsSkyFishParticleNum) == 0) {
|
||||||
|
// Head particle
|
||||||
|
Math_SmoothStepToF(&this->particles[i].scale, 0.25f, 0.1f, 0.001f, 0.00001f);
|
||||||
|
|
||||||
|
Math_SmoothStepToF(&this->particles[i].posBase.x, player->actor.world.pos.x, 0.5f, 1.0f, 0.2f);
|
||||||
|
Math_SmoothStepToF(&this->particles[i].posBase.y, player->actor.world.pos.y + 50.0f, 0.5f, 1.0f,
|
||||||
|
0.2f);
|
||||||
|
Math_SmoothStepToF(&this->particles[i].posBase.z, player->actor.world.pos.z, 0.5f, 1.0f, 0.2f);
|
||||||
|
|
||||||
|
Math_SmoothStepToF(&this->particles[i].posOffset.x,
|
||||||
|
Math_SinS(this->particles[i].LostWoodsSkyFishSpeedXZClock - 0x8000) *
|
||||||
|
this->particles[i].LostWoodsSkyFishPosOffsetMax,
|
||||||
|
0.5f, 2.0f, 0.2f);
|
||||||
|
Math_SmoothStepToF(&this->particles[i].posOffset.z,
|
||||||
|
Math_CosS(this->particles[i].LostWoodsSkyFishSpeedXZClock - 0x8000) *
|
||||||
|
this->particles[i].LostWoodsSkyFishPosOffsetMax,
|
||||||
|
0.5f, 2.0f, 0.2f);
|
||||||
|
this->particles[i].LostWoodsSkyFishSpeedXZClock += this->particles[i].LostWoodsSkyFishSpeedXZ;
|
||||||
|
this->particles[i].posOffset.y += __sinf(this->particles[i].speedClock.y);
|
||||||
|
this->particles[i].speedClock.x += 0.2f * Rand_ZeroOne(); // unused calculation
|
||||||
|
this->particles[i].speedClock.y += this->particles[i].LostWoodsSkyFishSpeedY;
|
||||||
|
this->particles[i].speedClock.z += 0.1f * Rand_ZeroOne(); // unused calculation
|
||||||
|
|
||||||
|
this->particles[i].posOffset.x =
|
||||||
|
Math_SinS(this->particles[i].LostWoodsSkyFishSpeedXZClock - 0x8000) *
|
||||||
|
this->particles[i].LostWoodsSkyFishPosOffsetMax;
|
||||||
|
this->particles[i].posOffset.z =
|
||||||
|
Math_CosS(this->particles[i].LostWoodsSkyFishSpeedXZClock - 0x8000) *
|
||||||
|
this->particles[i].LostWoodsSkyFishPosOffsetMax;
|
||||||
|
} else {
|
||||||
|
// Tail Particles
|
||||||
|
Math_SmoothStepToF(&this->particles[i].scale, 0.1, 0.1f, 0.001f, 0.00001f);
|
||||||
|
|
||||||
|
// Unused calculation, speed only used in posOffset calculations,
|
||||||
|
// but posOffset gets overwritten for tail particles immediately below
|
||||||
|
Math_SmoothStepToF(&this->particles[i].speed, 1.5f, 0.5f, 0.1f, 0.0002f);
|
||||||
|
|
||||||
|
// particles in the skyfish's tail are moved to the previous position of the particle directly
|
||||||
|
// in front
|
||||||
|
this->particles[i].posOffset.x =
|
||||||
|
this->particles[i - 1].posOffsetPrev.x +
|
||||||
|
(this->particles[i - 1].posBase.x - this->particles[i].posBase.x);
|
||||||
|
this->particles[i].posOffset.y =
|
||||||
|
this->particles[i - 1].posOffsetPrev.y +
|
||||||
|
(this->particles[i - 1].posBase.y - this->particles[i].posBase.y);
|
||||||
|
this->particles[i].posOffset.z =
|
||||||
|
this->particles[i - 1].posOffsetPrev.z +
|
||||||
|
(this->particles[i - 1].posBase.z - this->particles[i].posBase.z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this->particles[i].state != DEMO_KANKYO_STATE_SKYFISH) &&
|
||||||
|
((((this->particles[i].posBase.x + this->particles[i].posOffset.x) - posCenterX) >
|
||||||
|
repositionLimit) ||
|
||||||
|
(((this->particles[i].posBase.x + this->particles[i].posOffset.x) - posCenterX) <
|
||||||
|
-repositionLimit) ||
|
||||||
|
(((this->particles[i].posBase.y + this->particles[i].posOffset.y) - posCenterY) >
|
||||||
|
repositionLimit) ||
|
||||||
|
(((this->particles[i].posBase.y + this->particles[i].posOffset.y) - posCenterY) <
|
||||||
|
-repositionLimit) ||
|
||||||
|
(((this->particles[i].posBase.z + this->particles[i].posOffset.z) - posCenterZ) >
|
||||||
|
repositionLimit) ||
|
||||||
|
(((this->particles[i].posBase.z + this->particles[i].posOffset.z) - posCenterZ) <
|
||||||
|
-repositionLimit))) {
|
||||||
|
if (((this->particles[i].posOffset.x + this->particles[i].posBase.x) - posCenterX) >
|
||||||
|
repositionLimit) {
|
||||||
|
this->particles[i].posOffset.x = 0.0f;
|
||||||
|
this->particles[i].posBase.x = posCenterX - repositionLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.x + this->particles[i].posOffset.x) - posCenterX) <
|
||||||
|
-repositionLimit) {
|
||||||
|
this->particles[i].posOffset.x = 0.0f;
|
||||||
|
this->particles[i].posBase.x = posCenterX + repositionLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.y + this->particles[i].posOffset.y) - posCenterY) > 50.0f) {
|
||||||
|
this->particles[i].posOffset.y = 0.0f;
|
||||||
|
this->particles[i].posBase.y = posCenterY - 50.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.y + this->particles[i].posOffset.y) - posCenterY) < -50.0f) {
|
||||||
|
this->particles[i].posOffset.y = 0.0f;
|
||||||
|
this->particles[i].posBase.y = posCenterY + 50.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.z + this->particles[i].posOffset.z) - posCenterZ) >
|
||||||
|
repositionLimit) {
|
||||||
|
this->particles[i].posOffset.z = 0.0f;
|
||||||
|
this->particles[i].posBase.z = posCenterZ - repositionLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.z + this->particles[i].posOffset.z) - posCenterZ) <
|
||||||
|
-repositionLimit) {
|
||||||
|
this->particles[i].posOffset.z = 0.0f;
|
||||||
|
this->particles[i].posBase.z = posCenterZ + repositionLimit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_STATE_DISABLED:
|
||||||
|
this->particles[i].state = DEMO_KANKYO_STATE_INIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKakyo_GiantObjectCheck(DemoKankyo* this, GlobalContext* globalCtx) {
|
||||||
|
if (Object_IsLoaded(&globalCtx->objectCtx, this->objectId)) {
|
||||||
|
this->isSafeToDrawGiants = true;
|
||||||
|
this->actor.objBankIndex = this->objectId;
|
||||||
|
DemoKankyo_SetupAction(this, DemoKakyo_MoonSparklesActionFunc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* used by Moon AND giants types
|
||||||
|
*/
|
||||||
|
void DemoKakyo_MoonSparklesActionFunc(DemoKankyo* this, GlobalContext* globalCtx) {
|
||||||
|
s32 i;
|
||||||
|
Vec3f eyeToAt;
|
||||||
|
f32 eyeToAtNormX;
|
||||||
|
f32 eyeToAtNormY;
|
||||||
|
f32 eyeToAtNormZ;
|
||||||
|
f32 eyeToAtMag;
|
||||||
|
f32 halfScreenWidth;
|
||||||
|
f32 randZeroOne;
|
||||||
|
f32 pad0;
|
||||||
|
Vec3f newEye;
|
||||||
|
f32 halfScreenHeight;
|
||||||
|
s32 pad1;
|
||||||
|
Vec3f worldPos;
|
||||||
|
|
||||||
|
if (globalCtx->envCtx.unk_F2[3] < DEMOKANKYO_PARTICLE_COUNT) {
|
||||||
|
globalCtx->envCtx.unk_F2[3] += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
eyeToAt.x = globalCtx->view.at.x - globalCtx->view.eye.x;
|
||||||
|
eyeToAt.y = globalCtx->view.at.y - globalCtx->view.eye.y;
|
||||||
|
eyeToAt.z = globalCtx->view.at.z - globalCtx->view.eye.z;
|
||||||
|
eyeToAtMag = sqrtf(SQXYZ(eyeToAt));
|
||||||
|
eyeToAtNormX = eyeToAt.x / eyeToAtMag;
|
||||||
|
eyeToAtNormY = eyeToAt.y / eyeToAtMag;
|
||||||
|
eyeToAtNormZ = eyeToAt.z / eyeToAtMag;
|
||||||
|
|
||||||
|
halfScreenHeight = SCREEN_HEIGHT / 2;
|
||||||
|
|
||||||
|
for (i = 0; i < globalCtx->envCtx.unk_F2[3]; i++) {
|
||||||
|
switch (this->particles[i].state) {
|
||||||
|
case DEMO_KANKYO_STATE_INIT:
|
||||||
|
this->particles[i].posBase.x = globalCtx->view.eye.x + (eyeToAtNormX * halfScreenHeight);
|
||||||
|
this->particles[i].posBase.y = globalCtx->view.eye.y + (eyeToAtNormY * halfScreenHeight);
|
||||||
|
this->particles[i].posBase.z = globalCtx->view.eye.z + (eyeToAtNormZ * halfScreenHeight);
|
||||||
|
|
||||||
|
this->particles[i].posOffset.x = (Rand_ZeroOne() - 0.5f) * (2.0f * halfScreenHeight);
|
||||||
|
this->particles[i].posOffset.y = (Rand_ZeroOne() - 0.5f) * (2.0f * halfScreenHeight);
|
||||||
|
this->particles[i].posOffset.z = (Rand_ZeroOne() - 0.5f) * (2.0f * halfScreenHeight);
|
||||||
|
|
||||||
|
this->particles[i].speedTarget = (Rand_ZeroOne() * 1.6f) + 0.5f;
|
||||||
|
this->particles[i].alpha = 0;
|
||||||
|
this->particles[i].alphaClock = (Rand_ZeroOne() * 65535);
|
||||||
|
this->particles[i].scale = 0.2f;
|
||||||
|
|
||||||
|
// speedClock is angles in radians,
|
||||||
|
// should have used Rand_ZeroOne() * 2 * M_PI
|
||||||
|
// however, due to properties of sine waves, this is effectively still random
|
||||||
|
this->particles[i].speedClock.x = Rand_ZeroOne() * 360.0f;
|
||||||
|
this->particles[i].speedClock.y = Rand_ZeroOne() * 360.0f;
|
||||||
|
this->particles[i].speedClock.z = Rand_ZeroOne() * 360.0f;
|
||||||
|
|
||||||
|
this->particles[i].pad50 = 0;
|
||||||
|
this->particles[i].state += DEMO_KANKYO_STATE_SINGLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_STATE_SINGLE:
|
||||||
|
case DEMO_KANKYO_STATE_SKYFISH:
|
||||||
|
this->particles[i].alphaClock++;
|
||||||
|
|
||||||
|
if (this->actor.params == DEMO_KANKYO_TYPE_MOON) { // this function gets reused for giants too
|
||||||
|
this->particles[i].posBase.y =
|
||||||
|
globalCtx->view.eye.y + (eyeToAtNormY * halfScreenHeight) + (SCREEN_HEIGHT / 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
newEye.x = globalCtx->view.eye.x + (eyeToAtNormX * halfScreenHeight);
|
||||||
|
newEye.y = globalCtx->view.eye.y + (eyeToAtNormY * halfScreenHeight);
|
||||||
|
newEye.z = globalCtx->view.eye.z + (eyeToAtNormZ * halfScreenHeight);
|
||||||
|
|
||||||
|
Math_SmoothStepToF(&this->particles[i].scale, 0.2f, 0.1f, 0.001f, 0.00001f);
|
||||||
|
Math_SmoothStepToF(&this->particles[i].speed, this->particles[i].speedTarget, 0.5f, 0.2f, 0.02f);
|
||||||
|
|
||||||
|
this->particles[i].posOffset.x += __sinf(this->particles[i].speedClock.x) * this->particles[i].speed;
|
||||||
|
this->particles[i].posOffset.y += __sinf(this->particles[i].speedClock.y) * this->particles[i].speed;
|
||||||
|
this->particles[i].posOffset.z += __sinf(this->particles[i].speedClock.z) * this->particles[i].speed;
|
||||||
|
|
||||||
|
switch ((i >> 1) & 3) {
|
||||||
|
case 0:
|
||||||
|
this->particles[i].speedClock.x += 0.008f;
|
||||||
|
this->particles[i].speedClock.y += 0.05f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.015f;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.05f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.005f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.4f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.004f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3:
|
||||||
|
this->particles[i].speedClock.x += 0.01f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.y += 0.08f * Rand_ZeroOne();
|
||||||
|
this->particles[i].speedClock.z += 0.05f * Rand_ZeroOne();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.x + this->particles[i].posOffset.x) - newEye.x) > halfScreenHeight) {
|
||||||
|
this->particles[i].posBase.x = newEye.x - halfScreenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.x + this->particles[i].posOffset.x) - newEye.x) < -halfScreenHeight) {
|
||||||
|
this->particles[i].posBase.x = newEye.x + halfScreenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
worldPos.x = this->particles[i].posBase.x + this->particles[i].posOffset.x;
|
||||||
|
worldPos.y = this->particles[i].posBase.y + this->particles[i].posOffset.y;
|
||||||
|
worldPos.z = this->particles[i].posBase.z + this->particles[i].posOffset.z;
|
||||||
|
|
||||||
|
randZeroOne = Math_Vec3f_DistXZ(&worldPos, &globalCtx->view.eye) / 200.0f;
|
||||||
|
randZeroOne = CLAMP(randZeroOne, 0.0f, 1.0f);
|
||||||
|
halfScreenWidth = 100.0f + randZeroOne + 60.0f; // range 160 to 161...? thats about half screen width
|
||||||
|
|
||||||
|
// I think this code is shifting the particles 1 frame -> half screen at a time to keep it in-view
|
||||||
|
if (halfScreenWidth < ((this->particles[i].posBase.y + this->particles[i].posOffset.y) - newEye.y)) {
|
||||||
|
this->particles[i].posBase.y = newEye.y - halfScreenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.y + this->particles[i].posOffset.y) - newEye.y) < -halfScreenWidth) {
|
||||||
|
this->particles[i].posBase.y = newEye.y + halfScreenWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.z + this->particles[i].posOffset.z) - newEye.z) > halfScreenHeight) {
|
||||||
|
this->particles[i].posBase.z = newEye.z - halfScreenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((this->particles[i].posBase.z + this->particles[i].posOffset.z) - newEye.z) < -halfScreenHeight) {
|
||||||
|
this->particles[i].posBase.z = newEye.z + halfScreenHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_STATE_DISABLED:
|
||||||
|
this->particles[i].state = DEMO_KANKYO_STATE_INIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKankyo_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
s32 pad;
|
||||||
|
s32 i;
|
||||||
|
s32 objId;
|
||||||
|
|
||||||
|
// This must be a single line to match, possibly a macro?
|
||||||
|
// clang-format off
|
||||||
|
for (i = 0; i < ARRAY_COUNT(this->particles); i++) { this->particles[i].state = DEMO_KANKYO_STATE_INIT; }
|
||||||
|
// clang-format on
|
||||||
|
|
||||||
|
if (1) {};
|
||||||
|
|
||||||
|
switch (this->actor.params) {
|
||||||
|
case DEMO_KANKYO_TYPE_LOSTWOODS:
|
||||||
|
objId = OBJECT_UNSET_0;
|
||||||
|
this->actor.room = -1;
|
||||||
|
if (sLostWoodsSparklesMutex == false) {
|
||||||
|
DemoKankyo_SetupAction(this, DemoKakyo_LostWoodsSparkleActionFunc);
|
||||||
|
sLostWoodsSparklesMutex = true;
|
||||||
|
} else {
|
||||||
|
Actor_MarkForDeath(&this->actor);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_TYPE_GIANTS:
|
||||||
|
this->isSafeToDrawGiants = false;
|
||||||
|
objId = Object_GetIndex(&globalCtx->objectCtx, sObjectBubbleIndex);
|
||||||
|
DemoKankyo_SetupAction(this, DemoKakyo_GiantObjectCheck);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_TYPE_MOON:
|
||||||
|
objId = OBJECT_UNSET_0;
|
||||||
|
this->isSafeToDrawGiants = true;
|
||||||
|
DemoKankyo_SetupAction(this, DemoKakyo_MoonSparklesActionFunc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
//! @bug: this causes a crash because the actionfunc is never set
|
||||||
|
objId = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (objId > -1) {
|
||||||
|
this->objectId = objId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKankyo_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
|
||||||
|
Actor_MarkForDeath(&this->actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKankyo_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
|
||||||
|
this->actionFunc(this, globalCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, GlobalContext* globalCtx2) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
GlobalContext* globalCtx = globalCtx2;
|
||||||
|
s16 i;
|
||||||
|
f32 scaleAlpha;
|
||||||
|
Vec3f worldPos;
|
||||||
|
Vec3f screenPos;
|
||||||
|
|
||||||
|
// if not underwater
|
||||||
|
if (!(globalCtx->cameraPtrs[MAIN_CAM]->flags2 & 0x100)) {
|
||||||
|
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||||
|
|
||||||
|
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
|
||||||
|
|
||||||
|
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(&D_04079B10));
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, D_0407AB10);
|
||||||
|
|
||||||
|
for (i = 0; i < globalCtx->envCtx.unk_F2[3]; i++) {
|
||||||
|
worldPos.x = this->particles[i].posBase.x + this->particles[i].posOffset.x;
|
||||||
|
worldPos.y = this->particles[i].posBase.y + this->particles[i].posOffset.y;
|
||||||
|
worldPos.z = this->particles[i].posBase.z + this->particles[i].posOffset.z;
|
||||||
|
|
||||||
|
func_80169474(globalCtx, &worldPos, &screenPos); // unnamed Play_ function, func_800C016C from OoT
|
||||||
|
|
||||||
|
// checking if particle is on screen
|
||||||
|
if (screenPos.x >= 0.0f && screenPos.x < SCREEN_WIDTH && screenPos.y >= 0.0f &&
|
||||||
|
screenPos.y < SCREEN_HEIGHT) {
|
||||||
|
Matrix_InsertTranslation(worldPos.x, worldPos.y, worldPos.z, MTXMODE_NEW);
|
||||||
|
scaleAlpha = this->particles[i].alpha / 50.0f;
|
||||||
|
if (scaleAlpha > 1.0f) {
|
||||||
|
scaleAlpha = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix_Scale(this->particles[i].scale * scaleAlpha, this->particles[i].scale * scaleAlpha,
|
||||||
|
this->particles[i].scale * scaleAlpha, MTXMODE_APPLY);
|
||||||
|
|
||||||
|
// adjust transparency of this particle
|
||||||
|
if (i < 32) {
|
||||||
|
// Skyfish particles
|
||||||
|
if (this->particles[i].state != DEMO_KANKYO_STATE_SKYFISH) {
|
||||||
|
// still initializing
|
||||||
|
if (this->particles[i].alpha > 0) { // NOT DECR
|
||||||
|
this->particles[i].alpha--;
|
||||||
|
}
|
||||||
|
} else if (this->particles[i].alpha < 100) {
|
||||||
|
this->particles[i].alpha++;
|
||||||
|
}
|
||||||
|
} else if (this->particles[i].state != DEMO_KANKYO_STATE_SKYFISH) {
|
||||||
|
if ((this->particles[i].alphaClock & 31) < 16) {
|
||||||
|
if (this->particles[i].alpha < 235) {
|
||||||
|
this->particles[i].alpha += 20;
|
||||||
|
}
|
||||||
|
} else if (this->particles[i].alpha > 20) {
|
||||||
|
this->particles[i].alpha -= 20;
|
||||||
|
}
|
||||||
|
} else if ((this->particles[i].alphaClock & 15) < 8) {
|
||||||
|
if (this->particles[i].alpha < 255) {
|
||||||
|
this->particles[i].alpha += 100;
|
||||||
|
}
|
||||||
|
} else if (this->particles[i].alpha > 10) {
|
||||||
|
this->particles[i].alpha -= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
gDPPipeSync(POLY_XLU_DISP++);
|
||||||
|
|
||||||
|
switch (i & 1) {
|
||||||
|
case 0: // gold particles
|
||||||
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 155, this->particles[i].alpha);
|
||||||
|
gDPSetEnvColor(POLY_XLU_DISP++, 250, 180, 0, this->particles[i].alpha);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1: // silver particles
|
||||||
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, this->particles[i].alpha);
|
||||||
|
gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, this->particles[i].alpha);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matrix_InsertMatrix(&globalCtx->mf_187FC, MTXMODE_APPLY);
|
||||||
|
Matrix_InsertZRotation_f(DEGF_TO_RADF(globalCtx->state.frames * 20.0f), MTXMODE_APPLY);
|
||||||
|
|
||||||
|
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, D_0407AB58);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw, giants and moon
|
||||||
|
void DemoKankyo_DrawMoonAndGiant(Actor* thisx, GlobalContext* globalCtx2) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
GlobalContext* globalCtx = globalCtx2;
|
||||||
|
s16 i;
|
||||||
|
f32 alphaScale;
|
||||||
|
|
||||||
|
if (this->isSafeToDrawGiants != false) {
|
||||||
|
Vec3f worldPos;
|
||||||
|
Vec3f screenPos;
|
||||||
|
s32 pad;
|
||||||
|
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||||||
|
|
||||||
|
OPEN_DISPS(gfxCtx);
|
||||||
|
func_8012C2DC(gfxCtx);
|
||||||
|
|
||||||
|
for (i = 0; i < globalCtx->envCtx.unk_F2[3]; i++) {
|
||||||
|
worldPos.x = this->particles[i].posBase.x + this->particles[i].posOffset.x;
|
||||||
|
worldPos.y = this->particles[i].posBase.y + this->particles[i].posOffset.y;
|
||||||
|
worldPos.z = this->particles[i].posBase.z + this->particles[i].posOffset.z;
|
||||||
|
|
||||||
|
func_80169474(globalCtx, &worldPos, &screenPos); // unnamed Play_ function, func_800C016C from OoT
|
||||||
|
|
||||||
|
// checking if particle is on screen
|
||||||
|
if (screenPos.x >= 0.0f && screenPos.x < SCREEN_WIDTH && screenPos.y >= 0.0f &&
|
||||||
|
screenPos.y < SCREEN_HEIGHT) {
|
||||||
|
Matrix_InsertTranslation(worldPos.x, worldPos.y, worldPos.z, MTXMODE_NEW);
|
||||||
|
alphaScale = this->particles[i].alpha / 50.0f;
|
||||||
|
if (alphaScale > 1.0f) {
|
||||||
|
alphaScale = 1.0f;
|
||||||
|
}
|
||||||
|
Matrix_Scale(this->particles[i].scale * alphaScale, this->particles[i].scale * alphaScale,
|
||||||
|
this->particles[i].scale * alphaScale, MTXMODE_APPLY);
|
||||||
|
alphaScale = Math_Vec3f_DistXYZ(&worldPos, &globalCtx->view.eye) / 300.0f;
|
||||||
|
alphaScale = (alphaScale > 1.0f) ? 0.0f : (1.0f - alphaScale) > 1.0f ? 1.0f : 1.0f - alphaScale;
|
||||||
|
|
||||||
|
if (this->actor.params == DEMO_KANKYO_TYPE_GIANTS) {
|
||||||
|
this->particles[i].alpha = 255.0f * alphaScale;
|
||||||
|
} else {
|
||||||
|
this->particles[i].alpha = 160.0f * alphaScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
gDPPipeSync(POLY_XLU_DISP++);
|
||||||
|
|
||||||
|
switch (i & 1) { // half/half slightly different shades of yellow/tan
|
||||||
|
case 0:
|
||||||
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 230, 230, 220, this->particles[i].alpha);
|
||||||
|
gDPSetEnvColor(POLY_XLU_DISP++, 230, 230, 30, this->particles[i].alpha);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 200, 200, 190, this->particles[i].alpha);
|
||||||
|
gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 30, this->particles[i].alpha);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, &D_04023348);
|
||||||
|
|
||||||
|
Matrix_InsertMatrix(&globalCtx->mf_187FC, MTXMODE_APPLY);
|
||||||
|
|
||||||
|
Matrix_InsertZRotation_f(DEGF_TO_RADF(globalCtx->state.frames * 20.0f), MTXMODE_APPLY);
|
||||||
|
|
||||||
|
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
|
||||||
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||||
|
|
||||||
|
if (this->actor.params == DEMO_KANKYO_TYPE_GIANTS) {
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, D_06001000);
|
||||||
|
} else {
|
||||||
|
gSPDisplayList(POLY_XLU_DISP++, D_04023428);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CLOSE_DISPS(gfxCtx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DemoKankyo_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
DemoKankyo* this = THIS;
|
||||||
|
|
||||||
|
switch (this->actor.params) {
|
||||||
|
case DEMO_KANKYO_TYPE_LOSTWOODS:
|
||||||
|
DemoKakyo_DrawLostWoodsSparkle(&this->actor, globalCtx);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DEMO_KANKYO_TYPE_GIANTS:
|
||||||
|
case DEMO_KANKYO_TYPE_MOON:
|
||||||
|
DemoKankyo_DrawMoonAndGiant(&this->actor, globalCtx);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,13 +7,47 @@ struct DemoKankyo;
|
||||||
|
|
||||||
typedef void (*DemoKankyoActionFunc)(struct DemoKankyo*, GlobalContext*);
|
typedef void (*DemoKankyoActionFunc)(struct DemoKankyo*, GlobalContext*);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 0x000 */ u8 state;
|
||||||
|
/* 0x004 */ Vec3f posOffset;
|
||||||
|
/* 0x010 */ Vec3f posOffsetPrev;
|
||||||
|
/* 0x01C */ Vec3f posBase;
|
||||||
|
/* 0x028 */ Vec3f speedClock; // cycles in radians
|
||||||
|
/* 0x034 */ f32 speed;
|
||||||
|
/* 0x038 */ f32 speedTarget;
|
||||||
|
/* 0x03C */ u16 alphaClock;
|
||||||
|
/* 0x03E */ u16 LostWoodsSkyFishSpeedXZClock;
|
||||||
|
/* 0x040 */ u8 alpha;
|
||||||
|
/* 0x044 */ f32 scale; // size of the particle
|
||||||
|
/* 0x048 */ u16 LostWoodsSkyFishSpeedXZ; // the x-z speed (angular velocity) the lost woods skyfish oscillates around player. pos or neg 200-400
|
||||||
|
/* 0x04A */ u16 LostWoodsSkyFishPosOffsetMax; // The x-z range the lost woods skyfish oscillates around player. random value between 15-65
|
||||||
|
/* 0x04C */ f32 LostWoodsSkyFishSpeedY; // the y speed (angular velocity) the lost woods skyfish oscillates around player.
|
||||||
|
/* 0x050 */ u16 pad50; // unused, always assigned to 0, nothing else in this actor uses it
|
||||||
|
} DemoKankyoParticle; // size = 0x54
|
||||||
|
|
||||||
|
#define DEMOKANKYO_PARTICLE_COUNT 64
|
||||||
|
|
||||||
typedef struct DemoKankyo {
|
typedef struct DemoKankyo {
|
||||||
/* 0x0000 */ Actor actor;
|
/* 0x0000 */ Actor actor;
|
||||||
/* 0x0144 */ char unk_144[0x1500];
|
/* 0x0144 */ DemoKankyoParticle particles[DEMOKANKYO_PARTICLE_COUNT];
|
||||||
/* 0x1644 */ DemoKankyoActionFunc actionFunc;
|
/* 0x1644 */ DemoKankyoActionFunc actionFunc;
|
||||||
/* 0x1648 */ char unk_1648[0x8];
|
/* 0x1648 */ s32 objectId;
|
||||||
|
/* 0x164C */ u8 isSafeToDrawGiants;
|
||||||
} DemoKankyo; // size = 0x1650
|
} DemoKankyo; // size = 0x1650
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* 0 */ DEMO_KANKYO_TYPE_LOSTWOODS,
|
||||||
|
/* 1 */ DEMO_KANKYO_TYPE_GIANTS,
|
||||||
|
/* 2 */ DEMO_KANKYO_TYPE_MOON,
|
||||||
|
} DemoKankyoType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
/* 0 */ DEMO_KANKYO_STATE_INIT,
|
||||||
|
/* 1 */ DEMO_KANKYO_STATE_SINGLE,
|
||||||
|
/* 2 */ DEMO_KANKYO_STATE_SKYFISH,
|
||||||
|
/* 3 */ DEMO_KANKYO_STATE_DISABLED,
|
||||||
|
} DemoKankyoStateType;
|
||||||
|
|
||||||
extern const ActorInit Demo_Kankyo_InitVars;
|
extern const ActorInit Demo_Kankyo_InitVars;
|
||||||
|
|
||||||
#endif // Z_DEMO_KANKYO_H
|
#endif // Z_DEMO_KANKYO_H
|
||||||
|
|
Loading…
Reference in New Issue