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: "???"
239 lines
8.7 KiB
C
239 lines
8.7 KiB
C
/*
|
|
* File: z_bg_ice_objects.c
|
|
* Overlay: ovl_Bg_Ice_Objects
|
|
* Description: Pushable ice block (Ice Cavern)
|
|
*/
|
|
|
|
#include "z_bg_ice_objects.h"
|
|
#include "objects/object_ice_objects/object_ice_objects.h"
|
|
|
|
#define FLAGS 0
|
|
|
|
void BgIceObjects_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
void BgIceObjects_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
void BgIceObjects_Update(Actor* thisx, GlobalContext* globalCtx);
|
|
void BgIceObjects_Draw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void BgIceObjects_Idle(BgIceObjects* this, GlobalContext* globalCtx);
|
|
void BgIceObjects_Slide(BgIceObjects* this, GlobalContext* globalCtx);
|
|
void BgIceObjects_Reset(BgIceObjects* this, GlobalContext* globalCtx);
|
|
void BgIceObjects_Stuck(BgIceObjects* this, GlobalContext* globalCtx);
|
|
|
|
static Color_RGBA8 sWhite = { 250, 250, 250, 255 };
|
|
static Color_RGBA8 sGray = { 180, 180, 180, 255 };
|
|
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
|
|
|
|
const ActorInit Bg_Ice_Objects_InitVars = {
|
|
ACTOR_BG_ICE_OBJECTS,
|
|
ACTORCAT_PROP,
|
|
FLAGS,
|
|
OBJECT_ICE_OBJECTS,
|
|
sizeof(BgIceObjects),
|
|
(ActorFunc)BgIceObjects_Init,
|
|
(ActorFunc)BgIceObjects_Destroy,
|
|
(ActorFunc)BgIceObjects_Update,
|
|
(ActorFunc)BgIceObjects_Draw,
|
|
NULL,
|
|
};
|
|
|
|
static InitChainEntry sInitChain[] = {
|
|
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
|
|
};
|
|
|
|
void BgIceObjects_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
BgIceObjects* this = (BgIceObjects*)thisx;
|
|
CollisionHeader* colHeader = NULL;
|
|
|
|
Actor_ProcessInitChain(&this->dyna.actor, sInitChain);
|
|
DynaPolyActor_Init(&this->dyna, DPM_UNK);
|
|
CollisionHeader_GetVirtual(&object_ice_objects_Col_0003F0, &colHeader);
|
|
Math_Vec3f_Copy(&this->targetPos, &this->dyna.actor.home.pos);
|
|
this->actionFunc = BgIceObjects_Idle;
|
|
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
|
|
this->dyna.actor.params = 0;
|
|
}
|
|
|
|
void BgIceObjects_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
BgIceObjects* this = (BgIceObjects*)thisx;
|
|
|
|
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
|
|
}
|
|
|
|
static s16 sXStarts[] = {
|
|
-1060, -1200, -1240, -1387, -1580, -1680, -1780,
|
|
};
|
|
static s16 sZStarts[] = {
|
|
-580, -660, -780, -820, -860, -900, -1087,
|
|
};
|
|
static s16 sZStops[7][2] = {
|
|
{ -580, -1087 }, { -780, -1260 }, { -340, -820 }, { -260, -1260 }, { -340, -860 }, { -660, -1260 }, { -340, -740 },
|
|
};
|
|
static s16 sXStops[7][2] = {
|
|
{ -860, -1580 }, { -1240, -1780 }, { -860, -1680 }, { -860, -1680 },
|
|
{ -1387, -1680 }, { -860, -1200 }, { -860, -1800 },
|
|
};
|
|
|
|
/*
|
|
* Checks which of the eight possible x and z positions the block is at,
|
|
* defaulting to the maximum x wall or minimum z wall. Each x and z position
|
|
* has only one possible wall or pit on each side of it.
|
|
*/
|
|
void BgIceObjects_SetNextTarget(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
s16 x16;
|
|
s16 z16 = 0; // needed to match
|
|
s32 i;
|
|
|
|
if ((this->dyna.unk_158 == 0) || (this->dyna.unk_158 == -0x8000)) {
|
|
x16 = this->dyna.actor.world.pos.x;
|
|
for (i = 0; i < 7; i++) {
|
|
if (x16 == sXStarts[i]) {
|
|
z16 = (this->dyna.unk_158 == 0) ? sZStops[i][0] : sZStops[i][1];
|
|
this->targetPos.z = z16;
|
|
return;
|
|
}
|
|
}
|
|
this->targetPos.z = (this->dyna.unk_158 == 0) ? -340 : -1260;
|
|
} else {
|
|
z16 = this->dyna.actor.world.pos.z;
|
|
for (i = 0; i < 7; i++) {
|
|
if (z16 == sZStarts[i]) {
|
|
x16 = (this->dyna.unk_158 == 0x4000) ? sXStops[i][0] : sXStops[i][1];
|
|
this->targetPos.x = x16;
|
|
return;
|
|
}
|
|
}
|
|
this->targetPos.x = (this->dyna.unk_158 == 0x4000) ? -860 : -1780;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Checks if the block has fallen into any of the pits.
|
|
*/
|
|
void BgIceObjects_CheckPits(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
Actor* thisx = &this->dyna.actor;
|
|
|
|
if ((thisx->velocity.y > 0.0f) || ((thisx->world.pos.x <= -1660.0f) && (thisx->world.pos.z <= -1060.0f)) ||
|
|
((thisx->world.pos.x <= -1580.0f) && (thisx->world.pos.z >= -420.0f)) ||
|
|
((thisx->world.pos.x >= -980.0f) && (thisx->world.pos.z <= -1180.0f)) ||
|
|
((thisx->world.pos.x >= -860.0f) && (thisx->world.pos.z >= -700.0f))) {
|
|
|
|
thisx->velocity.y += 1.0f;
|
|
if (Math_StepToF(&thisx->world.pos.y, -300.0f, thisx->velocity.y)) {
|
|
thisx->velocity.y = 0.0f;
|
|
thisx->world.pos.x = thisx->home.pos.x;
|
|
thisx->world.pos.y = thisx->home.pos.y - 60.0f;
|
|
thisx->world.pos.z = thisx->home.pos.z;
|
|
if (thisx->params != 0) {
|
|
func_8002DF54(globalCtx, thisx, 7);
|
|
}
|
|
this->actionFunc = BgIceObjects_Reset;
|
|
}
|
|
}
|
|
}
|
|
|
|
void BgIceObjects_Idle(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
Actor* thisx = &this->dyna.actor;
|
|
|
|
if (this->dyna.unk_150 != 0.0f) {
|
|
player->stateFlags2 &= ~0x10;
|
|
if ((this->dyna.unk_150 > 0.0f) && !Player_InCsMode(globalCtx)) {
|
|
BgIceObjects_SetNextTarget(this, globalCtx);
|
|
if (Actor_WorldDistXZToPoint(thisx, &this->targetPos) > 1.0f) {
|
|
thisx->flags |= ACTOR_FLAG_4;
|
|
func_8002DF54(globalCtx, thisx, 8);
|
|
thisx->params = 1;
|
|
this->actionFunc = BgIceObjects_Slide;
|
|
}
|
|
}
|
|
this->dyna.unk_150 = 0.0f;
|
|
}
|
|
if (thisx->velocity.y > 0.0f) {
|
|
BgIceObjects_CheckPits(this, globalCtx);
|
|
}
|
|
}
|
|
|
|
void BgIceObjects_Slide(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
s32 atTarget;
|
|
Vec3f pos;
|
|
Vec3f velocity;
|
|
f32 spread;
|
|
Actor* thisx = &this->dyna.actor;
|
|
|
|
Math_StepToF(&thisx->speedXZ, 10.0f, 0.5f);
|
|
atTarget = Math_StepToF(&thisx->world.pos.x, this->targetPos.x, thisx->speedXZ);
|
|
atTarget &= Math_StepToF(&thisx->world.pos.z, this->targetPos.z, thisx->speedXZ);
|
|
if (atTarget) {
|
|
thisx->speedXZ = 0.0f;
|
|
this->targetPos.x = thisx->world.pos.x;
|
|
this->targetPos.z = thisx->world.pos.z;
|
|
if (thisx->velocity.y <= 0.0f) {
|
|
thisx->flags &= ~ACTOR_FLAG_4;
|
|
}
|
|
thisx->params = 0;
|
|
func_8002DF54(globalCtx, thisx, 7);
|
|
Audio_PlayActorSound2(thisx, NA_SE_EV_BLOCK_BOUND);
|
|
if ((fabsf(thisx->world.pos.x + 1387.0f) < 1.0f) && (fabsf(thisx->world.pos.z + 260.0f) < 1.0f)) {
|
|
this->actionFunc = BgIceObjects_Stuck;
|
|
} else {
|
|
this->actionFunc = BgIceObjects_Idle;
|
|
}
|
|
} else if ((thisx->speedXZ > 6.0f) && (thisx->world.pos.y >= 0.0f)) {
|
|
spread = Rand_CenteredFloat(120.0f);
|
|
velocity.x = -(1.5f + Rand_ZeroOne()) * Math_SinS(this->dyna.unk_158);
|
|
velocity.y = Rand_ZeroOne() + 1.0f;
|
|
velocity.z = -(1.5f + Rand_ZeroOne()) * Math_CosS(this->dyna.unk_158);
|
|
pos.x = thisx->world.pos.x - (60.0f * Math_SinS(this->dyna.unk_158)) - (Math_CosS(this->dyna.unk_158) * spread);
|
|
pos.z = thisx->world.pos.z - (60.0f * Math_CosS(this->dyna.unk_158)) + (Math_SinS(this->dyna.unk_158) * spread);
|
|
pos.y = thisx->world.pos.y;
|
|
func_8002829C(globalCtx, &pos, &velocity, &sZeroVec, &sWhite, &sGray, 250, Rand_S16Offset(40, 15));
|
|
spread = Rand_CenteredFloat(120.0f);
|
|
pos.x = thisx->world.pos.x - (60.0f * Math_SinS(this->dyna.unk_158)) + (Math_CosS(this->dyna.unk_158) * spread);
|
|
pos.z = thisx->world.pos.z - (60.0f * Math_CosS(this->dyna.unk_158)) - (Math_SinS(this->dyna.unk_158) * spread);
|
|
func_8002829C(globalCtx, &pos, &velocity, &sZeroVec, &sWhite, &sGray, 250, Rand_S16Offset(40, 15));
|
|
func_8002F974(thisx, NA_SE_PL_SLIP_ICE_LEVEL - SFX_FLAG);
|
|
}
|
|
BgIceObjects_CheckPits(this, globalCtx);
|
|
}
|
|
|
|
void BgIceObjects_Reset(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
Actor* thisx = &this->dyna.actor;
|
|
|
|
if (this->dyna.unk_150 != 0.0f) {
|
|
player->stateFlags2 &= ~0x10;
|
|
this->dyna.unk_150 = 0.0f;
|
|
}
|
|
if (Math_StepToF(&thisx->world.pos.y, thisx->home.pos.y, 1.0f)) {
|
|
thisx->flags &= ~ACTOR_FLAG_4;
|
|
Math_Vec3f_Copy(&this->targetPos, &thisx->home.pos);
|
|
this->actionFunc = BgIceObjects_Idle;
|
|
thisx->speedXZ = 0.0f;
|
|
}
|
|
}
|
|
|
|
void BgIceObjects_Stuck(BgIceObjects* this, GlobalContext* globalCtx) {
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
if (this->dyna.unk_150 != 0.0f) {
|
|
player->stateFlags2 &= ~0x10;
|
|
this->dyna.unk_150 = 0.0f;
|
|
}
|
|
}
|
|
|
|
void BgIceObjects_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
BgIceObjects* this = (BgIceObjects*)thisx;
|
|
|
|
this->actionFunc(this, globalCtx);
|
|
}
|
|
|
|
void BgIceObjects_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|
s32 pad;
|
|
BgIceObjects* this = (BgIceObjects*)thisx;
|
|
|
|
Gfx_DrawDListOpa(globalCtx, object_ice_objects_DL_000190);
|
|
}
|