mirror of https://github.com/zeldaret/mm.git
Document EnTanron5 (destructible props, fragments, and item drops in Twinmold's arena) (#1319)
* Document EnTanron5 (destructible props, fragments, and item drops in Twinmold's arena) * Respond to engineer's review * Updated the type names, used "ruin" instead of "prop" in comments, and addressed Anon's review * Missed this instance of "prop" * Respond to engineer's review * Update OutNames too
This commit is contained in:
parent
82318a1c1b
commit
08006cc0ea
|
|
@ -36,13 +36,13 @@
|
|||
<DList Name="gTwinmoldHeadRightMandibleDL" Offset="0x6C68" />
|
||||
|
||||
<!-- DisplayLists and Textures for the destructible props in Twinmold's arena -->
|
||||
<DList Name="gTwinmoldPyramidRuinDL" Offset="0x6FD0" />
|
||||
<Texture Name="gTwinmoldPyramidRuinTLUT" OutName="pyramid_ruin_tlut" Format="rgba16" Width="4" Height="4" Offset="0x7158" />
|
||||
<Texture Name="gTwinmoldPyramidRuinTex" OutName="pyramid_ruin" Format="ci4" Width="64" Height="64" Offset="0x7178" />
|
||||
<DList Name="gTwinmoldRuinPyramidDL" Offset="0x6FD0" />
|
||||
<Texture Name="gTwinmoldRuinPyramidTLUT" OutName="ruin_pyramid_tlut" Format="rgba16" Width="4" Height="4" Offset="0x7158" />
|
||||
<Texture Name="gTwinmoldRuinPyramidTex" OutName="ruin_pyramid" Format="ci4" Width="64" Height="64" Offset="0x7178" />
|
||||
<DList Name="gRuinFragmentDL" Offset="0x7A88" />
|
||||
<DList Name="gTwinmoldMajoraPillarDL" Offset="0x7D18" />
|
||||
<Texture Name="gTwinmoldMajoraPillarTLUT" OutName="majora_pillar_tlut" Format="rgba16" Width="4" Height="4" Offset="0x7E30" />
|
||||
<Texture Name="gTwinmoldMajoraPillarTex" OutName="majora_pillar" Format="ci4" Width="64" Height="64" Offset="0x7E50" />
|
||||
<DList Name="gTwinmoldRuinPillarDL" Offset="0x7D18" />
|
||||
<Texture Name="gTwinmoldRuinPillarTLUT" OutName="ruin_pillar_tlut" Format="rgba16" Width="4" Height="4" Offset="0x7E30" />
|
||||
<Texture Name="gTwinmoldRuinPillarTex" OutName="ruin_pillar" Format="ci4" Width="64" Height="64" Offset="0x7E50" />
|
||||
|
||||
<!-- Twinmold Title Card -->
|
||||
<Texture Name="gTwinmoldTitleCardTex" OutName="twinmold_title_card" Format="ia8" Width="128" Height="40" Offset="0x8650" />
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "z64rumble.h"
|
||||
#include "z64shrink_window.h"
|
||||
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
|
||||
#include "overlays/actors/ovl_En_Tanron5/z_en_tanron5.h"
|
||||
#include "overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
|
||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||
|
||||
|
|
@ -41,7 +42,7 @@ Boss02* sBlueTwinmold;
|
|||
Boss02* sTwinmoldStatic;
|
||||
u8 sMusicStartTimer;
|
||||
DoorWarp1* sBlueWarp;
|
||||
TwinmoldEffect sEffects[150];
|
||||
TwinmoldEffect sEffects[TWINMOLD_EFFECT_COUNT];
|
||||
|
||||
static DamageTable sBlueTwinmoldDamageTable = {
|
||||
/* Deku Nut */ DMG_ENTRY(0, 0x0),
|
||||
|
|
@ -125,7 +126,11 @@ ActorInit Boss_02_InitVars = {
|
|||
(ActorFunc)Boss02_Twinmold_Draw,
|
||||
};
|
||||
|
||||
f32 D_809DF5B0 = 1.0f;
|
||||
/**
|
||||
* Multiplies the scale differently depending on whether the player is wearing the Giant's Mask or not.
|
||||
* When the player is wearing the Giant's Mask, this value is smaller to make the player seem larger.
|
||||
*/
|
||||
static f32 sGiantModeScaleFactor = 1.0f;
|
||||
|
||||
s16 D_809DF5B4[] = {
|
||||
0, 195, 190, 185, 180, 175, 170, 165, 160, 155, 150, 145, 140, 135, 130, 125, 120, 115, 110, 105, 100, 95, 90, 0,
|
||||
|
|
@ -482,7 +487,7 @@ void func_809DA24C(PlayState* play) {
|
|||
void Boss02_SpawnEffectSand(TwinmoldEffect* effects, Vec3f* pos, f32 scale) {
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effects++) {
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effects++) {
|
||||
if (effects->type == TWINMOLD_EFFECT_NONE) {
|
||||
effects->type = TWINMOLD_EFFECT_SAND;
|
||||
effects->pos = *pos;
|
||||
|
|
@ -503,7 +508,7 @@ void Boss02_SpawnEffectSand(TwinmoldEffect* effects, Vec3f* pos, f32 scale) {
|
|||
void Boss02_SpawnEffectFragment(TwinmoldEffect* effects, Vec3f* pos) {
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effects++) {
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effects++) {
|
||||
if (effects->type == TWINMOLD_EFFECT_NONE) {
|
||||
effects->type = TWINMOLD_EFFECT_FRAGMENT;
|
||||
effects->pos = *pos;
|
||||
|
|
@ -525,7 +530,7 @@ void Boss02_SpawnEffectFragment(TwinmoldEffect* effects, Vec3f* pos) {
|
|||
void Boss02_SpawnEffectFlash(TwinmoldEffect* effects, Vec3f* pos) {
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effects++) {
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effects++) {
|
||||
if ((effects->type == TWINMOLD_EFFECT_NONE) || (effects->type == TWINMOLD_EFFECT_FRAGMENT)) {
|
||||
effects->type = TWINMOLD_EFFECT_FLASH;
|
||||
effects->pos = *pos;
|
||||
|
|
@ -543,7 +548,7 @@ void func_809DA50C(s32 arg0, ColliderJntSph* collider, Vec3f* arg2) {
|
|||
collider->elements[arg0].dim.worldSphere.center.y = arg2->y;
|
||||
collider->elements[arg0].dim.worldSphere.center.z = arg2->z;
|
||||
collider->elements[arg0].dim.worldSphere.radius =
|
||||
collider->elements[arg0].dim.modelSphere.radius * collider->elements[arg0].dim.scale * D_809DF5B0;
|
||||
collider->elements[arg0].dim.modelSphere.radius * collider->elements[arg0].dim.scale * sGiantModeScaleFactor;
|
||||
}
|
||||
|
||||
void Boss02_Init(Actor* thisx, PlayState* play) {
|
||||
|
|
@ -551,7 +556,8 @@ void Boss02_Init(Actor* thisx, PlayState* play) {
|
|||
s32 i;
|
||||
s32 pad[2];
|
||||
|
||||
if (CHECK_WEEKEVENTREG(WEEKEVENTREG_CLEARED_STONE_TOWER_TEMPLE) && (this->actor.params == TWINMOLD_RED)) {
|
||||
if (CHECK_WEEKEVENTREG(WEEKEVENTREG_CLEARED_STONE_TOWER_TEMPLE) &&
|
||||
(TWINMOLD_GET_TYPE(&this->actor) == TWINMOLD_TYPE_RED)) {
|
||||
sBlueWarp = (DoorWarp1*)Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_DOOR_WARP1, 0.0f, 60.0f,
|
||||
0.0f, 0, 0, 0, 1);
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_ITEM_B_HEART, 0.0f, 30.0f, -150.0f, 0, 1, 0, BHEART_PARAM_NORMAL);
|
||||
|
|
@ -560,7 +566,7 @@ void Boss02_Init(Actor* thisx, PlayState* play) {
|
|||
this->actor.targetMode = 10;
|
||||
this->subCamUp.z = this->subCamUp.x = 0.0f;
|
||||
this->subCamUp.y = 1.0f;
|
||||
if (this->actor.params == TWINMOLD_STATIC) {
|
||||
if (TWINMOLD_GET_TYPE(&this->actor) == TWINMOLD_TYPE_STATIC) {
|
||||
sTwinmoldStatic = this;
|
||||
play->specialEffects = (void*)sEffects;
|
||||
this->actor.update = Boss02_Static_Update;
|
||||
|
|
@ -574,21 +580,22 @@ void Boss02_Init(Actor* thisx, PlayState* play) {
|
|||
this->unk_1D20 = 1;
|
||||
}
|
||||
R_MAGIC_CONSUME_TIMER_GIANTS_MASK = KREG(14) + 20;
|
||||
this->unk_01AC = 1.0f;
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_TANRON5, 0.0f, 1000.0f, 0.0f, 0, 0, 0, 0);
|
||||
} else if (this->actor.params == TWINMOLD_TAIL) {
|
||||
this->giantModeScaleFactor = 1.0f;
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_TANRON5, 0.0f, 1000.0f, 0.0f, 0, 0, 0,
|
||||
TWINMOLD_PROP_PARAMS(TWINMOLD_PROP_TYPE_STATIC));
|
||||
} else if (TWINMOLD_GET_TYPE(&this->actor) == TWINMOLD_TYPE_TAIL) {
|
||||
this->actor.update = Boss02_Tail_Update;
|
||||
this->actor.draw = NULL;
|
||||
this->actor.hintId = TATL_HINT_ID_TWINMOLD;
|
||||
} else {
|
||||
if (this->actor.params != TWINMOLD_BLUE) {
|
||||
this->actor.params = TWINMOLD_RED;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_02, 0.0f, 0.0f, 0.0f, 0, 0, 0, TWINMOLD_STATIC);
|
||||
if (TWINMOLD_GET_TYPE(&this->actor) != TWINMOLD_TYPE_BLUE) {
|
||||
this->actor.params = TWINMOLD_TYPE_RED;
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_02, 0.0f, 0.0f, 0.0f, 0, 0, 0, TWINMOLD_TYPE_STATIC);
|
||||
sRedTwinmold = this;
|
||||
sBlueTwinmold =
|
||||
(Boss02*)Actor_Spawn(&play->actorCtx, play, ACTOR_BOSS_02, this->actor.world.pos.x,
|
||||
this->actor.world.pos.y, this->actor.world.pos.z, this->actor.world.rot.x,
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, TWINMOLD_BLUE);
|
||||
this->actor.world.rot.y, this->actor.world.rot.z, TWINMOLD_TYPE_BLUE);
|
||||
sRedTwinmold->actor.colChkInfo.damageTable = &sRedTwinmoldDamageTable;
|
||||
sBlueTwinmold->actor.colChkInfo.damageTable = &sBlueTwinmoldDamageTable;
|
||||
sRedTwinmold->otherTwinmold = sBlueTwinmold;
|
||||
|
|
@ -621,7 +628,7 @@ void Boss02_Init(Actor* thisx, PlayState* play) {
|
|||
this->unk_014C = Rand_ZeroFloat(1000.0f);
|
||||
this->unk_1678 = 22;
|
||||
Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_BOSS_02, 0.0f, 0.0f, 0.0f, 0, 0, 0,
|
||||
TWINMOLD_TAIL);
|
||||
TWINMOLD_TYPE_TAIL);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -710,10 +717,10 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
|
||||
this->unk_0168 = 2000.0f;
|
||||
if (this->unk_0195 != 0) {
|
||||
this->actor.speed = this->unk_01A8 * D_809DF5B0 * 1.25f;
|
||||
this->actor.speed = this->unk_01A8 * sGiantModeScaleFactor * 1.25f;
|
||||
this->skelAnime.playSpeed = 2.0f;
|
||||
} else {
|
||||
this->actor.speed = this->unk_01A8 * D_809DF5B0;
|
||||
this->actor.speed = this->unk_01A8 * sGiantModeScaleFactor;
|
||||
}
|
||||
|
||||
Actor_UpdateVelocityWithoutGravity(&this->actor);
|
||||
|
|
@ -757,7 +764,7 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
}
|
||||
|
||||
if ((this->unk_0144 < 10) && (otherTwinmold->unk_0144 >= 20)) {
|
||||
this->unk_01B0.y = -1000.0f * D_809DF5B0;
|
||||
this->unk_01B0.y = -1000.0f * sGiantModeScaleFactor;
|
||||
if (sIsInGiantMode) {
|
||||
this->unk_01B0.y += 3150.0f;
|
||||
}
|
||||
|
|
@ -770,28 +777,28 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
return;
|
||||
|
||||
case 0:
|
||||
if ((this->actor.params == 0) && (Rand_ZeroOne() < 0.75f)) {
|
||||
if ((TWINMOLD_GET_TYPE(&this->actor) == TWINMOLD_TYPE_RED) && (Rand_ZeroOne() < 0.75f)) {
|
||||
this->actor.world.pos.x = player->actor.world.pos.x;
|
||||
this->actor.world.pos.z = player->actor.world.pos.z;
|
||||
this->actor.world.pos.y = player->actor.world.pos.y - (600.0f * D_809DF5B0);
|
||||
this->actor.world.pos.y = player->actor.world.pos.y - (600.0f * sGiantModeScaleFactor);
|
||||
} else {
|
||||
this->actor.world.pos.x = Rand_CenteredFloat(5000.0f * D_809DF5B0);
|
||||
this->actor.world.pos.z = Rand_CenteredFloat(5000.0f * D_809DF5B0);
|
||||
this->actor.world.pos.y = -500.0f * D_809DF5B0;
|
||||
this->actor.world.pos.x = Rand_CenteredFloat(5000.0f * sGiantModeScaleFactor);
|
||||
this->actor.world.pos.z = Rand_CenteredFloat(5000.0f * sGiantModeScaleFactor);
|
||||
this->actor.world.pos.y = -500.0f * sGiantModeScaleFactor;
|
||||
if (sIsInGiantMode) {
|
||||
this->actor.world.pos.y += 3150.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if ((fabsf(this->actor.world.pos.x) < (500.0f * D_809DF5B0)) &&
|
||||
(fabsf(this->actor.world.pos.z) < (500.0f * D_809DF5B0))) {
|
||||
if ((fabsf(this->actor.world.pos.x) < (500.0f * sGiantModeScaleFactor)) &&
|
||||
(fabsf(this->actor.world.pos.z) < (500.0f * sGiantModeScaleFactor))) {
|
||||
return;
|
||||
}
|
||||
|
||||
case 100:
|
||||
this->actor.shape.rot.x = 0x4000;
|
||||
this->unk_01B0.x = this->actor.world.pos.x;
|
||||
this->unk_01B0.y = this->actor.world.pos.y + (1000.0f * D_809DF5B0);
|
||||
this->unk_01B0.y = this->actor.world.pos.y + (1000.0f * sGiantModeScaleFactor);
|
||||
this->unk_01B0.z = this->actor.world.pos.z;
|
||||
this->unk_0146[0] = 100;
|
||||
this->unk_0144 = 1;
|
||||
|
|
@ -803,14 +810,15 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
this->unk_0146[0] = 150;
|
||||
} else {
|
||||
this->unk_0144 = 2;
|
||||
this->unk_01B0.x = Rand_CenteredFloat(3000.0f * D_809DF5B0);
|
||||
this->unk_01B0.z = Rand_CenteredFloat(3000.0f * D_809DF5B0);
|
||||
if ((fabsf(this->unk_01B0.x) < (500.0f * D_809DF5B0)) &&
|
||||
(fabsf(this->unk_01B0.z) < (500.0f * D_809DF5B0))) {
|
||||
this->unk_01B0.x = Rand_CenteredFloat(3000.0f * sGiantModeScaleFactor);
|
||||
this->unk_01B0.z = Rand_CenteredFloat(3000.0f * sGiantModeScaleFactor);
|
||||
if ((fabsf(this->unk_01B0.x) < (500.0f * sGiantModeScaleFactor)) &&
|
||||
(fabsf(this->unk_01B0.z) < (500.0f * sGiantModeScaleFactor))) {
|
||||
this->unk_01B0.x = 500.0f;
|
||||
this->unk_01B0.z = 500.0f;
|
||||
}
|
||||
this->unk_01B0.y = Rand_ZeroFloat(800.0f * D_809DF5B0) + (200.0f * D_809DF5B0);
|
||||
this->unk_01B0.y =
|
||||
Rand_ZeroFloat(800.0f * sGiantModeScaleFactor) + (200.0f * sGiantModeScaleFactor);
|
||||
if (sIsInGiantMode) {
|
||||
this->unk_01B0.y += 3150.0f;
|
||||
}
|
||||
|
|
@ -825,9 +833,9 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
} else {
|
||||
phi_f2 = 500.0f;
|
||||
}
|
||||
if (sqrtf(SQ(spCC) + SQ(spC8) + SQ(spC4)) < (phi_f2 * D_809DF5B0)) {
|
||||
if (sqrtf(SQ(spCC) + SQ(spC8) + SQ(spC4)) < (phi_f2 * sGiantModeScaleFactor)) {
|
||||
this->unk_0144 = 3;
|
||||
this->unk_01B0.y = -3000.0f * D_809DF5B0;
|
||||
this->unk_01B0.y = -3000.0f * sGiantModeScaleFactor;
|
||||
if (sIsInGiantMode) {
|
||||
this->unk_01B0.y += 3150.0f;
|
||||
}
|
||||
|
|
@ -844,16 +852,16 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
|
||||
case 5:
|
||||
this->unk_01B0.x = player->actor.world.pos.x;
|
||||
this->unk_01B0.y = player->actor.world.pos.y + (100.0f * D_809DF5B0);
|
||||
this->unk_01B0.y = player->actor.world.pos.y + (100.0f * sGiantModeScaleFactor);
|
||||
this->unk_01B0.z = player->actor.world.pos.z;
|
||||
if (this->unk_0146[0] == 0) {
|
||||
this->unk_0144 = 3;
|
||||
this->unk_01B0.x = Rand_CenteredFloat(500.0f * D_809DF5B0) + this->actor.world.pos.x;
|
||||
this->unk_01B0.y = -3000.0f * D_809DF5B0;
|
||||
this->unk_01B0.x = Rand_CenteredFloat(500.0f * sGiantModeScaleFactor) + this->actor.world.pos.x;
|
||||
this->unk_01B0.y = -3000.0f * sGiantModeScaleFactor;
|
||||
if (sIsInGiantMode) {
|
||||
this->unk_01B0.y += 3150.0f;
|
||||
}
|
||||
this->unk_01B0.z = Rand_CenteredFloat(500.0f * D_809DF5B0) + this->actor.world.pos.z;
|
||||
this->unk_01B0.z = Rand_CenteredFloat(500.0f * sGiantModeScaleFactor) + this->actor.world.pos.z;
|
||||
this->unk_0146[0] = 150;
|
||||
this->unk_0164 = 0.0f;
|
||||
}
|
||||
|
|
@ -864,8 +872,8 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
this->unk_019A = 0x500;
|
||||
this->unk_01A0 = 0x1200;
|
||||
} else {
|
||||
this->colliderCylinder.dim.radius = 150.0f * D_809DF5B0;
|
||||
this->colliderCylinder.dim.height = 200.0f * D_809DF5B0;
|
||||
this->colliderCylinder.dim.radius = 150.0f * sGiantModeScaleFactor;
|
||||
this->colliderCylinder.dim.height = 200.0f * sGiantModeScaleFactor;
|
||||
this->colliderCylinder.dim.yShift = 0;
|
||||
Collider_UpdateCylinder(&this->actor, &this->colliderCylinder);
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->colliderCylinder.base);
|
||||
|
|
@ -915,10 +923,11 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
if ((s16)(BREG(71) + 140) < this->unk_0146[1]) {
|
||||
if (this->unk_0146[0] == 0) {
|
||||
Matrix_RotateYS(Math_Atan2S(-player->actor.world.pos.x, -player->actor.world.pos.z), MTXMODE_NEW);
|
||||
Matrix_MultVecZ(1500.0f * D_809DF5B0, &spA4);
|
||||
Matrix_MultVecZ(1500.0f * sGiantModeScaleFactor, &spA4);
|
||||
this->unk_0146[0] = 50;
|
||||
this->unk_01B0.x = player->actor.world.pos.x + spA4.x;
|
||||
this->unk_01B0.y = Rand_CenteredFloat(500.0f * D_809DF5B0) + (600.0f * D_809DF5B0);
|
||||
this->unk_01B0.y =
|
||||
Rand_CenteredFloat(500.0f * sGiantModeScaleFactor) + (600.0f * sGiantModeScaleFactor);
|
||||
if (sIsInGiantMode) {
|
||||
this->unk_01B0.y += 3150.0f;
|
||||
}
|
||||
|
|
@ -926,7 +935,7 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
}
|
||||
this->unk_0168 = 3000.0f;
|
||||
} else {
|
||||
this->unk_01B0.y += 10.0f * D_809DF5B0;
|
||||
this->unk_01B0.y += 10.0f * sGiantModeScaleFactor;
|
||||
this->unk_0168 = 5000.0f;
|
||||
}
|
||||
this->unk_019A = 0x1000;
|
||||
|
|
@ -961,21 +970,21 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
this->unk_1678--;
|
||||
if (this->unk_1678 <= 0) {
|
||||
this->unk_0144 = 22;
|
||||
this->actor.gravity = -1.0f * D_809DF5B0;
|
||||
this->actor.gravity = -1.0f * sGiantModeScaleFactor;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.terminalVelocity = -1000.0f * D_809DF5B0;
|
||||
this->actor.terminalVelocity = -1000.0f * sGiantModeScaleFactor;
|
||||
this->unk_0164 = Rand_CenteredFloat(0.05f);
|
||||
|
||||
spCC = player->actor.world.pos.x - this->actor.world.pos.x;
|
||||
spC4 = player->actor.world.pos.z - this->actor.world.pos.z;
|
||||
if (sqrtf(SQ(spCC) + SQ(spC4)) < (400.0f * D_809DF5B0)) {
|
||||
this->actor.speed = 15.0f * D_809DF5B0;
|
||||
if (sqrtf(SQ(spCC) + SQ(spC4)) < (400.0f * sGiantModeScaleFactor)) {
|
||||
this->actor.speed = 15.0f * sGiantModeScaleFactor;
|
||||
}
|
||||
|
||||
spCC = this->actor.world.pos.x;
|
||||
spC4 = this->actor.world.pos.z;
|
||||
if (sqrtf(SQ(spCC) + SQ(spC4)) < (400.0f * D_809DF5B0)) {
|
||||
this->actor.speed = 15.0f * D_809DF5B0;
|
||||
if (sqrtf(SQ(spCC) + SQ(spC4)) < (400.0f * sGiantModeScaleFactor)) {
|
||||
this->actor.speed = 15.0f * sGiantModeScaleFactor;
|
||||
}
|
||||
|
||||
if (otherTwinmold->unk_0144 >= 10) {
|
||||
|
|
@ -1026,30 +1035,30 @@ void func_809DAB78(Boss02* this, PlayState* play) {
|
|||
|
||||
for (i = 0; i < 15; i++) {
|
||||
Matrix_RotateYF(((2.0f * (i * M_PI)) / 15.0f) + sp9C, MTXMODE_NEW);
|
||||
Matrix_MultVecZ((10 - this->unk_0146[0]) * (D_809DF5B0 * 300.0f) * 0.1f, &sp90);
|
||||
Matrix_MultVecZ((10 - this->unk_0146[0]) * (sGiantModeScaleFactor * 300.0f) * 0.1f, &sp90);
|
||||
spD0.x = this->unk_0170.x + sp90.x;
|
||||
spD0.y = this->unk_0170.y + (1000.0f * D_809DF5B0);
|
||||
spD0.y = this->unk_0170.y + (1000.0f * sGiantModeScaleFactor);
|
||||
spD0.z = this->unk_0170.z + sp90.z;
|
||||
if (BgCheck_EntityRaycastFloor3(&play->colCtx, &sp8C, &sp88, &spD0) != BGCHECK_Y_MIN) {
|
||||
spA0 = BgCheck_EntityRaycastFloor1(&play->colCtx, &sp8C, &spD0);
|
||||
Matrix_MultVecZ(5.0f * D_809DF5B0, &sp70);
|
||||
sp70.y = 2.0f * D_809DF5B0;
|
||||
sp64.y = 0.3f * D_809DF5B0;
|
||||
Matrix_MultVecZ(5.0f * sGiantModeScaleFactor, &sp70);
|
||||
sp70.y = 2.0f * sGiantModeScaleFactor;
|
||||
sp64.y = 0.3f * sGiantModeScaleFactor;
|
||||
sp64.z = 0.0f;
|
||||
sp64.x = 0.0f;
|
||||
sp7C.x = spD0.x;
|
||||
sp7C.y = spA0;
|
||||
sp7C.z = spD0.z;
|
||||
func_800B0F18(play, &sp7C, &sp70, &sp64, &D_809DFA98, &D_809DFA98,
|
||||
(Rand_ZeroFloat(500.0f) + 1200.0f) * D_809DF5B0, 20.0f * D_809DF5B0,
|
||||
Rand_ZeroFloat(5.0f) + 14.0f);
|
||||
(Rand_ZeroFloat(500.0f) + 1200.0f) * sGiantModeScaleFactor,
|
||||
20.0f * sGiantModeScaleFactor, Rand_ZeroFloat(5.0f) + 14.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->colliderCylinder.dim.radius = 150.0f * D_809DF5B0;
|
||||
this->colliderCylinder.dim.height = 200.0f * D_809DF5B0;
|
||||
this->colliderCylinder.dim.radius = 150.0f * sGiantModeScaleFactor;
|
||||
this->colliderCylinder.dim.height = 200.0f * sGiantModeScaleFactor;
|
||||
this->colliderCylinder.dim.yShift = 0;
|
||||
Collider_UpdateCylinder(&this->actor, &this->colliderCylinder);
|
||||
CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderCylinder.base);
|
||||
|
|
@ -1206,16 +1215,16 @@ void Boss02_Twinmold_Update(Actor* thisx, PlayState* play) {
|
|||
Actor_PlaySfx(&this->actor, NA_SE_EN_INBOSS_SAND_OLD - SFX_FLAG);
|
||||
|
||||
if (this->unk_0144 > 20) {
|
||||
sp3C.x = Rand_CenteredFloat(100.0f * D_809DF5B0) + this->unk_0170.x;
|
||||
sp3C.y = Rand_CenteredFloat(50.0f * D_809DF5B0) + this->unk_0170.y;
|
||||
sp3C.z = Rand_CenteredFloat(100.0f * D_809DF5B0) + this->unk_0170.z;
|
||||
sp3C.x = Rand_CenteredFloat(100.0f * sGiantModeScaleFactor) + this->unk_0170.x;
|
||||
sp3C.y = Rand_CenteredFloat(50.0f * sGiantModeScaleFactor) + this->unk_0170.y;
|
||||
sp3C.z = Rand_CenteredFloat(100.0f * sGiantModeScaleFactor) + this->unk_0170.z;
|
||||
Boss02_SpawnEffectSand(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
}
|
||||
|
||||
if ((this->unk_014C % 2) == 0) {
|
||||
sp3C.x = Rand_CenteredFloat(100.0f * D_809DF5B0) + this->unk_0170.x;
|
||||
sp3C.y = Rand_CenteredFloat(50.0f * D_809DF5B0) + this->unk_0170.y;
|
||||
sp3C.z = Rand_CenteredFloat(100.0f * D_809DF5B0) + this->unk_0170.z;
|
||||
sp3C.x = Rand_CenteredFloat(100.0f * sGiantModeScaleFactor) + this->unk_0170.x;
|
||||
sp3C.y = Rand_CenteredFloat(50.0f * sGiantModeScaleFactor) + this->unk_0170.y;
|
||||
sp3C.z = Rand_CenteredFloat(100.0f * sGiantModeScaleFactor) + this->unk_0170.z;
|
||||
Boss02_SpawnEffectSand(play->specialEffects, &sp3C, Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
}
|
||||
}
|
||||
|
|
@ -1281,7 +1290,7 @@ void Boss02_Twinmold_Update(Actor* thisx, PlayState* play) {
|
|||
void Boss02_Static_Update(Actor* thisx, PlayState* play) {
|
||||
Boss02* this = THIS;
|
||||
|
||||
this->unk_01AC = D_809DF5B0;
|
||||
this->giantModeScaleFactor = sGiantModeScaleFactor;
|
||||
play->envCtx.sandstormState = 0xD;
|
||||
|
||||
if (sBlueWarp != NULL) {
|
||||
|
|
@ -1352,7 +1361,7 @@ void Boss02_Twinmold_Draw(Actor* thisx, PlayState* play2) {
|
|||
|
||||
Gfx_SetupDL25_Opa(play->state.gfxCtx);
|
||||
|
||||
if (this->actor.params == 0) {
|
||||
if (TWINMOLD_GET_TYPE(&this->actor) == TWINMOLD_TYPE_RED) {
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(gTwinmoldRedSkinTex));
|
||||
} else {
|
||||
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(gTwinmoldBlueSkinTex));
|
||||
|
|
@ -1478,12 +1487,12 @@ void Boss02_UpdateEffects(PlayState* play) {
|
|||
floorY = 3150.0f;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type) {
|
||||
effect->timer++;
|
||||
effect->pos.x += effect->velocity.x * D_809DF5B0;
|
||||
effect->pos.y += effect->velocity.y * D_809DF5B0;
|
||||
effect->pos.z += effect->velocity.z * D_809DF5B0;
|
||||
effect->pos.x += effect->velocity.x * sGiantModeScaleFactor;
|
||||
effect->pos.y += effect->velocity.y * sGiantModeScaleFactor;
|
||||
effect->pos.z += effect->velocity.z * sGiantModeScaleFactor;
|
||||
effect->velocity.y += effect->accel.y;
|
||||
|
||||
if (effect->type < TWINMOLD_EFFECT_FRAGMENT) {
|
||||
|
|
@ -1525,7 +1534,7 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
Gfx_SetupDL25_Opa(play->state.gfxCtx);
|
||||
Gfx_SetupDL25_Xlu(play->state.gfxCtx);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(sEffects); i++, effect++) {
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_SAND) {
|
||||
if (!flag) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustMaterialDL);
|
||||
|
|
@ -1545,7 +1554,8 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
|
||||
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY);
|
||||
Matrix_Scale(effect->scale * sGiantModeScaleFactor, effect->scale * sGiantModeScaleFactor, 1.0f,
|
||||
MTXMODE_APPLY);
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustModelDL);
|
||||
|
|
@ -1553,7 +1563,7 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
}
|
||||
|
||||
effect = (TwinmoldEffect*)play->specialEffects;
|
||||
for (i = 0, flag = false; i < ARRAY_COUNT(sEffects); i++, effect++) {
|
||||
for (i = 0, flag = false; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_FRAGMENT) {
|
||||
if (!flag) {
|
||||
gDPSetCombineLERP(POLY_OPA_DISP++, SHADE, 0, PRIMITIVE, 0, SHADE, 0, PRIMITIVE, 0, SHADE, 0, PRIMITIVE,
|
||||
|
|
@ -1565,8 +1575,8 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
|
||||
Matrix_RotateYS(effect->rotY, MTXMODE_APPLY);
|
||||
Matrix_RotateXS(effect->rotX, MTXMODE_APPLY);
|
||||
Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, effect->scale * D_809DF5B0,
|
||||
MTXMODE_APPLY);
|
||||
Matrix_Scale(effect->scale * sGiantModeScaleFactor, effect->scale * sGiantModeScaleFactor,
|
||||
effect->scale * sGiantModeScaleFactor, MTXMODE_APPLY);
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gEffFragments1DL);
|
||||
|
|
@ -1574,7 +1584,7 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
}
|
||||
|
||||
effect = (TwinmoldEffect*)play->specialEffects;
|
||||
for (i = 0, flag = false; i < ARRAY_COUNT(sEffects); i++, effect++) {
|
||||
for (i = 0, flag = false; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_FLASH) {
|
||||
if (!flag) { //! @bug - dev forgot to set flag to 1, should only apply to first entry?
|
||||
gSPDisplayList(POLY_XLU_DISP++, gLightOrbMaterial1DL);
|
||||
|
|
@ -1585,7 +1595,8 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
|
||||
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY);
|
||||
Matrix_Scale(effect->scale * sGiantModeScaleFactor, effect->scale * sGiantModeScaleFactor, 1.0f,
|
||||
MTXMODE_APPLY);
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gLightOrbModelDL);
|
||||
|
|
@ -1593,7 +1604,7 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
}
|
||||
|
||||
effect = (TwinmoldEffect*)play->specialEffects;
|
||||
for (i = 0, flag = false; i < ARRAY_COUNT(sEffects); i++, effect++) {
|
||||
for (i = 0, flag = false; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_BLACK_DUST) {
|
||||
if (!flag) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustMaterialDL);
|
||||
|
|
@ -1608,7 +1619,8 @@ void Boss02_DrawEffects(PlayState* play) {
|
|||
|
||||
Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
|
||||
Matrix_ReplaceRotation(&play->billboardMtxF);
|
||||
Matrix_Scale(effect->scale * D_809DF5B0, effect->scale * D_809DF5B0, 1.0f, MTXMODE_APPLY);
|
||||
Matrix_Scale(effect->scale * sGiantModeScaleFactor, effect->scale * sGiantModeScaleFactor, 1.0f,
|
||||
MTXMODE_APPLY);
|
||||
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, gTwinmoldDustModelDL);
|
||||
|
|
@ -1771,12 +1783,12 @@ void func_809DD934(Boss02* this, PlayState* play) {
|
|||
if (sp57) {
|
||||
sIsInGiantMode = 1 - sIsInGiantMode;
|
||||
if (!sIsInGiantMode) {
|
||||
D_809DF5B0 = 1.0f;
|
||||
sGiantModeScaleFactor = 1.0f;
|
||||
} else {
|
||||
D_809DF5B0 = 0.1f;
|
||||
sGiantModeScaleFactor = 0.1f;
|
||||
}
|
||||
|
||||
this->unk_01AC = D_809DF5B0;
|
||||
this->giantModeScaleFactor = sGiantModeScaleFactor;
|
||||
if (!sIsInGiantMode) {
|
||||
if (sBlueWarp != NULL) {
|
||||
sBlueWarp->unk_203 = 0;
|
||||
|
|
@ -2183,8 +2195,8 @@ void func_809DEAC4(Boss02* this, PlayState* play) {
|
|||
this->subCamEye.y = 3160.0f;
|
||||
}
|
||||
|
||||
if (this->subCamAtNext.y < (100.0f * D_809DF5B0)) {
|
||||
this->subCamAtNext.y = (100.0f * D_809DF5B0);
|
||||
if (this->subCamAtNext.y < (100.0f * sGiantModeScaleFactor)) {
|
||||
this->subCamAtNext.y = (100.0f * sGiantModeScaleFactor);
|
||||
}
|
||||
|
||||
this->subCamEye.z = player->actor.world.pos.z;
|
||||
|
|
@ -2236,7 +2248,7 @@ void func_809DEAC4(Boss02* this, PlayState* play) {
|
|||
|
||||
if ((this->unk_1D20 != 0) && (this->subCamId != SUB_CAM_ID_DONE)) {
|
||||
subCamEye = this->subCamEye;
|
||||
subCamEye.y += sp58 * D_809DF5B0;
|
||||
subCamEye.y += sp58 * sGiantModeScaleFactor;
|
||||
Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &subCamEye, &this->subCamUp);
|
||||
this->subCamUp.z = this->subCamUp.x = 0.0f;
|
||||
this->subCamUp.y = 1.0f;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
struct Boss02;
|
||||
|
||||
#define TWINMOLD_GET_TYPE(thisx) ((thisx)->params)
|
||||
|
||||
typedef void (*Boss02ActionFunc)(struct Boss02*, PlayState*);
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -25,17 +27,19 @@ typedef struct {
|
|||
typedef enum {
|
||||
/* 0 */ TWINMOLD_EFFECT_NONE,
|
||||
/* 1 */ TWINMOLD_EFFECT_SAND, // The sand kicked up when Twinmold touches the ground
|
||||
/* 2 */ TWINMOLD_EFFECT_BLACK_DUST, // Unused
|
||||
/* 2 */ TWINMOLD_EFFECT_BLACK_DUST, // The dust that appears when either Twinmold or the player destroys a ruin
|
||||
/* 3 */ TWINMOLD_EFFECT_FRAGMENT, // The fragments that fly off when the parts of Twinmold explode
|
||||
/* 4 */ TWINMOLD_EFFECT_FLASH // The flashes of light that appear when the parts of Twinmold explode
|
||||
} TwinmoldEffectType;
|
||||
|
||||
#define TWINMOLD_EFFECT_COUNT 150
|
||||
|
||||
typedef enum {
|
||||
/* 0 */ TWINMOLD_RED,
|
||||
/* 35 */ TWINMOLD_BLUE = 35,
|
||||
/* 100 */ TWINMOLD_TAIL = 100,
|
||||
/* 200 */ TWINMOLD_STATIC = 200
|
||||
} TwinmoldParam;
|
||||
/* 0 */ TWINMOLD_TYPE_RED,
|
||||
/* 35 */ TWINMOLD_TYPE_BLUE = 35,
|
||||
/* 100 */ TWINMOLD_TYPE_TAIL = 100,
|
||||
/* 200 */ TWINMOLD_TYPE_STATIC = 200
|
||||
} TwinmoldType;
|
||||
|
||||
typedef struct Boss02 {
|
||||
/* 0x0000 */ Actor actor;
|
||||
|
|
@ -66,7 +70,7 @@ typedef struct Boss02 {
|
|||
/* 0x01A0 */ f32 unk_01A0;
|
||||
/* 0x01A4 */ s16 unk_01A4;
|
||||
/* 0x01A8 */ f32 unk_01A8;
|
||||
/* 0x01AC */ f32 unk_01AC;
|
||||
/* 0x01AC */ f32 giantModeScaleFactor;
|
||||
/* 0x01B0 */ Vec3f unk_01B0;
|
||||
/* 0x01BC */ Vec3f unk_01BC[200];
|
||||
/* 0x0B1C */ Vec3f unk_0B1C[200];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,23 @@
|
|||
/*
|
||||
* File: z_en_tanron5.c
|
||||
* Overlay: ovl_En_Tanron5
|
||||
* Description: Destructible props in Twinmold's arena
|
||||
* Description: Destructible ruins, fragments, and item drops in Twinmold's arena.
|
||||
*
|
||||
* This actor is responsible for three different interactive props in Twinmold's arena, all of which can be further
|
||||
* divided into more categories. The main thing this actor handles are the destructible ruins placed around the arena,
|
||||
* of which there are two kinds. There are pillars with Majora's Mask on them, and there are ruins in a roughly
|
||||
* pyramidal shape. While both types of ruin behave in roughly the same way, how they implement this behavior can
|
||||
* sometimes be quite different.
|
||||
*
|
||||
* When Twinmold or the player wearing the Giant's Mask hits one of these destructible ruins, various fragments
|
||||
* of the ruin fly off from the point of impact. These fragments are handled by this actor as well. The fragments
|
||||
* can be large or small, and the two sizes behave almost identically outside of two small differences. Large
|
||||
* fragments can damage the player and sink into the sand once they hit the ground, whereas small fragments
|
||||
* deal no damage and despawn upon touching the ground.
|
||||
*
|
||||
* Sometimes, item drops can also appear when a destructible ruin is hit; this actor is responsible for handling
|
||||
* these drops too. There are drops that give the player 10 arrows, and drops that give the player a big magic
|
||||
* jar, and these drops behave identically outside of what item they give when collected by the player.
|
||||
*/
|
||||
|
||||
#include "z_en_tanron5.h"
|
||||
|
|
@ -18,10 +34,15 @@ void EnTanron5_Destroy(Actor* thisx, PlayState* play);
|
|||
void EnTanron5_Update(Actor* thisx, PlayState* play2);
|
||||
void EnTanron5_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void func_80BE5818(Actor* thisx, PlayState* play2);
|
||||
void func_80BE5C10(Actor* thisx, PlayState* play);
|
||||
void EnTanron5_RuinFragmentItemDrop_Update(Actor* thisx, PlayState* play2);
|
||||
void EnTanron5_ItemDrop_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
s32 D_80BE5D80 = 0;
|
||||
typedef enum {
|
||||
/* 0 */ TWINMOLD_PROP_ITEM_DROP_TYPE_10_ARROWS,
|
||||
/* 1 */ TWINMOLD_PROP_ITEM_DROP_TYPE_MAGIC_JAR_BIG
|
||||
} TwinmoldPropItemDropType;
|
||||
|
||||
s32 sFragmentAndItemDropCount = 0;
|
||||
|
||||
ActorInit En_Tanron5_InitVars = {
|
||||
ACTOR_EN_TANRON5,
|
||||
|
|
@ -55,90 +76,136 @@ static ColliderCylinderInit sCylinderInit = {
|
|||
{ 70, 450, 0, { 0, 0, 0 } },
|
||||
};
|
||||
|
||||
f32 D_80BE5DD0 = 1.0f;
|
||||
/**
|
||||
* Multiplies the scale differently depending on whether the player is wearing the Giant's Mask or not.
|
||||
* When the player is wearing the Giant's Mask, this value is smaller to make the player seem larger.
|
||||
*/
|
||||
static f32 sGiantModeScaleFactor = 1.0f;
|
||||
|
||||
Vec2s D_80BE5DD4[] = {
|
||||
{ 0x4B0, 0x9C4 }, { -0x4B0, 0x9C4 }, { 0x4B0, -0x9C4 }, { -0x4B0, -0x9C4 }, { 0x9C4, 0x4B0 },
|
||||
{ -0x9C4, 0x4B0 }, { 0x9C4, -0x4B0 }, { -0x9C4, -0x4B0 }, { 0x3E8, 0x3E8 }, { -0x3E8, 0x3E8 },
|
||||
{ 0x3E8, -0x3E8 }, { -0x3E8, -0x3E8 }, { 0x000, -0x3E8 }, { 0x000, 0x3E8 }, { 0x3E8, 0x000 },
|
||||
{ -0x3E8, 0x000 }, { 0x000, -0x7D0 }, { 0x000, 0x7D0 }, { 0x7D0, 0x000 }, { -0x7D0, 0x000 },
|
||||
/**
|
||||
* Stores the X and Z spawn positions for all of the ruins. Their Y spawn position is determined by the
|
||||
* height of the floor, so there's no need to store it.
|
||||
*/
|
||||
static Vec2s sSpawnPosList[] = {
|
||||
{ 1200, 2500 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_1
|
||||
{ -1200, 2500 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_2
|
||||
{ 1200, -2500 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_3
|
||||
{ -1200, -2500 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_4
|
||||
{ 2500, 1200 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_5
|
||||
{ -2500, 1200 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_6
|
||||
{ 2500, -1200 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_7
|
||||
{ -2500, -1200 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_8
|
||||
{ 1000, 1000 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_9
|
||||
{ -1000, 1000 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_10
|
||||
{ 1000, -1000 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_11
|
||||
{ -1000, -1000 }, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_12
|
||||
{ 0, -1000 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_1
|
||||
{ 0, 1000 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_2
|
||||
{ 1000, 0 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_3
|
||||
{ -1000, 0 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_4
|
||||
{ 0, -2000 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_5
|
||||
{ 0, 2000 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_6
|
||||
{ 2000, 0 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_7
|
||||
{ -2000, 0 }, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_8
|
||||
};
|
||||
|
||||
Gfx* D_80BE5E24[] = {
|
||||
gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL,
|
||||
gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL,
|
||||
gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL, gTwinmoldMajoraPillarDL,
|
||||
gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL,
|
||||
gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL, gTwinmoldPyramidRuinDL,
|
||||
/**
|
||||
* Display lists for all ruins.
|
||||
*/
|
||||
static Gfx* sDLists[] = {
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_1
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_2
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_3
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_4
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_5
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_6
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_7
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_8
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_9
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_10
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_11
|
||||
gTwinmoldRuinPillarDL, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_12
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_1
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_2
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_3
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_4
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_5
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_6
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_7
|
||||
gTwinmoldRuinPyramidDL, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_8
|
||||
};
|
||||
|
||||
f32 D_80BE5E74[] = {
|
||||
0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f,
|
||||
0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f, 0.09f,
|
||||
/**
|
||||
* The initial base scale for all ruins. In the final game, this array isn't very useful,
|
||||
* since they're all the same value, but this could be used to make some ruins larger or
|
||||
* smaller than the others.
|
||||
*/
|
||||
static f32 sBaseScales[] = {
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_1
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_2
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_3
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_4
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_5
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_6
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_7
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_8
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_9
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_10
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_11
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PILLAR_12
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_1
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_2
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_3
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_4
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_5
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_6
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_7
|
||||
0.09f, // TWINMOLD_PROP_TYPE_RUIN_PYRAMID_8
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ Vec3f unk_00;
|
||||
/* 0x0C */ f32 unk_0C;
|
||||
/* 0x10 */ f32 unk_10;
|
||||
/* 0x14 */ f32 unk_14;
|
||||
/* 0x18 */ Vec3f unk_18;
|
||||
/* 0x24 */ u8 unk_24;
|
||||
/* 0x26 */ s16 unk_26;
|
||||
/* 0x28 */ UNK_TYPE1 unk28[0x4];
|
||||
/* 0x2C */ s16 unk_2C;
|
||||
/* 0x2E */ UNK_TYPE1 unk2E[0x6];
|
||||
/* 0x34 */ f32 unk_34;
|
||||
/* 0x38 */ f32 unk_38;
|
||||
} EnTanron5Effect; // size = 0x3C
|
||||
|
||||
void func_80BE4930(EnTanron5Effect* effect, Vec3f* arg1, f32 arg2) {
|
||||
/**
|
||||
* Spawns the sand effect that appears when a ruin fragment hits the ground.
|
||||
*/
|
||||
void EnTanron5_SpawnEffectSand(TwinmoldEffect* effect, Vec3f* pos, f32 scale) {
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < 150; i++, effect++) {
|
||||
if (effect->unk_24 == 0) {
|
||||
effect->unk_24 = 1;
|
||||
|
||||
effect->unk_00 = *arg1;
|
||||
|
||||
effect->unk_0C = Rand_CenteredFloat(10.0f);
|
||||
effect->unk_10 = Rand_ZeroFloat(2.0f) + 3.0f;
|
||||
effect->unk_14 = Rand_CenteredFloat(10.0f);
|
||||
|
||||
effect->unk_18.y = -0.15f;
|
||||
effect->unk_18.x = 0.0f;
|
||||
effect->unk_18.z = 0.0f;
|
||||
|
||||
effect->unk_2C = Rand_ZeroFloat(100.0f) + 200.0f;
|
||||
effect->unk_26 = 0;
|
||||
effect->unk_34 = arg2;
|
||||
effect->unk_38 = 2.0f * arg2;
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_NONE) {
|
||||
effect->type = TWINMOLD_EFFECT_SAND;
|
||||
effect->pos = *pos;
|
||||
effect->velocity.x = Rand_CenteredFloat(10.0f);
|
||||
effect->velocity.y = Rand_ZeroFloat(2.0f) + 3.0f;
|
||||
effect->velocity.z = Rand_CenteredFloat(10.0f);
|
||||
effect->accel.y = -0.15f;
|
||||
effect->accel.x = effect->accel.z = 0.0f;
|
||||
effect->alpha = Rand_ZeroFloat(100.0f) + 200.0f;
|
||||
effect->timer = 0;
|
||||
effect->scale = scale;
|
||||
effect->targetScale = 2.0f * scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void func_80BE4A2C(EnTanron5Effect* effect, Vec3f* arg1, f32 arg2) {
|
||||
/**
|
||||
* Spawns the black dust that appears whenever part of a ruin is destroyed.
|
||||
*/
|
||||
void EnTanron5_SpawnEffectBlackDust(TwinmoldEffect* effect, Vec3f* pos, f32 scale) {
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < 150; i++, effect++) {
|
||||
if (effect->unk_24 == 0) {
|
||||
effect->unk_24 = 2;
|
||||
|
||||
effect->unk_00 = *arg1;
|
||||
|
||||
effect->unk_0C = Rand_CenteredFloat(30.0f);
|
||||
effect->unk_10 = Rand_ZeroFloat(7.0f);
|
||||
effect->unk_14 = Rand_CenteredFloat(30.0f);
|
||||
|
||||
effect->unk_18.y = -0.3f;
|
||||
effect->unk_18.x = 0.0f;
|
||||
effect->unk_18.z = 0.0f;
|
||||
|
||||
effect->unk_2C = Rand_ZeroFloat(70.0f) + 150.0f;
|
||||
effect->unk_26 = 0;
|
||||
effect->unk_34 = arg2;
|
||||
effect->unk_38 = 2.0f * arg2;
|
||||
for (i = 0; i < TWINMOLD_EFFECT_COUNT; i++, effect++) {
|
||||
if (effect->type == TWINMOLD_EFFECT_NONE) {
|
||||
effect->type = TWINMOLD_EFFECT_BLACK_DUST;
|
||||
effect->pos = *pos;
|
||||
effect->velocity.x = Rand_CenteredFloat(30.0f);
|
||||
effect->velocity.y = Rand_ZeroFloat(7.0f);
|
||||
effect->velocity.z = Rand_CenteredFloat(30.0f);
|
||||
effect->accel.y = -0.3f;
|
||||
effect->accel.x = effect->accel.z = 0.0f;
|
||||
effect->alpha = Rand_ZeroFloat(70.0f) + 150.0f;
|
||||
effect->timer = 0;
|
||||
effect->scale = scale;
|
||||
effect->targetScale = 2.0f * scale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -147,54 +214,60 @@ void func_80BE4A2C(EnTanron5Effect* effect, Vec3f* arg1, f32 arg2) {
|
|||
void EnTanron5_Init(Actor* thisx, PlayState* play) {
|
||||
EnTanron5* this = THIS;
|
||||
|
||||
if (ENTANRON5_GET(&this->actor) >= ENTANRON5_100) {
|
||||
D_80BE5D80++;
|
||||
if (D_80BE5D80 > 60) {
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) >= TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_1) {
|
||||
// This is a ruin fragment or item drop; if there are more than 60 fragments or drops
|
||||
// already spawned, immediately kill this one. Otherwise, set up the fragment or drop
|
||||
// to fly off while spinning randomly.
|
||||
sFragmentAndItemDropCount++;
|
||||
if (sFragmentAndItemDropCount > 60) {
|
||||
Actor_Kill(&this->actor);
|
||||
return;
|
||||
}
|
||||
|
||||
this->unk_198 = Rand_CenteredFloat(0x2000);
|
||||
this->unk_19A = Rand_CenteredFloat(0x2000);
|
||||
// fragmentRotationalVelocityX is in a union with itemDropRotZ, so for item drops, this code
|
||||
// will initialize its z-rotation to a random value.
|
||||
this->fragmentRotationalVelocityX = Rand_CenteredFloat(0x2000);
|
||||
this->fragmentRotationalVelocityY = Rand_CenteredFloat(0x2000);
|
||||
|
||||
if (ENTANRON5_GET(&this->actor) < ENTANRON5_107) {
|
||||
Actor_SetScale(&this->actor, (Rand_ZeroFloat(0.025f) + 0.085f) * D_80BE5DD0);
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) <= TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_7) {
|
||||
Actor_SetScale(&this->actor, (Rand_ZeroFloat(0.025f) + 0.085f) * sGiantModeScaleFactor);
|
||||
} else {
|
||||
Actor_SetScale(&this->actor, (Rand_ZeroFloat(0.015f) + 0.01f) * D_80BE5DD0);
|
||||
Actor_SetScale(&this->actor, (Rand_ZeroFloat(0.015f) + 0.01f) * sGiantModeScaleFactor);
|
||||
}
|
||||
|
||||
this->actor.speed = (Rand_ZeroFloat(10.0f) + 10.0f) * D_80BE5DD0;
|
||||
this->actor.velocity.y = (Rand_ZeroFloat(10.0f) + 15.0f) * D_80BE5DD0;
|
||||
this->actor.gravity = -2.5f * D_80BE5DD0;
|
||||
this->actor.terminalVelocity = -1000.0f * D_80BE5DD0;
|
||||
this->actor.update = func_80BE5818;
|
||||
this->actor.speed = (Rand_ZeroFloat(10.0f) + 10.0f) * sGiantModeScaleFactor;
|
||||
this->actor.velocity.y = (Rand_ZeroFloat(10.0f) + 15.0f) * sGiantModeScaleFactor;
|
||||
this->actor.gravity = -2.5f * sGiantModeScaleFactor;
|
||||
this->actor.terminalVelocity = -1000.0f * sGiantModeScaleFactor;
|
||||
this->actor.update = EnTanron5_RuinFragmentItemDrop_Update;
|
||||
|
||||
if (ENTANRON5_GET(&this->actor) >= ENTANRON5_110) {
|
||||
this->actor.draw = func_80BE5C10;
|
||||
this->unk_1A0 = Rand_ZeroFloat(1.999f);
|
||||
Actor_SetScale(&this->actor, D_80BE5DD0 * 0.03f);
|
||||
this->unk_144 = 250;
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) >= TWINMOLD_PROP_TYPE_ITEM_DROP_1) {
|
||||
this->actor.draw = EnTanron5_ItemDrop_Draw;
|
||||
this->itemDropType = Rand_ZeroFloat(1.999f);
|
||||
Actor_SetScale(&this->actor, sGiantModeScaleFactor * 0.03f);
|
||||
this->timer = 250;
|
||||
this->actor.shape.rot.x = this->actor.shape.rot.y = this->actor.shape.rot.z = 0;
|
||||
} else {
|
||||
this->unk_148 = gRuinFragmentDL;
|
||||
this->unk_144 = 150;
|
||||
this->dList = gRuinFragmentDL;
|
||||
this->timer = 150;
|
||||
}
|
||||
} else if (ENTANRON5_GET(&this->actor) == ENTANRON5_0) {
|
||||
} else if (TWINMOLD_PROP_GET_TYPE(&this->actor) == TWINMOLD_PROP_TYPE_STATIC) {
|
||||
EnTanron5* child;
|
||||
s32 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(D_80BE5E74); i++) {
|
||||
child =
|
||||
(EnTanron5*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, D_80BE5DD4[i].x,
|
||||
this->actor.world.pos.y, D_80BE5DD4[i].z, 0, Rand_ZeroFloat(0x10000), 0, i + 1);
|
||||
// Spawns all of the ruins in the right places. Gets killed after everything is spawned.
|
||||
for (i = 0; i < ARRAY_COUNT(sSpawnPosList); i++) {
|
||||
child = (EnTanron5*)Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, sSpawnPosList[i].x,
|
||||
this->actor.world.pos.y, sSpawnPosList[i].z, 0, Rand_ZeroFloat(0x10000), 0,
|
||||
TWINMOLD_PROP_PARAMS(TWINMOLD_PROP_TYPE_RUIN_PILLAR_1 + i));
|
||||
|
||||
child->actor.parent = this->actor.parent;
|
||||
child->unk_19C = D_80BE5E74[i];
|
||||
child->baseScale = sBaseScales[i];
|
||||
|
||||
Actor_SetScale(&child->actor, child->unk_19C);
|
||||
Actor_SetScale(&child->actor, child->baseScale);
|
||||
|
||||
child->unk_148 = D_80BE5E24[i];
|
||||
if (child->unk_148 == gTwinmoldPyramidRuinDL) {
|
||||
child->dList = sDLists[i];
|
||||
if (child->dList == gTwinmoldRuinPyramidDL) {
|
||||
child->actor.shape.rot.y = 0;
|
||||
}
|
||||
|
||||
|
|
@ -203,6 +276,8 @@ void EnTanron5_Init(Actor* thisx, PlayState* play) {
|
|||
|
||||
Actor_Kill(&this->actor);
|
||||
} else {
|
||||
// This is a ruin; update its y-position to be just below the floor, so it looks like it's
|
||||
// buried in the sand.
|
||||
Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 150.0f, 100.0f, UPDBGCHECKINFO_FLAG_4);
|
||||
this->actor.world.pos.y = this->actor.floorHeight + -20.0f;
|
||||
}
|
||||
|
|
@ -211,25 +286,31 @@ void EnTanron5_Init(Actor* thisx, PlayState* play) {
|
|||
void EnTanron5_Destroy(Actor* thisx, PlayState* play) {
|
||||
EnTanron5* this = THIS;
|
||||
|
||||
if (ENTANRON5_GET(&this->actor) >= ENTANRON5_100) {
|
||||
D_80BE5D80--;
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) >= TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_1) {
|
||||
sFragmentAndItemDropCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the update function for the destructible ruins (both the pillar and pyarmid ruins).
|
||||
*/
|
||||
void EnTanron5_Update(Actor* thisx, PlayState* play2) {
|
||||
PlayState* play = play2;
|
||||
EnTanron5* this = THIS;
|
||||
Boss02* boss02 = (Boss02*)this->actor.parent;
|
||||
Player* player = GET_PLAYER(play2);
|
||||
s32 i;
|
||||
s32 phi_v0;
|
||||
s32 spC4;
|
||||
Vec3f spB8;
|
||||
s32 yawDiff;
|
||||
s32 fragmentAndItemCount;
|
||||
Vec3f pos;
|
||||
|
||||
if (this->unk_1A0 >= 3) {
|
||||
this->unk_1A0++;
|
||||
// When a ruin is destroyed (i.e., it is hit three times), it will reduce its scale to 0.0f (making
|
||||
// it effectively invisible and intangible), then wait an additional 37 frames before actually
|
||||
// calling Actor_Kill to despawn. The reason for this extra waiting period is unknown.
|
||||
if (this->hitCount >= 3) {
|
||||
this->hitCount++;
|
||||
Actor_SetScale(&this->actor, 0.0f);
|
||||
if (this->unk_1A0 >= 40) {
|
||||
if (this->hitCount >= 40) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
return;
|
||||
|
|
@ -237,154 +318,184 @@ void EnTanron5_Update(Actor* thisx, PlayState* play2) {
|
|||
// required
|
||||
}
|
||||
|
||||
if (this->unk_144 != 0) {
|
||||
this->unk_144--;
|
||||
}
|
||||
DECR(this->timer);
|
||||
|
||||
//! @bug This code will keep sGiantModeScaleFactor up-to-date so long as at least one ruin is still active.
|
||||
//! However, once the last ruin is destroyed, this code will no longer run, so sGiantModeScaleFactor will
|
||||
//! get "stuck" at whatever its current value is. This is a problem, because other instances of EnTanron5,
|
||||
//! like the item drops, rely on this variable being updated to function properly. Getting in this "stuck"
|
||||
//! state can result in odd behavior for these other instances, like item drops not being obtainable when
|
||||
//! the player is normal-sized.
|
||||
//!
|
||||
//! The strange waiting period before despawning seen above may be an attempt to mitigate this, but it
|
||||
//! doesn't work. It doesn't update sGiantModeScaleFactor, and even if it did, waiting 37 frames before
|
||||
//! despawning is far too short of a time to wait, since item drops take 250 frames to despawn.
|
||||
if (boss02->actor.update != NULL) {
|
||||
D_80BE5DD0 = boss02->unk_01AC;
|
||||
sGiantModeScaleFactor = boss02->giantModeScaleFactor;
|
||||
} else {
|
||||
D_80BE5DD0 = 1.0f;
|
||||
sGiantModeScaleFactor = 1.0f;
|
||||
}
|
||||
|
||||
Actor_SetScale(&this->actor, this->unk_19C * D_80BE5DD0);
|
||||
Actor_SetScale(&this->actor, this->baseScale * sGiantModeScaleFactor);
|
||||
|
||||
if (this->unk_148 == gTwinmoldMajoraPillarDL) {
|
||||
this->collider.dim.radius = 65.0f * D_80BE5DD0;
|
||||
this->collider.dim.height = 380.0f * D_80BE5DD0;
|
||||
} else if (this->unk_1A0 == 0) {
|
||||
this->collider.dim.radius = 85.0f * D_80BE5DD0;
|
||||
this->collider.dim.height = 200.0f * D_80BE5DD0;
|
||||
} else if (this->unk_1A0 == 1) {
|
||||
this->collider.dim.radius = 95.0f * D_80BE5DD0;
|
||||
this->collider.dim.height = 100.0f * D_80BE5DD0;
|
||||
} else if (this->unk_1A0 == 2) {
|
||||
this->collider.dim.radius = 95.0f * D_80BE5DD0;
|
||||
this->collider.dim.height = 30.0f * D_80BE5DD0;
|
||||
if (this->dList == gTwinmoldRuinPillarDL) {
|
||||
this->collider.dim.radius = 65.0f * sGiantModeScaleFactor;
|
||||
this->collider.dim.height = 380.0f * sGiantModeScaleFactor;
|
||||
} else if (this->hitCount == 0) {
|
||||
this->collider.dim.radius = 85.0f * sGiantModeScaleFactor;
|
||||
this->collider.dim.height = 200.0f * sGiantModeScaleFactor;
|
||||
} else if (this->hitCount == 1) {
|
||||
this->collider.dim.radius = 95.0f * sGiantModeScaleFactor;
|
||||
this->collider.dim.height = 100.0f * sGiantModeScaleFactor;
|
||||
} else if (this->hitCount == 2) {
|
||||
this->collider.dim.radius = 95.0f * sGiantModeScaleFactor;
|
||||
this->collider.dim.height = 30.0f * sGiantModeScaleFactor;
|
||||
}
|
||||
|
||||
if (this->unk_144 == 0) {
|
||||
if (this->timer == 0) {
|
||||
if (this->collider.base.acFlags & AC_HIT) {
|
||||
ColliderInfo* acHitInfo = this->collider.info.acHitInfo;
|
||||
Actor* ac = this->collider.base.ac;
|
||||
|
||||
this->collider.base.acFlags &= ~AC_HIT;
|
||||
spC4 = 10;
|
||||
fragmentAndItemCount = 10;
|
||||
|
||||
if (Play_InCsMode(play)) {
|
||||
this->unk_144 = 1;
|
||||
// In Twinmold's opening cutscene, it emerges from the sand beneath a ruin and destroys it.
|
||||
// Setting the timer to 1 here allows Twinmold to hit the ruin every single frame during the
|
||||
// cutscene, allowing it to destory the ruin in only 3 frames.
|
||||
this->timer = 1;
|
||||
} else {
|
||||
this->unk_144 = 5;
|
||||
spC4 = (s32)Rand_ZeroFloat(2.99f) + 10;
|
||||
this->timer = 5;
|
||||
fragmentAndItemCount = (s32)Rand_ZeroFloat(2.99f) + 10;
|
||||
}
|
||||
|
||||
if ((KREG(19) != 0) || ((acHitInfo->toucher.dmgFlags & 0x05000202) && (D_80BE5DD0 < 0.5f)) ||
|
||||
if ((KREG(19) != 0) || ((acHitInfo->toucher.dmgFlags & 0x05000202) && (sGiantModeScaleFactor < 0.5f)) ||
|
||||
(ac->id == ACTOR_BOSS_02)) {
|
||||
if (this->unk_148 == gTwinmoldMajoraPillarDL) {
|
||||
Math_Vec3f_Copy(&spB8, &this->actor.world.pos);
|
||||
spB8.y += D_80BE5DD0 * 300.0f;
|
||||
if (this->dList == gTwinmoldRuinPillarDL) {
|
||||
// To create the appearance of the pillar shrinking after being hit, push it further into the floor,
|
||||
// spawn some ruin fragments, and also spawn some black dust effects.
|
||||
Math_Vec3f_Copy(&pos, &this->actor.world.pos);
|
||||
pos.y += sGiantModeScaleFactor * 300.0f;
|
||||
|
||||
for (i = 3; i < spC4; i++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, spB8.x, spB8.y, spB8.z,
|
||||
Rand_ZeroFloat(0x10000), Rand_ZeroFloat(0x10000), 0, i + 100);
|
||||
// This will spawn four normal-sized ruin fragments, three small ruin fragments, and
|
||||
// zero, one, or two item drops, depending on the result of Rand_ZeroFloat above.
|
||||
for (i = 3; i < fragmentAndItemCount; i++) {
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, pos.x, pos.y, pos.z,
|
||||
Rand_ZeroFloat(0x10000), Rand_ZeroFloat(0x10000), 0,
|
||||
TWINMOLD_PROP_PARAMS(TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_1 + i));
|
||||
}
|
||||
|
||||
for (i = 0; i < 6; i++) {
|
||||
func_80BE4A2C(play->specialEffects, &spB8, Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
EnTanron5_SpawnEffectBlackDust(play->specialEffects, &pos, Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
}
|
||||
|
||||
this->actor.world.pos.y -= D_80BE5DD0 * 130.0f;
|
||||
this->actor.world.pos.y -= sGiantModeScaleFactor * 130.0f;
|
||||
} else {
|
||||
f32 spAC;
|
||||
f32 spA8;
|
||||
Vec3f sp9C;
|
||||
f32 yFactor;
|
||||
f32 xzFactor;
|
||||
Vec3f fragmentAndDustPos;
|
||||
|
||||
if (this->unk_1A0 == 0) {
|
||||
spAC = 180.0f;
|
||||
this->unk_19C *= 1.4f;
|
||||
} else if (this->unk_1A0 == 1) {
|
||||
spAC = 230.0f;
|
||||
this->unk_19C *= 1.37f;
|
||||
} else if (this->unk_1A0 == 2) {
|
||||
spAC = 780.0f;
|
||||
this->unk_19C *= 1.5f;
|
||||
// Check the number of times this pyramid ruin has been hit to scale it accordingly.
|
||||
if (this->hitCount == 0) {
|
||||
yFactor = 180.0f;
|
||||
this->baseScale *= 1.4f;
|
||||
} else if (this->hitCount == 1) {
|
||||
yFactor = 230.0f;
|
||||
this->baseScale *= 1.37f;
|
||||
} else if (this->hitCount == 2) {
|
||||
yFactor = 780.0f;
|
||||
this->baseScale *= 1.5f;
|
||||
}
|
||||
// TODO: determine if unk_1A0 ever has a different value from these 3, which will cause UB from spAC
|
||||
// being uninitialised
|
||||
this->actor.world.pos.y -= D_80BE5DD0 * spAC;
|
||||
Actor_SetScale(&this->actor, this->unk_19C * D_80BE5DD0);
|
||||
Math_Vec3f_Copy(&spB8, &this->actor.world.pos);
|
||||
|
||||
for (i = 0; i < spC4; i++) {
|
||||
if (this->unk_1A0 == 0) {
|
||||
spA8 = 100.0f;
|
||||
spAC = 180.0f;
|
||||
} else if (this->unk_1A0 == 1) {
|
||||
spA8 = 200.0f;
|
||||
spAC = 100.0f;
|
||||
} else if (this->unk_1A0 == 2) {
|
||||
spA8 = 250.0f;
|
||||
spAC = 50.0f;
|
||||
this->actor.world.pos.y -= sGiantModeScaleFactor * yFactor;
|
||||
Actor_SetScale(&this->actor, this->baseScale * sGiantModeScaleFactor);
|
||||
Math_Vec3f_Copy(&pos, &this->actor.world.pos);
|
||||
|
||||
for (i = 0; i < fragmentAndItemCount; i++) {
|
||||
if (this->hitCount == 0) {
|
||||
xzFactor = 100.0f;
|
||||
yFactor = 180.0f;
|
||||
} else if (this->hitCount == 1) {
|
||||
xzFactor = 200.0f;
|
||||
yFactor = 100.0f;
|
||||
} else if (this->hitCount == 2) {
|
||||
xzFactor = 250.0f;
|
||||
yFactor = 50.0f;
|
||||
}
|
||||
|
||||
sp9C.x = (Rand_CenteredFloat(spA8) * D_80BE5DD0) + spB8.x;
|
||||
sp9C.z = (Rand_CenteredFloat(spA8) * D_80BE5DD0) + spB8.z;
|
||||
sp9C.y = this->actor.floorHeight + (spAC * D_80BE5DD0);
|
||||
fragmentAndDustPos.x = pos.x + (Rand_CenteredFloat(xzFactor) * sGiantModeScaleFactor);
|
||||
fragmentAndDustPos.z = pos.z + (Rand_CenteredFloat(xzFactor) * sGiantModeScaleFactor);
|
||||
fragmentAndDustPos.y = this->actor.floorHeight + (yFactor * sGiantModeScaleFactor);
|
||||
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, sp9C.x, sp9C.y, sp9C.z,
|
||||
Rand_ZeroFloat(0x10000), Rand_ZeroFloat(0x10000), 0, i + 100);
|
||||
// This will spawn seven normal-sized ruin fragments, three small ruin fragments, and
|
||||
// zero, one, or two item drops, depending on the result of Rand_ZeroFloat above.
|
||||
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TANRON5, fragmentAndDustPos.x, fragmentAndDustPos.y,
|
||||
fragmentAndDustPos.z, Rand_ZeroFloat(0x10000), Rand_ZeroFloat(0x10000), 0,
|
||||
TWINMOLD_PROP_PARAMS(TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_1 + i));
|
||||
|
||||
if (i < 8) {
|
||||
func_80BE4A2C(play->specialEffects, &sp9C, Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
EnTanron5_SpawnEffectBlackDust(play->specialEffects, &fragmentAndDustPos,
|
||||
Rand_ZeroFloat(3.0f) + 6.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// To better sell the illusion of the ruin being partially destroyed when it's hit
|
||||
// rather than just being pushed into the ground (which is what actually happens),
|
||||
// this code will rotate the ruin in a somewhat-random way.
|
||||
if (Rand_ZeroOne() < 0.333f) {
|
||||
phi_v0 = 0x4000;
|
||||
yawDiff = 0x4000;
|
||||
} else if (Rand_ZeroOne() < 0.5f) {
|
||||
phi_v0 = -0x8000;
|
||||
yawDiff = -0x8000;
|
||||
} else {
|
||||
phi_v0 = -0x4000;
|
||||
yawDiff = -0x4000;
|
||||
}
|
||||
|
||||
this->actor.shape.rot.y += phi_v0;
|
||||
this->actor.shape.rot.y += yawDiff;
|
||||
Actor_PlaySfx(&this->actor, NA_SE_IT_BIG_BOMB_EXPLOSION);
|
||||
Actor_RequestQuakeAndRumble(&this->actor, play, 4, 4);
|
||||
this->unk_1A0++;
|
||||
this->hitCount++;
|
||||
} else {
|
||||
Vec3f sp90;
|
||||
// Something hit the ruin, but it wasn't Twinmold, and it wasn't the player while in giant
|
||||
// mode. Play the reflect sound effect and spawn some sparks instead of breaking.
|
||||
Vec3f hitPos;
|
||||
ColliderInfo* info = this->collider.info.acHitInfo;
|
||||
|
||||
sp90.x = info->bumper.hitPos.x;
|
||||
sp90.y = info->bumper.hitPos.y;
|
||||
sp90.z = info->bumper.hitPos.z;
|
||||
hitPos.x = info->bumper.hitPos.x;
|
||||
hitPos.y = info->bumper.hitPos.y;
|
||||
hitPos.z = info->bumper.hitPos.z;
|
||||
|
||||
Actor_PlaySfx(&this->actor, NA_SE_IT_SHIELD_REFLECT_SW);
|
||||
CollisionCheck_SpawnShieldParticlesMetal(play, &sp90);
|
||||
CollisionCheck_SpawnShieldParticlesMetal(play, &hitPos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider);
|
||||
if (this->unk_148 == gTwinmoldPyramidRuinDL) {
|
||||
if (this->dList == gTwinmoldRuinPyramidDL) {
|
||||
this->collider.dim.pos.y = this->actor.floorHeight;
|
||||
}
|
||||
|
||||
if ((this->unk_148 == gTwinmoldMajoraPillarDL) || (D_80BE5DD0 < 0.5f)) {
|
||||
if ((this->dList == gTwinmoldRuinPillarDL) || (sGiantModeScaleFactor < 0.5f)) {
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
|
||||
} else {
|
||||
// The collider cylinder used for the pyramid ruin is smaller than the ruin's visual appearance. When
|
||||
// the player is wearing the Giant's Mask, it works fine, but when the player is normal-sized, they can
|
||||
// walk through the sides of the ruin and wander around inside it without the collider pushing them out.
|
||||
// The below code prevents this from happening by manually updating the player's position if they get
|
||||
// close enough to the ruin, effectively creating a collision "box" around it that pushes players out.
|
||||
f32 xDiff = player->actor.world.pos.x - this->actor.world.pos.x;
|
||||
f32 yDiff = player->actor.world.pos.z - this->actor.world.pos.z;
|
||||
f32 zDiff = player->actor.world.pos.z - this->actor.world.pos.z;
|
||||
|
||||
if ((fabsf(xDiff) < 120.0f) && (fabsf(yDiff) < 120.0f)) {
|
||||
if (fabsf(yDiff) < fabsf(xDiff)) {
|
||||
if ((fabsf(xDiff) < 120.0f) && (fabsf(zDiff) < 120.0f)) {
|
||||
if (fabsf(zDiff) < fabsf(xDiff)) {
|
||||
if (xDiff > 0.0f) {
|
||||
player->actor.prevPos.x = player->actor.world.pos.x = this->actor.world.pos.x + 120.0f;
|
||||
} else {
|
||||
player->actor.prevPos.x = player->actor.world.pos.x = this->actor.world.pos.x - 120.0f;
|
||||
}
|
||||
} else if (yDiff > 0.0f) {
|
||||
} else if (zDiff > 0.0f) {
|
||||
player->actor.prevPos.z = player->actor.world.pos.z = this->actor.world.pos.z + 120.0f;
|
||||
} else {
|
||||
player->actor.prevPos.z = player->actor.world.pos.z = this->actor.world.pos.z - 120.0f;
|
||||
|
|
@ -395,23 +506,29 @@ void EnTanron5_Update(Actor* thisx, PlayState* play2) {
|
|||
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
|
||||
}
|
||||
|
||||
void func_80BE5818(Actor* thisx, PlayState* play2) {
|
||||
f32 sp6C;
|
||||
/**
|
||||
* This is the update function for the fragments and the item drops that fly off from a destructible ruin.
|
||||
*/
|
||||
void EnTanron5_RuinFragmentItemDrop_Update(Actor* thisx, PlayState* play2) {
|
||||
f32 interactionDistSq;
|
||||
s32 i;
|
||||
Vec3f sp5C;
|
||||
Vec3f pos;
|
||||
EnTanron5* this = THIS;
|
||||
PlayState* play = play2;
|
||||
|
||||
if ((ENTANRON5_GET(&this->actor) < ENTANRON5_110) && (this->unk_1A0 != 0)) {
|
||||
this->unk_1A0++;
|
||||
this->actor.world.pos.y -= 2.0f * D_80BE5DD0;
|
||||
if (this->unk_1A0 == 40) {
|
||||
// When a ruin fragment hits the floor, it will slowly sink into the sand. After sinking for 38 frames,
|
||||
// the ruin fragment will despawn.
|
||||
if ((TWINMOLD_PROP_GET_TYPE(&this->actor) < TWINMOLD_PROP_TYPE_ITEM_DROP_1) && (this->sinkTimer != 0)) {
|
||||
this->sinkTimer++;
|
||||
this->actor.world.pos.y -= 2.0f * sGiantModeScaleFactor;
|
||||
if (this->sinkTimer == 40) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (DECR(this->unk_144) == 0) {
|
||||
if (DECR(this->timer) == 0) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
|
||||
|
|
@ -420,94 +537,102 @@ void func_80BE5818(Actor* thisx, PlayState* play2) {
|
|||
Actor_UpdateBgCheckInfo(play, &this->actor, 50.0f, 150.0f, 100.0f, UPDBGCHECKINFO_FLAG_4);
|
||||
}
|
||||
|
||||
if (ENTANRON5_GET(&this->actor) < ENTANRON5_110) {
|
||||
this->actor.shape.rot.x += this->unk_198;
|
||||
this->actor.shape.rot.y += this->unk_19A;
|
||||
sp6C = 1225.0f;
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) < TWINMOLD_PROP_TYPE_ITEM_DROP_1) {
|
||||
this->actor.shape.rot.x += this->fragmentRotationalVelocityX;
|
||||
this->actor.shape.rot.y += this->fragmentRotationalVelocityY;
|
||||
interactionDistSq = SQ(35.0f);
|
||||
|
||||
if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
|
||||
if (ENTANRON5_GET(&this->actor) < ENTANRON5_108) {
|
||||
Math_Vec3f_Copy(&sp5C, &this->actor.world.pos);
|
||||
sp5C.y = this->actor.floorHeight;
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) <= TWINMOLD_PROP_TYPE_FRAGMENT_SMALL_1) {
|
||||
Math_Vec3f_Copy(&pos, &this->actor.world.pos);
|
||||
pos.y = this->actor.floorHeight;
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
func_80BE4930(play->specialEffects, &sp5C, Rand_ZeroFloat(1.0f) + 2.0f);
|
||||
EnTanron5_SpawnEffectSand(play->specialEffects, &pos, Rand_ZeroFloat(1.0f) + 2.0f);
|
||||
}
|
||||
this->unk_1A0++;
|
||||
|
||||
// Set the sinkTimer to a non-zero value so that this fragment will start sinking on the next update.
|
||||
this->sinkTimer++;
|
||||
} else {
|
||||
// Small ruin fragments don't sink into the sand; they just immediately despawn.
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
sp6C = 400.0f;
|
||||
this->unk_198 += 0x2000;
|
||||
interactionDistSq = SQ(20.0f);
|
||||
this->itemDropRotZ += 0x2000;
|
||||
if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
|
||||
this->unk_198 = 0;
|
||||
this->itemDropRotZ = 0;
|
||||
this->actor.speed = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->unk_1A1 == 0) {
|
||||
if ((D_80BE5DD0 > 0.5f) &&
|
||||
((ENTANRON5_GET(&this->actor) < ENTANRON5_108) || (ENTANRON5_GET(&this->actor) >= ENTANRON5_110))) {
|
||||
if (this->hitTimer == 0) {
|
||||
if ((sGiantModeScaleFactor > 0.5f) &&
|
||||
((TWINMOLD_PROP_GET_TYPE(&this->actor) <= TWINMOLD_PROP_TYPE_FRAGMENT_SMALL_1) ||
|
||||
(TWINMOLD_PROP_GET_TYPE(&this->actor) >= TWINMOLD_PROP_TYPE_ITEM_DROP_1))) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
Vec3f temp;
|
||||
Vec3f pos;
|
||||
|
||||
temp.x = player->actor.world.pos.x - this->actor.world.pos.x;
|
||||
temp.y = (player->actor.world.pos.y + 10.0f) - this->actor.world.pos.y;
|
||||
temp.z = player->actor.world.pos.z - this->actor.world.pos.z;
|
||||
pos.x = player->actor.world.pos.x - this->actor.world.pos.x;
|
||||
pos.y = (player->actor.world.pos.y + 10.0f) - this->actor.world.pos.y;
|
||||
pos.z = player->actor.world.pos.z - this->actor.world.pos.z;
|
||||
|
||||
if (SQXYZ(temp) < sp6C) {
|
||||
if (ENTANRON5_GET(&this->actor) >= ENTANRON5_110) {
|
||||
if (this->unk_1A0 == 0) {
|
||||
if (SQXYZ(pos) < interactionDistSq) {
|
||||
if (TWINMOLD_PROP_GET_TYPE(&this->actor) >= TWINMOLD_PROP_TYPE_ITEM_DROP_1) {
|
||||
if (this->itemDropType == TWINMOLD_PROP_ITEM_DROP_TYPE_10_ARROWS) {
|
||||
Item_Give(play, ITEM_ARROWS_10);
|
||||
} else {
|
||||
Item_Give(play, ITEM_MAGIC_JAR_BIG);
|
||||
}
|
||||
|
||||
Actor_Kill(&this->actor);
|
||||
Audio_PlaySfx(NA_SE_SY_GET_ITEM);
|
||||
} else {
|
||||
this->unk_1A1 = 20;
|
||||
// Damages the player and knocks them back. Starts a 20-frame timer to prevent
|
||||
// this same ruin fragment from damaging the player again too quickly.
|
||||
this->hitTimer = 20;
|
||||
func_800B8D50(play, NULL, 5.0f, this->actor.world.rot.y, 0.0f, 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this->unk_1A1--;
|
||||
this->hitTimer--;
|
||||
}
|
||||
}
|
||||
|
||||
void EnTanron5_Draw(Actor* thisx, PlayState* play) {
|
||||
EnTanron5* this = THIS;
|
||||
|
||||
if ((-500.0f * D_80BE5DD0) < this->actor.projectedPos.z) {
|
||||
if ((-500.0f * sGiantModeScaleFactor) < this->actor.projectedPos.z) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
Gfx_SetupDL25_Opa(play->state.gfxCtx);
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, this->unk_148);
|
||||
gSPDisplayList(POLY_OPA_DISP++, this->dList);
|
||||
|
||||
CLOSE_DISPS(play->state.gfxCtx);
|
||||
}
|
||||
}
|
||||
|
||||
void func_80BE5C10(Actor* thisx, PlayState* play) {
|
||||
void EnTanron5_ItemDrop_Draw(Actor* thisx, PlayState* play) {
|
||||
EnTanron5* this = THIS;
|
||||
TexturePtr texture;
|
||||
s32 phi_v0;
|
||||
s32 shouldDraw;
|
||||
|
||||
if ((this->unk_144 > 50) || (this->unk_144 & 1)) {
|
||||
phi_v0 = true;
|
||||
// This makes the item drop flicker when it's close to despawning.
|
||||
if ((this->timer > 50) || (this->timer & 1)) {
|
||||
shouldDraw = true;
|
||||
} else {
|
||||
phi_v0 = false;
|
||||
shouldDraw = false;
|
||||
}
|
||||
|
||||
if (((-500.0f * D_80BE5DD0) < this->actor.projectedPos.z) && phi_v0) {
|
||||
if (((-500.0f * sGiantModeScaleFactor) < this->actor.projectedPos.z) && shouldDraw) {
|
||||
OPEN_DISPS(play->state.gfxCtx);
|
||||
|
||||
Gfx_SetupDL25_Opa(play->state.gfxCtx);
|
||||
if (this->unk_1A0 == 0) {
|
||||
if (this->itemDropType == TWINMOLD_PROP_ITEM_DROP_TYPE_10_ARROWS) {
|
||||
texture = gDropArrows1Tex;
|
||||
} else {
|
||||
texture = gDropMagicLargeTex;
|
||||
|
|
@ -518,7 +643,7 @@ void func_80BE5C10(Actor* thisx, PlayState* play) {
|
|||
gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(texture));
|
||||
|
||||
Matrix_Translate(0.0f, 200.0f, 0.0f, MTXMODE_APPLY);
|
||||
Matrix_RotateZS(this->unk_198, MTXMODE_APPLY);
|
||||
Matrix_RotateZS(this->itemDropRotZ, MTXMODE_APPLY);
|
||||
|
||||
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_OPA_DISP++, gItemDropDL);
|
||||
|
|
|
|||
|
|
@ -5,24 +5,62 @@
|
|||
|
||||
struct EnTanron5;
|
||||
|
||||
#define ENTANRON5_GET(thisx) ((thisx)->params)
|
||||
#define TWINMOLD_PROP_GET_TYPE(thisx) ((thisx)->params)
|
||||
#define TWINMOLD_PROP_PARAMS(type) (type)
|
||||
|
||||
#define ENTANRON5_0 0
|
||||
#define ENTANRON5_100 100
|
||||
#define ENTANRON5_107 107
|
||||
#define ENTANRON5_108 108
|
||||
#define ENTANRON5_110 110
|
||||
typedef enum {
|
||||
/* 0 */ TWINMOLD_PROP_TYPE_STATIC,
|
||||
/* 1 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_1,
|
||||
/* 2 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_2,
|
||||
/* 3 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_3,
|
||||
/* 4 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_4,
|
||||
/* 5 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_5,
|
||||
/* 6 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_6,
|
||||
/* 7 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_7,
|
||||
/* 8 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_8,
|
||||
/* 9 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_9,
|
||||
/* 10 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_10,
|
||||
/* 11 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_11,
|
||||
/* 12 */ TWINMOLD_PROP_TYPE_RUIN_PILLAR_12,
|
||||
/* 13 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_1,
|
||||
/* 14 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_2,
|
||||
/* 15 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_3,
|
||||
/* 16 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_4,
|
||||
/* 17 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_5,
|
||||
/* 18 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_6,
|
||||
/* 19 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_7,
|
||||
/* 20 */ TWINMOLD_PROP_TYPE_RUIN_PYRAMID_8,
|
||||
/* 100 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_1 = 100,
|
||||
/* 101 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_2,
|
||||
/* 102 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_3,
|
||||
/* 103 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_4,
|
||||
/* 104 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_5,
|
||||
/* 105 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_6,
|
||||
/* 106 */ TWINMOLD_PROP_TYPE_FRAGMENT_LARGE_7,
|
||||
/* 107 */ TWINMOLD_PROP_TYPE_FRAGMENT_SMALL_1,
|
||||
/* 108 */ TWINMOLD_PROP_TYPE_FRAGMENT_SMALL_2,
|
||||
/* 109 */ TWINMOLD_PROP_TYPE_FRAGMENT_SMALL_3,
|
||||
/* 110 */ TWINMOLD_PROP_TYPE_ITEM_DROP_1,
|
||||
/* 111 */ TWINMOLD_PROP_TYPE_ITEM_DROP_2
|
||||
} TwinmoldPropType;
|
||||
|
||||
typedef struct EnTanron5 {
|
||||
/* 0x000 */ Actor actor;
|
||||
/* 0x144 */ s16 unk_144;
|
||||
/* 0x148 */ Gfx* unk_148;
|
||||
/* 0x144 */ s16 timer;
|
||||
/* 0x148 */ Gfx* dList;
|
||||
/* 0x14C */ ColliderCylinder collider;
|
||||
/* 0x198 */ s16 unk_198;
|
||||
/* 0x19A */ s16 unk_19A;
|
||||
/* 0x19C */ f32 unk_19C;
|
||||
/* 0x1A0 */ u8 unk_1A0;
|
||||
/* 0x1A1 */ u8 unk_1A1;
|
||||
/* 0x198 */ union {
|
||||
s16 fragmentRotationalVelocityX;
|
||||
s16 itemDropRotZ;
|
||||
};
|
||||
/* 0x19A */ s16 fragmentRotationalVelocityY;
|
||||
/* 0x19C */ f32 baseScale;
|
||||
/* 0x1A0 */ union {
|
||||
u8 hitCount; // used by destructible ruins
|
||||
u8 sinkTimer; // used by ruin fragments
|
||||
u8 itemDropType; // used by item drops
|
||||
};
|
||||
/* 0x1A1 */ u8 hitTimer;
|
||||
} EnTanron5; // size = 0x1A4
|
||||
|
||||
#endif // Z_EN_TANRON5_H
|
||||
|
|
|
|||
|
|
@ -16100,14 +16100,14 @@
|
|||
0x80BE42A4:("EnTanron4_FlyNearActor",),
|
||||
0x80BE4734:("EnTanron4_Update",),
|
||||
0x80BE4804:("EnTanron4_Draw",),
|
||||
0x80BE4930:("func_80BE4930",),
|
||||
0x80BE4A2C:("func_80BE4A2C",),
|
||||
0x80BE4930:("EnTanron5_SpawnEffectSand",),
|
||||
0x80BE4A2C:("EnTanron5_SpawnEffectBlackDust",),
|
||||
0x80BE4B1C:("EnTanron5_Init",),
|
||||
0x80BE4F24:("EnTanron5_Destroy",),
|
||||
0x80BE4F54:("EnTanron5_Update",),
|
||||
0x80BE5818:("func_80BE5818",),
|
||||
0x80BE5818:("EnTanron5_RuinFragmentItemDrop_Update",),
|
||||
0x80BE5B58:("EnTanron5_Draw",),
|
||||
0x80BE5C10:("func_80BE5C10",),
|
||||
0x80BE5C10:("EnTanron5_ItemDrop_Draw",),
|
||||
0x80BE6040:("EnTanron6_Init",),
|
||||
0x80BE60AC:("EnTanron6_Destroy",),
|
||||
0x80BE60BC:("EnTanron6_DoNothing",),
|
||||
|
|
|
|||
|
|
@ -10024,7 +10024,7 @@
|
|||
0x809DF550:("D_809DF550","UNK_TYPE1","",0x1),
|
||||
0x809DF570:("D_809DF570","UNK_TYPE1","",0x1),
|
||||
0x809DF590:("Boss_02_InitVars","UNK_TYPE1","",0x1),
|
||||
0x809DF5B0:("D_809DF5B0","f32","",0x4),
|
||||
0x809DF5B0:("sGiantModeScaleFactor","f32","",0x4),
|
||||
0x809DF5B4:("D_809DF5B4","UNK_TYPE2","[24]",0x30),
|
||||
0x809DF5E4:("D_809DF5E4","UNK_TYPE2","[24]",0x30),
|
||||
0x809DF614:("D_809DF614","UNK_TYPE1","",0x1),
|
||||
|
|
@ -15917,13 +15917,13 @@
|
|||
0x80BE48AC:("D_80BE48AC","f32","",0x4),
|
||||
0x80BE48B0:("D_80BE48B0","f32","",0x4),
|
||||
0x80BE48B4:("D_80BE48B4","f32","",0x4),
|
||||
0x80BE5D80:("D_80BE5D80","UNK_TYPE4","",0x4),
|
||||
0x80BE5D80:("sFragmentAndItemDropCount","UNK_TYPE4","",0x4),
|
||||
0x80BE5D84:("En_Tanron5_InitVars","UNK_TYPE1","",0x1),
|
||||
0x80BE5DA4:("D_80BE5DA4","UNK_TYPE1","",0x1),
|
||||
0x80BE5DD0:("D_80BE5DD0","f32","",0x4),
|
||||
0x80BE5DD4:("D_80BE5DD4","UNK_TYPE2","",0x2),
|
||||
0x80BE5E24:("D_80BE5E24","UNK_TYPE1","",0x1),
|
||||
0x80BE5E74:("D_80BE5E74","UNK_TYPE1","",0x1),
|
||||
0x80BE5DD0:("sGiantModeScaleFactor","f32","",0x4),
|
||||
0x80BE5DD4:("sSpawnPosList","UNK_TYPE2","",0x2),
|
||||
0x80BE5E24:("sDLists","UNK_TYPE1","",0x1),
|
||||
0x80BE5E74:("sBaseScales","UNK_TYPE1","",0x1),
|
||||
0x80BE5ED0:("D_80BE5ED0","f32","",0x4),
|
||||
0x80BE5ED4:("D_80BE5ED4","f32","",0x4),
|
||||
0x80BE5ED8:("D_80BE5ED8","f32","",0x4),
|
||||
|
|
|
|||
Loading…
Reference in New Issue