From e4010be70ca17b4146d9332293b6d628e16e8189 Mon Sep 17 00:00:00 2001 From: Maide <34639600+Kelebek1@users.noreply.github.com> Date: Sun, 30 Jan 2022 01:00:43 +0000 Subject: [PATCH] Obj_Oshihiki (#636) --- include/functions.h | 2 +- spec | 3 +- .../actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c | 575 ++++++++++++++++-- .../actors/ovl_Obj_Oshihiki/z_obj_oshihiki.h | 52 +- .../actors/ovl_Obj_Switch/z_obj_switch.h | 6 + tools/disasm/functions.txt | 48 +- 6 files changed, 622 insertions(+), 64 deletions(-) diff --git a/include/functions.h b/include/functions.h index 7465d4dda5..016a87e09e 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2062,7 +2062,7 @@ void func_80123DA4(Player* player); void func_80123E90(GlobalContext* globalCtx, Actor* actor); void func_80123F2C(GlobalContext* globalCtx, s32 arg1); s32 func_80123F48(GlobalContext* globalCtx, Vec3f* arg1, f32 arg2, f32 arg3); -// void func_80124020(void); +s32 func_80124020(void); u8 Player_GetMask(GlobalContext* globalCtx); void Player_RemoveMask(GlobalContext* globalCtx); s32 func_8012405C(GlobalContext* globalCtx); diff --git a/spec b/spec index 7dc17a9c0e..f5a11b9d1a 100644 --- a/spec +++ b/spec @@ -1336,8 +1336,7 @@ beginseg name "ovl_Obj_Oshihiki" compress include "build/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.o" - include "build/data/ovl_Obj_Oshihiki/ovl_Obj_Oshihiki.data.o" - include "build/data/ovl_Obj_Oshihiki/ovl_Obj_Oshihiki.reloc.o" + include "build/src/overlays/actors/ovl_Obj_Oshihiki/ovl_Obj_Oshihiki_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c index 523cd7fb99..2d1149715f 100644 --- a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c +++ b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.c @@ -5,8 +5,10 @@ */ #include "z_obj_oshihiki.h" +#include "overlays/actors/ovl_Obj_Switch/z_obj_switch.h" +#include "objects/gameplay_dangeon_keep/gameplay_dangeon_keep.h" -#define FLAGS 0x00000010 +#define FLAGS (ACTOR_FLAG_10) #define THIS ((ObjOshihiki*)thisx) @@ -15,7 +17,14 @@ void ObjOshihiki_Destroy(Actor* thisx, GlobalContext* globalCtx); void ObjOshihiki_Update(Actor* thisx, GlobalContext* globalCtx); void ObjOshihiki_Draw(Actor* thisx, GlobalContext* globalCtx); -#if 0 +void ObjOshihiki_OnScene(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_SetupOnActor(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_OnActor(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_SetupPush(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_Push(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_SetupFall(ObjOshihiki* this, GlobalContext* globalCtx); +void ObjOshihiki_Fall(ObjOshihiki* this, GlobalContext* globalCtx); + const ActorInit Obj_Oshihiki_InitVars = { ACTOR_OBJ_OSHIHIKI, ACTORCAT_PROP, @@ -28,69 +37,567 @@ const ActorInit Obj_Oshihiki_InitVars = { (ActorFunc)ObjOshihiki_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_80918898[] = { +static f32 sScales[] = { 0.1f, 0.2f, 0.4f, 0.1f, 0.2f, 0.4f }; + +static Color_RGB8 sColors[] = { + { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, + { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 255 }, +}; + +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneScale, 500, ICHAIN_CONTINUE), ICHAIN_F32(uncullZoneDownward, 500, ICHAIN_STOP), }; -#endif +// The vertices and center of the bottom face +static Vec3f sColCheckPoints[] = { + { 29.99f, 1.01f, -29.99f }, { -29.99f, 1.01f, -29.99f }, { -29.99f, 1.01f, 29.99f }, + { 29.99f, 1.01f, 29.99f }, { 0.0f, 1.01f, 0.0f }, +}; -extern InitChainEntry D_80918898[]; +static Vec2f sFaceVtx[] = { + { -30.0f, 0.0f }, { 30.0f, 0.0f }, { -30.0f, 60.0f }, { 30.0f, 60.0f }, { -30.0f, 20.0f }, { 30.0f, 20.0f }, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917290.s") +static Vec2f sFaceDirection[] = { + { 1.0f, 1.0f }, { -1.0f, 1.0f }, { 1.0f, -1.0f }, { -1.0f, -1.0f }, { 1.0f, 3.0f }, { -1.0f, 3.0f }, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_809172E4.s") +s8 D_80918940[] = { 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_8091734C.s") +void ObjOshihiki_RotateXZ(Vec3f* out, Vec3f* in, f32 sn, f32 cs) { + out->x = (in->z * sn) + (in->x * cs); + out->y = in->y; + out->z = (in->z * cs) - (in->x * sn); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917378.s") +s32 ObjOshihiki_StrongEnough(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 strength = OBJOSHIHIKI_GET_F(&this->dyna.actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917408.s") + if (this->cantMove) { + return false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917538.s") + if ((strength == OBJOSHIHIKI_F_0) || (strength == OBJOSHIHIKI_F_3)) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917604.s") + if (func_80124020() >= 2) { + return true; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_8091763C.s") +void ObjOshihiki_ResetFloors(ObjOshihiki* this) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_8091768C.s") + for (i = 0; i < ARRAY_COUNT(this->floorBgIds); i++) { + this->floorBgIds[i] = BGCHECK_SCENE; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/ObjOshihiki_Init.s") +ObjOshihiki* ObjOshihiki_GetBlockUnder(ObjOshihiki* this, GlobalContext* globalCtx) { + DynaPolyActor* dyna; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/ObjOshihiki_Destroy.s") + if ((this->floorBgIds[this->highestFloor] != BGCHECK_SCENE) && + (fabsf(this->dyna.actor.floorHeight - this->dyna.actor.world.pos.y) < 0.001f)) { + dyna = DynaPoly_GetActor(&globalCtx->colCtx, this->floorBgIds[this->highestFloor]); + if ((dyna != NULL) && (dyna->actor.id == ACTOR_OBJ_OSHIHIKI)) { + return (ObjOshihiki*)dyna; + } + } + return NULL; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917840.s") +void ObjOshihiki_UpdateInitPos(ObjOshihiki* this) { + if (this->dyna.actor.home.pos.x < this->dyna.actor.world.pos.x) { + while ((this->dyna.actor.world.pos.x - this->dyna.actor.home.pos.x) >= 60.0f) { + this->dyna.actor.home.pos.x += 60.0f; + } + } else { + while ((this->dyna.actor.home.pos.x - this->dyna.actor.world.pos.x) >= 60.0f) { + this->dyna.actor.home.pos.x -= 60.0f; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_809179A0.s") + if (this->dyna.actor.home.pos.z < this->dyna.actor.world.pos.z) { + while ((this->dyna.actor.world.pos.z - this->dyna.actor.home.pos.z) >= 60.0f) { + this->dyna.actor.home.pos.z += 60.0f; + } + } else { + while ((this->dyna.actor.home.pos.z - this->dyna.actor.world.pos.z) >= 60.0f) { + this->dyna.actor.home.pos.z -= 60.0f; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917AEC.s") +s32 ObjOshihiki_NoSwitchPress(ObjOshihiki* this, DynaPolyActor* dyna, GlobalContext* globalCtx) { + s16 dynaSwitchFlag; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917B44.s") + if (dyna == NULL) { + return true; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917B9C.s") + if (dyna->actor.id == ACTOR_OBJ_SWITCH) { + dynaSwitchFlag = OBJSWITCH_GET_7F00(&dyna->actor); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917C14.s") + switch (OBJSWITCH_GET_33(&dyna->actor)) { + case OBJSWITCH_NORMAL_BLUE: + if ((dynaSwitchFlag == OBJOSHIHIKI_GET_7F00(&this->dyna.actor)) && + Flags_GetSwitch(globalCtx, dynaSwitchFlag)) { + return false; + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917E8C.s") + case OBJSWITCH_INVERSE_BLUE: + if ((dynaSwitchFlag == OBJOSHIHIKI_GET_7F00(&this->dyna.actor)) && + !Flags_GetSwitch(globalCtx, dynaSwitchFlag)) { + return false; + } + break; + } + } + return true; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917F88.s") +void ObjOshihiki_SetScale(ObjOshihiki* this, GlobalContext* globalCtx) { + Actor_SetScale(&this->dyna.actor, sScales[OBJOSHIHIKI_GET_F(&this->dyna.actor)]); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80917FC0.s") +void ObjOshihiki_SetTextureStep(ObjOshihiki* this, GlobalContext* globalCtx) { + switch (OBJOSHIHIKI_GET_F(&this->dyna.actor)) { + case OBJOSHIHIKI_F_0: + case OBJOSHIHIKI_F_3: + this->textureStep = 0; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_809180C8.s") + case OBJOSHIHIKI_F_1: + case OBJOSHIHIKI_F_4: + this->textureStep = 1; + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80918108.s") + case OBJOSHIHIKI_F_2: + case OBJOSHIHIKI_F_5: + this->textureStep = 2; + break; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80918314.s") +void ObjOshihiki_SetColor(ObjOshihiki* this, GlobalContext* globalCtx) { + Color_RGB8* src = &sColors[OBJOSHIHIKI_GET_F0(&this->dyna.actor)]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_8091834C.s") + this->color.r = src->r; + this->color.g = src->g; + this->color.b = src->b; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_8091851C.s") +void ObjOshihiki_Init(Actor* thisx, GlobalContext* globalCtx) { + ObjOshihiki* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/func_80918574.s") + DynaPolyActor_Init(&this->dyna, 1); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/ObjOshihiki_Update.s") + if ((OBJOSHIHIKI_GET_FF00(&this->dyna.actor) >= OBJOSHIHIKI_FF00_0) && + (OBJOSHIHIKI_GET_FF00(&this->dyna.actor) < OBJOSHIHIKI_FF00_80)) { + if (Flags_GetSwitch(globalCtx, OBJOSHIHIKI_GET_7F00(&this->dyna.actor))) { + switch (OBJOSHIHIKI_GET_F(&this->dyna.actor)) { + case OBJOSHIHIKI_F_0: + case OBJOSHIHIKI_F_1: + case OBJOSHIHIKI_F_2: + Actor_MarkForDeath(&this->dyna.actor); + return; + } + } else { + switch (OBJOSHIHIKI_GET_F(&this->dyna.actor)) { + case OBJOSHIHIKI_F_3: + case OBJOSHIHIKI_F_4: + case OBJOSHIHIKI_F_5: + Actor_MarkForDeath(&this->dyna.actor); + return; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Oshihiki/ObjOshihiki_Draw.s") + DynaPolyActor_LoadMesh(globalCtx, &this->dyna, &gameplay_dangeon_keep_Colheader_007498); + this->texture = Lib_SegmentedToVirtual(gameplay_dangeon_keep_Matanimheader_01B370); + ObjOshihiki_SetScale(this, globalCtx); + ObjOshihiki_SetTextureStep(this, globalCtx); + Actor_ProcessInitChain(&this->dyna.actor, sInitChain); + this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE; + ObjOshihiki_SetColor(this, globalCtx); + ObjOshihiki_ResetFloors(this); + ObjOshihiki_SetupOnActor(this, globalCtx); +} + +void ObjOshihiki_Destroy(Actor* thisx, GlobalContext* globalCtx) { + ObjOshihiki* this = THIS; + + DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId); +} + +void ObjOshihiki_SetFloors(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 pad; + Vec3f colCheckPoint; + Vec3f colCheckOffset; + s32 i; + + for (i = 0; i < ARRAY_COUNT(sColCheckPoints); i++) { + colCheckOffset.x = sColCheckPoints[i].x * (this->dyna.actor.scale.x * 10.0f); + colCheckOffset.y = sColCheckPoints[i].y * (this->dyna.actor.scale.y * 10.0f); + colCheckOffset.z = sColCheckPoints[i].z * (this->dyna.actor.scale.z * 10.0f); + + ObjOshihiki_RotateXZ(&colCheckPoint, &colCheckOffset, this->yawSin, this->yawCos); + + colCheckPoint.x += this->dyna.actor.world.pos.x; + colCheckPoint.y += this->dyna.actor.prevPos.y; + colCheckPoint.z += this->dyna.actor.world.pos.z; + + this->floorHeights[i] = BgCheck_EntityRaycastFloor6( + &globalCtx->colCtx, &this->floorPolys[i], &this->floorBgIds[i], &this->dyna.actor, &colCheckPoint, 0.0f); + } +} + +s16 ObjOshihiki_GetHighestFloor(ObjOshihiki* this) { + s32 i; + s16 highestFloor = 0; + + for (i = 1; i < ARRAY_COUNT(this->floorHeights); i++) { + if (this->floorHeights[i] > this->floorHeights[highestFloor]) { + highestFloor = i; + } else if ((this->floorBgIds[i] == BGCHECK_SCENE) && + ((this->floorHeights[i] - this->floorHeights[highestFloor]) > -0.001f)) { + highestFloor = i; + } + } + + return highestFloor; +} + +void ObjOshihiki_SetGround(ObjOshihiki* this, GlobalContext* globalCtx) { + ObjOshihiki_ResetFloors(this); + ObjOshihiki_SetFloors(this, globalCtx); + this->highestFloor = ObjOshihiki_GetHighestFloor(this); + this->dyna.actor.floorHeight = this->floorHeights[this->highestFloor]; +} + +s32 ObjOshihiki_CheckFloor(ObjOshihiki* this, GlobalContext* globalCtx) { + ObjOshihiki_SetGround(this, globalCtx); + + if ((this->dyna.actor.floorHeight - this->dyna.actor.world.pos.y) >= -0.001f) { + this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; + return true; + } + return false; +} + +s32 ObjOshihiki_CheckGround(ObjOshihiki* this, GlobalContext* globalCtx) { + if (this->dyna.actor.world.pos.y <= BGCHECK_Y_MIN + 10.0f) { + Actor_MarkForDeath(&this->dyna.actor); + return false; + } + + if ((this->dyna.actor.floorHeight - this->dyna.actor.world.pos.y) >= -0.001f) { + this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; + return true; + } + return false; +} + +s32 ObjOshihiki_CheckWall(GlobalContext* globalCtx, s16 angle, f32 direction, ObjOshihiki* this) { + f32 maxDists[2]; + f32 maxDist; + f32 sn; + f32 cs; + s32 i; + Vec3f faceVtx; + Vec3f faceVtxNext; + Vec3f posResult; + Vec3f faceVtxOffset; + s32 bgId; + CollisionPoly* outPoly; + + sn = Math_SinS(angle); + cs = Math_CosS(angle); + + maxDists[0] = ((this->dyna.actor.scale.x * 300.0f) + 60.0f) - 0.5f; + if (direction > 0.0f) { + maxDists[1] = maxDists[0]; + } else { + maxDists[0] = -maxDists[0]; + maxDists[1] = -(((this->dyna.actor.scale.x * 300.0f) + 90.0f) - 0.5f); + } + + for (i = 0; i < ARRAY_COUNT(sFaceDirection); i++) { + maxDist = maxDists[D_80918940[i]]; + + faceVtxOffset.x = (sFaceVtx[i].x * this->dyna.actor.scale.x * 10.0f) + sFaceDirection[i].x; + faceVtxOffset.y = (sFaceVtx[i].y * this->dyna.actor.scale.y * 10.0f) + sFaceDirection[i].y; + faceVtxOffset.z = 0.0f; + + ObjOshihiki_RotateXZ(&faceVtx, &faceVtxOffset, sn, cs); + + faceVtx.x += this->dyna.actor.world.pos.x; + faceVtx.y += this->dyna.actor.world.pos.y; + faceVtx.z += this->dyna.actor.world.pos.z; + + faceVtxNext.x = (maxDist * sn) + faceVtx.x; + faceVtxNext.y = faceVtx.y; + faceVtxNext.z = (maxDist * cs) + faceVtx.z; + + if (BgCheck_EntityLineTest3(&globalCtx->colCtx, &faceVtx, &faceVtxNext, &posResult, &outPoly, 1, 0, 0, 1, &bgId, + &this->dyna.actor, 0.0f)) { + return true; + } + } + return false; +} + +s32 ObjOshihiki_MoveWithBlockUnder(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 pad; + ObjOshihiki* blockUnder = ObjOshihiki_GetBlockUnder(this, globalCtx); + + if ((blockUnder != NULL) && (blockUnder->stateFlags & PUSHBLOCK_SETUP_PUSH)) { + if (!ObjOshihiki_CheckWall(globalCtx, blockUnder->dyna.yRotation, blockUnder->direction, this)) { + this->blockUnder = blockUnder; + } + } + + if (this->stateFlags & PUSHBLOCK_MOVE_UNDER) { + if (this->blockUnder != NULL) { + if (this->blockUnder->stateFlags & PUSHBLOCK_PUSH) { + this->underDistX = this->blockUnder->dyna.actor.world.pos.x - this->blockUnder->dyna.actor.prevPos.x; + this->underDistZ = this->blockUnder->dyna.actor.world.pos.z - this->blockUnder->dyna.actor.prevPos.z; + this->dyna.actor.world.pos.x += this->underDistX; + this->dyna.actor.world.pos.z += this->underDistZ; + ObjOshihiki_UpdateInitPos(this); + return true; + } + + if (!(this->blockUnder->stateFlags & PUSHBLOCK_SETUP_PUSH)) { + this->blockUnder = NULL; + } + } + } + return false; +} + +void ObjOshihiki_SetupOnScene(ObjOshihiki* this, GlobalContext* globalCtx) { + this->stateFlags |= PUSHBLOCK_SETUP_ON_SCENE; + this->dyna.actor.gravity = 0.0f; + this->dyna.actor.velocity.z = 0.0f; + this->dyna.actor.velocity.y = 0.0f; + this->dyna.actor.velocity.x = 0.0f; + this->actionFunc = ObjOshihiki_OnScene; +} + +void ObjOshihiki_OnScene(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 pad; + Player* player = GET_PLAYER(globalCtx); + + this->stateFlags |= PUSHBLOCK_ON_SCENE; + + if (this->timer <= 0) { + if (fabsf(this->dyna.pushForce) > 0.001f) { + if (ObjOshihiki_StrongEnough(this, globalCtx)) { + if (!ObjOshihiki_CheckWall(globalCtx, this->dyna.yRotation, this->dyna.pushForce, this)) { + this->direction = this->dyna.pushForce; + ObjOshihiki_SetupPush(this, globalCtx); + return; + } + } + player->stateFlags2 &= ~0x10; + this->dyna.pushForce = 0.0f; + } + } else if (fabsf(this->dyna.pushForce) > 0.001f) { + player->stateFlags2 &= ~0x10; + this->dyna.pushForce = 0.0f; + } +} + +void ObjOshihiki_SetupOnActor(ObjOshihiki* this, GlobalContext* globalCtx) { + this->stateFlags |= PUSHBLOCK_SETUP_ON_ACTOR; + this->dyna.actor.velocity.z = 0.0f; + this->dyna.actor.velocity.y = 0.0f; + this->dyna.actor.velocity.x = 0.0f; + this->dyna.actor.gravity = -1.0f; + this->actionFunc = ObjOshihiki_OnActor; +} + +void ObjOshihiki_OnActor(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 pad; + Player* player = GET_PLAYER(globalCtx); + DynaPolyActor* dyna; + s32 sp20 = false; + + this->stateFlags |= PUSHBLOCK_ON_ACTOR; + Actor_MoveWithGravity(&this->dyna.actor); + + if (ObjOshihiki_CheckFloor(this, globalCtx)) { + if (this->floorBgIds[this->highestFloor] == BGCHECK_SCENE) { + ObjOshihiki_SetupOnScene(this, globalCtx); + } else { + dyna = DynaPoly_GetActor(&globalCtx->colCtx, this->floorBgIds[this->highestFloor]); + if (dyna != NULL) { + DynaPolyActor_SetRidingFallingState(dyna); + DynaPolyActor_SetSwitchPressedState(dyna); + if ((this->timer <= 0) && (fabsf(this->dyna.pushForce) > 0.001f) && + ObjOshihiki_StrongEnough(this, globalCtx) && ObjOshihiki_NoSwitchPress(this, dyna, globalCtx) && + !ObjOshihiki_CheckWall(globalCtx, this->dyna.yRotation, this->dyna.pushForce, this)) { + this->direction = this->dyna.pushForce; + ObjOshihiki_SetupPush(this, globalCtx); + sp20 = true; + } + } else { + ObjOshihiki_SetupOnScene(this, globalCtx); + } + } + } else if (this->floorBgIds[this->highestFloor] == BGCHECK_SCENE) { + ObjOshihiki_SetupFall(this, globalCtx); + } else { + dyna = DynaPoly_GetActor(&globalCtx->colCtx, this->floorBgIds[this->highestFloor]); + if ((dyna != NULL) && (dyna->flags & 1)) { + DynaPolyActor_SetRidingFallingState(dyna); + DynaPolyActor_SetSwitchPressedState(dyna); + this->dyna.actor.world.pos.y = this->dyna.actor.floorHeight; + } else { + ObjOshihiki_SetupFall(this, globalCtx); + } + } + + if (!sp20 && (fabsf(this->dyna.pushForce) > 0.001f)) { + player->stateFlags2 &= ~0x10; + this->dyna.pushForce = 0.0f; + } +} + +void ObjOshihiki_SetupPush(ObjOshihiki* this, GlobalContext* globalCtx) { + this->stateFlags |= PUSHBLOCK_SETUP_PUSH; + this->dyna.actor.gravity = 0.0f; + this->pushSpeed = 2.0f; + this->actionFunc = ObjOshihiki_Push; +} + +void ObjOshihiki_Push(ObjOshihiki* this, GlobalContext* globalCtx) { + s32 pad; + Player* player = GET_PLAYER(globalCtx); + f32 pushDistSigned; + s32 stopFlag; + + this->stateFlags |= PUSHBLOCK_PUSH; + stopFlag = Math_StepToF(&this->pushDist, 60.0f, this->pushSpeed); + + pushDistSigned = ((this->direction >= 0.0f) ? 1.0f : -1.0f) * this->pushDist; + this->dyna.actor.world.pos.x = this->dyna.actor.home.pos.x + (pushDistSigned * this->yawSin); + this->dyna.actor.world.pos.z = this->dyna.actor.home.pos.z + (pushDistSigned * this->yawCos); + + if (!ObjOshihiki_CheckFloor(this, globalCtx)) { + this->dyna.actor.home.pos.x = this->dyna.actor.world.pos.x; + this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z; + player->stateFlags2 &= ~0x10; + this->dyna.pushForce = 0.0f; + this->pushDist = 0.0f; + this->pushSpeed = 0.0f; + ObjOshihiki_SetupFall(this, globalCtx); + } else if (stopFlag) { + player = GET_PLAYER(globalCtx); + + if (ObjOshihiki_CheckWall(globalCtx, this->dyna.yRotation, this->dyna.pushForce, this)) { + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); + } + + this->dyna.actor.home.pos.x = this->dyna.actor.world.pos.x; + this->dyna.actor.home.pos.z = this->dyna.actor.world.pos.z; + player->stateFlags2 &= ~0x10; + this->dyna.pushForce = 0.0f; + this->pushDist = 0.0f; + this->pushSpeed = 0.0f; + this->timer = 10; + + if (this->floorBgIds[this->highestFloor] == BGCHECK_SCENE) { + ObjOshihiki_SetupOnScene(this, globalCtx); + } else { + ObjOshihiki_SetupOnActor(this, globalCtx); + } + } + + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_ROCK_SLIDE - SFX_FLAG); +} + +void ObjOshihiki_SetupFall(ObjOshihiki* this, GlobalContext* globalCtx) { + this->stateFlags |= PUSHBLOCK_SETUP_FALL; + this->dyna.actor.velocity.z = 0.0f; + this->dyna.actor.velocity.y = 0.0f; + this->dyna.actor.velocity.x = 0.0f; + this->dyna.actor.gravity = -1.0f; + ObjOshihiki_SetGround(this, globalCtx); + this->actionFunc = ObjOshihiki_Fall; +} + +void ObjOshihiki_Fall(ObjOshihiki* this, GlobalContext* globalCtx) { + Player* player = GET_PLAYER(globalCtx); + s16 temp_t4; + + this->stateFlags |= PUSHBLOCK_FALL; + + if (fabsf(this->dyna.pushForce) > 0.001f) { + this->dyna.pushForce = 0.0f; + player->stateFlags2 &= ~0x10; + } + + Actor_MoveWithGravity(&this->dyna.actor); + + if (ObjOshihiki_CheckGround(this, globalCtx)) { + if (this->floorBgIds[this->highestFloor] == BGCHECK_SCENE) { + ObjOshihiki_SetupOnScene(this, globalCtx); + } else { + ObjOshihiki_SetupOnActor(this, globalCtx); + } + Actor_PlaySfxAtPos(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); + Actor_PlaySfxAtPos(&this->dyna.actor, + SurfaceType_GetSfx(&globalCtx->colCtx, this->floorPolys[this->highestFloor], + this->floorBgIds[this->highestFloor]) + + SFX_FLAG); + } +} + +void ObjOshihiki_Update(Actor* thisx, GlobalContext* globalCtx) { + ObjOshihiki* this = THIS; + + this->stateFlags &= + ~(PUSHBLOCK_SETUP_FALL | PUSHBLOCK_FALL | PUSHBLOCK_SETUP_PUSH | PUSHBLOCK_PUSH | PUSHBLOCK_SETUP_ON_ACTOR | + PUSHBLOCK_ON_ACTOR | PUSHBLOCK_SETUP_ON_SCENE | PUSHBLOCK_ON_SCENE); + this->stateFlags |= PUSHBLOCK_MOVE_UNDER; + if (this->timer > 0) { + this->timer--; + } + + this->dyna.actor.world.rot.y = this->dyna.yRotation; + this->yawSin = Math_SinS(this->dyna.actor.world.rot.y); + this->yawCos = Math_CosS(this->dyna.actor.world.rot.y); + + if (this->actionFunc != NULL) { + this->actionFunc(this, globalCtx); + } +} + +void ObjOshihiki_Draw(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ObjOshihiki* this = THIS; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + if (ObjOshihiki_MoveWithBlockUnder(this, globalCtx)) { + Matrix_InsertTranslation(this->underDistX * 10.0f, 0.0f, this->underDistZ * 10.0f, MTXMODE_APPLY); + } + + this->stateFlags &= ~PUSHBLOCK_MOVE_UNDER; + func_8012C28C(globalCtx->state.gfxCtx); + AnimatedMat_DrawStep(globalCtx, this->texture, this->textureStep); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gDPSetPrimColor(POLY_OPA_DISP++, 0xFF, 0xFF, this->color.r, this->color.g, this->color.b, 255); + gSPDisplayList(POLY_OPA_DISP++, gameplay_dangeon_keep_DL_0182A8); + + CLOSE_DISPS(globalCtx->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.h b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.h index 4b265f4bea..e08630132a 100644 --- a/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.h +++ b/src/overlays/actors/ovl_Obj_Oshihiki/z_obj_oshihiki.h @@ -7,11 +7,57 @@ struct ObjOshihiki; typedef void (*ObjOshihikiActionFunc)(struct ObjOshihiki*, GlobalContext*); +#define OBJOSHIHIKI_GET_F(thisx) ((thisx)->params & 0xF) +#define OBJOSHIHIKI_GET_F0(thisx) (((thisx)->params >> 4) & 0xF) +#define OBJOSHIHIKI_GET_7F00(thisx) (((thisx)->params >> 8) & 0x7F) +#define OBJOSHIHIKI_GET_FF00(thisx) (((thisx)->params >> 8) & 0xFF) + +enum { + /* 0 */ OBJOSHIHIKI_F_0, + /* 1 */ OBJOSHIHIKI_F_1, + /* 2 */ OBJOSHIHIKI_F_2, + /* 3 */ OBJOSHIHIKI_F_3, + /* 4 */ OBJOSHIHIKI_F_4, + /* 5 */ OBJOSHIHIKI_F_5, + /* 6 */ OBJOSHIHIKI_F_6, + /* 7 */ OBJOSHIHIKI_F_7, + /* 8 */ OBJOSHIHIKI_F_8, +}; + +#define OBJOSHIHIKI_FF00_0 0 +#define OBJOSHIHIKI_FF00_80 0x80 + +#define PUSHBLOCK_ON_SCENE (1 << 0) +#define PUSHBLOCK_SETUP_ON_SCENE (1 << 1) +#define PUSHBLOCK_ON_ACTOR (1 << 2) +#define PUSHBLOCK_SETUP_ON_ACTOR (1 << 3) +#define PUSHBLOCK_PUSH (1 << 4) +#define PUSHBLOCK_SETUP_PUSH (1 << 5) +#define PUSHBLOCK_FALL (1 << 6) +#define PUSHBLOCK_SETUP_FALL (1 << 7) +#define PUSHBLOCK_MOVE_UNDER (1 << 8) + typedef struct ObjOshihiki { - /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x18]; + /* 0x0000 */ DynaPolyActor dyna; /* 0x015C */ ObjOshihikiActionFunc actionFunc; - /* 0x0160 */ char unk_160[0x6C]; + /* 0x0160 */ u16 stateFlags; + /* 0x0162 */ s16 timer; + /* 0x0164 */ f32 yawSin; + /* 0x0168 */ f32 yawCos; + /* 0x016C */ f32 pushSpeed; + /* 0x0170 */ f32 pushDist; + /* 0x0174 */ f32 direction; + /* 0x0178 */ s32 floorBgIds[5]; + /* 0x018C */ CollisionPoly* floorPolys[5]; + /* 0x01A0 */ f32 floorHeights[5]; + /* 0x01B4 */ s16 highestFloor; + /* 0x01B6 */ u8 cantMove; + /* 0x01B8 */ struct ObjOshihiki* blockUnder; + /* 0x01BC */ f32 underDistX; + /* 0x01C0 */ f32 underDistZ; + /* 0x01C4 */ s8 textureStep; + /* 0x01C5 */ Color_RGB8 color; + /* 0x01C8 */ AnimatedMaterial* texture; } ObjOshihiki; // size = 0x1CC extern const ActorInit Obj_Oshihiki_InitVars; diff --git a/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h b/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h index 96b5f2bb6a..5d1134f124 100644 --- a/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h +++ b/src/overlays/actors/ovl_Obj_Switch/z_obj_switch.h @@ -7,6 +7,12 @@ struct ObjSwitch; typedef void (*ObjSwitchActionFunc)(struct ObjSwitch*, GlobalContext*); +#define OBJSWITCH_GET_33(thisx) ((thisx)->params & 0x33) +#define OBJSWITCH_GET_7F00(thisx) (((thisx)->params >> 8) & 0x7F) + +#define OBJSWITCH_NORMAL_BLUE 0x20 +#define OBJSWITCH_INVERSE_BLUE 0x30 + typedef struct ObjSwitch { /* 0x0000 */ Actor actor; /* 0x0144 */ char unk_144[0x18]; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 7bb9dbea6f..6ca4f0cbdd 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -6864,32 +6864,32 @@ 0x8090C884:("EnFishing_OwnerOverrideLimbDraw",), 0x8090C8BC:("EnFishing_OwnerPostLimbDraw",), 0x8090C96C:("EnFishing_DrawOwner",), - 0x80917290:("func_80917290",), - 0x809172E4:("func_809172E4",), - 0x8091734C:("func_8091734C",), - 0x80917378:("func_80917378",), - 0x80917408:("func_80917408",), - 0x80917538:("func_80917538",), - 0x80917604:("func_80917604",), - 0x8091763C:("func_8091763C",), - 0x8091768C:("func_8091768C",), + 0x80917290:("ObjOshihiki_RotateXZ",), + 0x809172E4:("ObjOshihiki_StrongEnough",), + 0x8091734C:("ObjOshihiki_ResetFloors",), + 0x80917378:("ObjOshihiki_GetBlockUnder",), + 0x80917408:("ObjOshihiki_UpdateInitPos",), + 0x80917538:("ObjOshihiki_NoSwitchPress",), + 0x80917604:("ObjOshihiki_SetScale",), + 0x8091763C:("ObjOshihiki_SetTextureStep",), + 0x8091768C:("ObjOshihiki_SetColor",), 0x809176D0:("ObjOshihiki_Init",), 0x8091780C:("ObjOshihiki_Destroy",), - 0x80917840:("func_80917840",), - 0x809179A0:("func_809179A0",), - 0x80917AEC:("func_80917AEC",), - 0x80917B44:("func_80917B44",), - 0x80917B9C:("func_80917B9C",), - 0x80917C14:("func_80917C14",), - 0x80917E8C:("func_80917E8C",), - 0x80917F88:("func_80917F88",), - 0x80917FC0:("func_80917FC0",), - 0x809180C8:("func_809180C8",), - 0x80918108:("func_80918108",), - 0x80918314:("func_80918314",), - 0x8091834C:("func_8091834C",), - 0x8091851C:("func_8091851C",), - 0x80918574:("func_80918574",), + 0x80917840:("ObjOshihiki_SetFloors",), + 0x809179A0:("ObjOshihiki_GetHighestFloor",), + 0x80917AEC:("ObjOshihiki_SetGround",), + 0x80917B44:("ObjOshihiki_CheckFloor",), + 0x80917B9C:("ObjOshihiki_CheckGround",), + 0x80917C14:("ObjOshihiki_CheckWall",), + 0x80917E8C:("ObjOshihiki_MoveWithBlockUnder",), + 0x80917F88:("ObjOshihiki_SetupOnScene",), + 0x80917FC0:("ObjOshihiki_OnScene",), + 0x809180C8:("ObjOshihiki_SetupOnActor",), + 0x80918108:("ObjOshihiki_OnActor",), + 0x80918314:("ObjOshihiki_SetupPush",), + 0x8091834C:("ObjOshihiki_Push",), + 0x8091851C:("ObjOshihiki_SetupFall",), + 0x80918574:("ObjOshihiki_Fall",), 0x80918678:("ObjOshihiki_Update",), 0x80918700:("ObjOshihiki_Draw",), 0x80918B40:("func_80918B40",),