mirror of https://github.com/zeldaret/mm.git
En_Bom_Chu (Bombchu) OK and documented (#679)
* EnBomChu_Init OK * EnBomChu_Destroy OK * func_808F7868 OK * func_808F79D4 OK * func_808F7E74 OK * func_808F7FA0 OK * func_808F77E4 OK * func_808F75D0 OK * func_808F7944 OK * func_808F7A84 OK * func_808F818C OK * func_808F8080 OK * func_808F7FD0 OK * EnBomChu_Update OK * EnBomChu_Draw OK * Drop unnecessary cast in Update * Import data into C * Object symbol * Use generated reloc * Port over OoT struct var names * Name all statics * Misc cleanup * Name some of the new struct vars introduced in MM * Port over most OoT function names * Name movingSpeed based on in-game observation * Name final param in EnBomChu_SpawnRipplesAndSplashes * More cleanup and OOT port * Some more names * More docs * Name last function * Final little cleanup * First round of review fixes * Change the name of that one function * More precise comment
This commit is contained in:
parent
5684b342b6
commit
d5e692d0e1
|
|
@ -838,8 +838,11 @@
|
|||
<DList Name="gameplay_keep_DL_015DB0" Offset="0x15DB0" />
|
||||
<Texture Name="gameplay_keep_Tex_015E40" OutName="tex_015E40" Format="rgba16" Width="8" Height="8" Offset="0x15E40" />
|
||||
<DList Name="gameplay_keep_DL_015FA0" Offset="0x15FA0" />
|
||||
<Texture Name="gameplay_keep_Tex_016060" OutName="tex_016060" Format="rgba16" Width="8" Height="8" Offset="0x16060" />
|
||||
<DList Name="gameplay_keep_DL_016360" Offset="0x16360" />
|
||||
|
||||
<!-- Bombchu -->
|
||||
<Texture Name="gBombchuBodyTex" OutName="bombchu_body" Format="rgba16" Width="8" Height="8" Offset="0x16060" />
|
||||
<DList Name="gBombchuDL" Offset="0x16360" />
|
||||
|
||||
<Texture Name="gameplay_keep_Tex_0164D0" OutName="tex_0164D0" Format="ia16" Width="32" Height="32" Offset="0x164D0" />
|
||||
<Texture Name="gameplay_keep_Tex_016CD0" OutName="tex_016CD0" Format="ia16" Width="32" Height="32" Offset="0x16CD0" />
|
||||
<Texture Name="gameplay_keep_Tex_0174D0" OutName="tex_0174D0" Format="ia16" Width="32" Height="32" Offset="0x174D0" />
|
||||
|
|
|
|||
3
spec
3
spec
|
|
@ -1285,8 +1285,7 @@ beginseg
|
|||
name "ovl_En_Bom_Chu"
|
||||
compress
|
||||
include "build/src/overlays/actors/ovl_En_Bom_Chu/z_en_bom_chu.o"
|
||||
include "build/data/ovl_En_Bom_Chu/ovl_En_Bom_Chu.data.o"
|
||||
include "build/data/ovl_En_Bom_Chu/ovl_En_Bom_Chu.reloc.o"
|
||||
include "build/src/overlays/actors/ovl_En_Bom_Chu/ovl_En_Bom_Chu_reloc.o"
|
||||
endseg
|
||||
|
||||
beginseg
|
||||
|
|
|
|||
|
|
@ -5,21 +5,26 @@
|
|||
*/
|
||||
|
||||
#include "z_en_bom_chu.h"
|
||||
#include "overlays/actors/ovl_En_Bom/z_en_bom.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_10)
|
||||
|
||||
#define THIS ((EnBomChu*)thisx)
|
||||
|
||||
#define BOMBCHU_SCALE 0.01f
|
||||
|
||||
void EnBomChu_Init(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBomChu_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBomChu_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnBomChu_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
void func_808F7868(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void func_808F7A84(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void func_808F7FA0(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void EnBomChu_WaitForRelease(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void EnBomChu_SetupMove(EnBomChu* this);
|
||||
void EnBomChu_Move(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void EnBomChu_Explode(EnBomChu* this, GlobalContext* globalCtx);
|
||||
void EnBomChu_WaitForDeath(EnBomChu* this, GlobalContext* globalCtx);
|
||||
|
||||
#if 0
|
||||
const ActorInit En_Bom_Chu_InitVars = {
|
||||
ACTOR_EN_BOM_CHU,
|
||||
ACTORCAT_EXPLOSIVES,
|
||||
|
|
@ -32,50 +37,536 @@ const ActorInit En_Bom_Chu_InitVars = {
|
|||
(ActorFunc)EnBomChu_Draw,
|
||||
};
|
||||
|
||||
// static ColliderSphereInit sSphereInit = {
|
||||
static ColliderSphereInit D_808F88E0 = {
|
||||
{ COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_1 | OC1_TYPE_2, OC2_TYPE_2, COLSHAPE_SPHERE, },
|
||||
{ ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
|
||||
static ColliderSphereInit sSphereInit = {
|
||||
{
|
||||
COLTYPE_NONE,
|
||||
AT_NONE,
|
||||
AC_ON | AC_TYPE_PLAYER,
|
||||
OC1_ON | OC1_TYPE_1 | OC1_TYPE_2,
|
||||
OC2_TYPE_2,
|
||||
COLSHAPE_SPHERE,
|
||||
},
|
||||
{
|
||||
ELEMTYPE_UNK0,
|
||||
{ 0x00000000, 0x00, 0x00 },
|
||||
{ 0xF7CFFFFF, 0x00, 0x00 },
|
||||
TOUCH_NONE | TOUCH_SFX_NORMAL,
|
||||
BUMP_ON,
|
||||
OCELEM_ON,
|
||||
},
|
||||
{ 1, { { 0, 0, 0 }, 13 }, 100 },
|
||||
};
|
||||
|
||||
// static InitChainEntry sInitChain[] = {
|
||||
static InitChainEntry D_808F890C[] = {
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_U8(targetMode, 2, ICHAIN_CONTINUE),
|
||||
ICHAIN_VEC3F_DIV1000(scale, 10, ICHAIN_STOP),
|
||||
ICHAIN_VEC3F_DIV1000(scale, 1000 * BOMBCHU_SCALE, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
#endif
|
||||
static EffectBlureInit2 sBlureInit = {
|
||||
0, 0, 0, { 250, 0, 0, 250 }, { 200, 0, 0, 130 }, { 150, 0, 0, 100 }, { 100, 0, 0, 50 }, 16,
|
||||
0, 0, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
extern ColliderSphereInit D_808F88E0;
|
||||
extern InitChainEntry D_808F890C[];
|
||||
void EnBomChu_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBomChu* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/EnBomChu_Init.s")
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
Collider_InitAndSetSphere(globalCtx, &this->collider, &this->actor, &sSphereInit);
|
||||
this->collider.dim.worldSphere.radius = sSphereInit.dim.modelSphere.radius;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/EnBomChu_Destroy.s")
|
||||
Effect_Add(globalCtx, &this->blure1Index, EFFECT_BLURE2, 0, 0, &sBlureInit);
|
||||
Effect_Add(globalCtx, &this->blure2Index, EFFECT_BLURE2, 0, 0, &sBlureInit);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F75D0.s")
|
||||
this->timer = 120;
|
||||
this->actor.room = -1;
|
||||
this->shouldTimerCountDown = true;
|
||||
this->unk_174 = 0.0f;
|
||||
this->actionFunc = EnBomChu_WaitForRelease;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F77E4.s")
|
||||
void EnBomChu_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBomChu* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7868.s")
|
||||
Effect_Destroy(globalCtx, this->blure1Index);
|
||||
Effect_Destroy(globalCtx, this->blure2Index);
|
||||
Collider_DestroySphere(globalCtx, &this->collider);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7944.s")
|
||||
/**
|
||||
* Returns true if floorPoly is valid for the Bombchu to move on, false otherwise.
|
||||
*/
|
||||
s32 EnBomChu_UpdateFloorPoly(EnBomChu* this, CollisionPoly* floorPoly, GlobalContext* globalCtx) {
|
||||
Vec3f normal;
|
||||
Vec3f vec;
|
||||
f32 angle;
|
||||
f32 magnitude;
|
||||
f32 normDotUp;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F79D4.s")
|
||||
this->actor.floorPoly = floorPoly;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7A84.s")
|
||||
// This NULL check means if the player releases a Bombchu with no collision
|
||||
// below them, the game will not crash, unlike OoT.
|
||||
if (floorPoly != NULL) {
|
||||
normal.x = COLPOLY_GET_NORMAL(floorPoly->normal.x);
|
||||
normal.y = COLPOLY_GET_NORMAL(floorPoly->normal.y);
|
||||
normal.z = COLPOLY_GET_NORMAL(floorPoly->normal.z);
|
||||
} else {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7E74.s")
|
||||
normDotUp = DOTXYZ(normal, this->axisUp);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7FA0.s")
|
||||
if (fabsf(normDotUp) >= 0.999f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F7FD0.s")
|
||||
angle = func_80086C48(normDotUp);
|
||||
if (angle < 0.001f) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F8080.s")
|
||||
Math3D_CrossProduct(&this->axisUp, &normal, &vec);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/func_808F818C.s")
|
||||
magnitude = Math3D_Vec3fMagnitude(&vec);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/EnBomChu_Update.s")
|
||||
if (magnitude < 0.001f) {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Bom_Chu/EnBomChu_Draw.s")
|
||||
Math_Vec3f_Scale(&vec, 1.0f / magnitude);
|
||||
Matrix_InsertRotationAroundUnitVector_f(angle, &vec, MTXMODE_NEW);
|
||||
Matrix_MultiplyVector3fByState(&this->axisLeft, &vec);
|
||||
Math_Vec3f_Copy(&this->axisLeft, &vec);
|
||||
Math3D_CrossProduct(&this->axisLeft, &normal, &this->axisForwards);
|
||||
|
||||
magnitude = Math3D_Vec3fMagnitude(&this->axisForwards);
|
||||
if (magnitude < 0.001f) {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
return false;
|
||||
}
|
||||
|
||||
Math_Vec3f_Scale(&this->axisForwards, 1.0f / magnitude);
|
||||
Math_Vec3f_Copy(&this->axisUp, &normal);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EnBomChu_UpdateRotation(EnBomChu* this) {
|
||||
MtxF mf;
|
||||
|
||||
mf.xx = this->axisLeft.x;
|
||||
mf.xy = this->axisLeft.y;
|
||||
mf.xz = this->axisLeft.z;
|
||||
|
||||
mf.yx = this->axisUp.x;
|
||||
mf.yy = this->axisUp.y;
|
||||
mf.yz = this->axisUp.z;
|
||||
|
||||
mf.zx = this->axisForwards.x;
|
||||
mf.zy = this->axisForwards.y;
|
||||
mf.zz = this->axisForwards.z;
|
||||
|
||||
func_8018219C(&mf, &this->actor.world.rot, 0);
|
||||
this->actor.world.rot.x = -this->actor.world.rot.x;
|
||||
}
|
||||
|
||||
void EnBomChu_WaitForRelease(EnBomChu* this, GlobalContext* globalCtx) {
|
||||
Player* player;
|
||||
|
||||
if (this->timer == 0) {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
} else if (Actor_HasNoParent(&this->actor, globalCtx)) {
|
||||
player = GET_PLAYER(globalCtx);
|
||||
Math_Vec3f_Copy(&this->actor.world.pos, &player->actor.world.pos);
|
||||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
|
||||
|
||||
this->actor.shape.rot.y = player->actor.shape.rot.y;
|
||||
this->actor.flags |= ACTOR_FLAG_1;
|
||||
func_800B8EF4(globalCtx, &this->actor);
|
||||
|
||||
this->isMoving = true;
|
||||
this->actor.speedXZ = 8.0f;
|
||||
this->movingSpeed = 8.0f;
|
||||
EnBomChu_SetupMove(this);
|
||||
}
|
||||
}
|
||||
|
||||
s32 EnBomChu_IsOnCollisionPoly(GlobalContext* globalCtx, Vec3f* posA, Vec3f* posB, Vec3f* posResult,
|
||||
CollisionPoly** poly, s32* bgId) {
|
||||
if ((BgCheck_EntityLineTest1(&globalCtx->colCtx, posA, posB, posResult, poly, true, true, true, true, bgId)) &&
|
||||
(!(func_800C9A4C(&globalCtx->colCtx, *poly, *bgId) & 0x30))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void EnBomChu_SetupMove(EnBomChu* this) {
|
||||
func_800BE3D0(&this->actor, this->actor.shape.rot.y, &this->actor.shape.rot);
|
||||
|
||||
Matrix_RotateY(this->actor.shape.rot.y, MTXMODE_NEW);
|
||||
Matrix_InsertXRotation_s(this->actor.shape.rot.x, MTXMODE_APPLY);
|
||||
Matrix_InsertZRotation_s(this->actor.shape.rot.z, MTXMODE_APPLY);
|
||||
|
||||
Matrix_GetStateTranslationAndScaledY(1.0f, &this->axisUp);
|
||||
Matrix_GetStateTranslationAndScaledZ(1.0f, &this->axisForwards);
|
||||
Matrix_GetStateTranslationAndScaledX(1.0f, &this->axisLeft);
|
||||
|
||||
this->actor.world.rot.x = -this->actor.shape.rot.x;
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
this->actor.world.rot.z = this->actor.shape.rot.z;
|
||||
this->actionFunc = EnBomChu_Move;
|
||||
}
|
||||
|
||||
void EnBomChu_Move(EnBomChu* this, GlobalContext* globalCtx) {
|
||||
CollisionPoly* polySide = NULL;
|
||||
CollisionPoly* polyUpDown = NULL;
|
||||
s32 bgIdSide;
|
||||
s32 bgIdUpDown;
|
||||
s32 i;
|
||||
s32 isFloorPolyValid;
|
||||
f32 lineLength;
|
||||
Vec3f posA;
|
||||
Vec3f posB;
|
||||
Vec3f posSide;
|
||||
Vec3f posUpDown;
|
||||
|
||||
bgIdUpDown = bgIdSide = BGCHECK_SCENE;
|
||||
isFloorPolyValid = false;
|
||||
|
||||
this->actor.speedXZ = this->movingSpeed;
|
||||
lineLength = 2.0f * this->movingSpeed;
|
||||
|
||||
if ((this->timer == 0) || (this->collider.base.acFlags & AC_HIT) || (this->collider.base.ocFlags1 & OC1_HIT)) {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
posA.x = this->actor.world.pos.x + (this->axisUp.x * 2.0f);
|
||||
posA.y = this->actor.world.pos.y + (this->axisUp.y * 2.0f);
|
||||
posA.z = this->actor.world.pos.z + (this->axisUp.z * 2.0f);
|
||||
|
||||
posB.x = this->actor.world.pos.x - (this->axisUp.x * 4.0f);
|
||||
posB.y = this->actor.world.pos.y - (this->axisUp.y * 4.0f);
|
||||
posB.z = this->actor.world.pos.z - (this->axisUp.z * 4.0f);
|
||||
|
||||
if (EnBomChu_IsOnCollisionPoly(globalCtx, &posA, &posB, &posUpDown, &polyUpDown, &bgIdUpDown)) {
|
||||
// forwards
|
||||
posB.x = (this->axisForwards.x * lineLength) + posA.x;
|
||||
posB.y = (this->axisForwards.y * lineLength) + posA.y;
|
||||
posB.z = (this->axisForwards.z * lineLength) + posA.z;
|
||||
|
||||
if (EnBomChu_IsOnCollisionPoly(globalCtx, &posA, &posB, &posSide, &polySide, &bgIdSide)) {
|
||||
isFloorPolyValid = EnBomChu_UpdateFloorPoly(this, polySide, globalCtx);
|
||||
Math_Vec3f_Copy(&this->actor.world.pos, &posSide);
|
||||
this->actor.floorBgId = bgIdSide;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
} else {
|
||||
if (this->actor.floorPoly != polyUpDown) {
|
||||
isFloorPolyValid = EnBomChu_UpdateFloorPoly(this, polyUpDown, globalCtx);
|
||||
}
|
||||
|
||||
Math_Vec3f_Copy(&this->actor.world.pos, &posUpDown);
|
||||
this->actor.floorBgId = bgIdUpDown;
|
||||
}
|
||||
} else {
|
||||
this->actor.speedXZ = 0.0f;
|
||||
lineLength *= 3.0f;
|
||||
Math_Vec3f_Copy(&posA, &posB);
|
||||
|
||||
for (i = 0; i < 3; i++) {
|
||||
if (i == 0) {
|
||||
// backwards
|
||||
posB.x = posA.x - (this->axisForwards.x * lineLength);
|
||||
posB.y = posA.y - (this->axisForwards.y * lineLength);
|
||||
posB.z = posA.z - (this->axisForwards.z * lineLength);
|
||||
} else if (i == 1) {
|
||||
// left
|
||||
posB.x = posA.x + (this->axisLeft.x * lineLength);
|
||||
posB.y = posA.y + (this->axisLeft.y * lineLength);
|
||||
posB.z = posA.z + (this->axisLeft.z * lineLength);
|
||||
} else {
|
||||
// right
|
||||
posB.x = posA.x - (this->axisLeft.x * lineLength);
|
||||
posB.y = posA.y - (this->axisLeft.y * lineLength);
|
||||
posB.z = posA.z - (this->axisLeft.z * lineLength);
|
||||
}
|
||||
|
||||
if (EnBomChu_IsOnCollisionPoly(globalCtx, &posA, &posB, &posSide, &polySide, &bgIdSide)) {
|
||||
isFloorPolyValid = EnBomChu_UpdateFloorPoly(this, polySide, globalCtx);
|
||||
Math_Vec3f_Copy(&this->actor.world.pos, &posSide);
|
||||
this->actor.floorBgId = bgIdSide;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 3) {
|
||||
// no collision nearby
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
if (isFloorPolyValid) {
|
||||
EnBomChu_UpdateRotation(this);
|
||||
this->actor.shape.rot.x = -this->actor.world.rot.x;
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
this->actor.shape.rot.z = this->actor.world.rot.z;
|
||||
}
|
||||
|
||||
if (this->isMoving) {
|
||||
func_800B8F98(&this->actor, NA_SE_IT_BOMBCHU_MOVE - SFX_FLAG);
|
||||
}
|
||||
|
||||
if (this->actor.speedXZ != 0.0f) {
|
||||
this->movingSpeed = this->actor.speedXZ;
|
||||
}
|
||||
}
|
||||
|
||||
void EnBomChu_Explode(EnBomChu* this, GlobalContext* globalCtx) {
|
||||
EnBom* bomb;
|
||||
s32 i;
|
||||
|
||||
bomb = (EnBom*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
|
||||
|
||||
this->shouldTimerCountDown = true;
|
||||
this->isMoving = false;
|
||||
|
||||
if (bomb != NULL) {
|
||||
bomb->timer = 0;
|
||||
}
|
||||
|
||||
this->timer = 1;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
|
||||
if (this->actor.depthInWater > 0.0f) {
|
||||
for (i = 0; i < 40; i++) {
|
||||
EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 1.0f, 5.0f, 30.0f, 0.25f);
|
||||
}
|
||||
}
|
||||
|
||||
this->actor.draw = NULL;
|
||||
this->actionFunc = EnBomChu_WaitForDeath;
|
||||
}
|
||||
|
||||
void EnBomChu_WaitForDeath(EnBomChu* this, GlobalContext* globalCtx) {
|
||||
if (this->timer == 0) {
|
||||
Actor_MarkForDeath(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform coordinates from actor coordinate space to world space, according to current orientation.
|
||||
* `offset` is expected to already be at world scale.
|
||||
*/
|
||||
void EnBomChu_ActorCoordsToWorld(EnBomChu* this, Vec3f* offset, Vec3f* pos) {
|
||||
f32 x = offset->x + this->visualJitter;
|
||||
|
||||
pos->x = this->actor.world.pos.x + (this->axisLeft.x * x) + (this->axisUp.x * offset->y) +
|
||||
(this->axisForwards.x * offset->z);
|
||||
pos->y = this->actor.world.pos.y + (this->axisLeft.y * x) + (this->axisUp.y * offset->y) +
|
||||
(this->axisForwards.y * offset->z);
|
||||
pos->z = this->actor.world.pos.z + (this->axisLeft.z * x) + (this->axisUp.z * offset->y) +
|
||||
(this->axisForwards.z * offset->z);
|
||||
}
|
||||
|
||||
void EnBomChu_SpawnRipplesAndSplashes(EnBomChu* this, GlobalContext* globalCtx, f32 y, s32 spawnExtraRipples) {
|
||||
s32 pad;
|
||||
Vec3f pos;
|
||||
|
||||
pos.x = this->actor.world.pos.x;
|
||||
pos.y = y;
|
||||
pos.z = this->actor.world.pos.z;
|
||||
|
||||
EffectSsGRipple_Spawn(globalCtx, &pos, 70, 500, 0);
|
||||
|
||||
if (spawnExtraRipples) {
|
||||
EffectSsGRipple_Spawn(globalCtx, &pos, 70, 500, 4);
|
||||
EffectSsGRipple_Spawn(globalCtx, &pos, 70, 500, 8);
|
||||
} else {
|
||||
pos.x -= this->axisForwards.x * 10.0f;
|
||||
pos.z -= this->axisForwards.z * 10.0f;
|
||||
}
|
||||
|
||||
pos.y += 5.0f;
|
||||
EffectSsGSplash_Spawn(globalCtx, &pos, NULL, NULL, 1, 450);
|
||||
}
|
||||
|
||||
void EnBomChu_HandleNonSceneCollision(EnBomChu* this, GlobalContext* globalCtx) {
|
||||
Vec3f originalWorldPos;
|
||||
Vec3f posA;
|
||||
Vec3f posB;
|
||||
Vec3f originalAxisUp;
|
||||
s16 yaw;
|
||||
f32 sin;
|
||||
f32 cos;
|
||||
f32 tempX;
|
||||
CollisionPoly* poly = NULL;
|
||||
s32 bgId = BGCHECK_SCENE;
|
||||
s32 isFloorPolyValid;
|
||||
|
||||
Math_Vec3f_Copy(&originalWorldPos, &this->actor.world.pos);
|
||||
Math_Vec3f_Copy(&originalAxisUp, &this->axisUp);
|
||||
yaw = this->actor.shape.rot.y;
|
||||
BgCheck2_UpdateActorAttachedToMesh(&globalCtx->colCtx, this->actor.floorBgId, &this->actor);
|
||||
|
||||
if (yaw != this->actor.shape.rot.y) {
|
||||
yaw = this->actor.shape.rot.y - yaw;
|
||||
|
||||
sin = Math_SinS(yaw);
|
||||
cos = Math_CosS(yaw);
|
||||
|
||||
tempX = this->axisForwards.x;
|
||||
this->axisForwards.x = (sin * this->axisForwards.z) + (cos * tempX);
|
||||
this->axisForwards.z = (cos * this->axisForwards.z) - (sin * tempX);
|
||||
|
||||
tempX = this->axisUp.x;
|
||||
this->axisUp.x = (sin * this->axisUp.z) + (cos * tempX);
|
||||
this->axisUp.z = (cos * this->axisUp.z) - (sin * tempX);
|
||||
|
||||
tempX = this->axisLeft.x;
|
||||
this->axisLeft.x = (sin * this->axisLeft.z) + (cos * tempX);
|
||||
this->axisLeft.z = (cos * this->axisLeft.z) - (sin * tempX);
|
||||
}
|
||||
|
||||
posA.x = originalWorldPos.x + (2.0f * originalAxisUp.x);
|
||||
posA.y = originalWorldPos.y + (2.0f * originalAxisUp.y);
|
||||
posA.z = originalWorldPos.z + (2.0f * originalAxisUp.z);
|
||||
|
||||
posB.x = this->actor.world.pos.x + (2.0f * this->axisUp.x);
|
||||
posB.y = this->actor.world.pos.y + (2.0f * this->axisUp.y);
|
||||
posB.z = this->actor.world.pos.z + (2.0f * this->axisUp.z);
|
||||
|
||||
if (EnBomChu_IsOnCollisionPoly(globalCtx, &posA, &posB, &originalWorldPos, &poly, &bgId)) {
|
||||
isFloorPolyValid = EnBomChu_UpdateFloorPoly(this, poly, globalCtx);
|
||||
Math_Vec3f_Copy(&this->actor.world.pos, &originalWorldPos);
|
||||
this->actor.floorBgId = bgId;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
|
||||
if (isFloorPolyValid) {
|
||||
EnBomChu_UpdateRotation(this);
|
||||
this->actor.shape.rot.x = -this->actor.world.rot.x;
|
||||
this->actor.shape.rot.y = this->actor.world.rot.y;
|
||||
this->actor.shape.rot.z = this->actor.world.rot.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnBomChu_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
static Vec3f sBlureP1Offset = { 0.0f, 7.0f, -6.0f };
|
||||
static Vec3f sBlureP2LeftOffset = { 12.0f, 0.0f, -5.0f };
|
||||
static Vec3f sBlureP2RightOffset = { -12.0f, 0.0f, -5.0f };
|
||||
s32 pad;
|
||||
EnBomChu* this = THIS;
|
||||
Vec3f blureP1;
|
||||
Vec3f blureP2;
|
||||
WaterBox* waterBox;
|
||||
f32 waterY;
|
||||
|
||||
if (this->actor.floorBgId != BGCHECK_SCENE) {
|
||||
EnBomChu_HandleNonSceneCollision(this, globalCtx);
|
||||
}
|
||||
|
||||
if (this->shouldTimerCountDown) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
this->actionFunc(this, globalCtx);
|
||||
|
||||
if ((this->actionFunc != EnBomChu_WaitForDeath) &&
|
||||
(SurfaceType_IsWallDamage(&globalCtx->colCtx, this->actor.floorPoly, this->actor.floorBgId))) {
|
||||
EnBomChu_Explode(this, globalCtx);
|
||||
return;
|
||||
}
|
||||
|
||||
Actor_MoveWithoutGravity(&this->actor);
|
||||
|
||||
this->collider.dim.worldSphere.center.x = this->actor.world.pos.x;
|
||||
this->collider.dim.worldSphere.center.y = this->actor.world.pos.y;
|
||||
this->collider.dim.worldSphere.center.z = this->actor.world.pos.z;
|
||||
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
if (this->actionFunc != EnBomChu_WaitForRelease) {
|
||||
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
|
||||
}
|
||||
|
||||
this->actor.focus.pos.x = this->actor.world.pos.x + (20.0f * this->axisUp.x);
|
||||
this->actor.focus.pos.y = this->actor.world.pos.y + (20.0f * this->axisUp.y);
|
||||
this->actor.focus.pos.z = this->actor.world.pos.z + (20.0f * this->axisUp.z);
|
||||
|
||||
if (this->isMoving) {
|
||||
this->visualJitter =
|
||||
(5.0f + (Rand_ZeroOne() * 3.0f)) * Math_SinS((((s32)(Rand_ZeroOne() * 512.0f) + 0x3000) * this->timer));
|
||||
EnBomChu_ActorCoordsToWorld(this, &sBlureP1Offset, &blureP1);
|
||||
|
||||
EnBomChu_ActorCoordsToWorld(this, &sBlureP2LeftOffset, &blureP2);
|
||||
EffectBlure_AddVertex(Effect_GetByIndex(this->blure1Index), &blureP1, &blureP2);
|
||||
|
||||
EnBomChu_ActorCoordsToWorld(this, &sBlureP2RightOffset, &blureP2);
|
||||
EffectBlure_AddVertex(Effect_GetByIndex(this->blure2Index), &blureP1, &blureP2);
|
||||
|
||||
waterY = this->actor.world.pos.y;
|
||||
|
||||
if (WaterBox_GetSurface1(globalCtx, &globalCtx->colCtx, this->actor.world.pos.x, this->actor.world.pos.z,
|
||||
&waterY, &waterBox)) {
|
||||
this->actor.depthInWater = waterY - this->actor.world.pos.y;
|
||||
|
||||
if (this->actor.depthInWater < 0.0f) {
|
||||
if (this->actor.bgCheckFlags & 0x20) {
|
||||
EnBomChu_SpawnRipplesAndSplashes(this, globalCtx, waterY, true);
|
||||
}
|
||||
|
||||
this->actor.bgCheckFlags &= ~0x20;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(this->actor.bgCheckFlags & 0x20) && (this->timer != 120)) {
|
||||
EnBomChu_SpawnRipplesAndSplashes(this, globalCtx, waterY, true);
|
||||
} else {
|
||||
EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 0.0f, 3.0f, 15.0f, 0.25f);
|
||||
}
|
||||
|
||||
this->actor.bgCheckFlags |= 0x20;
|
||||
} else {
|
||||
this->actor.bgCheckFlags &= ~0x20;
|
||||
this->actor.depthInWater = BGCHECK_Y_MIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnBomChu_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnBomChu* this = THIS;
|
||||
f32 colorIntensity;
|
||||
s32 blinkHalfPeriod;
|
||||
s32 blinkTime;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx);
|
||||
|
||||
func_8012C28C(globalCtx->state.gfxCtx);
|
||||
func_800B8050(&this->actor, globalCtx, 0);
|
||||
|
||||
if (this->timer >= 40) {
|
||||
blinkTime = this->timer % 20;
|
||||
blinkHalfPeriod = 10;
|
||||
} else if (this->timer >= 10) {
|
||||
blinkTime = this->timer % 10;
|
||||
blinkHalfPeriod = 5;
|
||||
} else {
|
||||
blinkTime = this->timer & 1;
|
||||
blinkHalfPeriod = 1;
|
||||
}
|
||||
|
||||
if (blinkTime > blinkHalfPeriod) {
|
||||
blinkTime = 2 * blinkHalfPeriod - blinkTime;
|
||||
}
|
||||
|
||||
colorIntensity = blinkTime / (f32)blinkHalfPeriod;
|
||||
gDPSetEnvColor(POLY_OPA_DISP++, (s32)(colorIntensity * 209.0f) + 9, (s32)(colorIntensity * 34.0f) + 9,
|
||||
(s32)(colorIntensity * -35.0f) + 35, 255);
|
||||
Matrix_InsertTranslation(this->visualJitter * (1.0f / BOMBCHU_SCALE), 0.0f, 0.0f, MTXMODE_APPLY);
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gBombchuDL);
|
||||
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,9 +8,21 @@ struct EnBomChu;
|
|||
typedef void (*EnBomChuActionFunc)(struct EnBomChu*, GlobalContext*);
|
||||
|
||||
typedef struct EnBomChu {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x0144 */ EnBomChuActionFunc actionFunc;
|
||||
/* 0x0148 */ char unk_148[0x98];
|
||||
/* 0x000 */ Actor actor;
|
||||
/* 0x144 */ EnBomChuActionFunc actionFunc;
|
||||
/* 0x148 */ u8 shouldTimerCountDown; // the actor always sets this to true
|
||||
/* 0x149 */ u8 isMoving;
|
||||
/* 0x14A */ s16 timer;
|
||||
/* 0x14C */ Vec3f axisForwards;
|
||||
/* 0x158 */ Vec3f axisUp;
|
||||
/* 0x164 */ Vec3f axisLeft;
|
||||
/* 0x170 */ f32 visualJitter;
|
||||
/* 0x174 */ f32 unk_174; // set but never used
|
||||
/* 0x178 */ UNK_TYPE1 unk_178[0x4];
|
||||
/* 0x17C */ f32 movingSpeed;
|
||||
/* 0x180 */ s32 blure1Index;
|
||||
/* 0x184 */ s32 blure2Index;
|
||||
/* 0x188 */ ColliderSphere collider;
|
||||
} EnBomChu; // size = 0x1E0
|
||||
|
||||
extern const ActorInit En_Bom_Chu_InitVars;
|
||||
|
|
|
|||
|
|
@ -6749,17 +6749,17 @@
|
|||
0x808F69B4:("EnIn_Draw",),
|
||||
0x808F74B0:("EnBomChu_Init",),
|
||||
0x808F7580:("EnBomChu_Destroy",),
|
||||
0x808F75D0:("func_808F75D0",),
|
||||
0x808F77E4:("func_808F77E4",),
|
||||
0x808F7868:("func_808F7868",),
|
||||
0x808F7944:("func_808F7944",),
|
||||
0x808F79D4:("func_808F79D4",),
|
||||
0x808F7A84:("func_808F7A84",),
|
||||
0x808F7E74:("func_808F7E74",),
|
||||
0x808F7FA0:("func_808F7FA0",),
|
||||
0x808F7FD0:("func_808F7FD0",),
|
||||
0x808F8080:("func_808F8080",),
|
||||
0x808F818C:("func_808F818C",),
|
||||
0x808F75D0:("EnBomChu_UpdateFloorPoly",),
|
||||
0x808F77E4:("EnBomChu_UpdateRotation",),
|
||||
0x808F7868:("EnBomChu_WaitForRelease",),
|
||||
0x808F7944:("EnBomChu_IsOnCollisionPoly",),
|
||||
0x808F79D4:("EnBomChu_SetupMove",),
|
||||
0x808F7A84:("EnBomChu_Move",),
|
||||
0x808F7E74:("EnBomChu_Explode",),
|
||||
0x808F7FA0:("EnBomChu_WaitForDeath",),
|
||||
0x808F7FD0:("EnBomChu_ActorCoordsToWorld",),
|
||||
0x808F8080:("EnBomChu_SpawnRipplesAndSplashes",),
|
||||
0x808F818C:("EnBomChu_HandleNonSceneCollision",),
|
||||
0x808F83B8:("EnBomChu_Update",),
|
||||
0x808F8714:("EnBomChu_Draw",),
|
||||
0x808F8AA0:("func_808F8AA0",),
|
||||
|
|
|
|||
Loading…
Reference in New Issue