From 6f626d91864e0164470cc2ac16f227adcef3f8d6 Mon Sep 17 00:00:00 2001 From: Isghj <42048411+isghj5@users.noreply.github.com> Date: Fri, 21 Feb 2025 16:31:45 -0800 Subject: [PATCH] `EnIshi` documentation pass, and `gameplay_field_keep` assets labeled (#1794) * Ishi: some docs * Ishi: more docs * Ishi: more docs * Ishi: field_keep assets labeled * Ishi: format * Ishi: minor docs/fixes * Ishi: requested changes * Spawn and Dust Funcs * Ishi: only us version * Ishi/Bombiwa: more requested changes * Ishi: format * Apply suggestions from code review Co-authored-by: Derek Hensley * Ishi: back to matching * Ishi: a value got inverted somehow --------- Co-authored-by: Derek Hensley --- assets/xml/objects/gameplay_field_keep.xml | 12 +- src/overlays/actors/ovl_En_Ishi/z_en_ishi.c | 639 ++++++++++-------- src/overlays/actors/ovl_En_Ishi/z_en_ishi.h | 44 +- .../actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c | 2 +- .../actors/ovl_Obj_Hamishi/z_obj_hamishi.c | 6 +- .../actors/ovl_player_actor/z_player.c | 3 +- tools/disasm/functions.txt | 54 +- 7 files changed, 414 insertions(+), 346 deletions(-) diff --git a/assets/xml/objects/gameplay_field_keep.xml b/assets/xml/objects/gameplay_field_keep.xml index 5a7086c5f0..bacc9a21c4 100644 --- a/assets/xml/objects/gameplay_field_keep.xml +++ b/assets/xml/objects/gameplay_field_keep.xml @@ -32,12 +32,12 @@ - - - - - - + + + + + + diff --git a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index 1001b2d8cb..0b2006329c 100644 --- a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -18,30 +18,29 @@ void EnIshi_Init(Actor* thisx, PlayState* play); void EnIshi_Destroy(Actor* thisx, PlayState* play2); void EnIshi_Update(Actor* thisx, PlayState* play); -void func_8095D804(Actor* thisx, PlayState* play); -void func_8095DABC(Actor* thisx, PlayState* play); -void func_8095DDA8(EnIshi* this, PlayState* play); -void func_8095DE9C(EnIshi* this, PlayState* play); -void func_8095E5AC(EnIshi* this); -void func_8095E5C0(EnIshi* this, PlayState* play); -void func_8095E64C(EnIshi* this); -void func_8095E660(EnIshi* this, PlayState* play); -void func_8095E934(EnIshi* this); -void func_8095E95C(EnIshi* this, PlayState* play); -void func_8095EA70(EnIshi* this); -void func_8095EBDC(EnIshi* this, PlayState* play); -void func_8095F060(EnIshi* this); -void func_8095F0A4(EnIshi* this, PlayState* play); -void func_8095F180(EnIshi* this); -void func_8095F194(EnIshi* this, PlayState* play); -void func_8095F210(EnIshi* this, PlayState* play); -void func_8095F36C(EnIshi* this, PlayState* play); -void func_8095F61C(Actor* thisx, PlayState* play); -void func_8095F654(Actor* thisx, PlayState* play); +void EnIshi_SpawnDebrisSmallRock(Actor* thisx, PlayState* play); +void EnIshi_SpawnDebrisBoulder(Actor* thisx, PlayState* play); +void EnIshi_SpawnDustSmallRock(Actor* thisx, PlayState* play); +void EnIshi_SpawnDustBoulder(Actor* thisx, PlayState* play); +void EnIshi_SetupWaitForObject(EnIshi* this); +void EnIshi_WaitForObject(EnIshi* this, PlayState* play); +void EnIshi_SetupIdle(EnIshi* this); +void EnIshi_Idle(EnIshi* this, PlayState* play); +void EnIshi_SetupHeldByPlayer(EnIshi* this); +void EnIshi_HeldByPlayer(EnIshi* this, PlayState* play); +void EnIshi_SetupThrown(EnIshi* this); +void EnIshi_Thrown(EnIshi* this, PlayState* play); +void EnIshi_SetupCutsceneExplode(EnIshi* this); +void EnIshi_CutsceneExplode(EnIshi* this, PlayState* play); +void EnIshi_SetupKill(EnIshi* this); +void EnIshi_Kill(EnIshi* this, PlayState* play); +void EnIshi_DrawGameplayKeepSmallRock(EnIshi* this, PlayState* play); +void EnIshi_DrawGameplayKeepBoulder(EnIshi* this, PlayState* play); +void EnIshi_DrawGameplayKeepObject(Actor* thisx, PlayState* play); +void EnIshi_DrawIshiObject(Actor* thisx, PlayState* play); -static s16 D_8095F690 = 0; - -static s16 D_8095F694 = 0; +static s16 sIshiThrownXRotationVel = 0; +static s16 sIshiThrownYRotationVel = 0; ActorProfile En_Ishi_Profile = { /**/ ACTOR_EN_ISHI, @@ -55,19 +54,22 @@ ActorProfile En_Ishi_Profile = { /**/ NULL, }; -static f32 D_8095F6B8[] = { 0.1f, 0.4f }; +static f32 sIshiSizes[] = { 0.1f, 0.4f }; -static f32 D_8095F6C0[] = { 58.0f, 80.0f }; +static f32 sIshiShapeYOffsets[] = { 58.0f, 80.0f }; -static f32 D_8095F6C8[] = { 0.0f, 0.005f }; +static f32 sIshiVelocities[] = { 0.0f, 0.005f }; -static u16 D_8095F6D0[] = { NA_SE_EV_ROCK_BROKEN, NA_SE_EV_WALL_BROKEN }; +static u16 sCutsceneSfxId[] = { NA_SE_EV_ROCK_BROKEN, NA_SE_EV_WALL_BROKEN }; -static u8 D_8095F6D4[] = { 25, 40 }; +static u8 sCutsceneSfxDuration[] = { 25, 40 }; -static EnIshiUnkFunc2 D_8095F6D8[] = { func_8095D804, func_8095DABC }; +static EnIshiSpawnFunc sIshiSpawnDebrisFuncs[] = { EnIshi_SpawnDebrisSmallRock, EnIshi_SpawnDebrisBoulder }; -static EnIshiUnkFunc D_8095F6E0[] = { func_8095DDA8, func_8095DE9C }; +static EnIshiSpawnFunc sIshiSpawnDustFuncs[] = { + EnIshi_SpawnDustSmallRock, + EnIshi_SpawnDustBoulder, +}; static s16 sObjectIds[] = { GAMEPLAY_FIELD_KEEP, OBJECT_ISHI }; @@ -114,13 +116,16 @@ static ColliderCylinderInit sCylinderInit[] = { static CollisionCheckInfoInit sColChkInfoInit = { 0, 12, 60, MASS_IMMOVABLE }; -static s16 D_8095F74C[] = { 16, 13, 11, 9, 7, 5 }; +static s16 sIshiSmallRockDebrisScales[] = { 16, 13, 11, 9, 7, 5 }; -static s16 D_8095F758[] = { 145, 135, 120, 100, 70, 50, 45, 40, 35 }; +static s16 sIshiBoulderDebrisScales[] = { 145, 135, 120, 100, 70, 50, 45, 40, 35 }; -static s16 D_8095F76C[] = { -1, 1, 2, 20, 8, 0 }; +static s16 sIshiItemDrops[] = { + ITEM00_NO_DROP, ITEM00_RUPEE_BLUE, ITEM00_RUPEE_RED, ITEM00_RUPEE_PURPLE, ITEM00_ARROWS_30, ITEM00_RUPEE_GREEN, +}; -static Vec3f D_8095F778 = { 0.0f, 1.0f, 0.0f }; +// used for spawning the collectable item drops +static Vec3f sUnitVecY = { 0.0f, 1.0f, 0.0f }; static InitChainEntry sInitChain[][5] = { { @@ -139,215 +144,239 @@ static InitChainEntry sInitChain[][5] = { }, }; -static u16 D_8095F7AC[] = { NA_SE_PL_PULL_UP_ROCK, NA_SE_PL_PULL_UP_BIGROCK }; +static u16 sIshiPullRockSfx[] = { NA_SE_PL_PULL_UP_ROCK, NA_SE_PL_PULL_UP_BIGROCK }; -static EnIshiUnkFunc D_8095F7B0[] = { func_8095F210, func_8095F36C }; +static EnIshiDrawFunc sIshiGameplayKeepObjectDrawFuncs[] = { + EnIshi_DrawGameplayKeepSmallRock, + EnIshi_DrawGameplayKeepBoulder, +}; -void func_8095D6E0(Actor* thisx, PlayState* play) { +void EnIshi_InitCollider(Actor* thisx, PlayState* play) { EnIshi* this = (EnIshi*)thisx; Collider_InitCylinder(play, &this->collider); - Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit[ENISHI_GET_1(&this->actor)]); + Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit[ENISHI_GET_SIZE_FLAG(&this->actor)]); Collider_UpdateCylinder(&this->actor, &this->collider); } -s32 func_8095D758(EnIshi* this, PlayState* play, f32 arg2) { - Vec3f sp24; +// Return true/false if the rock is able to snap to the floor and is above BGCHECK_Y_MIN. +s32 EnIshi_SnapToFloor(EnIshi* this, PlayState* play, f32 yOffset) { + Vec3f pos; s32 bgId; - sp24.x = this->actor.world.pos.x; - sp24.y = this->actor.world.pos.y + 30.0f; - sp24.z = this->actor.world.pos.z; + pos.x = this->actor.world.pos.x; + pos.y = this->actor.world.pos.y + 30.0f; + pos.z = this->actor.world.pos.z; this->actor.floorHeight = - BgCheck_EntityRaycastFloor5(&play->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &sp24); + BgCheck_EntityRaycastFloor5(&play->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &pos); if (this->actor.floorHeight > BGCHECK_Y_MIN) { - this->actor.world.pos.y = this->actor.floorHeight + arg2; + this->actor.world.pos.y = this->actor.floorHeight + yOffset; Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos); return true; + } else { + return false; } - return false; } -void func_8095D804(Actor* thisx, PlayState* play) { +void EnIshi_SpawnDebrisSmallRock(Actor* thisx, PlayState* play) { EnIshi* this = (EnIshi*)thisx; s32 i; s16 objectId; - Gfx* phi_s4; - Vec3f spC4; - Vec3f spB8; + Gfx* debrisModel; + Vec3f velocity; + Vec3f pos; - if (!ENISHI_GET_8(&this->actor)) { - phi_s4 = gameplay_field_keep_DL_0066B0; + if (!ENISHI_GET_USE_OBJECT(&this->actor)) { + debrisModel = gFieldSmallRockOpaDL; // same dl in gameplay keep } else { - phi_s4 = gSmallRockDL; + debrisModel = gSmallRockDL; } - objectId = sObjectIds[ENISHI_GET_8(&this->actor)]; + objectId = sObjectIds[ENISHI_GET_USE_OBJECT(&this->actor)]; - for (i = 0; i < ARRAY_COUNT(D_8095F74C); i++) { - spB8.x = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.x; - spB8.y = (Rand_ZeroOne() * 5.0f) + this->actor.world.pos.y + 5.0f; - spB8.z = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.z; - Math_Vec3f_Copy(&spC4, &this->actor.velocity); + for (i = 0; i < ARRAY_COUNT(sIshiSmallRockDebrisScales); i++) { + pos.x = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.x; + pos.y = (Rand_ZeroOne() * 5.0f) + this->actor.world.pos.y + 5.0f; + pos.z = ((Rand_ZeroOne() - 0.5f) * 8.0f) + this->actor.world.pos.z; + Math_Vec3f_Copy(&velocity, &this->actor.velocity); if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { - spC4.x *= 0.6f; - spC4.y *= -0.3f; - spC4.z *= 0.6f; + velocity.x *= 0.6f; + velocity.y *= -0.3f; + velocity.z *= 0.6f; } else if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - spC4.x *= -0.5f; - spC4.y *= 0.5f; - spC4.z *= -0.5f; + velocity.x *= -0.5f; + velocity.y *= 0.5f; + velocity.z *= -0.5f; } - spC4.x += (Rand_ZeroOne() - 0.5f) * 11.0f; - spC4.y += (Rand_ZeroOne() * 7.0f) + 6.0f; - spC4.z += (Rand_ZeroOne() - 0.5f) * 11.0f; + velocity.x += (Rand_ZeroOne() - 0.5f) * 11.0f; + velocity.y += (Rand_ZeroOne() * 7.0f) + 6.0f; + velocity.z += (Rand_ZeroOne() - 0.5f) * 11.0f; - EffectSsKakera_Spawn(play, &spB8, &spC4, &spB8, -420, ((s32)Rand_Next() > 0) ? 65 : 33, 30, 5, 0, D_8095F74C[i], - 3, 10, 40, -1, objectId, phi_s4); + // -420: gravity + // 40:life + EffectSsKakera_Spawn(play, &pos, &velocity, &pos, -420, ((s32)Rand_Next() > 0) ? 65 : 33, 30, 5, 0, + sIshiSmallRockDebrisScales[i], 3, 10, 40, -1, objectId, debrisModel); } } -void func_8095DABC(Actor* thisx, PlayState* play) { +// Spawn fragments after the boulder breaks apart. +void EnIshi_SpawnDebrisBoulder(Actor* thisx, PlayState* play) { EnIshi* this = (EnIshi*)thisx; - Vec3f spD8; - Vec3f spCC; - f32 temp_f20; - s16 temp_s1 = 0x1000; + Vec3f velocity; + Vec3f pos; + f32 randMagnitude; + s16 angle = 0x1000; s32 i; - s16 phi_v0; - s16 phi_v1; + s16 arg5; + s16 gravity; - for (i = 0; i < ARRAY_COUNT(D_8095F758); i++) { - temp_s1 += 0x4E20; - temp_f20 = Rand_ZeroOne() * 10.0f; + for (i = 0; i < ARRAY_COUNT(sIshiBoulderDebrisScales); i++) { + angle += 0x4E20; + randMagnitude = Rand_ZeroOne() * 10.0f; - spCC.x = (Math_SinS(temp_s1) * temp_f20) + this->actor.world.pos.x; - spCC.y = (Rand_ZeroOne() * 40.0f) + this->actor.world.pos.y + 5.0f; - spCC.z = (Math_CosS(temp_s1) * temp_f20) + this->actor.world.pos.z; + pos.x = (Math_SinS(angle) * randMagnitude) + this->actor.world.pos.x; + pos.y = (Rand_ZeroOne() * 40.0f) + this->actor.world.pos.y + 5.0f; + pos.z = (Math_CosS(angle) * randMagnitude) + this->actor.world.pos.z; - Math_Vec3f_Copy(&spD8, &this->actor.velocity); + Math_Vec3f_Copy(&velocity, &this->actor.velocity); if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { - spD8.x *= 0.9f; - spD8.y *= -0.8f; - spD8.z *= 0.9f; + velocity.x *= 0.9f; + velocity.y *= -0.8f; + velocity.z *= 0.9f; } else if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - spD8.x *= -0.9f; - spD8.y *= 0.8f; - spD8.z *= -0.9f; + velocity.x *= -0.9f; + velocity.y *= 0.8f; + velocity.z *= -0.9f; } - temp_f20 = Rand_ZeroOne() * 10.0f; - spD8.x += temp_f20 * Math_SinS(temp_s1); - spD8.y += (Rand_ZeroOne() * 4.0f) + (Rand_ZeroOne() * i * 0.7f); - spD8.z += temp_f20 * Math_CosS(temp_s1); + randMagnitude = Rand_ZeroOne() * 10.0f; + velocity.x += randMagnitude * Math_SinS(angle); + velocity.y += (Rand_ZeroOne() * 4.0f) + (Rand_ZeroOne() * i * 0.7f); + velocity.z += randMagnitude * Math_CosS(angle); if (i == 0) { - phi_v0 = 41; - phi_v1 = -450; + arg5 = 41; + gravity = -450; } else if (i < 4) { - phi_v0 = 37; - phi_v1 = -380; + arg5 = 37; + gravity = -380; } else { - phi_v0 = 69; - phi_v1 = -320; + arg5 = 69; + gravity = -320; } - EffectSsKakera_Spawn(play, &spCC, &spD8, &this->actor.world.pos, phi_v1, phi_v0, 30, 5, 0, D_8095F758[i], 5, 2, - 70, 0, GAMEPLAY_FIELD_KEEP, gameplay_field_keep_DL_006420); + EffectSsKakera_Spawn(play, &pos, &velocity, &this->actor.world.pos, gravity, arg5, 30, 5, 0, + sIshiBoulderDebrisScales[i], 5, 2, 70, 0, GAMEPLAY_FIELD_KEEP, + gFieldSilverBoulderDebrisDL); } } -void func_8095DDA8(EnIshi* this, PlayState* play) { - Vec3f sp2C; +void EnIshi_SpawnDustSmallRock(Actor* thisx, PlayState* play) { + Vec3f pos; - Math_Vec3f_Copy(&sp2C, &this->actor.world.pos); - if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { - sp2C.x += 2.0f * this->actor.velocity.x; - sp2C.y -= 2.0f * this->actor.velocity.y; - sp2C.z += 2.0f * this->actor.velocity.z; - } else if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - sp2C.x -= 2.0f * this->actor.velocity.x; - sp2C.y += 2.0f * this->actor.velocity.y; - sp2C.z -= 2.0f * this->actor.velocity.z; + Math_Vec3f_Copy(&pos, &thisx->world.pos); + if (thisx->bgCheckFlags & BGCHECKFLAG_GROUND) { + pos.x += 2.0f * thisx->velocity.x; + pos.y -= 2.0f * thisx->velocity.y; + pos.z += 2.0f * thisx->velocity.z; + } else if (thisx->bgCheckFlags & BGCHECKFLAG_WALL) { + pos.x -= 2.0f * thisx->velocity.x; + pos.y += 2.0f * thisx->velocity.y; + pos.z -= 2.0f * thisx->velocity.z; } - func_800BBFB0(play, &sp2C, 60.0f, 3, 80, 60, 1); + + // 60: distance from center + // 3: count of particle + // 80: scale multiplier + // 60: scale scale step, + func_800BBFB0(play, &pos, 60.0f, 3, 80, 60, true); } -void func_8095DE9C(EnIshi* this, PlayState* play) { - Vec3f sp2C; +void EnIshi_SpawnDustBoulder(Actor* thisx, PlayState* play) { + Vec3f pos; - Math_Vec3f_Copy(&sp2C, &this->actor.world.pos); - if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) { - sp2C.x += 2.0f * this->actor.velocity.x; - sp2C.y -= 2.0f * this->actor.velocity.y; - sp2C.z += 2.0f * this->actor.velocity.z; - } else if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - sp2C.x -= 2.0f * this->actor.velocity.x; - sp2C.y += 2.0f * this->actor.velocity.y; - sp2C.z -= 2.0f * this->actor.velocity.z; + Math_Vec3f_Copy(&pos, &thisx->world.pos); + if (thisx->bgCheckFlags & BGCHECKFLAG_GROUND) { + pos.x += 2.0f * thisx->velocity.x; + pos.y -= 2.0f * thisx->velocity.y; + pos.z += 2.0f * thisx->velocity.z; + } else if (thisx->bgCheckFlags & BGCHECKFLAG_WALL) { + pos.x -= 2.0f * thisx->velocity.x; + pos.y += 2.0f * thisx->velocity.y; + pos.z -= 2.0f * thisx->velocity.z; } - func_800BBFB0(play, &sp2C, 140.0f, 10, 180, 90, 1); + + // 140: distance from center + // 10: count of particle + // 180: scale multiplier + // 90: scale scale step, + func_800BBFB0(play, &pos, 140.0f, 10, 180, 90, true); } -void func_8095DF90(EnIshi* this, PlayState* play) { - if (!ENISHI_GET_1(&this->actor) && !ENISHI_GET_100(&this->actor)) { - Item_DropCollectibleRandom(play, NULL, &this->actor.world.pos, ENISHI_GET_F0(&this->actor) * 0x10); +void EnIshi_DropItem(EnIshi* this, PlayState* play) { + if ((ENISHI_GET_SIZE_FLAG(&this->actor) == ISHI_SIZE_SMALL_ROCK) && + !ENISHI_GET_IGNORE_DROP_TABLE_FLAG(&this->actor)) { + Item_DropCollectibleRandom(play, NULL, &this->actor.world.pos, ENISHI_GET_DROP_TABLE(&this->actor) * 0x10); } } -void func_8095DFF0(EnIshi* this, PlayState* play) { +void EnIshi_DropCollectable(EnIshi* this, PlayState* play) { s32 pad; - s32 temp = D_8095F76C[ENISHI_GET_70(&this->actor)]; - Actor* sp3C; + s32 collectableItem00Id = sIshiItemDrops[ENISHI_GET_COLLECTABLE_ID(&this->actor)]; + Actor* item; Vec3f sp30; - f32 sp2C; - f32 temp_f2; + f32 cosResult; + f32 verticalVelMagnitude; s16 temp_v1_2; - if (temp >= 0) { - sp3C = Item_DropCollectible(play, &this->actor.world.pos, temp | (ENISHI_GET_FLAG(&this->actor) << 8)); - if (sp3C != NULL) { + if (collectableItem00Id >= ITEM00_RUPEE_GREEN) { // not ITEM00_NO_DROP, the 0 index of the list + item = Item_DropCollectible(play, &this->actor.world.pos, + collectableItem00Id | (ENISHI_GET_COLLECTABLE_FLAG(&this->actor) << 8)); + if (item != NULL) { + // random direction/rotation calculations? + // none of the other Item_DropCollectible rotation changes are similar enough + // kinda looks like ObjSwitch_IsEyeSwitchHit code Matrix_Push(); Matrix_RotateYS(this->actor.shape.rot.y, MTXMODE_NEW); Matrix_RotateXS(this->actor.shape.rot.x, MTXMODE_APPLY); Matrix_RotateZS(this->actor.shape.rot.z, MTXMODE_APPLY); Matrix_MultVecY(1.0f, &sp30); - sp2C = Math3D_Cos(&sp30, &D_8095F778); - if (sp2C < 0.707f) { - temp_v1_2 = Math_Atan2S_XY(sp30.z, sp30.x) - sp3C->world.rot.y; + cosResult = Math3D_Cos(&sp30, &sUnitVecY); + if (cosResult < 0.707f) { + temp_v1_2 = Math_Atan2S_XY(sp30.z, sp30.x) - item->world.rot.y; if (ABS_ALT(temp_v1_2) > 0x4000) { - sp3C->world.rot.y = BINANG_ROT180(sp3C->world.rot.y); + item->world.rot.y = BINANG_ROT180(item->world.rot.y); } - temp_f2 = sp2C + 0.5f; - if (temp_f2 < 0.5f) { - temp_f2 = 0.5f; + verticalVelMagnitude = cosResult + 0.5f; + if (verticalVelMagnitude < 0.5f) { + verticalVelMagnitude = 0.5f; } - sp3C->velocity.y *= temp_f2; + item->velocity.y *= verticalVelMagnitude; } Matrix_Pop(); } } } -void func_8095E14C(EnIshi* this) { +void EnIshi_ApplyGravity(EnIshi* this) { this->actor.velocity.y += this->actor.gravity; if (this->actor.velocity.y < this->actor.terminalVelocity) { this->actor.velocity.y = this->actor.terminalVelocity; } } -void func_8095E180(Vec3f* arg0, f32 arg1) { - arg1 += ((Rand_ZeroOne() * 0.2f) - 0.1f) * arg1; +void EnIshi_SetVelocity(Vec3f* velocity, f32 scale) { + scale += ((Rand_ZeroOne() * 0.2f) - 0.1f) * scale; - arg0->x -= arg0->x * arg1; - arg0->y -= arg0->y * arg1; - arg0->z -= arg0->z * arg1; + velocity->x -= velocity->x * scale; + velocity->y -= velocity->y * scale; + velocity->z -= velocity->z * scale; } -void func_8095E204(EnIshi* this, PlayState* play) { +void EnIshi_SpawnBugs(EnIshi* this, PlayState* play) { s32 i; for (i = 0; i < 3; i++) { @@ -370,41 +399,42 @@ s32 EnIshi_IsUnderwater(EnIshi* this, PlayState* play) { &waterBox, &bgId) && (this->actor.world.pos.y < waterSurface)) { return true; + } else { + return false; } - return false; } void EnIshi_Init(Actor* thisx, PlayState* play) { s32 pad; EnIshi* this = (EnIshi*)thisx; - s32 sp34 = ENISHI_GET_1(&this->actor); - s32 sp30 = ENISHI_GET_4(&this->actor); + s32 rockSize = ENISHI_GET_SIZE_FLAG(&this->actor); + s32 ignoreSnapToFloor = ENISHI_GET_LEVITATE_FLAG(&this->actor); - if ((sp34 == 0) && (sp30 != 0)) { - this->unk_197 |= 2; + if ((rockSize == ISHI_SIZE_SMALL_ROCK) && ignoreSnapToFloor) { + this->flags |= ISHI_FLAG_CUTSCENE_ROCK; } - Actor_ProcessInitChain(&this->actor, sInitChain[sp34]); + Actor_ProcessInitChain(&this->actor, sInitChain[rockSize]); if (play->csCtx.state != CS_STATE_IDLE) { this->actor.cullingVolumeDistance += 1000.0f; } - if ((this->actor.shape.rot.y == 0) && !(this->unk_197 & 2)) { + if ((this->actor.shape.rot.y == ISHI_RANDOM_ROTATION_FLAG) && !(this->flags & ISHI_FLAG_CUTSCENE_ROCK)) { this->actor.shape.rot.y = this->actor.world.rot.y = Rand_Next() >> 0x10; } - Actor_SetScale(&this->actor, D_8095F6B8[sp34]); - func_8095D6E0(&this->actor, play); + Actor_SetScale(&this->actor, sIshiSizes[rockSize]); + EnIshi_InitCollider(&this->actor, play); - if ((sp34 == 1) && Flags_GetSwitch(play, ENISHI_GET_FLAG(&this->actor))) { + if ((rockSize == ISHI_SIZE_SILVER_BOULDER) && Flags_GetSwitch(play, ENISHI_GET_SWITCH_FLAG(&this->actor))) { Actor_Kill(&this->actor); return; } CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit); - if (sp34 == 1) { + if (rockSize == ISHI_SIZE_SILVER_BOULDER) { this->actor.shape.shadowDraw = ActorShadow_DrawCircle; this->actor.shape.shadowScale = 2.3f; } else { @@ -412,24 +442,24 @@ void EnIshi_Init(Actor* thisx, PlayState* play) { this->actor.shape.shadowAlpha = 160; } - this->actor.shape.yOffset = D_8095F6C0[sp34]; + this->actor.shape.yOffset = sIshiShapeYOffsets[rockSize]; - if ((sp30 == 0) && !func_8095D758(this, play, 0)) { + if (!ignoreSnapToFloor && !EnIshi_SnapToFloor(this, play, 0)) { Actor_Kill(&this->actor); return; } if (EnIshi_IsUnderwater(this, play)) { - this->unk_197 |= 1; + this->flags |= ISHI_FLAG_UNDERWATER; } - this->objectSlot = Object_GetSlot(&play->objectCtx, sObjectIds[ENISHI_GET_8(&this->actor)]); + this->objectSlot = Object_GetSlot(&play->objectCtx, sObjectIds[ENISHI_GET_USE_OBJECT(&this->actor)]); if (this->objectSlot <= OBJECT_SLOT_NONE) { Actor_Kill(&this->actor); return; } - func_8095E5AC(this); + EnIshi_SetupWaitForObject(this); } void EnIshi_Destroy(Actor* thisx, PlayState* play2) { @@ -439,70 +469,72 @@ void EnIshi_Destroy(Actor* thisx, PlayState* play2) { Collider_DestroyCylinder(play, &this->collider); } -void func_8095E5AC(EnIshi* this) { - this->actionFunc = func_8095E5C0; +void EnIshi_SetupWaitForObject(EnIshi* this) { + this->actionFunc = EnIshi_WaitForObject; } -void func_8095E5C0(EnIshi* this, PlayState* play) { +void EnIshi_WaitForObject(EnIshi* this, PlayState* play) { if (Object_IsLoaded(&play->objectCtx, this->objectSlot)) { this->actor.objectSlot = this->objectSlot; this->actor.flags &= ~ACTOR_FLAG_UPDATE_CULLING_DISABLED; - if (!ENISHI_GET_8(&this->actor)) { - this->actor.draw = func_8095F61C; + if (!ENISHI_GET_USE_OBJECT(&this->actor)) { + this->actor.draw = EnIshi_DrawGameplayKeepObject; } else { - this->actor.draw = func_8095F654; + this->actor.draw = EnIshi_DrawIshiObject; } - func_8095E64C(this); + EnIshi_SetupIdle(this); } } -void func_8095E64C(EnIshi* this) { - this->actionFunc = func_8095E660; +void EnIshi_SetupIdle(EnIshi* this) { + this->actionFunc = EnIshi_Idle; } -void func_8095E660(EnIshi* this, PlayState* play) { +void EnIshi_Idle(EnIshi* this, PlayState* play) { s32 pad; - s32 sp38 = ENISHI_GET_1(&this->actor); - s32 sp34 = (this->collider.base.acFlags & AC_HIT) != 0; - s32 sp30 = this->unk_197 & 2; + s32 rockSize = ENISHI_GET_SIZE_FLAG(&this->actor); + s32 colliderACHit = (this->collider.base.acFlags & AC_HIT) != 0; + s32 cutsceneRock = this->flags & ISHI_FLAG_CUTSCENE_ROCK; - if (sp34) { + if (colliderACHit) { this->collider.base.acFlags &= ~AC_HIT; } - if (Actor_HasParent(&this->actor, play)) { - func_8095E934(this); - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, D_8095F7AC[sp38]); - if (ENISHI_GET_2(&this->actor)) { - func_8095E204(this, play); + if (Actor_HasParent(&this->actor, play)) { // has been picked up by player + EnIshi_SetupHeldByPlayer(this); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, sIshiPullRockSfx[rockSize]); + if (ENISHI_GET_SPAWN_BUGS_FLAG(&this->actor)) { + EnIshi_SpawnBugs(this, play); } this->actor.shape.shadowDraw = ActorShadow_DrawCircle; return; } - if (sp34 && (sp38 == 0) && (this->collider.elem.acHitElem->atDmgInfo.dmgFlags & 0x508)) { - if (sp30 != 0) { - func_8095DFF0(this, play); - func_8095F060(this); + if (colliderACHit && (rockSize == ISHI_SIZE_SMALL_ROCK) && + (this->collider.elem.acHitElem->atDmgInfo.dmgFlags & 0x508)) { + if (cutsceneRock) { + EnIshi_DropCollectable(this, play); + EnIshi_SetupCutsceneExplode(this); return; } - func_8095DF90(this, play); - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, D_8095F6D4[sp38], D_8095F6D0[sp38]); - D_8095F6D8[sp38](&this->actor, play); - D_8095F6E0[sp38](this, play); + EnIshi_DropItem(this, play); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, sCutsceneSfxDuration[rockSize], + sCutsceneSfxId[rockSize]); + sIshiSpawnDebrisFuncs[rockSize](&this->actor, play); + sIshiSpawnDustFuncs[rockSize](&this->actor, play); Actor_Kill(&this->actor); return; } - if (sp34) { - this->unk_195 = 5; + if (colliderACHit) { + this->hitTimer = 5; } - if ((this->actor.xzDistToPlayer < 600.0f) || (sp30 != 0)) { - if (this->unk_195 > 0) { - this->unk_195--; - if (this->unk_195 == 0) { - this->collider.base.colMaterial = sCylinderInit[sp38].base.colMaterial; + if ((this->actor.xzDistToPlayer < 600.0f) || cutsceneRock) { + if (this->hitTimer > 0) { + this->hitTimer--; + if (this->hitTimer == 0) { + this->collider.base.colMaterial = sCylinderInit[rockSize].base.colMaterial; } else { this->collider.base.colMaterial = COL_MATERIAL_NONE; } @@ -511,8 +543,10 @@ void func_8095E660(EnIshi* this, PlayState* play) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); - if ((this->actor.xzDistToPlayer < 90.0f) && (sp30 == 0)) { - if (sp38 == 1) { + // pick up mechanic + if ((this->actor.xzDistToPlayer < 90.0f) && !cutsceneRock) { + if (rockSize == ISHI_SIZE_SILVER_BOULDER) { + // Silver can only be picked up by goron form Actor_OfferGetItem(&this->actor, play, GI_NONE, 80.0f, 20.0f); } else { Actor_OfferGetItem(&this->actor, play, GI_NONE, 50.0f, 10.0f); @@ -521,82 +555,88 @@ void func_8095E660(EnIshi* this, PlayState* play) { } } -void func_8095E934(EnIshi* this) { - this->actionFunc = func_8095E95C; +void EnIshi_SetupHeldByPlayer(EnIshi* this) { + this->actionFunc = EnIshi_HeldByPlayer; this->actor.room = -1; + // huh? is there someplace in the game where the camera can gain enough distance + // where the player is in camera view, in the distance, far enough to make it cull? this->actor.flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED; } -void func_8095E95C(EnIshi* this, PlayState* play) { +void EnIshi_HeldByPlayer(EnIshi* this, PlayState* play) { s32 pad; - Vec3f sp30; + Vec3f pos; s32 bgId; - if (Actor_HasNoParent(&this->actor, play)) { + if (Actor_HasNoParent(&this->actor, play)) { // player has tossed us this->actor.room = play->roomCtx.curRoom.num; - if (ENISHI_GET_1(&this->actor) == 1) { - Flags_SetSwitch(play, ENISHI_GET_FLAG(&this->actor)); + if (ENISHI_GET_SIZE_FLAG(&this->actor) == ISHI_SIZE_SILVER_BOULDER) { + Flags_SetSwitch(play, ENISHI_GET_SWITCH_FLAG(&this->actor)); } - func_8095EA70(this); - func_8095E14C(this); - func_8095E180(&this->actor.velocity, D_8095F6C8[ENISHI_GET_1(&this->actor)]); + EnIshi_SetupThrown(this); + EnIshi_ApplyGravity(this); + EnIshi_SetVelocity(&this->actor.velocity, sIshiVelocities[ENISHI_GET_SIZE_FLAG(&this->actor)]); Actor_UpdatePos(&this->actor); Actor_UpdateBgCheckInfo(play, &this->actor, 7.5f, 35.0f, 0.0f, UPDBGCHECKINFO_FLAG_1 | UPDBGCHECKINFO_FLAG_4 | UPDBGCHECKINFO_FLAG_40 | UPDBGCHECKINFO_FLAG_80); - } else { - sp30.x = this->actor.world.pos.x; - sp30.y = this->actor.world.pos.y + 20.0f; - sp30.z = this->actor.world.pos.z; + } else { // still being held, follow player + pos.x = this->actor.world.pos.x; + pos.y = this->actor.world.pos.y + 20.0f; + pos.z = this->actor.world.pos.z; + // why does it track floor height? it uses bgcollision to detect floor hit in Thrown this->actor.floorHeight = - BgCheck_EntityRaycastFloor5(&play->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &sp30); + BgCheck_EntityRaycastFloor5(&play->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &pos); } } -void func_8095EA70(EnIshi* this) { - f32 sp24; +void EnIshi_SetupThrown(EnIshi* this) { + f32 randomStart; this->actor.velocity.x = Math_SinS(this->actor.world.rot.y) * this->actor.speed; this->actor.velocity.z = Math_CosS(this->actor.world.rot.y) * this->actor.speed; - if (!ENISHI_GET_1(&this->actor)) { - sp24 = Rand_ZeroOne() - 0.9f; - D_8095F690 = sp24 * 11000.0f; - D_8095F694 = ((Rand_ZeroOne() - 0.5f) * 3000.0f) * (fabsf(sp24) + 0.1f); + if (!ENISHI_GET_SIZE_FLAG(&this->actor)) { + randomStart = Rand_ZeroOne() - 0.9f; + sIshiThrownXRotationVel = randomStart * 11000.0f; + sIshiThrownYRotationVel = ((Rand_ZeroOne() - 0.5f) * 3000.0f) * (fabsf(randomStart) + 0.1f); } else { - sp24 = Rand_ZeroOne() - 0.5f; - D_8095F690 = sp24 * 6000.0f; - D_8095F694 = ((Rand_ZeroOne() - 0.5f) * 1200.0f) * (fabsf(sp24) + 0.5f); + randomStart = Rand_ZeroOne() - 0.5f; + sIshiThrownXRotationVel = randomStart * 6000.0f; + sIshiThrownYRotationVel = ((Rand_ZeroOne() - 0.5f) * 1200.0f) * (fabsf(randomStart) + 0.5f); } + this->actor.colChkInfo.mass = 200; - this->unk_194 = 100; - this->actionFunc = func_8095EBDC; + this->thrownTimer = 100; + this->actionFunc = EnIshi_Thrown; } -void func_8095EBDC(EnIshi* this, PlayState* play) { +void EnIshi_Thrown(EnIshi* this, PlayState* play) { s32 pad; - s32 sp70 = ENISHI_GET_1(&this->actor); - s16 temp_s0; + s32 rockSize = ENISHI_GET_SIZE_FLAG(&this->actor); + s16 pad2; s32 i; - s16 phi_s0; - Vec3f sp58; - s32 temp_v0 = (this->collider.base.atFlags & AT_HIT) != 0; + s16 spashAngle; + Vec3f pos; + s32 colliderATHit = (this->collider.base.atFlags & AT_HIT) != 0; - if (temp_v0) { + if (colliderATHit) { this->collider.base.atFlags &= ~AT_HIT; } - this->unk_194--; + this->thrownTimer--; - if ((this->actor.bgCheckFlags & (BGCHECKFLAG_GROUND | BGCHECKFLAG_WALL)) || temp_v0 || (this->unk_194 <= 0)) { - func_8095DF90(this, play); - D_8095F6D8[sp70](&this->actor, play); + if ((this->actor.bgCheckFlags & (BGCHECKFLAG_GROUND | BGCHECKFLAG_WALL)) || colliderATHit || + (this->thrownTimer <= 0)) { + EnIshi_DropItem(this, play); + sIshiSpawnDebrisFuncs[rockSize](&this->actor, play); if (!(this->actor.bgCheckFlags & BGCHECKFLAG_WATER)) { - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, D_8095F6D4[sp70], D_8095F6D0[sp70]); - D_8095F6E0[sp70](this, play); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, sCutsceneSfxDuration[rockSize], + sCutsceneSfxId[rockSize]); + sIshiSpawnDustFuncs[rockSize](&this->actor, play); } - if (sp70 == 1) { + if (rockSize == ISHI_SIZE_SILVER_BOULDER) { s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 17232); @@ -611,24 +651,24 @@ void func_8095EBDC(EnIshi* this, PlayState* play) { } if (this->actor.bgCheckFlags & BGCHECKFLAG_WATER_TOUCH) { - if (sp70 == 0) { - sp58.x = this->actor.world.pos.x; - sp58.y = this->actor.world.pos.y + this->actor.depthInWater; - sp58.z = this->actor.world.pos.z; - EffectSsGSplash_Spawn(play, &sp58, NULL, NULL, 0, 350); - EffectSsGRipple_Spawn(play, &sp58, 150, 650, 0); + if (rockSize == ISHI_SIZE_SMALL_ROCK) { + pos.x = this->actor.world.pos.x; + pos.y = this->actor.world.pos.y + this->actor.depthInWater; + pos.z = this->actor.world.pos.z; + EffectSsGSplash_Spawn(play, &pos, NULL, NULL, 0, 350); + EffectSsGRipple_Spawn(play, &pos, 150, 650, 0); } else { - sp58.y = this->actor.world.pos.y + this->actor.depthInWater; + pos.y = this->actor.world.pos.y + this->actor.depthInWater; - for (phi_s0 = 0, i = 0; i < 11; i++, phi_s0 += 0x1746) { - sp58.x = this->actor.world.pos.x + (Math_SinS((s32)(Rand_ZeroOne() * 2000.0f) + phi_s0) * 50.0f); - sp58.z = this->actor.world.pos.z + (Math_CosS((s32)(Rand_ZeroOne() * 2000.0f) + phi_s0) * 50.0f); - EffectSsGSplash_Spawn(play, &sp58, NULL, NULL, 0, 350); + for (spashAngle = 0, i = 0; i < 11; i++, spashAngle += 0x1746) { + pos.x = this->actor.world.pos.x + (Math_SinS((s32)(Rand_ZeroOne() * 2000.0f) + spashAngle) * 50.0f); + pos.z = this->actor.world.pos.z + (Math_CosS((s32)(Rand_ZeroOne() * 2000.0f) + spashAngle) * 50.0f); + EffectSsGSplash_Spawn(play, &pos, NULL, NULL, 0, 350); } - sp58.x = this->actor.world.pos.x; - sp58.z = this->actor.world.pos.z; - EffectSsGRipple_Spawn(play, &sp58, 500, 900, 4); + pos.x = this->actor.world.pos.x; + pos.z = this->actor.world.pos.z; + EffectSsGRipple_Spawn(play, &pos, 500, 900, 4); } this->actor.terminalVelocity = -6.0f; @@ -637,19 +677,19 @@ void func_8095EBDC(EnIshi* this, PlayState* play) { this->actor.velocity.z *= 0.12f; this->actor.gravity *= 0.5f; - D_8095F690 >>= 2; - D_8095F694 >>= 2; + sIshiThrownXRotationVel >>= 2; + sIshiThrownYRotationVel >>= 2; SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 40, NA_SE_EV_DIVE_INTO_WATER_L); this->actor.bgCheckFlags &= ~BGCHECKFLAG_WATER_TOUCH; } Math_StepToF(&this->actor.shape.yOffset, 0.0f, 2.0f); - func_8095E14C(this); - func_8095E180(&this->actor.velocity, D_8095F6C8[sp70]); + EnIshi_ApplyGravity(this); + EnIshi_SetVelocity(&this->actor.velocity, sIshiVelocities[rockSize]); Actor_UpdatePos(&this->actor); - this->actor.shape.rot.x += D_8095F690; - this->actor.shape.rot.y += D_8095F694; + this->actor.shape.rot.x += sIshiThrownXRotationVel; + this->actor.shape.rot.y += sIshiThrownYRotationVel; Actor_UpdateBgCheckInfo(play, &this->actor, 7.5f, 35.0f, 0.0f, UPDBGCHECKINFO_FLAG_1 | UPDBGCHECKINFO_FLAG_4 | UPDBGCHECKINFO_FLAG_40 | UPDBGCHECKINFO_FLAG_80); @@ -658,33 +698,38 @@ void func_8095EBDC(EnIshi* this, PlayState* play) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base); } -void func_8095F060(EnIshi* this) { +// This should trigger cutscenes, but I couldnt get it to trigger in testing +// and this should trigger for all wall rocks in TF +void EnIshi_SetupCutsceneExplode(EnIshi* this) { this->actor.flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED; CutsceneManager_Queue(this->actor.csId); - this->actionFunc = func_8095F0A4; + this->actionFunc = EnIshi_CutsceneExplode; } -void func_8095F0A4(EnIshi* this, PlayState* play) { +void EnIshi_CutsceneExplode(EnIshi* this, PlayState* play) { s32 pad; - s32 sp28 = ENISHI_GET_1(&this->actor); + // Weirdly, you shouldnt be able to get here as silver boulder, + // it's explicitly ignored in EnIshi_Idle, the only path here + s32 rockSize = ENISHI_GET_SIZE_FLAG(&this->actor); if (CutsceneManager_IsNext(this->actor.csId)) { CutsceneManager_StartWithPlayerCs(this->actor.csId, &this->actor); - SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, D_8095F6D4[sp28], D_8095F6D0[sp28]); - D_8095F6D8[sp28](&this->actor, play); - D_8095F6E0[sp28](this, play); + SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, sCutsceneSfxDuration[rockSize], + sCutsceneSfxId[rockSize]); + sIshiSpawnDebrisFuncs[rockSize](&this->actor, play); + sIshiSpawnDustFuncs[rockSize](&this->actor, play); this->actor.draw = NULL; - func_8095F180(this); + EnIshi_SetupKill(this); } else { CutsceneManager_Queue(this->actor.csId); } } -void func_8095F180(EnIshi* this) { - this->actionFunc = func_8095F194; +void EnIshi_SetupKill(EnIshi* this) { + this->actionFunc = EnIshi_Kill; } -void func_8095F194(EnIshi* this, PlayState* play) { +void EnIshi_Kill(EnIshi* this, PlayState* play) { if (this->actor.csId <= CS_ID_NONE) { Actor_Kill(&this->actor); } else if (CutsceneManager_GetCurrentCsId() != this->actor.csId) { @@ -698,12 +743,13 @@ void EnIshi_Update(Actor* thisx, PlayState* play) { this->actionFunc(this, play); } -void func_8095F210(EnIshi* this, PlayState* play) { +void EnIshi_DrawGameplayKeepSmallRock(EnIshi* this, PlayState* play) { s32 pad; - s32 sp28; + s32 alpha; - if ((this->actor.projectedPos.z <= 1200.0f) || ((this->unk_197 & 1) && (this->actor.projectedPos.z < 1300.0f))) { - Gfx_DrawDListOpa(play, gameplay_field_keep_DL_0066B0); + if ((this->actor.projectedPos.z <= 1200.0f) || + ((this->flags & ISHI_FLAG_UNDERWATER) && (this->actor.projectedPos.z < 1300.0f))) { + Gfx_DrawDListOpa(play, gFieldSmallRockOpaDL); return; } @@ -712,41 +758,44 @@ void func_8095F210(EnIshi* this, PlayState* play) { Gfx_SetupDL25_Xlu(play->state.gfxCtx); - sp28 = (1300.0f - this->actor.projectedPos.z) * 2.55f; + alpha = (1300.0f - this->actor.projectedPos.z) * 2.55f; // lower alpha as the object falls toward the core MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, play->state.gfxCtx); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)sp28); - gSPDisplayList(POLY_XLU_DISP++, gameplay_field_keep_DL_006760); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)alpha); + gSPDisplayList(POLY_XLU_DISP++, gFieldSmallRockXluDL); CLOSE_DISPS(play->state.gfxCtx); } } -void func_8095F36C(EnIshi* this, PlayState* play) { +void EnIshi_DrawGameplayKeepBoulder(EnIshi* this, PlayState* play) { s32 pad; OPEN_DISPS(play->state.gfxCtx); - if ((this->actor.projectedPos.z <= 2150.0f) || ((this->unk_197 & 1) && (this->actor.projectedPos.z < 2250.0f))) { + if ((this->actor.projectedPos.z <= 2150.0f) || + ((this->flags & ISHI_FLAG_UNDERWATER) && (this->actor.projectedPos.z < 2250.0f))) { this->actor.shape.shadowAlpha = 160; Gfx_SetupDL25_Opa(play->state.gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); + gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); // empty displaylist MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255); - gSPDisplayList(POLY_OPA_DISP++, gameplay_field_keep_DL_0061E8); - } else if (this->actor.projectedPos.z < 2250.0f) { - f32 sp20 = (2250.0f - this->actor.projectedPos.z) * 2.55f; + gSPDisplayList(POLY_OPA_DISP++, gFieldSilverBoulderDL); - this->actor.shape.shadowAlpha = sp20 * 0.627451f; + } else if (this->actor.projectedPos.z < 2250.0f) { // falling after breaking + f32 alpha = (2250.0f - this->actor.projectedPos.z) * 2.55f; + + this->actor.shape.shadowAlpha = alpha * (160.0f / 255.0f); Gfx_SetupDL25_Xlu(play->state.gfxCtx); - gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); + gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); // in z_actor, transparency dl I think MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, play->state.gfxCtx); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)sp20); - gSPDisplayList(POLY_XLU_DISP++, gameplay_field_keep_DL_0061E8); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s32)alpha); + gSPDisplayList(POLY_XLU_DISP++, gFieldSilverBoulderDL); + } else { this->actor.shape.shadowAlpha = 0; } @@ -754,12 +803,12 @@ void func_8095F36C(EnIshi* this, PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); } -void func_8095F61C(Actor* thisx, PlayState* play) { +void EnIshi_DrawGameplayKeepObject(Actor* thisx, PlayState* play) { EnIshi* this = (EnIshi*)thisx; - D_8095F7B0[ENISHI_GET_1(&this->actor)](this, play); + sIshiGameplayKeepObjectDrawFuncs[ENISHI_GET_SIZE_FLAG(&this->actor)](this, play); } -void func_8095F654(Actor* thisx, PlayState* play) { +void EnIshi_DrawIshiObject(Actor* thisx, PlayState* play) { Gfx_DrawDListOpa(play, gSmallRockDL); } diff --git a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h index fe1898c13b..61f97519f0 100644 --- a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h +++ b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.h @@ -6,26 +6,44 @@ struct EnIshi; typedef void (*EnIshiActionFunc)(struct EnIshi*, PlayState*); -typedef void (*EnIshiUnkFunc)(struct EnIshi*, PlayState*); -typedef void (*EnIshiUnkFunc2)(Actor*, PlayState*); +typedef void (*EnIshiDrawFunc)(struct EnIshi*, PlayState*); +typedef void (*EnIshiSpawnFunc)(Actor*, PlayState*); -#define ENISHI_GET_1(thisx) ((thisx)->params & 1) -#define ENISHI_GET_2(thisx) (((thisx)->params >> 1) & 1) -#define ENISHI_GET_4(thisx) (((thisx)->params >> 2) & 1) -#define ENISHI_GET_8(thisx) (((thisx)->params >> 3) & 1) -#define ENISHI_GET_70(thisx) (((thisx)->params >> 4) & 7) -#define ENISHI_GET_F0(thisx) (((thisx)->params >> 4) & 0xF) -#define ENISHI_GET_100(thisx) (((thisx)->params >> 8) & 1) -#define ENISHI_GET_FLAG(thisx) (((thisx)->params >> 9) & 0x7F) +// silver boulder instead of small rock +#define ENISHI_GET_SIZE_FLAG(thisx) ((thisx)->params & 1) +#define ENISHI_GET_SPAWN_BUGS_FLAG(thisx) (((thisx)->params >> 1) & 1) +// for sitting still on rock/dirt cliffs in TF/Ikana Graveyard +#define ENISHI_GET_LEVITATE_FLAG(thisx) (((thisx)->params >> 2) & 1) +// dual objects: this actor can use field_keep or object_ishi +// the only place its used in the US version is the swamp spiderhouse, which uses dangeon_keep +#define ENISHI_GET_USE_OBJECT(thisx) (((thisx)->params >> 3) & 1) +// index of a collectable item list in .data +#define ENISHI_GET_COLLECTABLE_ID(thisx) (((thisx)->params >> 4) & 7) +#define ENISHI_GET_DROP_TABLE(thisx) (((thisx)->params >> 4) & 0xF) +#define ENISHI_GET_IGNORE_DROP_TABLE_FLAG(thisx) (((thisx)->params >> 8) & 1) +// these two are the same, but are used by different subtypes +#define ENISHI_GET_COLLECTABLE_FLAG(thisx) (((thisx)->params >> 9) & 0x7F) +#define ENISHI_GET_SWITCH_FLAG(thisx) (((thisx)->params >> 9) & 0x7F) + +#define ISHI_FLAG_UNDERWATER (1 << 0) +#define ISHI_FLAG_CUTSCENE_ROCK (1 << 1) + +typedef enum IshiSize { + /* 0 */ ISHI_SIZE_SMALL_ROCK, + /* 1 */ ISHI_SIZE_SILVER_BOULDER +} IshiSize; + +// if yRot is zero, y rotation gets randomized +#define ISHI_RANDOM_ROTATION_FLAG 0 typedef struct EnIshi { /* 0x000 */ Actor actor; /* 0x144 */ ColliderCylinder collider; /* 0x190 */ EnIshiActionFunc actionFunc; - /* 0x194 */ s8 unk_194; - /* 0x195 */ s8 unk_195; + /* 0x194 */ s8 thrownTimer; + /* 0x195 */ s8 hitTimer; /* 0x196 */ s8 objectSlot; - /* 0x197 */ u8 unk_197; + /* 0x197 */ u8 flags; } EnIshi; // size = 0x198 #endif // Z_EN_ISHI_H diff --git a/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c b/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c index 690c6ec11e..a755309593 100644 --- a/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c +++ b/src/overlays/actors/ovl_Obj_Bombiwa/z_obj_bombiwa.c @@ -462,7 +462,7 @@ void func_8093A418(Actor* thisx, PlayState* play) { sp28 = (2300.0f - this->actor.projectedPos.z) * 2.55f; - this->actor.shape.shadowAlpha = sp28 * (32.0f / 51); + this->actor.shape.shadowAlpha = sp28 * (160.0f / 255.0f); Gfx_SetupDL25_Xlu(play->state.gfxCtx); MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, play->state.gfxCtx); diff --git a/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c b/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c index ec23a3c11c..11366e7027 100644 --- a/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c +++ b/src/overlays/actors/ovl_Obj_Hamishi/z_obj_hamishi.c @@ -124,7 +124,7 @@ void func_809A10F4(ObjHamishi* this, PlayState* play) { } EffectSsKakera_Spawn(play, &spBC, &spC8, &this->actor.world.pos, gravity, phi_v0, 30, 5, 0, D_809A1AD4[i], 3, 0, - 70, 1, GAMEPLAY_FIELD_KEEP, gameplay_field_keep_DL_006420); + 70, 1, GAMEPLAY_FIELD_KEEP, gFieldSilverBoulderDebrisDL); } func_800BBFB0(play, &this->actor.world.pos, 140.0f, 6, 180, 90, 1); @@ -270,7 +270,7 @@ void ObjHamishi_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_OPA_DISP++, 0x08, D_801AEFA0); MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 170, 130, 255); - gSPDisplayList(POLY_OPA_DISP++, gameplay_field_keep_DL_0061E8); + gSPDisplayList(POLY_OPA_DISP++, gFieldSilverBoulderDL); } else if (thisx->projectedPos.z < 2250.0f) { f32 sp20 = (2250.0f - thisx->projectedPos.z) * 2.55f; @@ -280,7 +280,7 @@ void ObjHamishi_Draw(Actor* thisx, PlayState* play) { gSPSegment(POLY_XLU_DISP++, 0x08, D_801AEF88); MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, play->state.gfxCtx); gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 170, 130, (s32)sp20); - gSPDisplayList(POLY_XLU_DISP++, gameplay_field_keep_DL_0061E8); + gSPDisplayList(POLY_XLU_DISP++, gFieldSilverBoulderDL); } else { thisx->shape.shadowAlpha = 0; } diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 62ff276224..ab7b50d69b 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -7279,7 +7279,8 @@ void func_808379C0(PlayState* play, Player* this) { Actor* interactRangeActor = this->interactRangeActor; PlayerAnimationHeader* anim; - if ((interactRangeActor->id == ACTOR_EN_ISHI) && (ENISHI_GET_1(interactRangeActor) != 0)) { + if ((interactRangeActor->id == ACTOR_EN_ISHI) && + (ENISHI_GET_SIZE_FLAG(interactRangeActor) != ISHI_SIZE_SMALL_ROCK)) { Player_SetAction(play, this, Player_Action_38, 0); anim = &gPlayerAnim_link_silver_carry; } else if (((interactRangeActor->id == ACTOR_EN_BOMBF) || (interactRangeActor->id == ACTOR_EN_KUSA) || diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 2155bc78ba..4356900e43 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -7759,37 +7759,37 @@ 0x8095CFC8:("EnOwl_Draw",), 0x8095D074:("func_8095D074",), 0x8095D24C:("EnOwl_ChangeMode",), - 0x8095D6E0:("func_8095D6E0",), - 0x8095D758:("func_8095D758",), - 0x8095D804:("func_8095D804",), - 0x8095DABC:("func_8095DABC",), - 0x8095DDA8:("func_8095DDA8",), - 0x8095DE9C:("func_8095DE9C",), - 0x8095DF90:("func_8095DF90",), - 0x8095DFF0:("func_8095DFF0",), - 0x8095E14C:("func_8095E14C",), - 0x8095E180:("func_8095E180",), - 0x8095E204:("func_8095E204",), + 0x8095D6E0:("EnIshi_InitCollider",), + 0x8095D758:("EnIshi_SnapToFloor",), + 0x8095D804:("EnIshi_SpawnDebrisSmallRock",), + 0x8095DABC:("EnIshi_SpawnDebrisBoulder",), + 0x8095DDA8:("EnIshi_SpawnDustSmallRock",), + 0x8095DE9C:("EnIshi_SpawnDustBoulder",), + 0x8095DF90:("EnIshi_DropItem",), + 0x8095DFF0:("EnIshi_DropCollectable",), + 0x8095E14C:("EnIshi_ApplyGravity",), + 0x8095E180:("EnIshi_SetVelocity",), + 0x8095E204:("EnIshi_SpawnBugs",), 0x8095E2B0:("EnIshi_IsUnderwater",), 0x8095E328:("EnIshi_Init",), 0x8095E580:("EnIshi_Destroy",), - 0x8095E5AC:("func_8095E5AC",), - 0x8095E5C0:("func_8095E5C0",), - 0x8095E64C:("func_8095E64C",), - 0x8095E660:("func_8095E660",), - 0x8095E934:("func_8095E934",), - 0x8095E95C:("func_8095E95C",), - 0x8095EA70:("func_8095EA70",), - 0x8095EBDC:("func_8095EBDC",), - 0x8095F060:("func_8095F060",), - 0x8095F0A4:("func_8095F0A4",), - 0x8095F180:("func_8095F180",), - 0x8095F194:("func_8095F194",), + 0x8095E5AC:("EnIshi_SetupWaitForObject",), + 0x8095E5C0:("EnIshi_WaitForObject",), + 0x8095E64C:("EnIshi_SetupIdle",), + 0x8095E660:("EnIshi_Idle",), + 0x8095E934:("EnIshi_SetupHeldByPlayer",), + 0x8095E95C:("EnIshi_HeldByPlayer",), + 0x8095EA70:("EnIshi_SetupThrown",), + 0x8095EBDC:("EnIshi_Thrown",), + 0x8095F060:("EnIshi_SetupCutsceneExplode",), + 0x8095F0A4:("EnIshi_CutsceneExplode",), + 0x8095F180:("EnIshi_SetupKill",), + 0x8095F194:("EnIshi_Kill",), 0x8095F1EC:("EnIshi_Update",), - 0x8095F210:("func_8095F210",), - 0x8095F36C:("func_8095F36C",), - 0x8095F61C:("func_8095F61C",), - 0x8095F654:("func_8095F654",), + 0x8095F210:("EnIshi_DrawIshiObject",), + 0x8095F36C:("EnIshi_DrawGameplayKeepBoulder",), + 0x8095F61C:("EnIshi_DrawGameplayKeepObject",), + 0x8095F654:("EnIshi_DrawIshiObject",), 0x8095FB10:("ObjHana_Init",), 0x8095FB38:("ObjHana_Destroy",), 0x8095FB48:("ObjHana_Update",),