EnOkuta (Octorok and its projectiles) OK and documented (#1641)

* Match EnOkuta

* Match data

* Use the generated reloc

* Delete extern stuff and format

* Extract the DL

* Fix lots of stuff

* Copy a lot of names over from EnSyatekiOkuta

* SFX enums

* Lots more stuff

* Constants and other stuff

* Some more stuff I missed

* Name more functions using OoT/SyatekiOkuta as reference

* An easy function I missed

* Some floats

* Getter macros

* Types enum

* Name the cylinder inits a little clearer

* Create bodyparts enum and name all data

* Name all functions

* Name `timer` struct var and all temps

* Name the `jumpHeight` struct var

* Create damage effect enum

* Name the extracted DL

* Name `numConsecutiveProjectiles`

* Finish docs

* Document XML

* Clarify that this blue Octorok isn't the shooting gallery one

* Respond to reviews

* Stuff

---------

Co-authored-by: Synray <31429825+Synray@users.noreply.github.com>
Co-authored-by: Derek Hensley <hensley.derek58@gmail.com>
This commit is contained in:
Tom Overton
2024-06-23 18:09:22 -07:00
committed by GitHub
parent 3682a13ec5
commit bb221b4a0f
12 changed files with 1210 additions and 243 deletions
+23 -25
View File
@@ -616,32 +616,30 @@ s32 EnBb_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* po
}
/**
* This maps a given limb based on its limbIndex to its appropriate index
* in the bodyPartsPos/Velocity arrays.
* This maps a given limb based on its limbIndex to its appropriate index in the `bodyPartsPos/Velocity` arrays.
*/
static s8 sLimbToBodyParts[BUBBLE_LIMB_MAX] = {
BODYPART_NONE, // BUBBLE_LIMB_NONE
BODYPART_NONE, // BUBBLE_LIMB_ROOT
BODYPART_NONE, // BUBBLE_LIMB_CRANIUM_ROOT
BODYPART_NONE, // BUBBLE_LIMB_JAW_ROOT
BUBBLE_BODYPART_0, // BUBBLE_LIMB_JAW
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WEBBING_ROOT
BUBBLE_BODYPART_1, // BUBBLE_LIMB_LEFT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_BONE
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WEBBING_ROOT
BUBBLE_BODYPART_2, // BUBBLE_LIMB_RIGHT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_BONE
BUBBLE_BODYPART_3, // BUBBLE_LIMB_CRANIUM
BODYPART_NONE, // BUBBLE_LIMB_NONE
BODYPART_NONE, // BUBBLE_LIMB_ROOT
BODYPART_NONE, // BUBBLE_LIMB_CRANIUM_ROOT
BODYPART_NONE, // BUBBLE_LIMB_JAW_ROOT
BUBBLE_BODYPART_JAW, // BUBBLE_LIMB_JAW
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WEBBING_ROOT
BUBBLE_BODYPART_LEFT_WING_WEBBING, // BUBBLE_LIMB_LEFT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_BONE
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WEBBING_ROOT
BUBBLE_BODYPART_RIGHT_WING_WEBBING, // BUBBLE_LIMB_RIGHT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_BONE
BUBBLE_BODYPART_CRANIUM, // BUBBLE_LIMB_CRANIUM
};
/**
* The last element of the bodyParts arrays is a duplicate of the cranium
* limb, which is then offset by a certain amount. There is no display list
* associated with this, so it is only used for effects.
* The last element of the `bodyParts` arrays is not tied to any particular limb and is instead used to control the
* placement of effects. The positions of these effects are offset by a certain amount from the Bubble's cranium limb.
*/
static Vec3f sEffectsBodyPartOffset = { 1000.0f, -700.0f, 0.0f };
@@ -652,10 +650,10 @@ void EnBb_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot,
if (this->bodyPartDrawStatus == BB_BODY_PART_DRAW_STATUS_ALIVE) {
if (sLimbToBodyParts[limbIndex] != BODYPART_NONE) {
if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_0) {
Matrix_MultVecX(1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_0]);
} else if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_3) {
Matrix_MultVecX(-1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_3]);
if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_JAW) {
Matrix_MultVecX(1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_JAW]);
} else if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_CRANIUM) {
Matrix_MultVecX(-1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_CRANIUM]);
Matrix_MultVec3f(&sEffectsBodyPartOffset, &this->bodyPartsPos[BUBBLE_BODYPART_EFFECTS]);
} else {
Matrix_MultZero(&this->bodyPartsPos[sLimbToBodyParts[limbIndex]]);
+4 -4
View File
@@ -11,10 +11,10 @@ struct EnBb;
typedef void (*EnBbActionFunc)(struct EnBb*, PlayState*);
typedef enum BubbleBodyPart {
/* 0 */ BUBBLE_BODYPART_0,
/* 1 */ BUBBLE_BODYPART_1,
/* 2 */ BUBBLE_BODYPART_2,
/* 3 */ BUBBLE_BODYPART_3,
/* 0 */ BUBBLE_BODYPART_JAW,
/* 1 */ BUBBLE_BODYPART_LEFT_WING_WEBBING,
/* 2 */ BUBBLE_BODYPART_RIGHT_WING_WEBBING,
/* 3 */ BUBBLE_BODYPART_CRANIUM,
/* 4 */ BUBBLE_BODYPART_EFFECTS,
/* 5 */ BUBBLE_BODYPART_MAX
} BubbleBodyPart;
+23 -25
View File
@@ -652,32 +652,30 @@ s32 EnBbfall_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f
}
/**
* This maps a given limb based on its limbIndex to its appropriate index
* in the bodyPartsPos/Velocity arrays.
* This maps a given limb based on its limbIndex to its appropriate index in the `bodyPartsPos/Velocity` arrays.
*/
static s8 sLimbToBodyParts[BUBBLE_LIMB_MAX] = {
BODYPART_NONE, // BUBBLE_LIMB_NONE
BODYPART_NONE, // BUBBLE_LIMB_ROOT
BODYPART_NONE, // BUBBLE_LIMB_CRANIUM_ROOT
BODYPART_NONE, // BUBBLE_LIMB_JAW_ROOT
BUBBLE_BODYPART_0, // BUBBLE_LIMB_JAW
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WEBBING_ROOT
BUBBLE_BODYPART_1, // BUBBLE_LIMB_LEFT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_BONE
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WEBBING_ROOT
BUBBLE_BODYPART_2, // BUBBLE_LIMB_RIGHT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_BONE
BUBBLE_BODYPART_3, // BUBBLE_LIMB_CRANIUM
BODYPART_NONE, // BUBBLE_LIMB_NONE
BODYPART_NONE, // BUBBLE_LIMB_ROOT
BODYPART_NONE, // BUBBLE_LIMB_CRANIUM_ROOT
BODYPART_NONE, // BUBBLE_LIMB_JAW_ROOT
BUBBLE_BODYPART_JAW, // BUBBLE_LIMB_JAW
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_WEBBING_ROOT
BUBBLE_BODYPART_LEFT_WING_WEBBING, // BUBBLE_LIMB_LEFT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_LEFT_WING_BONE
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_ROOT
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WRAPPER
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_WEBBING_ROOT
BUBBLE_BODYPART_RIGHT_WING_WEBBING, // BUBBLE_LIMB_RIGHT_WING_WEBBING
BODYPART_NONE, // BUBBLE_LIMB_RIGHT_WING_BONE
BUBBLE_BODYPART_CRANIUM, // BUBBLE_LIMB_CRANIUM
};
/**
* The last element of the bodyParts arrays is a duplicate of the cranium
* limb, which is then offset by a certain amount. There is no display list
* associated with this, so it is only used for effects.
* The last element of the `bodyParts` arrays is not tied to any particular limb and is instead used to control the
* placement of effects. The positions of these effects are offset by a certain amount from the Bubble's cranium limb.
*/
static Vec3f sEffectsBodyPartOffset = { 1000.0f, -700.0f, 0.0f };
@@ -688,10 +686,10 @@ void EnBbfall_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* r
if (this->bodyPartDrawStatus == BBFALL_BODY_PART_DRAW_STATUS_ALIVE) {
if (sLimbToBodyParts[limbIndex] != BODYPART_NONE) {
if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_0) {
Matrix_MultVecX(1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_0]);
} else if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_3) {
Matrix_MultVecX(-1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_3]);
if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_JAW) {
Matrix_MultVecX(1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_JAW]);
} else if (sLimbToBodyParts[limbIndex] == BUBBLE_BODYPART_CRANIUM) {
Matrix_MultVecX(-1000.0f, &this->bodyPartsPos[BUBBLE_BODYPART_CRANIUM]);
Matrix_MultVec3f(&sEffectsBodyPartOffset, &this->bodyPartsPos[BUBBLE_BODYPART_EFFECTS]);
} else {
Matrix_MultZero(&this->bodyPartsPos[sLimbToBodyParts[limbIndex]]);
@@ -551,7 +551,7 @@ void EnBigokuta_Update(Actor* thisx, PlayState* play) {
Math_StepToF(&this->drawDmgEffAlpha, 0.0f, 0.05f);
this->drawDmgEffScale = (this->drawDmgEffAlpha + 1.0f) * 0.6f;
this->drawDmgEffScale = CLAMP_MAX(this->drawDmgEffScale, 1.2f);
} else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 1.2f, 0.030000001f)) {
} else if (!Math_StepToF(&this->drawDmgEffFrozenSteamScale, 1.2f, 30.0f * 0.001f)) {
Actor_PlaySfx_Flagged(&this->picto.actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
}
}
File diff suppressed because it is too large Load Diff
+39 -2
View File
@@ -2,16 +2,53 @@
#define Z_EN_OKUTA_H
#include "global.h"
#include "objects/object_okuta/object_okuta.h"
struct EnOkuta;
typedef void (*EnOkutaActionFunc)(struct EnOkuta*, PlayState*);
#define EN_OKUTA_GET_NUM_CONSECUTIVE_PROJECTILES(thisx) (((thisx)->params >> 8) & 0xFF)
#define EN_OKUTA_GET_TYPE(thisx) ((thisx)->params)
typedef enum EnOkutaType {
/* 0 */ EN_OKUTA_TYPE_RED_OCTOROK,
/* 1 */ EN_OKUTA_TYPE_BLUE_OCTOROK, // Unused in the final game. This variant is invincible to all attacks and can chase the player underwater if they dive.
/* 16 */ EN_OKUTA_TYPE_PROJECTILE_BASE = 16,
/* 16 */ EN_OKUTA_TYPE_RED_PROJECTILE = EN_OKUTA_TYPE_RED_OCTOROK + EN_OKUTA_TYPE_PROJECTILE_BASE,
/* 17 */ EN_OKUTA_TYPE_BLUE_PROJECTILE = EN_OKUTA_TYPE_BLUE_OCTOROK + EN_OKUTA_TYPE_PROJECTILE_BASE
} EnOkutaType;
typedef enum EnOkutaBodyPart {
/* 0 */ EN_OKUTA_BODYPART_BODY,
/* 1 */ EN_OKUTA_BODYPART_FRONT_LEFT_ARM_END,
/* 2 */ EN_OKUTA_BODYPART_FRONT_RIGHT_ARM_END,
/* 3 */ EN_OKUTA_BODYPART_BACK_LEFT_ARM_END,
/* 4 */ EN_OKUTA_BODYPART_BACK_RIGHT_ARM_END,
/* 5 */ EN_OKUTA_BODYPART_SNOUT,
/* 6 */ EN_OKUTA_BODYPART_HEAD,
/* 7 */ EN_OKUTA_BODYPART_EFFECTS_1,
/* 8 */ EN_OKUTA_BODYPART_EFFECTS_2,
/* 9 */ EN_OKUTA_BODYPART_EFFECTS_3,
/* 10 */ EN_OKUTA_BODYPART_MAX
} EnOkutaBodyPart;
typedef struct EnOkuta {
/* 0x000 */ Actor actor;
/* 0x144 */ char unk_144[0x44];
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ EnOkutaActionFunc actionFunc;
/* 0x18C */ char unk_18C[0x1A8];
/* 0x18C */ u8 drawDmgEffType;
/* 0x18E */ s16 timer;
/* 0x190 */ s16 numConsecutiveProjectiles; // when the Octorok starts shooting projectiles, it will shoot this many projectiles in a row before stopping
/* 0x192 */ Vec3s jointTable[OCTOROK_LIMB_MAX];
/* 0x1F2 */ Vec3s morphTable[OCTOROK_LIMB_MAX];
/* 0x254 */ f32 drawDmgEffAlpha;
/* 0x258 */ f32 drawDmgEffScale;
/* 0x25C */ f32 drawDmgEffFrozenSteamScale;
/* 0x260 */ f32 jumpHeight;
/* 0x264 */ Vec3f headScale;
/* 0x270 */ Vec3f bodyPartsPos[EN_OKUTA_BODYPART_MAX];
/* 0x2E8 */ ColliderCylinder collider;
} EnOkuta; // size = 0x334
#endif // Z_EN_OKUTA_H
@@ -124,11 +124,11 @@ void EnSyatekiOkuta_Destroy(Actor* thisx, PlayState* play) {
/**
* Spawns the puff of smoke that appears when the Octorok disappears when it dies.
*/
void EnSyatekiOkuta_SpawnDust(Vec3f* pos, Vec3f* velocity, s16 scaleStep, PlayState* play) {
static Color_RGBA8 sDustPrimColor = { 255, 255, 255, 255 };
static Color_RGBA8 sDustEnvColor = { 150, 150, 150, 255 };
void EnSyatekiOkuta_SpawnSmoke(Vec3f* pos, Vec3f* velocity, s16 scaleStep, PlayState* play) {
static Color_RGBA8 sSmokePrimColor = { 255, 255, 255, 255 };
static Color_RGBA8 sSmokeEnvColor = { 150, 150, 150, 255 };
func_800B0DE0(play, pos, velocity, &gZeroVec3f, &sDustPrimColor, &sDustEnvColor, 400, scaleStep);
func_800B0DE0(play, pos, velocity, &gZeroVec3f, &sSmokePrimColor, &sSmokeEnvColor, 400, scaleStep);
}
/**
@@ -308,7 +308,7 @@ void EnSyatekiOkuta_Die(EnSyatekiOkuta* this, PlayState* play) {
velocity.x = 0.0f;
velocity.y = -0.5f;
velocity.z = 0.0f;
EnSyatekiOkuta_SpawnDust(&pos, &velocity, -20, play);
EnSyatekiOkuta_SpawnSmoke(&pos, &velocity, -20, play);
Actor_PlaySfx(&this->actor, NA_SE_EN_OCTAROCK_DEAD2);
}
@@ -502,8 +502,9 @@ void EnSyatekiOkuta_UpdateHeadScale(EnSyatekiOkuta* this) {
}
/**
* Returns true if the snout scale should be updated, false otherwise. The snout scale is returned via the scale
* parameter.
* Gets the scaling factor for animating the snout limb. If the limb is not being transformed, no scale value is
* returned. Returns true if the snout scale should be updated, false otherwise. The snout scale is returned via the
* `scale` parameter.
*/
s32 EnSyatekiOkuta_GetSnoutScale(EnSyatekiOkuta* this, f32 curFrame, Vec3f* scale) {
if (this->actionFunc == EnSyatekiOkuta_Appear) {