Obj_Kendo_Kanban OK and Documented (Decomp was mostly done already) (#1057)

* stuff

* Renaming in-process

- Changed action names and setup names based on examples.
- Undid some ill-advised changes that broke matching.
- Misc variable naming. Need verification and not all complete.

* wip renaming

* A bit more progress on determining names for everything.

* Done with naming.

* Touchup before review

* Updates from review:

- Leave displacementY/unk_AC0 naming to z_actor work.
- Remove unnecessary include of z64math.h, indirect inclusion preferred
- Add trailing comma for better formatting of sDisplayLists
- Rename of static vectors sNullVec3f->sZeroVec, sUnitVectorX->sUnitVecX
- Restore pad instead of using local const. Change const to #define
- Prefer index over idx
- Remove 'b' prefix from bHasNewRootCornerPos
- Const -> Enum and formatting in ObjKendoKanban_IsPlayerOnTop
- Rename 'Aerial' to 'Tumble'

* Missed items in review:
- Missed an instance of displacementY->unk_AC0 renaming (Cause of build failure)
- Whitespace formatting
- UNK_TYPE2 undo

* More adjustments from review:
- Undo accidental formatting changes to z64player.h, restoring to master.
- Naming and Formatting changes.
- Removing some comments.

* From review, qualify enum and #define with obj name, whitespace cleanup.
This commit is contained in:
StickyThwomp 2022-09-24 13:00:53 -05:00 committed by GitHub
parent 0aede274ae
commit d968e58f9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 242 additions and 235 deletions

4
spec
View File

@ -3910,11 +3910,7 @@ beginseg
name "ovl_Obj_Kendo_Kanban"
compress
include "build/src/overlays/actors/ovl_Obj_Kendo_Kanban/z_obj_kendo_kanban.o"
#ifdef NON_MATCHING
include "build/src/overlays/actors/ovl_Obj_Kendo_Kanban/ovl_Obj_Kendo_Kanban_reloc.o"
#else
include "build/data/ovl_Obj_Kendo_Kanban/ovl_Obj_Kendo_Kanban.reloc.o"
#endif
endseg
beginseg

View File

@ -1,7 +1,7 @@
/*
* File: z_obj_kendo_kanban.c
* Overlay: ovl_Obj_Kendo_Kanban
* Description: Swordsman's School - Cuttable Board
* Description: Swordsman's School - Cuttable Board at back of school
*/
#include "z_obj_kendo_kanban.h"
@ -9,20 +9,40 @@
#define FLAGS 0x00000000
// Board Fragment Flags: Identify which of the 4 quadrants of the board are present.
#define OBJKENDOKANBAN_PART_FULL 0
#define OBJKENDOKANBAN_PART_TOP_RIGHT (1 << 0)
#define OBJKENDOKANBAN_PART_TOP_LEFT (1 << 1)
#define OBJKENDOKANBAN_PART_BOTTOM_RIGHT (1 << 2)
#define OBJKENDOKANBAN_PART_BOTTOM_LEFT (1 << 3)
#define OBJKENDOKANBAN_RIGHT_HALF (OBJKENDOKANBAN_PART_TOP_RIGHT | OBJKENDOKANBAN_PART_BOTTOM_RIGHT)
#define OBJKENDOKANBAN_LEFT_HALF (OBJKENDOKANBAN_PART_TOP_LEFT | OBJKENDOKANBAN_PART_BOTTOM_LEFT)
#define OBJKENDOKANBAN_TOP_HALF (OBJKENDOKANBAN_PART_TOP_RIGHT | OBJKENDOKANBAN_PART_TOP_LEFT)
#define OBJKENDOKANBAN_BOTTOM_HALF (OBJKENDOKANBAN_PART_BOTTOM_RIGHT | OBJKENDOKANBAN_PART_BOTTOM_LEFT)
// Number of bounces the board takes before settling.
#define MAX_BOUNCE_COUNT (7)
#define THIS ((ObjKendoKanban*)thisx)
typedef enum {
/* -1 */ OBJKENDOKANBAN_DIR_DOWN = -1,
/* 0 */ OBJKENDOKANBAN_DIR_UNDETERMINED,
/* 1 */ OBJKENDOKANBAN_DIR_UP,
} ObjKendoKanbanDirection;
void ObjKendoKanban_Init(Actor* thisx, PlayState* play);
void ObjKendoKanban_Destroy(Actor* thisx, PlayState* play);
void ObjKendoKanban_Update(Actor* thisx, PlayState* play);
void ObjKendoKanban_Draw(Actor* thisx, PlayState* play);
void func_80B65880(ObjKendoKanban* this);
void func_80B65894(ObjKendoKanban* this, PlayState* play);
void func_80B658A4(ObjKendoKanban* this, PlayState* play);
void func_80B65CE0(ObjKendoKanban* this, PlayState* play);
void func_80B65D68(ObjKendoKanban* this, PlayState* play);
void func_80B65DA8(ObjKendoKanban* this, PlayState* play);
s32 func_80B6618C(ObjKendoKanban* this, PlayState* play);
void ObjKendoKanban_SetupDoNothing(ObjKendoKanban* this);
void ObjKendoKanban_DoNothing(ObjKendoKanban* this, PlayState* play);
void ObjKendoKanban_SetupTumble(ObjKendoKanban* this, PlayState* play);
void ObjKendoKanban_Tumble(ObjKendoKanban* this, PlayState* play);
void ObjKendoKanban_Settled(ObjKendoKanban* this, PlayState* play);
void ObjKendoKanban_HandlePhysics(ObjKendoKanban* this, PlayState* play);
s32 ObjKendoKanban_IsPlayerOnTop(ObjKendoKanban* this, PlayState* play);
const ActorInit Obj_Kendo_Kanban_InitVars = {
ACTOR_OBJ_KENDO_KANBAN,
@ -36,29 +56,36 @@ const ActorInit Obj_Kendo_Kanban_InitVars = {
(ActorFunc)ObjKendoKanban_Draw,
};
Vec3f D_80B66660 = { -1.5f, 10.0f, 0.5f };
Vec3f D_80B6666C = { 1.5f, 10.0f, 0.5f };
Vec3f D_80B66678 = { 0.0f, 4.0f, -1.0f };
Vec3f D_80B66684 = { 1.0f, 7.0f, 4.0f };
Vec3f D_80B66690 = { -150.0f, 425.0f, 40.0f };
Vec3f D_80B6669C = { 150.0f, 425.0f, 40.0f };
Vec3f D_80B666A8 = { 0.0f, 140.0f, 40.0f };
Vec3f D_80B666B4 = { 0.0f, 565.0f, 40.0f };
// Directly applied to the velocity of the actor upon object creation.
static Vec3f sVelocityLeftHalf = { -1.5f, 10.0f, 0.5f }; // Push Left/Up/Forward (Left side Breakaway)
static Vec3f sVelocityRightHalf = { 1.5f, 10.0f, 0.5f }; // Push Right/Up/Forward (Right side Breakaway)
static Vec3f sVelocityBottomHalf = { 0.0f, 4.0f, -1.0f }; // Push _/Up/Back (Bottom Breakaway)
static Vec3f sVelocityTopHalf = { 1.0f, 7.0f, 4.0f }; // Push Right/Up/Forward (Top Breakaway)
Gfx* D_80B666C0 = gKendoKanbanTopRightDL;
Gfx* D_80B666C4 = gKendoKanbanTopLeftDL;
Gfx* D_80B666C8 = gKendoKanbanBottomRightDL;
Gfx* D_80B666CC = gKendoKanbanBottomLeftDL;
// Centerpoint of the piece
static Vec3f sCenterPointLeftHalf = { -150.0f, 425.0f, 40.0f };
static Vec3f sCenterPointRightHalf = { 150.0f, 425.0f, 40.0f };
static Vec3f sCenterPointBottomHalf = { 0.0f, 140.0f, 40.0f };
static Vec3f sCenterPointTopHalf = { 0.0f, 565.0f, 40.0f };
Vec3f D_80B666D0 = { -300.0f, 850.0f, 40.0f };
Vec3f D_80B666DC = { 10.0f, 850.0f, 40.0f };
Vec3f D_80B666E8 = { 300.0f, 850.0f, 40.0f };
Vec3f D_80B666F4 = { -300.0f, 310.0f, 40.0f };
Vec3f D_80B66700 = { 0.0f, 280.0f, 40.0f };
Vec3f D_80B6670C = { 300.0f, 250.0f, 40.0f };
Vec3f D_80B66718 = { -300.0f, 10.0f, 40.0f };
Vec3f D_80B66724 = { 0.0f, 10.0f, 40.0f };
Vec3f D_80B66730 = { 300.0f, 10.0f, 40.0f };
// Displaylists for the 4 pieces.
static Gfx* sDisplayLists[] = {
gKendoKanbanTopRightDL,
gKendoKanbanTopLeftDL,
gKendoKanbanBottomRightDL,
gKendoKanbanBottomLeftDL,
};
// Coordinates on the object face upon which the board can break
static Vec3f sPointTL = { -300.0f, 850.0f, 40.0f };
static Vec3f sPointTC = { 10.0f, 850.0f, 40.0f };
static Vec3f sPointTR = { 300.0f, 850.0f, 40.0f };
static Vec3f sPointCL = { -300.0f, 310.0f, 40.0f };
static Vec3f sPointCC = { 0.0f, 280.0f, 40.0f }; // Unused
static Vec3f sPointCR = { 300.0f, 250.0f, 40.0f };
static Vec3f sPointBL = { -300.0f, 10.0f, 40.0f };
static Vec3f sPointBC = { 0.0f, 10.0f, 40.0f };
static Vec3f sPointBR = { 300.0f, 10.0f, 40.0f };
static ColliderTrisElementInit sTrisElementsInit[] = {
{
@ -155,13 +182,13 @@ static DamageTable sDamageTable = {
static CollisionCheckInfoInit2 sColChkInfoInit = { 8, 0, 0, 0, MASS_HEAVY };
Vec3f D_80B6681C = { 0.0f, 0.0f, 0.0f };
Vec3f D_80B66828 = { 1.0f, 0.0f, 0.0f };
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
static Vec3f sUnitVecX = { 1.0f, 0.0f, 0.0f };
void ObjKendoKanban_Init(Actor* thisx, PlayState* play) {
s32 pad[2];
ObjKendoKanban* this = THIS;
Vec3f sp70[3];
Vec3f vertices[3];
s32 i;
s32 j;
@ -178,35 +205,35 @@ void ObjKendoKanban_Init(Actor* thisx, PlayState* play) {
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
for (i = 0; i < ARRAY_COUNT(this->colliderTrisElements); i++) {
for (j = 0; j < ARRAY_COUNT(sp70); j++) {
Matrix_MultVec3f(&sTrisElementsInit[i].dim.vtx[j], &sp70[j]);
for (j = 0; j < ARRAY_COUNT(vertices); j++) {
Matrix_MultVec3f(&sTrisElementsInit[i].dim.vtx[j], &vertices[j]);
}
Collider_SetTrisVertices(&this->colliderTris, i, &sp70[0], &sp70[1], &sp70[2]);
Collider_SetTrisVertices(&this->colliderTris, i, &vertices[0], &vertices[1], &vertices[2]);
}
Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4);
this->unk_30C = OBJKENDOKANBAN_GET_F(&this->actor);
this->boardFragments = OBJKENDOKANBAN_GET_BOARD_FRAGMENTS(&this->actor);
this->actor.gravity = -2.0f;
this->unk_2CC = D_80B6681C;
this->unk_2D8 = D_80B6681C;
this->unk_2E4 = D_80B6681C;
this->unk_2F0 = D_80B66828;
this->unk_302 = 0;
this->unk_304 = 0;
this->unk_2FC = -1;
this->unk_300 = 0;
this->unk_308 = 0;
this->centerPoint = sZeroVec;
this->centerPos = sZeroVec;
this->rootCornerPos = sZeroVec;
this->rotAxis = sUnitVecX;
this->rotAngle = 0;
this->rotVelocity = 0;
this->indexLastRootCornerPos = -1;
this->hasNewRootCornerPos = false;
this->numBounces = 0;
for (i = 0; i < ARRAY_COUNT(this->unk_26C); i++) {
this->unk_26C[i] = this->unk_29C[i] = D_80B6681C;
for (i = 0; i < ARRAY_COUNT(this->cornerPos); i++) {
this->cornerPos[i] = this->cornerPoints[i] = sZeroVec;
}
this->unk_30A = 0;
if (this->unk_30C == OBJKENDOKANBAN_F_0) {
func_80B65880(this);
if (this->boardFragments == OBJKENDOKANBAN_PART_FULL) {
ObjKendoKanban_SetupDoNothing(this);
} else {
func_80B658A4(this, play);
ObjKendoKanban_SetupTumble(this, play);
}
}
@ -217,135 +244,138 @@ void ObjKendoKanban_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyTris(play, &this->colliderTris);
}
void func_80B65880(ObjKendoKanban* this) {
this->actionFunc = func_80B65894;
void ObjKendoKanban_SetupDoNothing(ObjKendoKanban* this) {
this->actionFunc = ObjKendoKanban_DoNothing;
}
void func_80B65894(ObjKendoKanban* this, PlayState* play) {
void ObjKendoKanban_DoNothing(ObjKendoKanban* this, PlayState* play) {
}
void func_80B658A4(ObjKendoKanban* this, PlayState* play) {
void ObjKendoKanban_SetupTumble(ObjKendoKanban* this, PlayState* play) {
Player* player = GET_PLAYER(play);
if (this->unk_30C == OBJKENDOKANBAN_F_0) {
if (this->boardFragments == OBJKENDOKANBAN_PART_FULL) {
if ((player->meleeWeaponAnimation == PLAYER_MWA_FORWARD_SLASH_1H) ||
(player->meleeWeaponAnimation == PLAYER_MWA_FORWARD_SLASH_2H) ||
(player->meleeWeaponAnimation == PLAYER_MWA_JUMPSLASH_FINISH)) {
this->unk_30C = (OBJKENDOKANBAN_F_4 | OBJKENDOKANBAN_F_1);
this->unk_304 = 0x71C;
this->actor.velocity = D_80B6666C;
this->unk_2CC = D_80B6669C;
// Vertical cuts initialize the right half, spawn the left half.
this->boardFragments = OBJKENDOKANBAN_RIGHT_HALF;
this->rotVelocity = 0x71C; // 10 degrees
this->actor.velocity = sVelocityRightHalf;
this->centerPoint = sCenterPointRightHalf;
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_OBJ_KENDO_KANBAN,
this->actor.home.pos.x - 5.0f, this->actor.home.pos.y, this->actor.home.pos.z, 0, 0, 0,
0xA);
OBJKENDOKANBAN_LEFT_HALF);
this->unk_29C[0] = D_80B666DC;
this->unk_29C[1] = D_80B666E8;
this->unk_29C[2] = D_80B66730;
this->unk_29C[3] = D_80B66724;
this->cornerPoints[0] = sPointTC;
this->cornerPoints[1] = sPointTR;
this->cornerPoints[2] = sPointBR;
this->cornerPoints[3] = sPointBC;
} else {
this->unk_30C = (OBJKENDOKANBAN_F_8 | OBJKENDOKANBAN_F_4);
this->unk_304 = -0x71C;
this->actor.velocity = D_80B66678;
this->unk_2CC = D_80B666A8;
// Horizontal cuts initialize the bottom half, spawn the top half.
this->boardFragments = OBJKENDOKANBAN_BOTTOM_HALF;
this->rotVelocity = -0x71C; // -10 degrees
this->actor.velocity = sVelocityBottomHalf;
this->centerPoint = sCenterPointBottomHalf;
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_OBJ_KENDO_KANBAN, this->actor.home.pos.x,
this->actor.home.pos.y + 5.0f, this->actor.home.pos.z, 0, 0, 0, 3);
this->actor.home.pos.y + 5.0f, this->actor.home.pos.z, 0, 0, 0, OBJKENDOKANBAN_TOP_HALF);
this->unk_29C[0] = D_80B666F4;
this->unk_29C[1] = D_80B6670C;
this->unk_29C[2] = D_80B66730;
this->unk_29C[3] = D_80B66718;
this->cornerPoints[0] = sPointCL;
this->cornerPoints[1] = sPointCR;
this->cornerPoints[2] = sPointBR;
this->cornerPoints[3] = sPointBL;
}
} else if (this->unk_30C == (OBJKENDOKANBAN_F_8 | OBJKENDOKANBAN_F_2)) {
this->unk_304 = 0x71C;
this->actor.velocity = D_80B66660;
this->unk_2CC = D_80B66690;
} else if (this->boardFragments == OBJKENDOKANBAN_LEFT_HALF) {
// Initialize the newly spawned left half
this->rotVelocity = 0x71C; // 10 degrees
this->actor.velocity = sVelocityLeftHalf;
this->centerPoint = sCenterPointLeftHalf;
this->unk_29C[0] = D_80B666D0;
this->unk_29C[1] = D_80B666DC;
this->unk_29C[2] = D_80B66724;
this->unk_29C[3] = D_80B66718;
} else if (this->unk_30C == (OBJKENDOKANBAN_F_2 | OBJKENDOKANBAN_F_1)) {
this->unk_304 = 0x71C;
this->actor.velocity = D_80B66684;
this->unk_2CC = D_80B666B4;
this->cornerPoints[0] = sPointTL;
this->cornerPoints[1] = sPointTC;
this->cornerPoints[2] = sPointBC;
this->cornerPoints[3] = sPointBL;
} else if (this->boardFragments == OBJKENDOKANBAN_TOP_HALF) {
// Initialize the newly spawned top half
this->rotVelocity = 0x71C; // 10 degrees
this->actor.velocity = sVelocityTopHalf;
this->centerPoint = sCenterPointTopHalf;
this->unk_29C[0] = D_80B666D0;
this->unk_29C[1] = D_80B666E8;
this->unk_29C[2] = D_80B6670C;
this->unk_29C[3] = D_80B666F4;
this->cornerPoints[0] = sPointTL;
this->cornerPoints[1] = sPointTR;
this->cornerPoints[2] = sPointCR;
this->cornerPoints[3] = sPointCL;
}
this->unk_30A = 0;
this->actionFunc = func_80B65CE0;
this->actionFunc = ObjKendoKanban_Tumble;
}
void func_80B65CE0(ObjKendoKanban* this, PlayState* play) {
void ObjKendoKanban_Tumble(ObjKendoKanban* this, PlayState* play) {
this->actor.velocity.y += this->actor.gravity;
Actor_UpdatePos(&this->actor);
this->unk_302 += this->unk_304;
func_80B65DA8(this, play);
this->rotAngle += this->rotVelocity;
ObjKendoKanban_HandlePhysics(this, play);
if (this->actor.world.pos.y < -200.0f) {
this->actor.world.pos.y = -200.0f;
}
}
void func_80B65D54(ObjKendoKanban* this) {
this->actionFunc = func_80B65D68;
void ObjKendoKanban_SetupSettled(ObjKendoKanban* this) {
this->actionFunc = ObjKendoKanban_Settled;
}
void func_80B65D68(ObjKendoKanban* this, PlayState* play) {
void ObjKendoKanban_Settled(ObjKendoKanban* this, PlayState* play) {
Player* player = GET_PLAYER(play);
if (func_80B6618C(this, play) == 1) {
if (ObjKendoKanban_IsPlayerOnTop(this, play) == true) {
player->unk_AC0 = 700.0f;
}
}
void func_80B65DA8(ObjKendoKanban* this, PlayState* play) {
Vec3f sp5C;
void ObjKendoKanban_HandlePhysics(ObjKendoKanban* this, PlayState* play) {
Vec3f rootCornerPos = this->cornerPos[0];
s32 pad[2];
Vec3f sp48;
Vec3f vecCenterOut = this->actor.world.pos;
s32 pad2;
s32 index = 0;
s32 indexRootCornerPos = 0;
s32 i;
f32 sp38;
f32 verticalScalar;
sp5C = this->unk_26C[0];
sp48 = this->actor.world.pos;
sp48.x -= this->unk_2D8.x;
sp48.y -= this->unk_2D8.y;
sp48.z -= this->unk_2D8.z;
sp38 = (this->unk_2F0.x * sp48.z) + (this->unk_2F0.z * -sp48.x);
if (sp38 < 0.0f) {
this->unk_304 += 0x64;
// Calculate an affect on the rotation from gravity.
vecCenterOut.x -= this->centerPos.x;
vecCenterOut.y -= this->centerPos.y;
vecCenterOut.z -= this->centerPos.z;
verticalScalar = (this->rotAxis.x * vecCenterOut.z) + (this->rotAxis.z * -vecCenterOut.x);
if (verticalScalar < 0.0f) {
this->rotVelocity += 0x64;
} else {
this->unk_304 -= 0x64;
this->rotVelocity -= 0x64;
}
for (i = 0; i < ARRAY_COUNT(this->unk_26C); i++) {
if (this->unk_26C[i].y < sp5C.y) {
sp5C = this->unk_26C[i];
index = i;
// Find the lowest point
for (i = 0; i < ARRAY_COUNT(this->cornerPos); i++) {
if (this->cornerPos[i].y < rootCornerPos.y) {
rootCornerPos = this->cornerPos[i];
indexRootCornerPos = i;
}
}
if (index != this->unk_2FC) {
this->unk_300 = 1;
this->unk_2FC = index;
this->unk_2E4 = this->unk_29C[index];
// When the lowest point changes, re-initialize the actor position to that point
if (indexRootCornerPos != this->indexLastRootCornerPos) {
this->hasNewRootCornerPos = true;
this->indexLastRootCornerPos = indexRootCornerPos;
this->rootCornerPos = this->cornerPoints[indexRootCornerPos];
Matrix_Push();
Matrix_SetTranslateRotateYXZ(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z,
&this->actor.shape.rot);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
Matrix_MultVec3f(&this->unk_2E4, &this->actor.world.pos);
this->actor.world.pos = sp5C;
Matrix_MultVec3f(&this->rootCornerPos, &this->actor.world.pos);
this->actor.world.pos = rootCornerPos;
this->actor.prevPos = this->actor.world.pos;
Matrix_Pop();
}
@ -353,102 +383,105 @@ void func_80B65DA8(ObjKendoKanban* this, PlayState* play) {
Actor_UpdateBgCheckInfo(play, &this->actor, 0.0f, 0.0f, 0.0f, 4);
if (this->actor.bgCheckFlags & 1) {
// When on the ground, apply some friction.
this->actor.velocity.x *= 0.8f;
this->actor.velocity.z *= 0.8f;
}
if (this->unk_300 == 1) {
if (this->unk_308 >= 7) {
s16 temp_v0_3 = this->unk_302 & 0x3FFF;
if (this->hasNewRootCornerPos == true) {
if (this->numBounces >= MAX_BOUNCE_COUNT) {
s16 deltaRotAngle = this->rotAngle & 0x3FFF;
if (temp_v0_3 >= 0x2000) {
temp_v0_3 -= 0x4000;
if (deltaRotAngle >= 0x2000) { // 45 degrees
deltaRotAngle -= 0x4000; // 90 degrees
}
this->unk_302 -= temp_v0_3;
this->unk_304 = 0;
func_80B65D54(this);
this->rotAngle -= deltaRotAngle;
this->rotVelocity = 0;
ObjKendoKanban_SetupSettled(this);
return;
}
if (this->actor.bgCheckFlags & 2) {
// Upon touching the ground...
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_WOODPLATE_BOUND);
this->unk_300 = 0;
this->hasNewRootCornerPos = false;
this->actor.velocity.y *= 0.5f;
} else if (this->actor.bgCheckFlags & 1) {
this->unk_308++;
this->unk_300 = 0;
// When on the ground...
this->numBounces++;
this->hasNewRootCornerPos = false;
this->actor.velocity.x *= 0.3f;
this->actor.velocity.z *= 0.3f;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_WOODPLATE_BOUND);
if (sp38 > 0.0f) {
if (this->unk_304 > 0) {
this->unk_304 *= 1.2f;
// Adjust and (potentially) reverse rotation depending on the current
// facing of the board and the direction in which it is rotating.
if (verticalScalar > 0.0f) {
if (this->rotVelocity > 0) {
this->rotVelocity *= 1.2f;
} else {
this->unk_304 *= -0.6f;
this->rotVelocity *= -0.6f;
}
} else if (this->unk_304 < 0) {
this->unk_304 *= 1.2f;
} else {
this->unk_304 *= -0.6f;
if (this->rotVelocity < 0) {
this->rotVelocity *= 1.2f;
} else {
this->rotVelocity *= -0.6f;
}
}
}
}
}
s32 func_80B6618C(ObjKendoKanban* this, PlayState* play) {
s32 ObjKendoKanban_IsPlayerOnTop(ObjKendoKanban* this, PlayState* play) {
Player* player = GET_PLAYER(play);
s32 phi_v0;
s32 phi_v1 = 0;
s32 i;
f32 x;
f32 z;
f32 x2;
f32 z2;
s32 j;
Vec2f playerToCornerA;
Vec2f playerToCornerB;
s32 priorDir = OBJKENDOKANBAN_DIR_UNDETERMINED;
for (i = 0; i < ARRAY_COUNT(this->unk_26C); i++) {
if (i != 3) {
phi_v0 = i + 1;
} else {
phi_v0 = 0;
}
for (i = 0; i < ARRAY_COUNT(this->cornerPos); i++) {
j = (i != 3) ? (i + 1) : 0;
z = this->unk_26C[i].z - player->actor.world.pos.z;
x = this->unk_26C[i].x - player->actor.world.pos.x;
z2 = (this->unk_26C[phi_v0].z - player->actor.world.pos.z);
x2 = (this->unk_26C[phi_v0].x - player->actor.world.pos.x);
if ((x * z2) < (z * x2)) {
if (phi_v1 == 0) {
phi_v1 = 1;
} else if (phi_v1 != 1) {
// For each pair of points (moving clockwise around the shape), verify that the normal
// vector's magnitute is in the same direction. This condition being true means
// the player is within the bounds of the four cornerPoints.
playerToCornerA.z = this->cornerPos[i].z - player->actor.world.pos.z;
playerToCornerA.x = this->cornerPos[i].x - player->actor.world.pos.x;
playerToCornerB.z = this->cornerPos[j].z - player->actor.world.pos.z;
playerToCornerB.x = this->cornerPos[j].x - player->actor.world.pos.x;
if ((playerToCornerA.x * playerToCornerB.z) < (playerToCornerA.z * playerToCornerB.x)) {
if (priorDir == OBJKENDOKANBAN_DIR_UNDETERMINED) {
priorDir = OBJKENDOKANBAN_DIR_UP;
} else if (priorDir != OBJKENDOKANBAN_DIR_UP) {
return false;
}
} else {
if (priorDir == OBJKENDOKANBAN_DIR_UNDETERMINED) {
priorDir = OBJKENDOKANBAN_DIR_DOWN;
} else if (priorDir != OBJKENDOKANBAN_DIR_DOWN) {
return false;
}
} else if (phi_v1 == 0) {
phi_v1 = -1;
} else if (phi_v1 != -1) {
return false;
}
}
return true;
}
void func_80B66304(ObjKendoKanban* this, PlayState* play) {
if ((this->actionFunc != func_80B65CE0) && (this->actionFunc != func_80B65D68)) {
void ObjKendoKanban_UpdateCollision(ObjKendoKanban* this, PlayState* play) {
if ((this->actionFunc != ObjKendoKanban_Tumble) && (this->actionFunc != ObjKendoKanban_Settled)) {
if (this->colliderTris.base.acFlags & AC_HIT) {
this->colliderTris.base.acFlags &= ~AC_HIT;
func_80B658A4(this, play);
ObjKendoKanban_SetupTumble(this, play);
}
Collider_UpdateCylinder(&this->actor, &this->colliderCylinder);
this->colliderCylinder.dim.pos.z -= (s16)(20.0f * Math_CosS(this->actor.shape.rot.y));
this->colliderCylinder.dim.pos.x -= (s16)(20.0f * Math_SinS(this->actor.shape.rot.y));
if (this->actionFunc == func_80B65894) {
if (this->actionFunc == ObjKendoKanban_DoNothing) {
CollisionCheck_SetAC(play, &play->colChkCtx, &this->colliderTris.base);
}
CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliderCylinder.base);
}
}
@ -457,54 +490,38 @@ void ObjKendoKanban_Update(Actor* thisx, PlayState* play) {
ObjKendoKanban* this = THIS;
this->actionFunc(this, play);
func_80B66304(this, play);
ObjKendoKanban_UpdateCollision(this, play);
}
#ifdef NON_MATCHING
void ObjKendoKanban_Draw(Actor* thisx, PlayState* play) {
ObjKendoKanban* this = THIS;
s32 i;
Gfx* poly;
OPEN_DISPS(play->state.gfxCtx);
func_8012C28C(play->state.gfxCtx);
if (this->unk_30C == OBJKENDOKANBAN_F_0) {
if (this->boardFragments == OBJKENDOKANBAN_PART_FULL) {
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gKendoKanbanDL);
} else {
Matrix_RotateAxisS(this->unk_302, &this->unk_2F0, MTXMODE_APPLY);
Matrix_Translate(-this->unk_2E4.x, -this->unk_2E4.y, -this->unk_2E4.z, MTXMODE_APPLY);
Matrix_RotateAxisS(this->rotAngle, &this->rotAxis, MTXMODE_APPLY);
Matrix_Translate(-this->rootCornerPos.x, -this->rootCornerPos.y, -this->rootCornerPos.z, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
if (this->unk_30C & OBJKENDOKANBAN_F_1) {
gSPDisplayList(POLY_OPA_DISP++, D_80B666C0);
}
if (this->unk_30C & OBJKENDOKANBAN_F_2) {
gSPDisplayList(POLY_OPA_DISP++, D_80B666C4);
}
if (this->unk_30C & OBJKENDOKANBAN_F_4) {
gSPDisplayList(POLY_OPA_DISP++, D_80B666C8);
}
if (this->unk_30C & OBJKENDOKANBAN_F_8) {
gSPDisplayList(POLY_OPA_DISP++, D_80B666CC);
// Display only the fragments of the board which are present
for (i = 0; i < ARRAY_COUNT(sDisplayLists); i++) {
if ((1 << i) & this->boardFragments) {
gSPDisplayList(POLY_OPA_DISP++, sDisplayLists[i]);
}
}
}
CLOSE_DISPS(play->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->unk_26C); i++) {
Matrix_MultVec3f(&this->unk_29C[i], &this->unk_26C[i]);
// Update the alternate position trackers (Corners and Center of the board)
for (i = 0; i < ARRAY_COUNT(this->cornerPos); i++) {
Matrix_MultVec3f(&this->cornerPoints[i], &this->cornerPos[i]);
}
Matrix_MultVec3f(&this->unk_2CC, &this->unk_2D8);
Matrix_MultVec3f(&this->centerPoint, &this->centerPos);
}
#else
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Obj_Kendo_Kanban/ObjKendoKanban_Draw.s")
#endif

View File

@ -7,13 +7,7 @@ struct ObjKendoKanban;
typedef void (*ObjKendoKanbanActionFunc)(struct ObjKendoKanban*, PlayState*);
#define OBJKENDOKANBAN_GET_F(thisx) ((thisx)->params & 0xF)
#define OBJKENDOKANBAN_F_0 0
#define OBJKENDOKANBAN_F_1 (1 << 0)
#define OBJKENDOKANBAN_F_2 (1 << 1)
#define OBJKENDOKANBAN_F_4 (1 << 2)
#define OBJKENDOKANBAN_F_8 (1 << 3)
#define OBJKENDOKANBAN_GET_BOARD_FRAGMENTS(thisx) ((thisx)->params & 0xF)
typedef struct ObjKendoKanban {
/* 0x000 */ Actor actor;
@ -21,20 +15,20 @@ typedef struct ObjKendoKanban {
/* 0x190 */ ColliderTris colliderTris;
/* 0x1B0 */ ColliderTrisElement colliderTrisElements[2];
/* 0x268 */ ObjKendoKanbanActionFunc actionFunc;
/* 0x26C */ Vec3f unk_26C[4];
/* 0x29C */ Vec3f unk_29C[4];
/* 0x2CC */ Vec3f unk_2CC;
/* 0x2D8 */ Vec3f unk_2D8;
/* 0x2E4 */ Vec3f unk_2E4;
/* 0x2F0 */ Vec3f unk_2F0;
/* 0x2FC */ s32 unk_2FC;
/* 0x300 */ s16 unk_300;
/* 0x302 */ s16 unk_302;
/* 0x304 */ s16 unk_304;
/* 0x26C */ Vec3f cornerPos[4];
/* 0x29C */ Vec3f cornerPoints[4];
/* 0x2CC */ Vec3f centerPoint;
/* 0x2D8 */ Vec3f centerPos;
/* 0x2E4 */ Vec3f rootCornerPos;
/* 0x2F0 */ Vec3f rotAxis;
/* 0x2FC */ s32 indexLastRootCornerPos;
/* 0x300 */ s16 hasNewRootCornerPos;
/* 0x302 */ s16 rotAngle;
/* 0x304 */ s16 rotVelocity;
/* 0x306 */ UNK_TYPE1 pad306[2];
/* 0x308 */ s16 unk_308;
/* 0x308 */ s16 numBounces;
/* 0x30A */ s16 unk_30A;
/* 0x30C */ u8 unk_30C;
/* 0x30C */ u8 boardFragments;
} ObjKendoKanban; // size = 0x310
extern const ActorInit Obj_Kendo_Kanban_InitVars;

View File

@ -14230,15 +14230,15 @@
0x80B64DFC:("func_80B64DFC",),
0x80B654C0:("ObjKendoKanban_Init",),
0x80B65840:("ObjKendoKanban_Destroy",),
0x80B65880:("func_80B65880",),
0x80B65894:("func_80B65894",),
0x80B658A4:("func_80B658A4",),
0x80B65CE0:("func_80B65CE0",),
0x80B65D54:("func_80B65D54",),
0x80B65D68:("func_80B65D68",),
0x80B65DA8:("func_80B65DA8",),
0x80B6618C:("func_80B6618C",),
0x80B66304:("func_80B66304",),
0x80B65880:("ObjKendoKanban_SetupDoNothing",),
0x80B65894:("ObjKendoKanban_DoNothing",),
0x80B658A4:("ObjKendoKanban_SetupTumble",),
0x80B65CE0:("ObjKendoKanban_Tumble",),
0x80B65D54:("ObjKendoKanban_SetupSettled",),
0x80B65D68:("ObjKendoKanban_Settled",),
0x80B65DA8:("ObjKendoKanban_HandlePhysics",),
0x80B6618C:("ObjKendoKanban_IsPlayerOnTop",),
0x80B66304:("ObjKendoKanban_UpdateCollision",),
0x80B66418:("ObjKendoKanban_Update",),
0x80B66454:("ObjKendoKanban_Draw",),
0x80B66A20:("ObjHariko_Init",),