Shipwright/soh/src/overlays/actors/ovl_Bg_Mizu_Water/z_bg_mizu_water.c

349 lines
13 KiB
C

/*
* File: z_bg_mizu_water.c
* Overlay: ovl_Bg_Mizu_Water
* Description: Water plane in Water Temple. Changes height based on switches 0x1C, 0x1D, 0x1E.
*/
#include "z_bg_mizu_water.h"
#include "objects/object_mizu_objects/object_mizu_objects.h"
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
void BgMizuWater_Init(Actor* thisx, GlobalContext* globalCtx);
void BgMizuWater_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BgMizuWater_Update(Actor* thisx, GlobalContext* globalCtx);
void BgMizuWater_Draw(Actor* thisx, GlobalContext* globalCtx);
void BgMizuWater_WaitForAction(BgMizuWater* this, GlobalContext* globalCtx);
void BgMizuWater_ChangeWaterLevel(BgMizuWater* this, GlobalContext* globalCtx);
typedef struct {
s32 switchFlag;
s32 yDiff;
} WaterLevel;
static WaterLevel sWaterLevels[] = {
{ 0x00, 0 },
{ WATER_TEMPLE_WATER_F3_FLAG, 0 },
{ WATER_TEMPLE_WATER_F2_FLAG, WATER_TEMPLE_WATER_F2_Y - WATER_TEMPLE_WATER_F3_Y },
{ WATER_TEMPLE_WATER_F1_FLAG, WATER_TEMPLE_WATER_F1_Y - WATER_TEMPLE_WATER_F3_Y },
};
const ActorInit Bg_Mizu_Water_InitVars = {
ACTOR_BG_MIZU_WATER,
ACTORCAT_BG,
FLAGS,
OBJECT_MIZU_OBJECTS,
sizeof(BgMizuWater),
(ActorFunc)BgMizuWater_Init,
(ActorFunc)BgMizuWater_Destroy,
(ActorFunc)BgMizuWater_Update,
(ActorFunc)BgMizuWater_Draw,
NULL,
};
static f32 sUnused1 = 0;
static f32 sUnused2 = 110.0f;
static u32 sWaterBoxIndexes[] = { 2, 3, 5, 7, 12, 20, 21, 22 };
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F(scale, 1, ICHAIN_STOP),
};
u32 BgMizuWater_GetWaterLevelActionIndex(s16 switchFlag, GlobalContext* globalCtx) {
u32 ret;
if (bREG(0) != 0) {
switch (bREG(1)) {
case 0:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG);
break;
case 1:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG);
break;
case 2:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG);
break;
}
bREG(0) = 0;
}
if (Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG) && (switchFlag != WATER_TEMPLE_WATER_F1_FLAG)) {
ret = 3;
} else if (Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG) && (switchFlag != WATER_TEMPLE_WATER_F2_FLAG)) {
ret = 2;
} else if (Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG) && (switchFlag != WATER_TEMPLE_WATER_F3_FLAG)) {
ret = 1;
} else {
ret = 0;
}
return ret;
}
void BgMizuWater_SetWaterBoxesHeight(WaterBox* waterBoxes, s16 height) {
u32 i;
for (i = 0; i < 8; i++) {
waterBoxes[sWaterBoxIndexes[i]].ySurface = height;
}
}
void BgMizuWater_Init(Actor* thisx, GlobalContext* globalCtx) {
BgMizuWater* this = (BgMizuWater*)thisx;
f32 initialActorY;
WaterBox* waterBoxes;
s32 waterLevelActionIndex;
waterBoxes = globalCtx->colCtx.colHeader->waterBoxes;
this->type = this->actor.params & 0xFF;
this->switchFlag = (this->actor.params >> 8) & 0xFF;
Actor_ProcessInitChain(&this->actor, sInitChain);
initialActorY = this->actor.world.pos.y;
this->baseY = initialActorY;
this->targetY = initialActorY;
switch (this->type) {
case 0:
if (bREG(15) == 0) {
osSyncPrintf("<コンストラクト>%x %x %x\n", Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG),
Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG),
Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG));
}
waterLevelActionIndex = BgMizuWater_GetWaterLevelActionIndex(-1, globalCtx);
this->actor.world.pos.y = sWaterLevels[waterLevelActionIndex].yDiff + this->baseY;
BgMizuWater_SetWaterBoxesHeight(waterBoxes, this->actor.world.pos.y);
this->actor.params = sWaterLevels[waterLevelActionIndex].switchFlag;
Flags_UnsetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG);
Flags_UnsetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG);
Flags_UnsetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG);
switch (this->actor.params) {
case 0x1E:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG);
break;
case 0x1D:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG);
break;
case 0x1C:
default:
Flags_SetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG);
break;
}
this->targetY = this->actor.world.pos.y;
break;
case 1:
break;
case 2:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->actor.world.pos.y = this->baseY + 85.0f;
}
waterBoxes[6].ySurface = this->actor.world.pos.y;
break;
case 3:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->actor.world.pos.y = this->baseY + 110.0f;
this->targetY = this->actor.world.pos.y;
}
waterBoxes[8].ySurface = this->actor.world.pos.y;
break;
case 4:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->actor.world.pos.y = this->baseY + 160.0f;
this->targetY = this->actor.world.pos.y;
}
waterBoxes[16].ySurface = this->actor.world.pos.y;
break;
}
this->actionFunc = BgMizuWater_WaitForAction;
}
void BgMizuWater_Destroy(Actor* thisx, GlobalContext* globalCtx) {
}
void BgMizuWater_WaitForAction(BgMizuWater* this, GlobalContext* globalCtx) {
s32 pad;
s32 waterLevelActionIndex;
s16 prevSwitchFlag;
switch (this->type) {
case 0:
prevSwitchFlag = this->actor.params;
waterLevelActionIndex = BgMizuWater_GetWaterLevelActionIndex(this->actor.params, globalCtx);
if (waterLevelActionIndex != 0) {
if (prevSwitchFlag != sWaterLevels[waterLevelActionIndex].switchFlag) {
OnePointCutscene_Init(globalCtx, 3120, -100 - waterLevelActionIndex, NULL, MAIN_CAM);
this->actor.params = sWaterLevels[waterLevelActionIndex].switchFlag;
this->targetY = sWaterLevels[waterLevelActionIndex].yDiff + this->baseY;
}
}
if ((prevSwitchFlag != this->actor.params) && (prevSwitchFlag != 0)) {
Flags_UnsetSwitch(globalCtx, prevSwitchFlag);
}
break;
case 1:
break;
case 2:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 85.0f;
} else {
this->targetY = this->baseY;
}
break;
case 3:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 110.0f;
} else {
this->targetY = this->baseY;
}
break;
case 4:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 160.0f;
} else {
this->targetY = this->baseY;
}
}
if (this->targetY != this->actor.world.pos.y) {
this->actionFunc = BgMizuWater_ChangeWaterLevel;
}
}
void BgMizuWater_ChangeWaterLevel(BgMizuWater* this, GlobalContext* globalCtx) {
s32 pad;
s16 prevSwitchFlag;
s32 waterLevelActionIndex;
WaterBox* waterBoxes;
waterBoxes = globalCtx->colCtx.colHeader->waterBoxes;
switch (this->type) {
case 0:
prevSwitchFlag = this->actor.params;
waterLevelActionIndex = BgMizuWater_GetWaterLevelActionIndex(this->actor.params, globalCtx);
if (waterLevelActionIndex != 0) {
if (prevSwitchFlag != sWaterLevels[waterLevelActionIndex].switchFlag) {
this->actor.params = sWaterLevels[waterLevelActionIndex].switchFlag;
this->targetY = sWaterLevels[waterLevelActionIndex].yDiff + this->baseY;
}
}
if ((prevSwitchFlag != this->actor.params) && (prevSwitchFlag != 0)) {
Flags_UnsetSwitch(globalCtx, prevSwitchFlag);
}
if (Math_StepToF(&this->actor.world.pos.y, this->targetY, 5.0f)) {
globalCtx->roomCtx.unk_74[0] = 0;
this->actionFunc = BgMizuWater_WaitForAction;
Message_CloseTextbox(globalCtx);
}
BgMizuWater_SetWaterBoxesHeight(globalCtx->colCtx.colHeader->waterBoxes, this->actor.world.pos.y);
break;
case 1:
break;
case 2:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 85.0f;
} else {
this->targetY = this->baseY;
}
if (Math_StepToF(&this->actor.world.pos.y, this->targetY, 1.0f)) {
globalCtx->roomCtx.unk_74[0] = 0;
this->actionFunc = BgMizuWater_WaitForAction;
}
waterBoxes[6].ySurface = this->actor.world.pos.y;
break;
case 3:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 110.0f;
} else {
this->targetY = this->baseY;
}
if (Math_StepToF(&this->actor.world.pos.y, this->targetY, 1.0f)) {
globalCtx->roomCtx.unk_74[0] = 0;
this->actionFunc = BgMizuWater_WaitForAction;
}
waterBoxes[8].ySurface = this->actor.world.pos.y;
break;
case 4:
if (Flags_GetSwitch(globalCtx, this->switchFlag)) {
this->targetY = this->baseY + 160.0f;
} else {
this->targetY = this->baseY;
}
if (Math_StepToF(&this->actor.world.pos.y, this->targetY, 1.0f)) {
globalCtx->roomCtx.unk_74[0] = 0;
this->actionFunc = BgMizuWater_WaitForAction;
}
waterBoxes[16].ySurface = this->actor.world.pos.y;
break;
}
if (this->targetY < this->actor.world.pos.y) {
func_800AA000(0.0f, 0x78, 0x14, 0xA);
func_8002F948(&this->actor, NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
} else if (this->targetY > this->actor.world.pos.y) {
func_800AA000(0.0f, 0x78, 0x14, 0xA);
func_8002F948(&this->actor, NA_SE_EV_WATER_LEVEL_DOWN - SFX_FLAG);
}
}
void BgMizuWater_Update(Actor* thisx, GlobalContext* globalCtx) {
BgMizuWater* this = (BgMizuWater*)thisx;
s32 posY;
s32 unk0;
s32 unk1;
s32 pad;
if (bREG(15) == 0) {
osSyncPrintf("%x %x %x\n", Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F1_FLAG),
Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F2_FLAG),
Flags_GetSwitch(globalCtx, WATER_TEMPLE_WATER_F3_FLAG));
}
if (this->type == 0) {
posY = this->actor.world.pos.y;
unk0 = 0;
unk1 = 0;
if (posY < WATER_TEMPLE_WATER_F1_Y) {
unk0 = 0;
unk1 = (posY - WATER_TEMPLE_WATER_B1_Y) / (WATER_TEMPLE_WATER_F1_Y - WATER_TEMPLE_WATER_B1_Y) * 200;
} else if (posY < WATER_TEMPLE_WATER_F2_Y) {
unk0 = 1;
unk1 = 255 - (s32)((posY - WATER_TEMPLE_WATER_F1_Y) / (WATER_TEMPLE_WATER_F2_Y - WATER_TEMPLE_WATER_F1_Y) *
(255 - 160));
} else if (posY <= WATER_TEMPLE_WATER_F3_Y) {
unk0 = 2;
unk1 = 255 - (s32)((posY - WATER_TEMPLE_WATER_F2_Y) / (WATER_TEMPLE_WATER_F3_Y - WATER_TEMPLE_WATER_F2_Y) *
(255 - 160));
}
globalCtx->roomCtx.unk_74[1] = ((u8)unk0 << 8) | (unk1 & 0xFF);
}
this->actionFunc(this, globalCtx);
}
void BgMizuWater_Draw(Actor* thisx, GlobalContext* globalCtx) {
BgMizuWater* this = (BgMizuWater*)thisx;
s32 gameplayFrames;
OPEN_DISPS(globalCtx->state.gfxCtx);
gameplayFrames = globalCtx->gameplayFrames;
func_80093D84(globalCtx->state.gfxCtx);
gSPSegment(POLY_XLU_DISP++, 0x0C,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, -gameplayFrames * 1, gameplayFrames * 1, 32, 32, 1, 0,
-gameplayFrames * 1, 32, 32));
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 102);
gSPDisplayList(POLY_XLU_DISP++, gObjectMizuObjectsWaterDL_004B20);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}