Shipwright/soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c

2106 lines
77 KiB
C

#include "z_en_go2.h"
#include "overlays/actors/ovl_En_Bom/z_en_bom.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_oF1d_map/object_oF1d_map.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
/*
FLAGS
gSaveContext.eventChkInf[2] & 0x8 - DC entrance boulder blown up as child
InfTable
gSaveContext.infTable[11] & 0x10
gSaveContext.infTable[14] & 0x1 - Talked to DMT Goron at DC entrance (Before DC is opened as child)
gSaveContext.infTable[14] & 0x8 - Talked to GC Goron in bottom level stairwell
gSaveContext.infTable[14] & 0x40 - Talked to GC Goron at LW entrance (Before LW shortcut is opened)
gSaveContext.infTable[14] & 0x800 - Talked to DMT Goron at Bomb Flower with goron bracelet
gSaveContext.infTable[15] & 0x1 - Talked to Goron at GC Entrance (Before goron ruby is obtained)
gSaveContext.infTable[15] & 0x10 - Talked to Goron at GC Island (Before goron ruby is obtained)
gSaveContext.infTable[15] & 0x100 - (not on cloud modding) Talked to GC Goron outside Darunias door (after opening door,
before getting goron bracelet) gSaveContext.infTable[16] & 0x200 - Obtained Fire Tunic from Goron Link
gSaveContext.infTable[16] & 0x400 - (not on cloud modding)
gSaveContext.infTable[16] & 0x800 - Spoke to Goron Link About Volvagia
gSaveContext.infTable[16] & 0x1000 - Stopped Goron Link's Rolling
gSaveContext.infTable[16] & 0x2000 - EnGo Exclusive
gSaveContext.infTable[16] & 0x4000 - Spoke to Goron Link
gSaveContext.infTable[16] & 0x8000 - (not on cloud modding)
gSaveContext.infTable[17] & 0x4000 - Bomb bag upgrade obtained from rolling Goron
EnGo
pathIndex: this->actor.params & 0xF
Goron: this->actor.params & 0xF0
EnGo2
(this->actor.params & 0x3E0) >> 5
(this->actor.params & 0xFC00) >> 0xA - Gorons in Fire Temple
this->actor.params & 0x1F
Gorons only move when this->unk_194.unk_00 == 0
*/
void EnGo2_Init(Actor* thisx, GlobalContext* globalCtx);
void EnGo2_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnGo2_Update(Actor* thisx, GlobalContext* globalCtx);
void EnGo2_Draw(Actor* thisx, GlobalContext* globalCtx);
void EnGo2_StopRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_CurledUp(EnGo2* this, GlobalContext* globalCtx);
void func_80A46B40(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_GoronDmtBombFlowerAnimation(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_GoronRollingBigContinueRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_ContinueRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_SlowRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_GroundRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_ReverseRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_SetupGetItem(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_SetGetItem(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_GoronLinkStopRolling(EnGo2* this, GlobalContext* globalCtx);
void EnGo2_GoronFireGenericAction(EnGo2* this, GlobalContext* globalCtx);
static void* sDustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex };
static Vec3f sPos = { 0.0f, 0.0f, 0.0f };
static Vec3f sVelocity = { 0.0f, 0.0f, 0.0f };
static Vec3f sAccel = { 0.0f, 0.3f, 0.0f };
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_ON | AC_TYPE_PLAYER,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_2,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00000008, 0x00, 0x00 },
TOUCH_NONE,
BUMP_NONE,
OCELEM_ON,
},
{ 40, 65, 0, { 0, 0, 0 } },
};
static CollisionCheckInfoInit2 sColChkInfoInit = {
0, 0, 0, 0, MASS_IMMOVABLE,
};
const ActorInit En_Go2_InitVars = {
ACTOR_EN_GO2,
ACTORCAT_NPC,
FLAGS,
OBJECT_OF1D_MAP,
sizeof(EnGo2),
(ActorFunc)EnGo2_Init,
(ActorFunc)EnGo2_Destroy,
(ActorFunc)EnGo2_Update,
(ActorFunc)EnGo2_Draw,
NULL,
};
static EnGo2DataStruct1 D_80A4816C[14] = {
{ 0, 0, 0, 68, 148 }, { 0, 0, 0, 24, 52 }, { 0, 320, 380, 400, 120 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 46, 90 },
{ 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 },
{ 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 }, { 0, 0, 0, 30, 68 },
};
static EnGo2DataStruct2 D_80A481F8[14] = {
{ 30.0f, 0.026f, 6, 60.0f }, { 24.0f, 0.008f, 6, 30.0f }, { 28.0f, 0.16f, 5, 380.0f }, { 28.0f, 0.01f, 7, 40.0f },
{ 30.0f, 0.015f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f },
{ 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f },
{ 28.0f, 0.01f, 6, 30.0f }, { 28.0f, 0.01f, 6, 30.0f },
};
static f32 D_80A482D8[14][2] = {
{ 80.0f, 80.0f }, { -10.0f, -10.0f }, { 800.0f, 800.0f }, { 0.0f, 0.0f }, { 20.0f, 40.0f },
{ 20.0f, 20.0f }, { 20.0f, 20.0f }, { 20.0f, 20.0f }, { 20.0f, 20.0f }, { 20.0f, 20.0f },
{ 20.0f, 20.0f }, { 20.0f, 20.0f }, { 20.0f, 20.0f }, { 20.0f, 20.0f },
};
typedef enum {
/* 0 */ ENGO2_ANIM_0,
/* 1 */ ENGO2_ANIM_1,
/* 2 */ ENGO2_ANIM_2,
/* 3 */ ENGO2_ANIM_3,
/* 4 */ ENGO2_ANIM_4,
/* 5 */ ENGO2_ANIM_5,
/* 6 */ ENGO2_ANIM_6,
/* 7 */ ENGO2_ANIM_7,
/* 8 */ ENGO2_ANIM_8,
/* 9 */ ENGO2_ANIM_9,
/* 10 */ ENGO2_ANIM_10,
/* 11 */ ENGO2_ANIM_11,
/* 12 */ ENGO2_ANIM_12,
} EnGo2Animation;
static AnimationInfo sAnimationInfo[] = {
{ &gGoronAnim_004930, 0.0f, 0.0f, -1.0f, 0x00, 0.0f }, { &gGoronAnim_004930, 0.0f, 0.0f, -1.0f, 0x00, -8.0f },
{ &gGoronAnim_0029A8, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_010590, 1.0f, 0.0f, -1.0f, 0x00, -8.0f },
{ &gGoronAnim_003768, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_0038E4, 1.0f, 0.0f, -1.0f, 0x02, -8.0f },
{ &gGoronAnim_002D80, 1.0f, 0.0f, -1.0f, 0x02, -8.0f }, { &gGoronAnim_00161C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f },
{ &gGoronAnim_001A00, 1.0f, 0.0f, -1.0f, 0x00, -8.0f }, { &gGoronAnim_0021D0, 1.0f, 0.0f, -1.0f, 0x00, -8.0f },
{ &gGoronAnim_004930, 0.0f, 0.0f, -1.0f, 0x01, -8.0f }, { &gGoronAnim_000750, 1.0f, 0.0f, -1.0f, 0x00, -8.0f },
{ &gGoronAnim_000D5C, 1.0f, 0.0f, -1.0f, 0x00, -8.0f },
};
static EnGo2DustEffectData sDustEffectData[2][4] = {
{
{ 12, 0.2f, 0.2f, 1, 18.0f, 0.0f },
{ 12, 0.1f, 0.2f, 12, 26.0f, 0.0f },
{ 12, 0.1f, 0.3f, 4, 10.0f, 0.0f },
{ 12, 0.2f, 0.2f, 1, 18.0f, 0.0f },
},
{
{ 12, 0.5f, 0.4f, 3, 42.0f, 0.0f },
{ 12, 0.5f, 0.4f, 3, 42.0f, 0.0f },
{ 12, 0.5f, 0.4f, 3, 42.0f, 0.0f },
{ 12, 0.5f, 0.4f, 3, 42.0f, 0.0f },
},
};
static Vec3f sZeroVec = { 0.0f, 0.0f, 0.0f };
void EnGo2_AddDust(EnGo2* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep) {
EnGoEffect* dustEffect = this->dustEffects;
s16 i;
s16 timer;
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
if (dustEffect->type != 1) {
dustEffect->scale = scale;
dustEffect->scaleStep = scaleStep;
timer = initialTimer;
dustEffect->timer = timer;
dustEffect->type = 1;
dustEffect->initialTimer = initialTimer;
dustEffect->pos = *pos;
dustEffect->accel = *accel;
dustEffect->velocity = *velocity;
return;
}
}
}
void EnGo2_UpdateDust(EnGo2* this) {
EnGoEffect* dustEffect = this->dustEffects;
f32 randomNumber;
s16 i;
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
if (dustEffect->type) {
dustEffect->timer--;
if (dustEffect->timer == 0) {
dustEffect->type = 0;
}
dustEffect->accel.x = (Rand_ZeroOne() * 0.4f) - 0.2f;
randomNumber = Rand_ZeroOne() * 0.4f;
dustEffect->accel.z = randomNumber - 0.2f;
dustEffect->pos.x += dustEffect->velocity.x;
dustEffect->pos.y += dustEffect->velocity.y;
dustEffect->pos.z += dustEffect->velocity.z;
dustEffect->velocity.x += dustEffect->accel.x;
dustEffect->velocity.y += dustEffect->accel.y;
dustEffect->velocity.z += randomNumber - 0.2f;
dustEffect->scale += dustEffect->scaleStep;
}
}
}
void EnGo2_DrawDust(EnGo2* this, GlobalContext* globalCtx) {
EnGoEffect* dustEffect = this->dustEffects;
s16 alpha;
s16 firstDone;
s16 index;
s16 i;
OPEN_DISPS(globalCtx->state.gfxCtx);
firstDone = false;
func_80093D84(globalCtx->state.gfxCtx);
for (i = 0; i < ARRAY_COUNT(this->dustEffects); i++, dustEffect++) {
if (dustEffect->type) {
if (!firstDone) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD40);
gDPSetEnvColor(POLY_XLU_DISP++, 100, 60, 20, 0);
firstDone = true;
}
alpha = dustEffect->timer * (255.0f / dustEffect->initialTimer);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 170, 130, 90, alpha);
gDPPipeSync(POLY_XLU_DISP++);
Matrix_Translate(dustEffect->pos.x, dustEffect->pos.y, dustEffect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&globalCtx->billboardMtxF);
Matrix_Scale(dustEffect->scale, dustEffect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
index = dustEffect->timer * (8.0f / dustEffect->initialTimer);
gSPSegment(POLY_XLU_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(sDustTex[index]));
gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD50);
}
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
s32 EnGo2_SpawnDust(EnGo2* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 numDustEffects, f32 radius,
f32 yAccel) {
Vec3f pos = sPos;
Vec3f velocity = sVelocity;
Vec3f accel = sAccel;
s32 i;
s16 angle;
pos = this->actor.world.pos; // overwrites sPos data
pos.y = this->actor.floorHeight;
angle = (Rand_ZeroOne() - 0.5f) * 0x10000;
i = numDustEffects;
while (i >= 0) {
accel.y += Rand_ZeroOne() * yAccel;
pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x;
pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z;
EnGo2_AddDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep);
angle += (s16)(0x10000 / numDustEffects);
i--;
}
return 0;
}
void EnGo2_GetItem(EnGo2* this, GlobalContext* globalCtx, s32 getItemId) {
this->getItemId = getItemId;
func_8002F434(&this->actor, globalCtx, getItemId, this->actor.xzDistToPlayer + 1.0f,
fabsf(this->actor.yDistToPlayer) + 1.0f);
}
s32 EnGo2_GetDialogState(EnGo2* this, GlobalContext* globalCtx) {
s16 dialogState = Message_GetState(&globalCtx->msgCtx);
if ((this->dialogState == TEXT_STATE_AWAITING_NEXT) || (this->dialogState == TEXT_STATE_EVENT) ||
(this->dialogState == TEXT_STATE_CLOSING) || (this->dialogState == TEXT_STATE_DONE_HAS_NEXT)) {
if (dialogState != this->dialogState) {
this->unk_20C++;
}
}
this->dialogState = dialogState;
return dialogState;
}
u16 EnGo2_GoronFireGenericGetTextId(EnGo2* this) {
switch ((this->actor.params & 0xFC00) >> 0xA) {
case 3:
return 0x3069;
case 5:
return 0x306A;
case 4:
return 0x306B;
case 2:
return 0x306C;
case 10:
return 0x306D;
case 8:
return 0x306E;
case 11:
return 0x306F;
case 1:
return 0x3070;
default:
return 0x3052;
}
}
u16 EnGo2_GetTextIdGoronCityRollingBig(GlobalContext* globalCtx, EnGo2* this) {
if (gSaveContext.infTable[17] & 0x4000) {
return 0x3013;
} else if ((CUR_CAPACITY(UPG_BOMB_BAG) >= 20 || gSaveContext.n64ddFlag) && this->waypoint > 7 && this->waypoint < 12) {
return 0x3012;
} else {
return 0x3011;
}
}
s16 EnGo2_GetStateGoronCityRollingBig(GlobalContext* globalCtx, EnGo2* this) {
s32 bombBagUpgrade;
switch (Message_GetState(&globalCtx->msgCtx)) {
case TEXT_STATE_CLOSING:
return 2;
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(globalCtx)) {
if (this->actor.textId == 0x3012) {
this->actionFunc = EnGo2_SetupGetItem;
if(!gSaveContext.n64ddFlag) {
bombBagUpgrade = CUR_CAPACITY(UPG_BOMB_BAG) == 30 ? GI_BOMB_BAG_40 : GI_BOMB_BAG_30;
} else {
bombBagUpgrade = Randomizer_GetItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_CHILD, GI_BOMB_BAG_40);
}
EnGo2_GetItem(this, globalCtx, bombBagUpgrade);
Message_CloseTextbox(globalCtx);
gSaveContext.infTable[17] |= 0x4000;
return 2;
} else {
return 2;
}
}
default:
return 1;
}
}
u16 EnGo2_GetTextIdGoronDmtBombFlower(GlobalContext* globalCtx, EnGo2* this) {
return CHECK_QUEST_ITEM(QUEST_GORON_RUBY) ? 0x3027 : 0x300A;
}
// DMT Goron by Bomb Flower Choice
s16 EnGo2_GetStateGoronDmtBombFlower(GlobalContext* globalCtx, EnGo2* this) {
switch (Message_GetState(&globalCtx->msgCtx)) {
case TEXT_STATE_CLOSING:
if ((this->actor.textId == 0x300B) && (gSaveContext.infTable[14] & 0x800) == 0) {
gSaveContext.infTable[14] |= 0x800;
return 2;
} else {
return 0;
}
case TEXT_STATE_CHOICE:
if (Message_ShouldAdvance(globalCtx)) {
// Ask question to DMT Goron by bomb flower
if (this->actor.textId == 0x300A) {
if (globalCtx->msgCtx.choiceIndex == 0) {
this->actor.textId = CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x300B : 0x300C;
} else {
this->actor.textId = 0x300D;
}
Message_ContinueTextbox(globalCtx, this->actor.textId);
}
return 1;
}
default:
return 1;
}
}
u16 EnGo2_GetTextIdGoronDmtRollingSmall(GlobalContext* globalCtx, EnGo2* this) {
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else {
return (gSaveContext.eventChkInf[2] & 0x8) ? 0x3026 : 0x3009;
}
}
s16 EnGo2_GetStateGoronDmtRollingSmall(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronDmtDcEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
return 0x3027;
} else {
return gSaveContext.eventChkInf[2] & 0x8 ? 0x3021 : gSaveContext.infTable[14] & 0x1 ? 0x302A : 0x3008;
}
}
s16 EnGo2_GetStateGoronDmtDcEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x3008) {
gSaveContext.infTable[14] |= 0x1;
}
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
return 0x3027;
} else {
return gSaveContext.infTable[15] & 0x1 ? 0x3015 : 0x3014;
}
}
s16 EnGo2_GetStateGoronCityEntrance(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x3014) {
gSaveContext.infTable[15] |= 0x1;
}
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityIsland(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
return 0x3027;
} else {
return gSaveContext.infTable[15] & 0x10 ? 0x3017 : 0x3016;
}
}
s16 EnGo2_GetStateGoronCityIsland(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x3016) {
gSaveContext.infTable[15] |= 0x10;
}
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityLowestFloor(GlobalContext* globalCtx, EnGo2* this) {
if (((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
return 0x3043;
} else if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[0])) {
return 0x3027;
} else {
return CUR_UPG_VALUE(UPG_STRENGTH) != 0 ? 0x302C
: !Flags_GetSwitch(globalCtx, 0x1B) ? 0x3017
: gSaveContext.infTable[15] & 0x100 ? 0x3019
: 0x3018;
}
}
s16 EnGo2_GetStateGoronCityLowestFloor(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x3018) {
gSaveContext.infTable[15] |= 0x100;
}
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityLink(GlobalContext* globalCtx, EnGo2* this) {
if(gSaveContext.n64ddFlag) {
return 0x3036;
}
if (CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) {
return gSaveContext.infTable[16] & 0x8000 ? 0x3042 : 0x3041;
} else if (CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1)) {
return gSaveContext.infTable[16] & 0x4000 ? 0x3038 : 0x3037;
} else if (gSaveContext.infTable[16] & 0x1000) {
this->unk_20C = 0;
this->dialogState = TEXT_STATE_NONE;
return gSaveContext.infTable[16] & 0x400 ? 0x3033 : 0x3032;
} else {
return 0x3030;
}
}
s16 EnGo2_GetStateGoronCityLink(GlobalContext* globalCtx, EnGo2* this) {
switch (EnGo2_GetDialogState(this, globalCtx)) {
case TEXT_STATE_CLOSING:
if(!gSaveContext.n64ddFlag) {
switch (this->actor.textId) {
case 0x3036:
EnGo2_GetItem(this, globalCtx, GI_TUNIC_GORON);
this->actionFunc = EnGo2_SetupGetItem;
return 2;
case 0x3037:
gSaveContext.infTable[16] |= 0x4000;
default:
return 0;
}
} else {
if (Flags_GetTreasure(globalCtx, 0x1F)) {
return 0;
}
gSaveContext.infTable[16] |= 0x200;
EnGo2_GetItem(this, globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_GC_ROLLING_GORON_AS_ADULT, GI_TUNIC_GORON));
this->actionFunc = EnGo2_SetupGetItem;
Flags_SetTreasure(globalCtx, 0x1F);
return 2;
}
case TEXT_STATE_CHOICE:
if (Message_ShouldAdvance(globalCtx)) {
if (this->actor.textId == 0x3034) {
if (globalCtx->msgCtx.choiceIndex == 0) {
this->actor.textId = gSaveContext.infTable[16] & 0x800 ? 0x3033 : 0x3035;
if (this->actor.textId == 0x3035) {
Audio_StopSfxById(NA_SE_EN_GOLON_CRY);
}
} else {
this->actor.textId = gSaveContext.infTable[16] & 0x800 ? 0x3036 : 0x3033;
if (this->actor.textId == 0x3036) {
Audio_StopSfxById(NA_SE_EN_GOLON_CRY);
}
}
Message_ContinueTextbox(globalCtx, this->actor.textId);
this->unk_20C = 0;
}
} else {
break;
}
return 1;
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(globalCtx)) {
switch (this->actor.textId) {
case 0x3035:
gSaveContext.infTable[16] |= 0x800;
case 0x3032:
case 0x3033:
this->actor.textId = 0x3034;
Message_ContinueTextbox(globalCtx, this->actor.textId);
return 1;
default:
return 2;
}
}
}
return 1;
}
u16 EnGo2_GetTextIdGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
Player* player = GET_PLAYER(globalCtx);
if (gSaveContext.bgsFlag) {
player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK;
return 0x305E;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
player->exchangeItemId = EXCH_ITEM_CLAIM_CHECK;
return 0x305E;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_PRESCRIPTION) {
player->exchangeItemId = EXCH_ITEM_EYEDROPS;
return 0x3058;
} else {
player->exchangeItemId = EXCH_ITEM_SWORD_BROKEN;
return 0x3053;
}
}
s16 EnGo2_GetStateGoronDmtBiggoron(GlobalContext* globalCtx, EnGo2* this) {
s32 unusedPad;
u8 dialogState = this->dialogState;
switch (EnGo2_GetDialogState(this, globalCtx)) {
case TEXT_STATE_DONE:
if (this->actor.textId == 0x305E) {
if((!gSaveContext.n64ddFlag && gSaveContext.bgsFlag) || (gSaveContext.n64ddFlag && Flags_GetTreasure(globalCtx, 0x1F))) {
return 0;
}
if(gSaveContext.n64ddFlag) {
if (INV_CONTENT(ITEM_CLAIM_CHECK) != ITEM_CLAIM_CHECK) {
return 0;
}
EnGo2_GetItem(this, globalCtx, Randomizer_GetItemIdFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS));
Flags_SetTreasure(globalCtx, 0x1F);
} else {
EnGo2_GetItem(this, globalCtx, GI_SWORD_BGS);
}
this->actionFunc = EnGo2_SetupGetItem;
return 2;
} else {
return 0;
}
case TEXT_STATE_DONE_FADING:
switch (this->actor.textId) {
case 0x305E:
if (func_8002F368(globalCtx) != EXCH_ITEM_CLAIM_CHECK) {
break;
}
case 0x3059:
if (dialogState == TEXT_STATE_NONE) {
func_800F4524(&D_801333D4, NA_SE_EN_GOLON_WAKE_UP, 60);
}
case 0x3054:
if (dialogState == TEXT_STATE_NONE) {
Audio_PlaySoundGeneral(NA_SE_SY_TRE_BOX_APPEAR, &D_801333D4, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
}
}
return 1;
case TEXT_STATE_CHOICE:
if (Message_ShouldAdvance(globalCtx)) {
if ((this->actor.textId == 0x3054) || (this->actor.textId == 0x3055)) {
if (globalCtx->msgCtx.choiceIndex == 0) {
EnGo2_GetItem(this, globalCtx, GI_PRESCRIPTION);
this->actionFunc = EnGo2_SetupGetItem;
return 2;
}
this->actor.textId = 0x3056;
Message_ContinueTextbox(globalCtx, this->actor.textId);
}
return 1;
}
break;
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(globalCtx)) {
if (this->actor.textId == 0x3059) {
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
this->actionFunc = EnGo2_BiggoronEyedrops;
}
return 2;
}
}
return 1;
}
u16 EnGo2_GetTextIdGoronFireGeneric(GlobalContext* globalCtx, EnGo2* this) {
if (Flags_GetSwitch(globalCtx, (this->actor.params & 0xFC00) >> 0xA)) {
return 0x3071;
} else {
return 0x3051;
}
}
s16 EnGo2_GetStateGoronFireGeneric(GlobalContext* globalCtx, EnGo2* this) {
switch (Message_GetState(&globalCtx->msgCtx)) {
case TEXT_STATE_CLOSING:
return 0;
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(globalCtx)) {
if (this->actor.textId == 0x3071) {
this->actor.textId = EnGo2_GoronFireGenericGetTextId(this);
Message_ContinueTextbox(globalCtx, this->actor.textId);
}
return 1;
}
default:
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityStairwell(GlobalContext* globalCtx, EnGo2* this) {
return !LINK_IS_ADULT ? gSaveContext.infTable[14] & 0x8 ? 0x3022 : 0x300E : 0x3043;
}
s16 EnGo2_GetStateGoronCityStairwell(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x300E) {
gSaveContext.infTable[14] |= 0x8;
}
return 0;
} else {
return 1;
}
}
// Goron in child market bazaar after obtaining Goron Ruby
u16 EnGo2_GetTextIdGoronMarketBazaar(GlobalContext* globalCtx, EnGo2* this) {
return 0x7122;
}
s16 EnGo2_GetStateGoronMarketBazaar(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextIdGoronCityLostWoods(GlobalContext* globalCtx, EnGo2* this) {
if (!LINK_IS_ADULT) {
if (Flags_GetSwitch(globalCtx, 0x1C)) {
return 0x302F;
} else {
return gSaveContext.infTable[14] & 0x40 ? 0x3025 : 0x3024;
}
} else {
return 0x3043;
}
}
s16 EnGo2_GetStateGoronCityLostWoods(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
if (this->actor.textId == 0x3024) {
gSaveContext.infTable[14] |= 0x40;
}
return 0;
} else {
return 1;
}
}
// Goron at base of DMT summit
u16 EnGo2_GetTextIdGoronDmtFairyHint(GlobalContext* globalCtx, EnGo2* this) {
if (!LINK_IS_ADULT) {
return CHECK_QUEST_ITEM(QUEST_GORON_RUBY) ? 0x3065 : 0x3064;
} else {
return 0x3043;
}
}
s16 EnGo2_GetStateGoronDmtFairyHint(GlobalContext* globalCtx, EnGo2* this) {
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
return 0;
} else {
return 1;
}
}
u16 EnGo2_GetTextId(GlobalContext* globalCtx, Actor* thisx) {
EnGo2* this = (EnGo2*)thisx;
u16 faceReaction = Text_GetFaceReaction(globalCtx, 0x20);
if (faceReaction) {
return faceReaction;
} else {
switch (this->actor.params & 0x1F) {
case GORON_CITY_ROLLING_BIG:
return EnGo2_GetTextIdGoronCityRollingBig(globalCtx, this);
case GORON_CITY_LINK:
return EnGo2_GetTextIdGoronCityLink(globalCtx, this);
case GORON_DMT_BIGGORON:
return EnGo2_GetTextIdGoronDmtBiggoron(globalCtx, this);
case GORON_FIRE_GENERIC:
return EnGo2_GetTextIdGoronFireGeneric(globalCtx, this);
case GORON_DMT_BOMB_FLOWER:
return EnGo2_GetTextIdGoronDmtBombFlower(globalCtx, this);
case GORON_DMT_ROLLING_SMALL:
return EnGo2_GetTextIdGoronDmtRollingSmall(globalCtx, this);
case GORON_DMT_DC_ENTRANCE:
return EnGo2_GetTextIdGoronDmtDcEntrance(globalCtx, this);
case GORON_CITY_ENTRANCE:
return EnGo2_GetTextIdGoronCityEntrance(globalCtx, this);
case GORON_CITY_ISLAND:
return EnGo2_GetTextIdGoronCityIsland(globalCtx, this);
case GORON_CITY_LOWEST_FLOOR:
return EnGo2_GetTextIdGoronCityLowestFloor(globalCtx, this);
case GORON_CITY_STAIRWELL:
return EnGo2_GetTextIdGoronCityStairwell(globalCtx, this);
case GORON_CITY_LOST_WOODS:
return EnGo2_GetTextIdGoronCityLostWoods(globalCtx, this);
case GORON_DMT_FAIRY_HINT:
return EnGo2_GetTextIdGoronDmtFairyHint(globalCtx, this);
case GORON_MARKET_BAZAAR:
return EnGo2_GetTextIdGoronMarketBazaar(globalCtx, this);
}
}
}
s16 EnGo2_GetState(GlobalContext* globalCtx, Actor* thisx) {
EnGo2* this = (EnGo2*)thisx;
switch (this->actor.params & 0x1F) {
case GORON_CITY_ROLLING_BIG:
return EnGo2_GetStateGoronCityRollingBig(globalCtx, this);
case GORON_CITY_LINK:
return EnGo2_GetStateGoronCityLink(globalCtx, this);
case GORON_DMT_BIGGORON:
return EnGo2_GetStateGoronDmtBiggoron(globalCtx, this);
case GORON_FIRE_GENERIC:
return EnGo2_GetStateGoronFireGeneric(globalCtx, this);
case GORON_DMT_BOMB_FLOWER:
return EnGo2_GetStateGoronDmtBombFlower(globalCtx, this);
case GORON_DMT_ROLLING_SMALL:
return EnGo2_GetStateGoronDmtRollingSmall(globalCtx, this);
case GORON_DMT_DC_ENTRANCE:
return EnGo2_GetStateGoronDmtDcEntrance(globalCtx, this);
case GORON_CITY_ENTRANCE:
return EnGo2_GetStateGoronCityEntrance(globalCtx, this);
case GORON_CITY_ISLAND:
return EnGo2_GetStateGoronCityIsland(globalCtx, this);
case GORON_CITY_LOWEST_FLOOR:
return EnGo2_GetStateGoronCityLowestFloor(globalCtx, this);
case GORON_CITY_STAIRWELL:
return EnGo2_GetStateGoronCityStairwell(globalCtx, this);
case GORON_CITY_LOST_WOODS:
return EnGo2_GetStateGoronCityLostWoods(globalCtx, this);
case GORON_DMT_FAIRY_HINT:
return EnGo2_GetStateGoronDmtFairyHint(globalCtx, this);
case GORON_MARKET_BAZAAR:
return EnGo2_GetStateGoronMarketBazaar(globalCtx, this);
}
}
s32 func_80A44790(EnGo2* this, GlobalContext* globalCtx) {
if ((this->actor.params & 0x1F) != GORON_DMT_BIGGORON && (this->actor.params & 0x1F) != GORON_CITY_ROLLING_BIG) {
return func_800343CC(globalCtx, &this->actor, &this->unk_194.unk_00, this->unk_218, EnGo2_GetTextId,
EnGo2_GetState);
} else if (((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) && ((this->collider.base.ocFlags2 & 1) == 0)) {
return false;
} else {
if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
this->unk_194.unk_00 = 1;
return true;
} else if (this->unk_194.unk_00 != 0) {
this->unk_194.unk_00 = EnGo2_GetState(globalCtx, &this->actor);
return false;
} else if (func_8002F2CC(&this->actor, globalCtx, this->unk_218)) {
this->actor.textId = EnGo2_GetTextId(globalCtx, &this->actor);
}
return false;
}
}
void EnGo2_SetColliderDim(EnGo2* this) {
u8 index = this->actor.params & 0x1F;
this->collider.dim.radius = D_80A4816C[index].radius;
this->collider.dim.height = D_80A4816C[index].height;
}
void EnGo2_SetShape(EnGo2* this) {
u8 index = this->actor.params & 0x1F;
this->actor.shape.shadowScale = D_80A481F8[index].shape_unk_10;
Actor_SetScale(&this->actor, D_80A481F8[index].scale);
this->actor.targetMode = D_80A481F8[index].actor_unk_1F;
this->unk_218 = D_80A481F8[index].unk_218;
this->unk_218 += this->collider.dim.radius;
}
void EnGo2_CheckCollision(EnGo2* this, GlobalContext* globalCtx) {
Vec3s pos;
f32 xzDist;
pos.x = this->actor.world.pos.x;
pos.y = this->actor.world.pos.y;
pos.z = this->actor.world.pos.z;
xzDist = D_80A4816C[this->actor.params & 0x1F].xzDist;
pos.x += (s16)(xzDist * Math_SinS(this->actor.shape.rot.y));
pos.z += (s16)(xzDist * Math_CosS(this->actor.shape.rot.y));
pos.y += D_80A4816C[this->actor.params & 0x1F].yDist;
this->collider.dim.pos = pos;
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
void EnGo2_SwapInitialFrameAnimFrameCount(EnGo2* this) {
f32 initialFrame;
initialFrame = this->skelAnime.startFrame;
this->skelAnime.startFrame = this->skelAnime.endFrame;
this->skelAnime.endFrame = initialFrame;
}
s32 func_80A44AB0(EnGo2* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
f32 arg2;
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
return false;
} else {
if ((this->actionFunc != EnGo2_SlowRolling) && (this->actionFunc != EnGo2_ReverseRolling) &&
(this->actionFunc != EnGo2_ContinueRolling)) {
return false;
} else {
if (this->collider.base.acFlags & 2) {
Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8);
this->actor.flags &= ~ACTOR_FLAG_24;
this->collider.base.acFlags &= ~0x2;
EnGo2_StopRolling(this, globalCtx);
return true;
}
if (player->invincibilityTimer <= 0) {
this->collider.base.ocFlags1 |= 8;
} else {
return false;
}
if (this->collider.base.ocFlags2 & 1) {
this->collider.base.ocFlags2 &= ~1;
arg2 = this->actionFunc == EnGo2_ContinueRolling ? 1.5f : this->actor.speedXZ * 1.5f;
globalCtx->damagePlayer(globalCtx, -4);
func_8002F71C(globalCtx, &this->actor, arg2, this->actor.yawTowardsPlayer, 6.0f);
Audio_PlayActorSound2(&player->actor, NA_SE_PL_BODY_HIT);
this->collider.base.ocFlags1 &= ~0x8;
}
}
}
return false;
}
s32 EnGo2_UpdateWaypoint(EnGo2* this, GlobalContext* globalCtx) {
s32 change;
if (this->path == NULL) {
return 0;
}
change = (u8)(this->path->count - 1);
if (this->reverse) {
this->waypoint--;
if (this->waypoint < 0) {
this->waypoint = change - 1;
}
} else {
this->waypoint++;
if (this->waypoint >= change) {
this->waypoint = 0;
}
}
return 1;
}
s32 EnGo2_Orient(EnGo2* this, GlobalContext* globalCtx) {
s16 targetYaw;
f32 waypointDistSq = Path_OrientAndGetDistSq(&this->actor, this->path, this->waypoint, &targetYaw);
Math_SmoothStepToS(&this->actor.world.rot.y, targetYaw, 6, 4000, 1);
if (waypointDistSq > 0.0f && waypointDistSq < SQ(30.0f)) {
return EnGo2_UpdateWaypoint(this, globalCtx);
} else {
return 0;
}
}
s32 func_80A44D84(EnGo2* this) {
s16 targetYaw;
Path_OrientAndGetDistSq(&this->actor, this->path, this->waypoint, &targetYaw);
this->actor.world.rot.y = targetYaw;
return 1;
}
s32 EnGo2_IsWakingUp(EnGo2* this) {
s16 yawDiff;
f32 xyzDist = (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ? 800.0f : 200.0f;
f32 yDist = (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ? 400.0f : 60.0f;
s16 yawDiffAbs;
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
if ((this->collider.base.ocFlags2 & 1) == 0) {
this->actor.flags &= ~ACTOR_FLAG_0;
return false;
} else {
this->actor.flags |= ACTOR_FLAG_0;
return true;
}
}
xyzDist = SQ(xyzDist);
yawDiff = (f32)this->actor.yawTowardsPlayer - (f32)this->actor.shape.rot.y;
yawDiffAbs = ABS(yawDiff);
if (this->actor.xyzDistToPlayerSq <= xyzDist && fabsf(this->actor.yDistToPlayer) < yDist && yawDiffAbs < 0x2AA8) {
return true;
} else {
return false;
}
}
s32 EnGo2_IsRollingOnGround(EnGo2* this, s16 arg1, f32 arg2, s16 arg3) {
if ((this->actor.bgCheckFlags & 1) == 0 || this->actor.velocity.y > 0.0f) {
return false;
}
if (DECR(this->unk_590)) {
if (!arg3) {
return true;
} else {
this->actor.world.pos.y =
(this->unk_590 & 1) ? this->actor.world.pos.y + 1.5f : this->actor.world.pos.y - 1.5f;
Audio_PlayActorSound2(&this->actor, NA_SE_EV_BIGBALL_ROLL - SFX_FLAG);
return true;
}
}
if (this->unk_59C >= 2) {
Audio_PlayActorSound2(&this->actor, (this->actor.params & 0x1F) == GORON_CITY_ROLLING_BIG
? NA_SE_EN_GOLON_LAND_BIG
: NA_SE_EN_DODO_M_GND);
}
this->unk_59C--;
if (this->unk_59C <= 0) {
if (this->unk_59C == 0) {
this->unk_590 = Rand_S16Offset(60, 30);
this->unk_59C = 0;
this->actor.velocity.y = 0.0f;
return true;
} else {
this->unk_59C = arg1;
}
}
this->actor.velocity.y = ((f32)this->unk_59C / (f32)arg1) * arg2;
return true;
}
void EnGo2_BiggoronSetTextId(EnGo2* this, GlobalContext* globalCtx, Player* player) {
u16 textId;
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
if (gSaveContext.bgsFlag) {
if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) {
this->actor.textId = 0x3003;
} else {
this->actor.textId = 0x305E;
}
player->actor.textId = this->actor.textId;
} else if (!gSaveContext.bgsFlag && (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK)) {
if (func_8002F368(globalCtx) == EXCH_ITEM_CLAIM_CHECK) {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
textId = 0x305E;
} else {
textId = 0x305D;
}
this->actor.textId = textId;
} else {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
textId = 0x3002;
} else {
textId = 0x305D;
}
this->actor.textId = textId;
}
player->actor.textId = this->actor.textId;
} else if ((INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_PRESCRIPTION) &&
(INV_CONTENT(ITEM_TRADE_ADULT) <= ITEM_CLAIM_CHECK)) {
if (func_8002F368(globalCtx) == EXCH_ITEM_EYEDROPS) {
this->actor.textId = 0x3059;
} else {
this->actor.textId = 0x3058;
}
if (this->actor.textId == 0x3059) {
gSaveContext.timer2State = 0;
}
player->actor.textId = this->actor.textId;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) <= ITEM_SWORD_BROKEN) {
if (func_8002F368(globalCtx) == EXCH_ITEM_SWORD_BROKEN) {
if (gSaveContext.infTable[11] & 0x10) {
textId = 0x3055;
} else {
textId = 0x3054;
}
this->actor.textId = textId;
} else {
this->actor.textId = 0x3053;
}
player->actor.textId = this->actor.textId;
} else {
this->actor.textId = 0x3053;
player->actor.textId = this->actor.textId;
}
}
}
void func_80A45288(EnGo2* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s32 linkAge;
if (this->actionFunc != EnGo2_GoronFireGenericAction) {
this->unk_194.unk_18 = player->actor.world.pos;
linkAge = gSaveContext.linkAge;
this->unk_194.unk_14 = D_80A482D8[this->actor.params & 0x1F][linkAge];
func_80034A14(&this->actor, &this->unk_194, 4, this->unk_26E);
}
if ((this->actionFunc != EnGo2_SetGetItem) && (this->isAwake == true)) {
if (func_80A44790(this, globalCtx)) {
EnGo2_BiggoronSetTextId(this, globalCtx, player);
}
}
}
void func_80A45360(EnGo2* this, f32* alpha) {
f32 alphaTarget =
(this->skelAnime.animation == &gGoronAnim_004930) && (this->skelAnime.curFrame <= 32.0f) ? 0.0f : 255.0f;
Math_ApproachF(alpha, alphaTarget, 0.4f, 100.0f);
this->actor.shape.shadowAlpha = (u8)(u32)*alpha;
}
void EnGo2_RollForward(EnGo2* this) {
f32 speedXZ = this->actor.speedXZ;
if (this->unk_194.unk_00 != 0) {
this->actor.speedXZ = 0.0f;
}
if (this->actionFunc != EnGo2_ContinueRolling) {
Actor_MoveForward(&this->actor);
}
this->actor.speedXZ = speedXZ;
}
void func_80A454CC(EnGo2* this) {
switch (this->actor.params & 0x1F) {
case GORON_CITY_ROLLING_BIG:
case GORON_DMT_DC_ENTRANCE:
case GORON_CITY_ENTRANCE:
case GORON_CITY_STAIRWELL:
case GORON_DMT_FAIRY_HINT:
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_9);
break;
case GORON_DMT_BIGGORON:
if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_SWORD_BROKEN && INV_CONTENT(ITEM_TRADE_ADULT) <= ITEM_EYEDROPS) {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_4);
break;
}
default:
this->skelAnime.playSpeed = 0.0f;
break;
}
}
f32 EnGo2_GetTargetXZSpeed(EnGo2* this) {
f32 yDist = (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ? 400.0f : 60.0f;
s32 index = this->actor.params & 0x1F;
if (index == GORON_CITY_LINK && (fabsf(this->actor.yDistToPlayer) < yDist) &&
(this->actor.xzDistToPlayer < 400.0f)) {
return 9.0f;
} else {
return index == GORON_CITY_ROLLING_BIG ? 3.6000001f : 6.0f;
}
}
s32 EnGo2_IsCameraModified(EnGo2* this, GlobalContext* globalCtx) {
Camera* camera = globalCtx->cameraPtrs[MAIN_CAM];
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
if (EnGo2_IsWakingUp(this)) {
Camera_ChangeSetting(camera, CAM_SET_DIRECTED_YAW);
func_8005AD1C(camera, 4);
} else if (!EnGo2_IsWakingUp(this) && (camera->setting == CAM_SET_DIRECTED_YAW)) {
Camera_ChangeSetting(camera, CAM_SET_DUNGEON1);
func_8005ACFC(camera, 4);
}
}
if ((this->actor.params & 0x1F) == GORON_FIRE_GENERIC || (this->actor.params & 0x1F) == GORON_CITY_ROLLING_BIG ||
(this->actor.params & 0x1F) == GORON_CITY_STAIRWELL || (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ||
(this->actor.params & 0x1F) == GORON_MARKET_BAZAAR) {
return true;
} else if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1)) {
return true;
} else {
return false;
}
}
void EnGo2_DefaultWakingUp(EnGo2* this) {
if (EnGo2_IsWakingUp(this)) {
this->unk_26E = 2;
} else {
this->unk_26E = 1;
}
if (this->unk_194.unk_00 != 0) {
this->unk_26E = 4;
}
this->isAwake = true;
}
void EnGo2_WakingUp(EnGo2* this) {
f32 xyzDist = (this->actor.params & 0x1F) == GORON_DMT_BIGGORON ? 800.0f : 200.0f;
s32 isTrue = true;
xyzDist = SQ(xyzDist);
this->unk_26E = 1;
if ((this->actor.xyzDistToPlayerSq <= xyzDist) || (this->unk_194.unk_00 != 0)) {
this->unk_26E = 4;
}
this->isAwake = isTrue;
}
void EnGo2_BiggoronWakingUp(EnGo2* this) {
if (EnGo2_IsWakingUp(this) || this->unk_194.unk_00 != 0) {
this->unk_26E = 2;
this->isAwake = true;
} else {
this->unk_26E = 1;
this->isAwake = false;
}
}
void EnGo2_SelectGoronWakingUp(EnGo2* this) {
switch (this->actor.params & 0x1F) {
case GORON_DMT_BOMB_FLOWER:
this->isAwake = true;
this->unk_26E = EnGo2_IsWakingUp(this) ? 2 : 1;
break;
case GORON_FIRE_GENERIC:
EnGo2_WakingUp(this);
break;
case GORON_DMT_BIGGORON:
EnGo2_BiggoronWakingUp(this);
break;
case GORON_CITY_LINK:
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1)) {
EnGo2_WakingUp(this);
break;
}
default:
EnGo2_DefaultWakingUp(this);
}
}
void EnGo2_EyeMouthTexState(EnGo2* this) {
switch (this->eyeMouthTexState) {
case 1:
this->blinkTimer = 0;
this->eyeTexIndex = 0;
this->mouthTexIndex = 0;
break;
case 2:
this->blinkTimer = 0;
this->eyeTexIndex = 1;
this->mouthTexIndex = 0;
break;
// case 3 only when biggoron is given eyedrops. Biggoron smiles. (only use of second mouth texture)
case 3:
this->blinkTimer = 0;
this->eyeTexIndex = 0;
this->mouthTexIndex = 1;
break;
default:
if (DECR(this->blinkTimer) == 0) {
this->eyeTexIndex++;
if (this->eyeTexIndex >= 4) {
this->blinkTimer = Rand_S16Offset(30, 30);
this->eyeTexIndex = 1;
}
}
}
}
void EnGo2_SitDownAnimation(EnGo2* this) {
if ((this->skelAnime.playSpeed != 0.0f) && (this->skelAnime.animation == &gGoronAnim_004930)) {
if (this->skelAnime.playSpeed > 0.0f && this->skelAnime.curFrame == 14.0f) {
if ((this->actor.params & 0x1F) != GORON_DMT_BIGGORON) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_SIT_DOWN);
} else {
func_800F4524(&D_801333D4, NA_SE_EN_GOLON_SIT_DOWN, 60);
}
}
if (this->skelAnime.playSpeed < 0.0f) {
if (this->skelAnime.curFrame == 1.0f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_DODO_M_GND);
}
if (this->skelAnime.curFrame == 40.0f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_SIT_DOWN);
}
}
}
}
void EnGo2_GetDustData(EnGo2* this, s32 index2) {
s32 index1 = (this->actor.params & 0x1F) == GORON_CITY_ROLLING_BIG ? 1 : 0;
EnGo2DustEffectData* dustEffectData = &sDustEffectData[index1][index2];
EnGo2_SpawnDust(this, dustEffectData->initialTimer, dustEffectData->scale, dustEffectData->scaleStep,
dustEffectData->numDustEffects, dustEffectData->radius, dustEffectData->yAccel);
}
void EnGo2_RollingAnimation(EnGo2* this, GlobalContext* globalCtx) {
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
this->actor.flags &= ~ACTOR_FLAG_0;
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10);
this->skelAnime.playSpeed = -0.5f;
} else {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1);
this->skelAnime.playSpeed = -1.0f;
}
EnGo2_SwapInitialFrameAnimFrameCount(this);
this->unk_26E = 1;
this->unk_211 = false;
this->isAwake = false;
this->actionFunc = EnGo2_CurledUp;
}
void EnGo2_WakeUp(EnGo2* this, GlobalContext* globalCtx) {
if (this->skelAnime.playSpeed == 0.0f) {
if ((this->actor.params & 0x1F) != GORON_DMT_BIGGORON) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_WAKE_UP);
} else {
func_800F4524(&D_801333D4, NA_SE_EN_GOLON_WAKE_UP, 60);
}
}
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
OnePointCutscene_Init(globalCtx, 4200, -99, &this->actor, MAIN_CAM);
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_10);
this->skelAnime.playSpeed = 0.5f;
} else {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1);
this->skelAnime.playSpeed = 1.0f;
}
this->actionFunc = func_80A46B40;
}
void EnGo2_GetItemAnimation(EnGo2* this, GlobalContext* globalCtx) {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1);
this->unk_211 = true;
this->actionFunc = func_80A46B40;
this->skelAnime.playSpeed = 0.0f;
this->actor.speedXZ = 0.0f;
this->skelAnime.curFrame = this->skelAnime.endFrame;
}
void EnGo2_SetupRolling(EnGo2* this, GlobalContext* globalCtx) {
if ((this->actor.params & 0x1F) == GORON_CITY_ROLLING_BIG || (this->actor.params & 0x1F) == GORON_CITY_LINK) {
this->collider.info.bumperFlags = 1;
this->actor.speedXZ = gSaveContext.infTable[17] & 0x4000 ? 6.0f : 3.6000001f;
} else {
this->actor.speedXZ = 6.0f;
}
this->actor.flags |= ACTOR_FLAG_24;
this->animTimer = 10;
this->actor.shape.yOffset = 1800.0f;
this->actor.speedXZ += this->actor.speedXZ; // Speeding up
this->actionFunc = EnGo2_ContinueRolling;
}
void EnGo2_StopRolling(EnGo2* this, GlobalContext* globalCtx) {
EnBom* bomb;
if (((this->actor.params & 0x1F) != GORON_CITY_ROLLING_BIG) && ((this->actor.params & 0x1F) != GORON_CITY_LINK)) {
if ((this->actor.params & 0x1F) == GORON_DMT_ROLLING_SMALL) {
bomb = (EnBom*)Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_BOM, this->actor.world.pos.x,
this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0);
if (bomb != NULL) {
bomb->timer = 0;
}
}
} else {
this->collider.info.bumperFlags = 0;
}
this->actor.shape.rot = this->actor.world.rot;
this->unk_59C = 0;
this->unk_590 = 0;
this->actionFunc = EnGo2_GroundRolling;
this->actor.shape.yOffset = 0.0f;
this->actor.speedXZ = 0.0f;
}
s32 EnGo2_IsFreeingGoronInFire(EnGo2* this, GlobalContext* globalCtx) {
if ((this->actor.params & 0x1F) != GORON_FIRE_GENERIC) {
return false;
}
// shaking curled up
this->actor.world.pos.x += (globalCtx->state.frames & 1) ? 1.0f : -1.0f;
if (Flags_GetSwitch(globalCtx, (this->actor.params & 0xFC00) >> 0xA)) {
return true;
}
return false;
}
s32 EnGo2_IsGoronDmtBombFlower(EnGo2* this) {
if ((this->actor.params & 0x1F) != GORON_DMT_BOMB_FLOWER || this->unk_194.unk_00 != 2) {
return false;
}
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_3);
this->unk_194.unk_00 = 0;
this->isAwake = false;
this->unk_26E = 1;
this->actionFunc = EnGo2_GoronDmtBombFlowerAnimation;
return true;
}
s32 EnGo2_IsGoronRollingBig(EnGo2* this, GlobalContext* globalCtx) {
if ((this->actor.params & 0x1F) != GORON_CITY_ROLLING_BIG || (this->unk_194.unk_00 != 2)) {
return false;
}
this->unk_194.unk_00 = 0;
EnGo2_RollingAnimation(this, globalCtx);
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
return true;
}
s32 EnGo2_IsGoronFireGeneric(EnGo2* this) {
if ((this->actor.params & 0x1F) != GORON_FIRE_GENERIC || this->unk_194.unk_00 == 0) {
return false;
}
this->actionFunc = EnGo2_GoronFireGenericAction;
return true;
}
s32 EnGo2_IsGoronLinkReversing(EnGo2* this) {
if ((this->actor.params & 0x1F) != GORON_CITY_LINK || (this->waypoint >= this->unk_216) ||
!EnGo2_IsWakingUp(this)) {
return false;
}
return true;
}
s32 EnGo2_IsRolling(EnGo2* this) {
if (this->unk_194.unk_00 == 0 || this->actor.speedXZ < 1.0f) {
return false;
}
if (EnGo2_IsRollingOnGround(this, 2, 20.0 / 3.0f, 0)) {
if ((this->unk_590 >= 9) && (this->unk_59C == 0)) {
this->unk_590 = 8;
}
EnGo2_GetDustData(this, 0);
}
return true;
}
void EnGo2_GoronLinkAnimation(EnGo2* this, GlobalContext* globalCtx) {
s32 animation = ARRAY_COUNT(sAnimationInfo);
if ((this->actor.params & 0x1F) == GORON_CITY_LINK) {
if ((this->actor.textId == 0x3035 && this->unk_20C == 0) ||
(this->actor.textId == 0x3036 && this->unk_20C == 0)) {
if (this->skelAnime.animation != &gGoronAnim_000D5C) {
animation = ENGO2_ANIM_12;
this->eyeMouthTexState = 0;
}
}
if ((this->actor.textId == 0x3032 && this->unk_20C == 12) || (this->actor.textId == 0x3033) ||
(this->actor.textId == 0x3035 && this->unk_20C == 6)) {
if (this->skelAnime.animation != &gGoronAnim_000750) {
animation = ENGO2_ANIM_11;
this->eyeMouthTexState = 1;
}
}
if (this->skelAnime.animation == &gGoronAnim_000750) {
if (this->skelAnime.curFrame == 20.0f) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOLON_CRY);
}
}
if (animation != ARRAY_COUNT(sAnimationInfo)) {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, animation);
}
}
}
void EnGo2_GoronFireCamera(EnGo2* this, GlobalContext* globalCtx) {
s16 yaw;
this->camId = Gameplay_CreateSubCamera(globalCtx);
Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_WAIT);
Gameplay_ChangeCameraStatus(globalCtx, this->camId, CAM_STAT_ACTIVE);
Path_CopyLastPoint(this->path, &this->at);
yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->at) + 0xE38;
this->eye.x = Math_SinS(yaw) * 100.0f + this->actor.world.pos.x;
this->eye.z = Math_CosS(yaw) * 100.0f + this->actor.world.pos.z;
this->eye.y = this->actor.world.pos.y + 20.0f;
this->at.x = this->actor.world.pos.x;
this->at.y = this->actor.world.pos.y + 40.0f;
this->at.z = this->actor.world.pos.z;
Gameplay_CameraSetAtEye(globalCtx, this->camId, &this->at, &this->eye);
}
void EnGo2_GoronFireClearCamera(EnGo2* this, GlobalContext* globalCtx) {
Gameplay_ChangeCameraStatus(globalCtx, MAIN_CAM, CAM_STAT_ACTIVE);
Gameplay_ClearCamera(globalCtx, this->camId);
}
void EnGo2_BiggoronAnimation(EnGo2* this) {
if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_SWORD_BROKEN && INV_CONTENT(ITEM_TRADE_ADULT) <= ITEM_EYEDROPS &&
(this->actor.params & 0x1F) == GORON_DMT_BIGGORON && this->unk_194.unk_00 == 0) {
if (DECR(this->animTimer) == 0) {
this->animTimer = Rand_S16Offset(30, 30);
func_800F4524(&D_801333D4, NA_SE_EN_GOLON_EYE_BIG, 60);
}
}
}
void EnGo2_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGo2* this = (EnGo2*)thisx;
s32 pad;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 28.0f);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGoronSkel, NULL, this->jointTable, this->morphTable, 18);
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
// Not GORON_CITY_ROLLING_BIG, GORON_CITY_LINK, GORON_DMT_BIGGORON
switch (this->actor.params & 0x1F) {
case GORON_FIRE_GENERIC:
case GORON_DMT_BOMB_FLOWER:
case GORON_DMT_ROLLING_SMALL:
case GORON_DMT_DC_ENTRANCE:
case GORON_CITY_ENTRANCE:
case GORON_CITY_ISLAND:
case GORON_CITY_LOWEST_FLOOR:
case GORON_CITY_STAIRWELL:
case GORON_CITY_LOST_WOODS:
case GORON_DMT_FAIRY_HINT:
case GORON_MARKET_BAZAAR:
this->actor.flags &= ~ACTOR_FLAG_4;
this->actor.flags &= ~ACTOR_FLAG_5;
}
EnGo2_SetColliderDim(this);
EnGo2_SetShape(this);
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_0);
this->actor.gravity = -1.0f;
this->alpha = this->actor.shape.shadowAlpha = 0;
this->reverse = 0;
this->isAwake = false;
this->unk_211 = false;
this->goronState = 0;
this->waypoint = 0;
this->unk_216 = this->actor.shape.rot.z;
this->unk_26E = 1;
this->path = Path_GetByIndex(globalCtx, (this->actor.params & 0x3E0) >> 5, 0x1F);
switch (this->actor.params & 0x1F) {
case GORON_CITY_ENTRANCE:
case GORON_CITY_ISLAND:
case GORON_CITY_LOWEST_FLOOR:
case GORON_CITY_STAIRWELL:
case GORON_CITY_LOST_WOODS:
if (((!gSaveContext.n64ddFlag && !CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && !gSaveContext.dungeonsDone[4])) && LINK_IS_ADULT) {
Actor_Kill(&this->actor);
}
this->actionFunc = EnGo2_CurledUp;
break;
case GORON_MARKET_BAZAAR:
if ((LINK_IS_ADULT) || !CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
Actor_Kill(&this->actor);
}
EnGo2_GetItemAnimation(this, globalCtx);
break;
case GORON_CITY_LINK:
if ((gSaveContext.infTable[16] & 0x200)) {
Path_CopyLastPoint(this->path, &this->actor.world.pos);
this->actor.home.pos = this->actor.world.pos;
if (!CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE) && CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1)) {
EnGo2_GetItemAnimation(this, globalCtx);
} else {
this->actionFunc = EnGo2_CurledUp;
}
} else {
gSaveContext.infTable[16] &= ~0x1000;
this->collider.dim.height = (D_80A4816C[this->actor.params & 0x1F].height * 0.6f);
EnGo2_SetupRolling(this, globalCtx);
this->isAwake = true;
}
break;
case GORON_CITY_ROLLING_BIG:
case GORON_DMT_ROLLING_SMALL:
this->collider.dim.height = (D_80A4816C[this->actor.params & 0x1F].height * 0.6f);
EnGo2_SetupRolling(this, globalCtx);
break;
case GORON_FIRE_GENERIC:
if (Flags_GetSwitch(globalCtx, (this->actor.params & 0xFC00) >> 0xA)) {
Actor_Kill(&this->actor);
} else {
this->isAwake = true;
this->actionFunc = EnGo2_CurledUp;
}
break;
case GORON_DMT_BIGGORON:
this->actor.shape.shadowDraw = NULL;
this->actor.flags &= ~ACTOR_FLAG_0;
if ((INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_SWORD_BROKEN) &&
(INV_CONTENT(ITEM_TRADE_ADULT) <= ITEM_EYEDROPS)) {
this->eyeMouthTexState = 1;
}
this->collider.base.acFlags = 0;
this->collider.base.ocFlags1 = 0xD; // OC_PLAYER | OC_NO_PUSH | OC_ON
this->actionFunc = EnGo2_CurledUp;
break;
case GORON_DMT_BOMB_FLOWER:
if (gSaveContext.infTable[14] & 0x800) {
Path_CopyLastPoint(this->path, &this->actor.world.pos);
this->actor.home.pos = this->actor.world.pos;
}
case GORON_DMT_DC_ENTRANCE:
case GORON_DMT_FAIRY_HINT:
default:
this->actionFunc = EnGo2_CurledUp;
}
}
void EnGo2_Destroy(Actor* thisx, GlobalContext* globalCtx) {
}
void EnGo2_CurledUp(EnGo2* this, GlobalContext* globalCtx) {
u8 index = this->actor.params & 0x1F;
s16 height;
s32 quake;
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
quake = Quake_Add(GET_ACTIVE_CAM(globalCtx), 3);
Quake_SetSpeed(quake, -0x3CB0);
Quake_SetQuakeValues(quake, 8, 0, 0, 0);
Quake_SetCountdown(quake, 16);
} else {
EnGo2_GetDustData(this, 1);
}
this->skelAnime.playSpeed = 0.0f;
}
if ((s32)this->skelAnime.curFrame == 0) {
this->collider.dim.height = (D_80A4816C[index].height * 0.6f);
} else {
height = D_80A4816C[index].height;
this->collider.dim.height =
((D_80A4816C[index].height * 0.4f * (this->skelAnime.curFrame / this->skelAnime.startFrame)) +
(height * 0.6f));
}
if (EnGo2_IsFreeingGoronInFire(this, globalCtx)) {
this->isAwake = false;
EnGo2_WakeUp(this, globalCtx);
}
if (((this->actor.params & 0x1F) != GORON_FIRE_GENERIC) && EnGo2_IsWakingUp(this)) {
EnGo2_WakeUp(this, globalCtx);
}
}
void func_80A46B40(EnGo2* this, GlobalContext* globalCtx) {
u8 index = (this->actor.params & 0x1F);
f32 height;
if (this->unk_211 == true) {
EnGo2_BiggoronAnimation(this);
EnGo2_GoronLinkAnimation(this, globalCtx);
EnGo2_SelectGoronWakingUp(this);
if (!EnGo2_IsGoronRollingBig(this, globalCtx) && !EnGo2_IsGoronFireGeneric(this)) {
if (EnGo2_IsGoronDmtBombFlower(this)) {
return;
}
} else {
return;
}
} else {
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
if ((this->actor.params & 0x1F) == GORON_DMT_BIGGORON) {
this->actor.flags |= ACTOR_FLAG_0;
}
func_80A454CC(this);
this->unk_211 = true;
this->collider.dim.height = D_80A4816C[index].height;
} else {
height = D_80A4816C[index].height;
this->collider.dim.height =
(s16)((height * 0.4f * (this->skelAnime.curFrame / this->skelAnime.endFrame)) + (height * 0.6f));
}
}
if ((!EnGo2_IsCameraModified(this, globalCtx)) && (!EnGo2_IsWakingUp(this))) {
EnGo2_RollingAnimation(this, globalCtx);
}
}
void EnGo2_GoronDmtBombFlowerAnimation(EnGo2* this, GlobalContext* globalCtx) {
f32 float1 = this->skelAnime.endFrame;
f32 float2 = this->skelAnime.curFrame * ((f32)0x8000 / float1);
this->actor.speedXZ = Math_SinS(float2);
if ((EnGo2_Orient(this, globalCtx)) && (this->waypoint == 0)) {
EnGo2_GetItemAnimation(this, globalCtx);
}
}
void EnGo2_GoronRollingBigContinueRolling(EnGo2* this, GlobalContext* globalCtx) {
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
EnGo2_GetDustData(this, 1);
this->skelAnime.playSpeed = 0.0f;
EnGo2_SetupRolling(this, globalCtx);
}
}
void EnGo2_ContinueRolling(EnGo2* this, GlobalContext* globalCtx) {
f32 float1 = 1000.0f;
if (((this->actor.params & 0x1F) != GORON_DMT_ROLLING_SMALL || !(this->actor.xyzDistToPlayerSq > SQ(float1))) &&
DECR(this->animTimer) == 0) {
this->actionFunc = EnGo2_SlowRolling;
this->actor.speedXZ *= 0.5f; // slowdown
}
EnGo2_GetDustData(this, 2);
}
void EnGo2_SlowRolling(EnGo2* this, GlobalContext* globalCtx) {
s32 orientation;
s32 index;
if (!EnGo2_IsRolling(this)) {
if (EnGo2_IsRollingOnGround(this, 4, 8.0f, 1) == true) {
if (EnGo2_IsGoronLinkReversing(this)) {
this->actionFunc = EnGo2_ReverseRolling;
return;
}
EnGo2_GetDustData(this, 3);
}
orientation = EnGo2_Orient(this, globalCtx);
index = this->actor.params & 0x1F;
if (index != GORON_CITY_LINK) {
if ((index == GORON_DMT_ROLLING_SMALL) && (orientation == 1) && (this->waypoint == 0)) {
EnGo2_StopRolling(this, globalCtx);
return;
}
} else if ((orientation == 2) && (this->waypoint == 1)) {
EnGo2_StopRolling(this, globalCtx);
return;
}
Math_ApproachF(&this->actor.speedXZ, EnGo2_GetTargetXZSpeed(this), 0.4f, 0.6f);
this->actor.shape.rot = this->actor.world.rot;
}
}
void EnGo2_GroundRolling(EnGo2* this, GlobalContext* globalCtx) {
if (EnGo2_IsRollingOnGround(this, 4, 8.0f, 0)) {
EnGo2_GetDustData(this, 0);
if (this->unk_59C == 0) {
switch (this->actor.params & 0x1F) {
case GORON_CITY_LINK:
this->goronState = 0;
this->actionFunc = EnGo2_GoronLinkStopRolling;
break;
case GORON_CITY_ROLLING_BIG:
EnGo2_WakeUp(this, globalCtx);
break;
default:
this->actionFunc = EnGo2_CurledUp;
}
}
}
}
void EnGo2_ReverseRolling(EnGo2* this, GlobalContext* globalCtx) {
if (!EnGo2_IsRolling(this)) {
Math_ApproachF(&this->actor.speedXZ, 0.0f, 0.6f, 0.8f);
if (this->actor.speedXZ >= 1.0f) {
EnGo2_GetDustData(this, 3);
}
if ((s32)this->actor.speedXZ == 0) {
this->actor.world.rot.y ^= 0x8000;
this->actor.shape.rot.y = this->actor.world.rot.y;
this->reverse ^= 1;
EnGo2_UpdateWaypoint(this, globalCtx);
EnGo2_SetupRolling(this, globalCtx);
}
}
}
void EnGo2_SetupGetItem(EnGo2* this, GlobalContext* globalCtx) {
if (Actor_HasParent(&this->actor, globalCtx)) {
this->actor.parent = NULL;
this->actionFunc = EnGo2_SetGetItem;
} else {
func_8002F434(&this->actor, globalCtx, this->getItemId, this->actor.xzDistToPlayer + 1.0f,
fabsf(this->actor.yDistToPlayer) + 1.0f);
}
}
void EnGo2_SetGetItem(EnGo2* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_DONE) && Message_ShouldAdvance(globalCtx)) {
this->unk_194.unk_00 = 0;
switch (this->getItemId) {
case GI_CLAIM_CHECK:
Environment_ClearBgsDayCount();
EnGo2_GetItemAnimation(this, globalCtx);
return;
case GI_TUNIC_GORON:
if (!gSaveContext.n64ddFlag) {
gSaveContext.infTable[16] |= 0x200;
}
EnGo2_GetItemAnimation(this, globalCtx);
return;
case GI_SWORD_BGS:
gSaveContext.bgsFlag = true;
break;
case GI_BOMB_BAG_30:
case GI_BOMB_BAG_40:
EnGo2_RollingAnimation(this, globalCtx);
this->actionFunc = EnGo2_GoronRollingBigContinueRolling;
return;
}
this->actionFunc = func_80A46B40;
}
}
void EnGo2_BiggoronEyedrops(EnGo2* this, GlobalContext* globalCtx) {
switch (this->goronState) {
case 0:
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_5);
this->actor.flags &= ~ACTOR_FLAG_0;
this->actor.shape.rot.y += 0x5B0;
this->unk_26E = 1;
this->animTimer = this->skelAnime.endFrame + 60.0f + 60.0f; // eyeDrops animation timer
this->eyeMouthTexState = 2;
this->unk_20C = 0;
this->goronState++;
func_800F483C(0x28, 5);
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
break;
case 1:
if (DECR(this->animTimer)) {
if (this->animTimer == 60 || this->animTimer == 120) {
func_8005B1A4(GET_ACTIVE_CAM(globalCtx));
func_800F4524(&D_801333D4, NA_SE_EV_GORON_WATER_DROP, 60);
}
} else {
func_800F4524(&D_801333D4, NA_SE_EN_GOLON_GOOD_BIG, 60);
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_6);
Message_ContinueTextbox(globalCtx, 0x305A);
this->eyeMouthTexState = 3;
this->goronState++;
func_800F483C(0x7F, 5);
}
break;
case 2:
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
this->eyeMouthTexState = 0;
}
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_1);
this->actor.flags |= ACTOR_FLAG_0;
this->unk_26E = 2;
this->skelAnime.playSpeed = 0.0f;
this->skelAnime.curFrame = this->skelAnime.endFrame;
EnGo2_GetItem(this, globalCtx, GI_CLAIM_CHECK);
this->actionFunc = EnGo2_SetupGetItem;
this->goronState = 0;
}
break;
}
}
void EnGo2_GoronLinkStopRolling(EnGo2* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
switch (this->goronState) {
case 0:
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_NONE) {
return;
} else {
Message_StartTextbox(globalCtx, 0x3031, NULL);
player->actor.freezeTimer = 10;
this->goronState++;
}
case 1:
break;
default:
return;
}
if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING) {
player->actor.freezeTimer = 10;
} else {
gSaveContext.infTable[16] |= 0x1000;
this->unk_26E = 1;
this->unk_211 = false;
this->isAwake = false;
this->actionFunc = EnGo2_CurledUp;
}
}
void EnGo2_GoronFireGenericAction(EnGo2* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Vec3s D_80A4854C = { 0x00, 0x00, 0x00 };
switch (this->goronState) {
case 0: // Wake up
if (Message_GetState(&globalCtx->msgCtx) == TEXT_STATE_CLOSING) {
EnGo2_GoronFireCamera(this, globalCtx);
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
Animation_ChangeByInfo(&this->skelAnime, sAnimationInfo, ENGO2_ANIM_2);
this->waypoint = 1;
this->skelAnime.playSpeed = 2.0f;
func_80A44D84(this);
this->actor.shape.rot = this->actor.world.rot;
this->animTimer = 60;
this->actor.gravity = 0.0f;
this->actor.speedXZ = 2.0f;
this->unk_194.unk_08 = D_80A4854C;
this->unk_194.unk_0E = D_80A4854C;
this->goronState++;
this->goronState++;
player->actor.world.rot.y = this->actor.world.rot.y;
player->actor.shape.rot.y = this->actor.world.rot.y;
player->actor.world.pos.x =
(f32)((Math_SinS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.x);
player->actor.world.pos.z =
(f32)((Math_CosS(this->actor.world.rot.y) * -30.0f) + this->actor.world.pos.z);
func_8002DF54(globalCtx, &this->actor, 8);
Audio_PlayFanfare(NA_BGM_APPEAR);
}
break;
case 2: // Walking away
if (DECR(this->animTimer)) {
if (!(this->animTimer % 8)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_MORIBLIN_WALK);
}
Actor_MoveForward(&this->actor);
} else {
this->animTimer = 0;
this->actor.speedXZ = 0.0f;
if ((((this->actor.params & 0xFC00) >> 0xA) != 1) && (((this->actor.params & 0xFC00) >> 0xA) != 2) &&
(((this->actor.params & 0xFC00) >> 0xA) != 4) && (((this->actor.params & 0xFC00) >> 0xA) != 5) &&
(((this->actor.params & 0xFC00) >> 0xA) != 9) && (((this->actor.params & 0xFC00) >> 0xA) != 11)) {
this->goronState++;
}
this->goronState++;
}
break;
case 3: // Walking away
this->animTimer++;
if (!(this->animTimer % 8) && (this->animTimer < 10)) {
Audio_PlayActorSound2(&this->actor, NA_SE_EN_MORIBLIN_WALK);
}
if (this->animTimer == 10) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_IRON_DOOR_OPEN);
}
if (this->animTimer > 44) {
SoundSource_PlaySfxAtFixedWorldPos(globalCtx, &this->actor.world.pos, 20, NA_SE_EV_IRON_DOOR_CLOSE);
} else {
break;
}
case 4: // Finalize walking away
Message_CloseTextbox(globalCtx);
EnGo2_GoronFireClearCamera(this, globalCtx);
func_8002DF54(globalCtx, &this->actor, 7);
Actor_Kill(&this->actor);
break;
case 1:
break;
}
}
void EnGo2_Update(Actor* thisx, GlobalContext* globalCtx) {
EnGo2* this = (EnGo2*)thisx;
func_80A45360(this, &this->alpha);
EnGo2_SitDownAnimation(this);
SkelAnime_Update(&this->skelAnime);
EnGo2_RollForward(this);
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, (f32)this->collider.dim.height * 0.5f,
(f32)this->collider.dim.radius * 0.6f, 0.0f, 5);
if (this->unk_194.unk_00 == 0) {
func_80A44AB0(this, globalCtx);
}
this->actionFunc(this, globalCtx);
if (this->unk_211 == true) {
func_80034F54(globalCtx, this->unk_226, this->unk_24A, 18);
}
func_80A45288(this, globalCtx);
EnGo2_EyeMouthTexState(this);
EnGo2_CheckCollision(this, globalCtx);
}
s32 EnGo2_DrawCurledUp(EnGo2* this, GlobalContext* globalCtx) {
Vec3f D_80A48554 = { 0.0f, 0.0f, 0.0f };
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00BD80);
CLOSE_DISPS(globalCtx->state.gfxCtx);
Matrix_MultVec3f(&D_80A48554, &this->actor.focus.pos);
return 1;
}
s32 EnGo2_DrawRolling(EnGo2* this, GlobalContext* globalCtx) {
s32 pad;
Vec3f D_80A48560 = { 0.0f, 0.0f, 0.0f };
f32 speedXZ;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
speedXZ = this->actionFunc == EnGo2_ReverseRolling ? 0.0f : this->actor.speedXZ;
Matrix_RotateZYX((globalCtx->state.frames * ((s16)speedXZ * 1400)), 0, this->actor.shape.rot.z, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, gGoronDL_00C140);
CLOSE_DISPS(globalCtx->state.gfxCtx);
Matrix_MultVec3f(&D_80A48560, &this->actor.focus.pos);
return 1;
}
s32 EnGo2_OverrideLimbDraw(GlobalContext* globalCtx, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
EnGo2* this = (EnGo2*)thisx;
Vec3s vec1;
f32 float1;
if (limb == 17) {
Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
vec1 = this->unk_194.unk_08;
float1 = (vec1.y / (f32)0x8000) * M_PI;
Matrix_RotateX(float1, MTXMODE_APPLY);
float1 = (vec1.x / (f32)0x8000) * M_PI;
Matrix_RotateZ(float1, MTXMODE_APPLY);
Matrix_Translate(-2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
}
if (limb == 10) {
vec1 = this->unk_194.unk_0E;
float1 = (vec1.y / (f32)0x8000) * M_PI;
Matrix_RotateY(float1, MTXMODE_APPLY);
float1 = (vec1.x / (f32)0x8000) * M_PI;
Matrix_RotateX(float1, MTXMODE_APPLY);
}
if ((limb == 10) || (limb == 11) || (limb == 14)) {
float1 = Math_SinS(this->unk_226[limb]);
rot->y += float1 * 200.0f;
float1 = Math_CosS(this->unk_24A[limb]);
rot->z += float1 * 200.0f;
}
return 0;
}
void EnGo2_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
EnGo2* this = (EnGo2*)thisx;
Vec3f D_80A4856C = { 600.0f, 0.0f, 0.0f };
if (limbIndex == 17) {
Matrix_MultVec3f(&D_80A4856C, &this->actor.focus.pos);
}
}
void EnGo2_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnGo2* this = (EnGo2*)thisx;
void* eyeTextures[] = { gGoronCsEyeClosed2Tex, gGoronCsEyeOpenTex, gGoronCsEyeHalfTex, gGoronCsEyeClosedTex };
void* mouthTextures[] = { gGoronCsMouthNeutralTex, gGoronCsMouthSmileTex };
EnGo2_UpdateDust(this);
Matrix_Push();
EnGo2_DrawDust(this, globalCtx);
Matrix_Pop();
if ((this->actionFunc == EnGo2_CurledUp) && (this->skelAnime.playSpeed == 0.0f) &&
(this->skelAnime.curFrame == 0.0f)) {
EnGo2_DrawCurledUp(this, globalCtx);
} else if (this->actionFunc == EnGo2_SlowRolling || this->actionFunc == EnGo2_ReverseRolling ||
this->actionFunc == EnGo2_ContinueRolling) {
EnGo2_DrawRolling(this, globalCtx);
} else {
OPEN_DISPS(globalCtx->state.gfxCtx);
func_80093D18(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeTexIndex]));
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(mouthTextures[this->mouthTexIndex]));
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, EnGo2_OverrideLimbDraw, EnGo2_PostLimbDraw, this);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
}