mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
39cc86c260
subrepo: subdir: "soh" merged: "ba904bbd0" upstream: origin: "https://github.com/HarbourMasters/soh.git" branch: "master" commit: "ba904bbd0" git-subrepo: version: "0.4.1" origin: "???" commit: "???"
518 lines
18 KiB
C
518 lines
18 KiB
C
#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_4
|
|
|
|
#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 EnBomChu_WaitForRelease(EnBomChu* this, GlobalContext* globalCtx);
|
|
void EnBomChu_Move(EnBomChu* this, GlobalContext* globalCtx);
|
|
void EnBomChu_WaitForKill(EnBomChu* this, GlobalContext* globalCtx);
|
|
|
|
const ActorInit En_Bom_Chu_InitVars = {
|
|
ACTOR_EN_BOM_CHU,
|
|
ACTORCAT_EXPLOSIVE,
|
|
FLAGS,
|
|
OBJECT_GAMEPLAY_KEEP,
|
|
sizeof(EnBomChu),
|
|
(ActorFunc)EnBomChu_Init,
|
|
(ActorFunc)EnBomChu_Destroy,
|
|
(ActorFunc)EnBomChu_Update,
|
|
(ActorFunc)EnBomChu_Draw,
|
|
NULL,
|
|
};
|
|
|
|
static ColliderJntSphElementInit sJntSphElemInit[] = {
|
|
{
|
|
{
|
|
ELEMTYPE_UNK0,
|
|
{ 0x00000000, 0x00, 0x00 },
|
|
{ 0xFFCFFFFF, 0x00, 0x00 },
|
|
TOUCH_NONE,
|
|
BUMP_ON,
|
|
OCELEM_ON,
|
|
},
|
|
{ 1, { { 0, 0, 0 }, 12 }, 100 },
|
|
},
|
|
};
|
|
|
|
static ColliderJntSphInit sJntSphInit = {
|
|
{
|
|
COLTYPE_NONE,
|
|
AT_NONE,
|
|
AC_ON | AC_TYPE_PLAYER,
|
|
OC1_ON | OC1_TYPE_1 | OC1_TYPE_2,
|
|
OC2_TYPE_2,
|
|
COLSHAPE_JNTSPH,
|
|
},
|
|
ARRAY_COUNT(sJntSphElemInit),
|
|
sJntSphElemInit,
|
|
};
|
|
|
|
static InitChainEntry sInitChain[] = {
|
|
ICHAIN_U8(targetMode, 2, ICHAIN_CONTINUE),
|
|
ICHAIN_VEC3F_DIV1000(scale, 1000 * BOMBCHU_SCALE, ICHAIN_STOP),
|
|
};
|
|
|
|
void EnBomChu_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
static u8 p1StartColor[] = { 250, 0, 0, 250 };
|
|
static u8 p2StartColor[] = { 200, 0, 0, 130 };
|
|
static u8 p1EndColor[] = { 150, 0, 0, 100 };
|
|
static u8 p2EndColor[] = { 100, 0, 0, 50 };
|
|
EnBomChu* this = (EnBomChu*)thisx;
|
|
EffectBlureInit1 blureInit;
|
|
s32 i;
|
|
|
|
Actor_ProcessInitChain(&this->actor, sInitChain);
|
|
Collider_InitJntSph(globalCtx, &this->collider);
|
|
Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &sJntSphInit, this->colliderElements);
|
|
|
|
this->collider.elements[0].dim.worldSphere.radius = this->collider.elements[0].dim.modelSphere.radius;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
blureInit.p1StartColor[i] = p1StartColor[i];
|
|
blureInit.p2StartColor[i] = p2StartColor[i];
|
|
blureInit.p1EndColor[i] = p1EndColor[i];
|
|
blureInit.p2EndColor[i] = p2EndColor[i];
|
|
}
|
|
|
|
blureInit.elemDuration = 16;
|
|
blureInit.unkFlag = 0;
|
|
blureInit.calcMode = 0;
|
|
|
|
Effect_Add(globalCtx, &this->blure1Index, EFFECT_BLURE1, 0, 0, &blureInit);
|
|
Effect_Add(globalCtx, &this->blure2Index, EFFECT_BLURE1, 0, 0, &blureInit);
|
|
|
|
this->actor.room = -1;
|
|
this->timer = 120;
|
|
this->actionFunc = EnBomChu_WaitForRelease;
|
|
}
|
|
|
|
void EnBomChu_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
EnBomChu* this = (EnBomChu*)thisx;
|
|
|
|
Effect_Delete(globalCtx, this->blure1Index);
|
|
Effect_Delete(globalCtx, this->blure2Index);
|
|
Collider_DestroyJntSph(globalCtx, &this->collider);
|
|
}
|
|
|
|
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, BOMB_BODY);
|
|
if (bomb != NULL) {
|
|
bomb->timer = 0;
|
|
}
|
|
|
|
this->timer = 1;
|
|
this->actor.speedXZ = 0.0f;
|
|
|
|
if (this->actor.yDistToWater > 0.0f) {
|
|
for (i = 0; i < 40; i++) {
|
|
EffectSsBubble_Spawn(globalCtx, &this->actor.world.pos, 1.0f, 5.0f, 30.0f, 0.25f);
|
|
}
|
|
}
|
|
|
|
this->actionFunc = EnBomChu_WaitForKill;
|
|
}
|
|
|
|
void EnBomChu_CrossProduct(Vec3f* a, Vec3f* b, Vec3f* dest) {
|
|
dest->x = (a->y * b->z) - (a->z * b->y);
|
|
dest->y = (a->z * b->x) - (a->x * b->z);
|
|
dest->z = (a->x * b->y) - (a->y * b->x);
|
|
}
|
|
|
|
void EnBomChu_UpdateFloorPoly(EnBomChu* this, CollisionPoly* floorPoly, GlobalContext* globalCtx) {
|
|
Vec3f normal;
|
|
Vec3f vec;
|
|
f32 angle;
|
|
f32 magnitude;
|
|
f32 normDotUp;
|
|
MtxF mf;
|
|
|
|
this->actor.floorPoly = floorPoly;
|
|
|
|
normal.x = COLPOLY_GET_NORMAL(floorPoly->normal.x);
|
|
normal.y = COLPOLY_GET_NORMAL(floorPoly->normal.y);
|
|
normal.z = COLPOLY_GET_NORMAL(floorPoly->normal.z);
|
|
|
|
normDotUp = DOTXYZ(normal, this->axisUp);
|
|
|
|
if (!(fabsf(normDotUp) >= 1.0f)) {
|
|
angle = Math_FAcosF(normDotUp);
|
|
|
|
if (!(angle < 0.001f)) {
|
|
EnBomChu_CrossProduct(&this->axisUp, &normal, &vec);
|
|
//! @bug this function expects a unit vector but `vec` is not normalized
|
|
Matrix_RotateAxis(angle, &vec, MTXMODE_NEW);
|
|
|
|
Matrix_MultVec3f(&this->axisLeft, &vec);
|
|
this->axisLeft = vec;
|
|
|
|
EnBomChu_CrossProduct(&this->axisLeft, &normal, &this->axisForwards);
|
|
|
|
magnitude = Math3D_Vec3fMagnitude(&this->axisForwards);
|
|
|
|
if (magnitude < 0.001f) {
|
|
EnBomChu_Explode(this, globalCtx);
|
|
return;
|
|
}
|
|
|
|
this->axisForwards.x *= 1.0f / magnitude;
|
|
this->axisForwards.y *= 1.0f / magnitude;
|
|
this->axisForwards.z *= 1.0f / magnitude;
|
|
|
|
this->axisUp = normal;
|
|
|
|
if (1) {}
|
|
|
|
// mf = (axisLeft | axisUp | axisForwards)
|
|
|
|
mf.xx = this->axisLeft.x;
|
|
mf.yx = this->axisLeft.y;
|
|
mf.zx = this->axisLeft.z;
|
|
|
|
mf.xy = normal.x;
|
|
mf.yy = normal.y;
|
|
mf.zy = normal.z;
|
|
|
|
mf.xz = this->axisForwards.x;
|
|
mf.yz = this->axisForwards.y;
|
|
mf.zz = this->axisForwards.z;
|
|
|
|
Matrix_MtxFToYXZRotS(&mf, &this->actor.world.rot, 0);
|
|
|
|
// A hack for preventing bombchus from sticking to ledges.
|
|
// The visual rotation reverts the sign inversion (shape.rot.x = -world.rot.x).
|
|
// The better fix would be making func_8002D908 compute XYZ velocity better,
|
|
// or not using it and make the bombchu compute its own velocity.
|
|
this->actor.world.rot.x = -this->actor.world.rot.x;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnBomChu_WaitForRelease(EnBomChu* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
if (this->timer != 0) {
|
|
this->timer--;
|
|
}
|
|
|
|
if (this->timer == 0) {
|
|
EnBomChu_Explode(this, globalCtx);
|
|
return;
|
|
}
|
|
|
|
if (Actor_HasNoParent(&this->actor, globalCtx)) {
|
|
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;
|
|
|
|
// rot.y = 0 -> +z (forwards in model space)
|
|
this->axisForwards.x = Math_SinS(this->actor.shape.rot.y);
|
|
this->axisForwards.y = 0.0f;
|
|
this->axisForwards.z = Math_CosS(this->actor.shape.rot.y);
|
|
|
|
// +y (up in model space)
|
|
this->axisUp.x = 0.0f;
|
|
this->axisUp.y = 1.0f;
|
|
this->axisUp.z = 0.0f;
|
|
|
|
// rot.y = 0 -> +x (left in model space)
|
|
this->axisLeft.x = Math_SinS(this->actor.shape.rot.y + 0x4000);
|
|
this->axisLeft.y = 0;
|
|
this->axisLeft.z = Math_CosS(this->actor.shape.rot.y + 0x4000);
|
|
|
|
this->actor.speedXZ = 8.0f;
|
|
//! @bug there is no NULL check on the floor poly. If the player is out of bounds the floor poly will be NULL
|
|
//! and will cause a crash inside this function.
|
|
EnBomChu_UpdateFloorPoly(this, this->actor.floorPoly, globalCtx);
|
|
this->actor.flags |= ACTOR_FLAG_0; // make chu targetable
|
|
func_8002F850(globalCtx, &this->actor);
|
|
this->actionFunc = EnBomChu_Move;
|
|
}
|
|
}
|
|
|
|
void EnBomChu_Move(EnBomChu* this, GlobalContext* globalCtx) {
|
|
CollisionPoly* polySide;
|
|
CollisionPoly* polyUpDown;
|
|
s32 bgIdSide;
|
|
s32 bgIdUpDown;
|
|
s32 i;
|
|
f32 lineLength;
|
|
Vec3f posA;
|
|
Vec3f posB;
|
|
Vec3f posSide;
|
|
Vec3f posUpDown;
|
|
|
|
this->actor.speedXZ = 8.0f;
|
|
lineLength = this->actor.speedXZ * 2.0f;
|
|
|
|
if (this->timer != 0) {
|
|
this->timer--;
|
|
}
|
|
|
|
if ((this->timer == 0) || (this->collider.base.acFlags & AC_HIT) ||
|
|
((this->collider.base.ocFlags1 & OC1_HIT) && (this->collider.base.oc->category != ACTORCAT_PLAYER))) {
|
|
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 (BgCheck_EntityLineTest1(&globalCtx->colCtx, &posA, &posB, &posUpDown, &polyUpDown, true, true, true, true,
|
|
&bgIdUpDown) &&
|
|
!(func_80041DB8(&globalCtx->colCtx, polyUpDown, bgIdUpDown) & 0x30) && // && not crawl space?
|
|
!SurfaceType_IsIgnoredByProjectiles(&globalCtx->colCtx, 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 (BgCheck_EntityLineTest1(&globalCtx->colCtx, &posA, &posB, &posSide, &polySide, true, true, true, true,
|
|
&bgIdSide) &&
|
|
!(func_80041DB8(&globalCtx->colCtx, polySide, bgIdSide) & 0x30) &&
|
|
!SurfaceType_IsIgnoredByProjectiles(&globalCtx->colCtx, polySide, bgIdSide)) {
|
|
EnBomChu_UpdateFloorPoly(this, polySide, globalCtx);
|
|
this->actor.world.pos = posSide;
|
|
this->actor.floorBgId = bgIdSide;
|
|
this->actor.speedXZ = 0.0f;
|
|
} else {
|
|
if (this->actor.floorPoly != polyUpDown) {
|
|
EnBomChu_UpdateFloorPoly(this, polyUpDown, globalCtx);
|
|
}
|
|
|
|
this->actor.world.pos = posUpDown;
|
|
this->actor.floorBgId = bgIdUpDown;
|
|
}
|
|
} else {
|
|
this->actor.speedXZ = 0.0f;
|
|
lineLength *= 3.0f;
|
|
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 (BgCheck_EntityLineTest1(&globalCtx->colCtx, &posA, &posB, &posSide, &polySide, true, true, true, true,
|
|
&bgIdSide) &&
|
|
!(func_80041DB8(&globalCtx->colCtx, polySide, bgIdSide) & 0x30) &&
|
|
!SurfaceType_IsIgnoredByProjectiles(&globalCtx->colCtx, polySide, bgIdSide)) {
|
|
EnBomChu_UpdateFloorPoly(this, polySide, globalCtx);
|
|
this->actor.world.pos = posSide;
|
|
this->actor.floorBgId = bgIdSide;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i == 3) {
|
|
// no collision nearby
|
|
EnBomChu_Explode(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
Math_ScaledStepToS(&this->actor.shape.rot.x, -this->actor.world.rot.x, 0x800);
|
|
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.world.rot.y, 0x800);
|
|
Math_ScaledStepToS(&this->actor.shape.rot.z, this->actor.world.rot.z, 0x800);
|
|
|
|
func_8002F8F0(&this->actor, NA_SE_IT_BOMBCHU_MOVE - SFX_FLAG);
|
|
}
|
|
|
|
void EnBomChu_WaitForKill(EnBomChu* this, GlobalContext* globalCtx) {
|
|
if (this->timer != 0) {
|
|
this->timer--;
|
|
}
|
|
|
|
if (this->timer == 0) {
|
|
Actor_Kill(&this->actor);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Transform coordinates from model space to world space, according to current orientation.
|
|
* `posModel` is expected to already be at world scale (1/100 compared to model scale)
|
|
*/
|
|
void EnBomChu_ModelToWorld(EnBomChu* this, Vec3f* posModel, Vec3f* dest) {
|
|
f32 x = posModel->x + this->visualJitter;
|
|
|
|
dest->x = this->actor.world.pos.x + (this->axisLeft.x * x) + (this->axisUp.x * posModel->y) +
|
|
(this->axisForwards.x * posModel->z);
|
|
dest->y = this->actor.world.pos.y + (this->axisLeft.y * x) + (this->axisUp.y * posModel->y) +
|
|
(this->axisForwards.y * posModel->z);
|
|
dest->z = this->actor.world.pos.z + (this->axisLeft.z * x) + (this->axisUp.z * posModel->y) +
|
|
(this->axisForwards.z * posModel->z);
|
|
}
|
|
|
|
void EnBomChu_SpawnRipples(EnBomChu* this, GlobalContext* globalCtx, f32 y) {
|
|
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);
|
|
EffectSsGRipple_Spawn(globalCtx, &pos, 70, 500, 4);
|
|
EffectSsGRipple_Spawn(globalCtx, &pos, 70, 500, 8);
|
|
}
|
|
|
|
void EnBomChu_Update(Actor* thisx, GlobalContext* globalCtx2) {
|
|
static Vec3f blureP1Model = { 0.0f, 7.0f, -6.0f };
|
|
static Vec3f blureP2LeftModel = { 12.0f, 0.0f, -5.0f };
|
|
static Vec3f blureP2RightModel = { -12.0f, 0.0f, -5.0f };
|
|
GlobalContext* globalCtx = globalCtx2;
|
|
EnBomChu* this = (EnBomChu*)thisx;
|
|
s16 yaw;
|
|
f32 sin;
|
|
f32 cos;
|
|
f32 tempX;
|
|
Vec3f blureP1;
|
|
Vec3f blureP2;
|
|
WaterBox* waterBox;
|
|
f32 waterY;
|
|
|
|
if (this->actor.floorBgId != BGCHECK_SCENE) {
|
|
yaw = this->actor.shape.rot.y;
|
|
func_800433A4(&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 = (this->axisForwards.z * sin) + (cos * tempX);
|
|
this->axisForwards.z = (this->axisForwards.z * cos) - (sin * tempX);
|
|
|
|
tempX = this->axisUp.x;
|
|
this->axisUp.x = (this->axisUp.z * sin) + (cos * tempX);
|
|
this->axisUp.z = (this->axisUp.z * cos) - (sin * tempX);
|
|
|
|
tempX = this->axisLeft.x;
|
|
this->axisLeft.x = (this->axisLeft.z * sin) + (cos * tempX);
|
|
this->axisLeft.z = (this->axisLeft.z * cos) - (sin * tempX);
|
|
}
|
|
}
|
|
|
|
this->actionFunc(this, globalCtx);
|
|
func_8002D97C(&this->actor);
|
|
|
|
this->collider.elements[0].dim.worldSphere.center.x = this->actor.world.pos.x;
|
|
this->collider.elements[0].dim.worldSphere.center.y = this->actor.world.pos.y;
|
|
this->collider.elements[0].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);
|
|
}
|
|
|
|
Actor_SetFocus(&this->actor, 0.0f);
|
|
|
|
if (this->actionFunc == EnBomChu_Move) {
|
|
this->visualJitter =
|
|
(5.0f + (Rand_ZeroOne() * 3.0f)) * Math_SinS(((Rand_ZeroOne() * (f32)0x200) + (f32)0x3000) * this->timer);
|
|
|
|
EnBomChu_ModelToWorld(this, &blureP1Model, &blureP1);
|
|
|
|
EnBomChu_ModelToWorld(this, &blureP2LeftModel, &blureP2);
|
|
EffectBlure_AddVertex(Effect_GetByIndex(this->blure1Index), &blureP1, &blureP2);
|
|
|
|
EnBomChu_ModelToWorld(this, &blureP2RightModel, &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.yDistToWater = waterY - this->actor.world.pos.y;
|
|
|
|
if (this->actor.yDistToWater < 0.0f) {
|
|
if (this->actor.bgCheckFlags & 0x20) {
|
|
EnBomChu_SpawnRipples(this, globalCtx, waterY);
|
|
}
|
|
|
|
this->actor.bgCheckFlags &= ~0x20;
|
|
} else {
|
|
if (!(this->actor.bgCheckFlags & 0x20) && (this->timer != 120)) {
|
|
EnBomChu_SpawnRipples(this, globalCtx, waterY);
|
|
} 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.yDistToWater = BGCHECK_Y_MIN;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnBomChu_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
EnBomChu* this = (EnBomChu*)thisx;
|
|
f32 colorIntensity;
|
|
s32 blinkHalfPeriod;
|
|
s32 blinkTime;
|
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_bom_chu.c", 921);
|
|
|
|
func_80093D18(globalCtx->state.gfxCtx);
|
|
func_8002EBCC(&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++, 9.0f + (colorIntensity * 209.0f), 9.0f + (colorIntensity * 34.0f),
|
|
35.0f + (colorIntensity * -35.0f), 255);
|
|
Matrix_Translate(this->visualJitter * (1.0f / BOMBCHU_SCALE), 0.0f, 0.0f, MTXMODE_APPLY);
|
|
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_bom_chu.c", 956),
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
gSPDisplayList(POLY_OPA_DISP++, gBombchuDL);
|
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_bom_chu.c", 961);
|
|
}
|