Shipwright/soh/src/overlays/actors/ovl_En_Go/z_en_go.c
Christopher Leggett 168e84498f
Rework Get Item Table to be more flexible for adding custom items (#1050)
* Adds ItemTableManager class.

* Implements new getItem table in game.

* Adds rando item table and way to differentiate tables in GetItemEntry.

* Adds rough ability to differentiate between rando and vanilla items.merge stashed changes from before develop-zhora merge

* Change ItemTableID to be uint16_t so we can use ModIndex for it.

* Should fix switch build

* Should fix switch build pt 2

* Adds new files to CMakeLists.

* Implements fixes for competing getItem calls.

* Correctly renders freestanding items

Particle effects are probably broken, need to fix them still, I pretty
much know how I would do that.

* Fixed Particle effects in the new getItem system.

* Fixes item fanfares

* Partially fixes Ice Traps

Obtaining a freestanding Ice Trap causes link to slide forward
and receiving one from an NPC plays the sound effect and damage
animation but doesn't freeze link.

* Some more partial ice trap fixing that wasn't pushed earlier

* Removes unused function override

* Replaces ::find with ::at and adds exception handling

* Removes some commented out code.

* Refactors rando's GetItemEntry array into two arrays.

One array is for the vanilla items that don't have GetItemEntries in
vanilla, the other is for rando exclusive items. They are stored in
separate arrays before getting added to the table so that we can apply
different modIndexes. The items in the first table have are handled
by the vanilla Item_Give, and the second table needed a custom
`Randomizer_Item_Give` function.

* Renames, relocates, and implements ModIndex enum.

* Removes now unused ItemIDs and GetItemIDs

Also makes all the necessary changes to other code that was still
using them indirectly through the GI to GID map that was removed.
There's quite a lot of changes here and I haven't had time to test them
yet.

* Re-implements GIMESSAGE_UNTRANSLATED as macro

* Removes commented out function.

* Throws exception if an invalid itemID is used

Addresses https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r943694857

* Removes ARRAY_SIZE in favor of ARRAY_COUNT

ARRAY_COUNT already exists in `macros.h`, I just didn't find it before.

Addresses https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r943153833

* Inverts CheckContainsRandoItem to CheckContainsVanillaItem.

Addresses https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r940895135

* Cleanup, bugfixes, removing the `- 1`s from `z_player.c`

* Fixes some funky formatting that got committed earlier.

* Adds else if to added fanfare sound cases.

Addresses https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r940112924 and https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r940113492

* Extends GetItemEntry to include getItemId

Also adapts some existing calls for both the entry and the id to only
get the entry.

* Extends GetItemEntry to include GID.

This allows for using it later when drawing freestanding items.

Addresses https://github.com/HarbourMasters/Shipwright/pull/1050#discussion_r943168136

* Rando-specific items use new textId again.

This got lost when merging develop-zhora in because I didn't have custom
messages merged when I started this.

* Sets global modIndex to MOD_NONE on scene load

Fixes a crash when buying items in shops due to them
not triggering the rando code that normally sets these items.
May have also been crashing vanilla playthroughs.

* Realized I had the bgm conditions wrong.

* Fixes "static drops" (i.e. sticks from withered babas)

* Fixes LACS/Prelude situation... again.

* Fixes too many arguments error.

Not sure why this didn't fail to build on Windows before.

* Fixes Link's Pocket items.

* Simplifies sram init for rando-specific items

* Fixes issues with approaching bottleable items.

* Fixes Ruto's Letter.

It was accidentally getting classified as a rando item.

* Should re-fix freestanding ice traps

* Makes freestanding items set player->getItemEntry.

This prevents freestanding items from setting the global modIndex.
This is part of a larger transition that needs to happen to switch
to setting getItemEntries for all of the rando items. This prevents
some things that set getItemId of GI_MAX from granting a Fire Medallion
when the global modIndex is MOD_RANDOMIZER.

* Makes sure we aren't using getItemEntry when not randoed.

* Replace Randomizer_GetRandomizedItemId with Randomizer_GetRandomizedItem and Randomizer_GetItemIdFromKnownCheck with Randomizer_GetItemFromKnownCheck

* Introduce some new methods and migrate most actors to them

* Fixes ocarina game skull kids to set player->getItemEntry

* Sets `z_en_box.c` to set `player->getItemEntry`

* Fix logical errors and migrate most of the rest of the rando checks to GiveItemEntryFromActor

* Use GiveItemEntryFromActorWithFixedRange in item00

* Fixes Anju to set player->getItemEntry.

* Add a few missing cases

* Additional fix for Skull Kid

* Fixes vanilla ice traps and randomized ice smoke

* Fixes rendering of treasure chest game items.

* Removes unused `Randomizer_GetItemIdFromGetItemId`.

* Cleans up an if statement for item00.

* Cleans up another if statement in item00

* This should fix a bug with the Gerudo Archery minigame.

I wasn't able to get the bug to happen after making this change.

* Documents our new GiveItemEntry fuctions.

* Uses more descriptive type name for ItemIDs for creating custom messages.

* Fixes potential issue with if statement.

* Fixes missed type change.

Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
2022-08-23 20:11:38 -04:00

1249 lines
44 KiB
C

#include "z_en_go.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"
#include "soh/frame_interpolation.h"
#define FLAGS (ACTOR_FLAG_0 | ACTOR_FLAG_3 | ACTOR_FLAG_4 | ACTOR_FLAG_5)
void EnGo_Init(Actor* thisx, GlobalContext* globalCtx);
void EnGo_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnGo_Update(Actor* thisx, GlobalContext* globalCtx);
void EnGo_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80A3FEB4(EnGo* this, GlobalContext* globalCtx);
void EnGo_StopRolling(EnGo* this, GlobalContext* globalCtx);
void func_80A4008C(EnGo* this, GlobalContext* globalCtx);
void EnGo_GoronLinkRolling(EnGo* this, GlobalContext* globalCtx);
void EnGo_FireGenericActionFunc(EnGo* this, GlobalContext* globalCtx);
void EnGo_CurledUp(EnGo* this, GlobalContext* globalCtx);
void EnGo_WakeUp(EnGo* this, GlobalContext* globalCtx);
void func_80A40494(EnGo* this, GlobalContext* globalCtx);
void func_80A405CC(EnGo* this, GlobalContext* globalCtx);
void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx);
void func_80A408D8(EnGo* this, GlobalContext* globalCtx);
void func_80A40B1C(EnGo* this, GlobalContext* globalCtx);
void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx);
void func_80A40C78(EnGo* this, GlobalContext* globalCtx);
void EnGo_Eyedrops(EnGo* this, GlobalContext* globalCtx);
void func_80A40DCC(EnGo* this, GlobalContext* globalCtx);
void EnGo_AddDust(EnGo* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, u8 initialTimer, f32 scale, f32 scaleStep);
void EnGo_UpdateDust(EnGo* this);
void EnGo_DrawDust(EnGo* this, GlobalContext* globalCtx);
const ActorInit En_Go_InitVars = {
ACTOR_EN_GO,
ACTORCAT_NPC,
FLAGS,
OBJECT_OF1D_MAP,
sizeof(EnGo),
(ActorFunc)EnGo_Init,
(ActorFunc)EnGo_Destroy,
(ActorFunc)EnGo_Update,
(ActorFunc)EnGo_Draw,
NULL,
};
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_NONE,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_2,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK0,
{ 0x00000000, 0x00, 0x00 },
{ 0x00000000, 0x00, 0x00 },
TOUCH_NONE,
BUMP_NONE,
OCELEM_ON,
},
{ 20, 46, 0, { 0, 0, 0 } },
};
static CollisionCheckInfoInit2 sColChkInfoInit = {
0, 0, 0, 0, MASS_IMMOVABLE,
};
typedef enum {
/* 0 */ ENGO_ANIM_0,
/* 1 */ ENGO_ANIM_1,
/* 2 */ ENGO_ANIM_2,
/* 3 */ ENGO_ANIM_3
} EnGoAnimation;
static AnimationSpeedInfo sAnimationInfo[] = {
{ &gGoronAnim_004930, 0.0f, ANIMMODE_LOOP_INTERP, 0.0f },
{ &gGoronAnim_004930, 0.0f, ANIMMODE_LOOP_INTERP, -10.0f },
{ &gGoronAnim_0029A8, 1.0f, ANIMMODE_LOOP_INTERP, -10.0f },
{ &gGoronAnim_010590, 1.0f, ANIMMODE_LOOP_INTERP, -10.0f },
};
void EnGo_SetupAction(EnGo* this, EnGoActionFunc actionFunc) {
this->actionFunc = actionFunc;
}
u16 EnGo_GetTextID(GlobalContext* globalCtx, Actor* thisx) {
Player* player = GET_PLAYER(globalCtx);
switch (thisx->params & 0xF0) {
case 0x90:
if (gSaveContext.bgsFlag) {
return 0x305E;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_CLAIM_CHECK) {
if (Environment_GetBgsDayCount() >= CVar_GetS32("gForgeTime", 3)) {
return 0x305E;
} else {
return 0x305D;
}
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_EYEDROPS) {
player->exchangeItemId = EXCH_ITEM_EYEDROPS;
return 0x3059;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) >= ITEM_PRESCRIPTION) {
return 0x3058;
} else {
player->exchangeItemId = EXCH_ITEM_SWORD_BROKEN;
return 0x3053;
}
case 0x00:
if ((!gSaveContext.n64ddFlag && CHECK_QUEST_ITEM(QUEST_MEDALLION_FIRE)) ||
(gSaveContext.n64ddFlag && gSaveContext.dungeonsDone[4])) {
if (gSaveContext.infTable[16] & 0x8000) {
return 0x3042;
} else {
return 0x3041;
}
} else if (CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1) || (gSaveContext.infTable[16] & 0x2000)) {
if (gSaveContext.infTable[16] & 0x4000) {
return 0x3038;
} else {
return 0x3037;
}
} else {
if (gSaveContext.infTable[16] & 0x200) {
if (gSaveContext.infTable[16] & 0x400) {
return 0x3033;
} else {
return 0x3032;
}
} else {
return 0x3030;
}
}
case 0x10:
if (Flags_GetSwitch(globalCtx, thisx->params >> 8)) {
return 0x3052;
} else {
return 0x3051;
}
case 0x20:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.eventChkInf[2] & 0x8) {
return 0x3021;
} else if (gSaveContext.infTable[14] & 0x1) {
return 0x302A;
} else {
return 0x3008;
}
case 0x30:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.eventChkInf[2] & 0x8) {
return 0x3026;
} else {
return 0x3009;
}
case 0x40:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.eventChkInf[2] & 0x8) {
return 0x3026;
} else {
return 0x300A;
}
case 0x50:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.infTable[15] & 1) {
return 0x3015;
} else {
return 0x3014;
}
case 0x60:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.infTable[15] & 0x10) {
return 0x3017;
} else {
return 0x3016;
}
case 0x70:
if (CHECK_QUEST_ITEM(QUEST_GORON_RUBY)) {
return 0x3027;
} else if (gSaveContext.infTable[15] & 0x100) {
return 0x3019;
} else {
return 0x3018;
}
default:
return 0x0000;
}
}
s16 EnGo_SetFlagsGetStates(GlobalContext* globalCtx, Actor* thisx) {
s16 unkState = 1;
f32 xzRange;
f32 yRange = fabsf(thisx->yDistToPlayer) + 1.0f;
xzRange = thisx->xzDistToPlayer + 1.0f;
switch (Message_GetState(&globalCtx->msgCtx)) {
if (globalCtx) {}
case TEXT_STATE_CLOSING:
switch (thisx->textId) {
case 0x3008:
gSaveContext.infTable[14] |= 1;
unkState = 0;
break;
case 0x300B:
gSaveContext.infTable[14] |= 0x800;
unkState = 0;
break;
case 0x3014:
gSaveContext.infTable[15] |= 1;
unkState = 0;
break;
case 0x3016:
gSaveContext.infTable[15] |= 0x10;
unkState = 0;
break;
case 0x3018:
gSaveContext.infTable[15] |= 0x100;
unkState = 0;
break;
case 0x3036:
func_8002F434(thisx, globalCtx, GI_TUNIC_GORON, xzRange, yRange);
gSaveContext.infTable[16] |= 0x2000; // EnGo exclusive flag
unkState = 2;
break;
case 0x3037:
gSaveContext.infTable[16] |= 0x4000;
unkState = 0;
break;
case 0x3041:
gSaveContext.infTable[16] |= 0x8000;
unkState = 0;
break;
case 0x3059:
unkState = 2;
break;
case 0x3052:
case 0x3054:
case 0x3055:
case 0x305A:
unkState = 2;
break;
case 0x305E:
unkState = 2;
break;
default:
unkState = 0;
break;
}
break;
case TEXT_STATE_CHOICE:
if (Message_ShouldAdvance(globalCtx)) {
switch (thisx->textId) {
case 0x300A:
if (globalCtx->msgCtx.choiceIndex == 0) {
if (CUR_UPG_VALUE(UPG_STRENGTH) != 0 || (gSaveContext.infTable[14] & 0x800)) {
thisx->textId = 0x300B;
} else {
thisx->textId = 0x300C;
}
} else {
thisx->textId = 0x300D;
}
Message_ContinueTextbox(globalCtx, thisx->textId);
unkState = 1;
break;
case 0x3034:
if (globalCtx->msgCtx.choiceIndex == 0) {
if (gSaveContext.infTable[16] & 0x800) {
thisx->textId = 0x3033;
} else {
thisx->textId = 0x3035;
}
} else if (gSaveContext.infTable[16] & 0x800) {
thisx->textId = 0x3036;
} else {
thisx->textId = 0x3033;
}
Message_ContinueTextbox(globalCtx, thisx->textId);
unkState = 1;
break;
case 0x3054:
case 0x3055:
if (globalCtx->msgCtx.choiceIndex == 0) {
unkState = 2;
} else {
thisx->textId = 0x3056;
Message_ContinueTextbox(globalCtx, thisx->textId);
unkState = 1;
}
gSaveContext.infTable[11] |= 0x10;
break;
}
}
break;
case TEXT_STATE_EVENT:
if (Message_ShouldAdvance(globalCtx)) {
switch (thisx->textId) {
case 0x3035:
gSaveContext.infTable[16] |= 0x800;
case 0x3032:
case 0x3033:
thisx->textId = 0x3034;
Message_ContinueTextbox(globalCtx, thisx->textId);
unkState = 1;
break;
default:
unkState = 2;
break;
}
}
break;
case TEXT_STATE_DONE:
if (Message_ShouldAdvance(globalCtx)) {
unkState = 3;
}
break;
case TEXT_STATE_NONE:
case TEXT_STATE_DONE_HAS_NEXT:
case TEXT_STATE_DONE_FADING:
case TEXT_STATE_SONG_DEMO_DONE:
case TEXT_STATE_9:
break;
}
return unkState;
}
s32 func_80A3ED24(GlobalContext* globalCtx, EnGo* this, struct_80034A14_arg1* arg2, f32 arg3,
u16 (*getTextId)(GlobalContext*, Actor*), s16 (*unkFunc2)(GlobalContext*, Actor*)) {
if (arg2->unk_00) {
arg2->unk_00 = unkFunc2(globalCtx, &this->actor);
return false;
} else if (Actor_ProcessTalkRequest(&this->actor, globalCtx)) {
arg2->unk_00 = 1;
return true;
} else if (!func_8002F2CC(&this->actor, globalCtx, arg3)) {
return false;
} else {
this->actor.textId = getTextId(globalCtx, &this->actor);
return false;
}
}
void EnGo_ChangeAnim(EnGo* this, s32 index) {
Animation_Change(&this->skelAnime, sAnimationInfo[index].animation,
sAnimationInfo[index].playSpeed * ((this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f), 0.0f,
Animation_GetLastFrame(sAnimationInfo[index].animation), sAnimationInfo[index].mode,
sAnimationInfo[index].morphFrames);
}
s32 EnGo_IsActorSpawned(EnGo* this, GlobalContext* globalCtx) {
if (((this->actor.params) & 0xF0) == 0x90) {
return true;
} else if (globalCtx->sceneNum == SCENE_HIDAN && !Flags_GetSwitch(globalCtx, (this->actor.params) >> 8) &&
LINK_IS_ADULT && (this->actor.params & 0xF0) == 0x10) {
return true;
} else if (globalCtx->sceneNum == SCENE_SPOT18 && LINK_IS_ADULT && (this->actor.params & 0xF0) == 0x00) {
return true;
} else if (globalCtx->sceneNum == SCENE_SPOT16 && LINK_IS_CHILD &&
((this->actor.params & 0xF0) == 0x20 || (this->actor.params & 0xF0) == 0x30 ||
(this->actor.params & 0xF0) == 0x40)) {
return true;
} else if (globalCtx->sceneNum == SCENE_SPOT18 && LINK_IS_CHILD &&
((this->actor.params & 0xF0) == 0x50 || (this->actor.params & 0xF0) == 0x60 ||
(this->actor.params & 0xF0) == 0x70)) {
return true;
} else {
return false;
}
}
f32 EnGo_GetGoronSize(EnGo* this) {
switch (this->actor.params & 0xF0) {
case 0x00:
return 10.0f;
case 0x20:
case 0x30:
case 0x50:
case 0x60:
case 0x70:
return 20.0f;
case 0x40:
return 60.0f;
default:
return 20.0f;
}
}
void func_80A3F060(EnGo* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s16 unkVal;
if (this->actionFunc != EnGo_BiggoronActionFunc && this->actionFunc != EnGo_FireGenericActionFunc &&
this->actionFunc != func_80A40B1C) {
unkVal = 1;
}
this->unk_1E0.unk_18 = player->actor.world.pos;
this->unk_1E0.unk_14 = EnGo_GetGoronSize(this);
func_80034A14(&this->actor, &this->unk_1E0, 4, unkVal);
}
void func_80A3F0E4(EnGo* this) {
if (DECR(this->unk_214) == 0) {
this->unk_216++;
if (this->unk_216 >= 3) {
this->unk_214 = Rand_S16Offset(30, 30);
this->unk_216 = 0;
}
}
}
s32 EnGo_IsCameraModified(EnGo* this, GlobalContext* globalCtx) {
f32 xyzDist;
s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y;
Camera* camera = globalCtx->cameraPtrs[MAIN_CAM];
if (fabsf(yawDiff) > 10920.0f) {
return 0;
}
xyzDist = (this->actor.scale.x / 0.01f) * 10000.0f;
if ((this->actor.params & 0xF0) == 0x90) {
Camera_ChangeSetting(camera, CAM_SET_DIRECTED_YAW);
xyzDist *= 4.8f;
}
if (fabsf(this->actor.xyzDistToPlayerSq) > xyzDist) {
if (camera->setting == CAM_SET_DIRECTED_YAW) {
Camera_ChangeSetting(camera, CAM_SET_NORMAL0);
}
return 0;
} else {
return 1;
}
}
void EnGo_ReverseAnimation(EnGo* this) {
f32 startFrame = this->skelAnime.startFrame;
this->skelAnime.startFrame = this->skelAnime.endFrame;
this->skelAnime.endFrame = startFrame;
}
void EnGo_UpdateShadow(EnGo* this) {
s16 shadowAlpha;
f32 currentFrame = this->skelAnime.curFrame;
s16 shadowAlphaTarget = (this->skelAnime.animation == &gGoronAnim_004930 && currentFrame > 32.0f) ||
this->skelAnime.animation != &gGoronAnim_004930
? 255
: 0;
shadowAlpha = this->actor.shape.shadowAlpha;
Math_SmoothStepToS(&shadowAlpha, shadowAlphaTarget, 10, 60, 1);
this->actor.shape.shadowAlpha = shadowAlpha;
}
s32 EnGo_FollowPath(EnGo* this, GlobalContext* globalCtx) {
Path* path;
Vec3s* pointPos;
f32 xDist;
f32 zDist;
if ((this->actor.params & 0xF) == 15) {
return false;
}
path = &globalCtx->setupPathList[this->actor.params & 0xF];
pointPos = SEGMENTED_TO_VIRTUAL(path->points);
pointPos += this->unk_218;
xDist = pointPos->x - this->actor.world.pos.x;
zDist = pointPos->z - this->actor.world.pos.z;
Math_SmoothStepToS(&this->actor.world.rot.y, (s16)(Math_FAtan2F(xDist, zDist) * ((f32)0x8000 / M_PI)), 10, 1000, 1);
if ((SQ(xDist) + SQ(zDist)) < 600.0f) {
this->unk_218++;
if (this->unk_218 >= path->count) {
this->unk_218 = 0;
}
if ((this->actor.params & 0xF0) != 0x00) {
return true;
} else if (Flags_GetSwitch(globalCtx, this->actor.params >> 8)) {
return true;
} else if (this->unk_218 >= this->actor.shape.rot.z) {
this->unk_218 = 0;
}
return true;
}
return false;
}
s32 EnGo_SetMovedPos(EnGo* this, GlobalContext* globalCtx) {
Path* path;
Vec3s* pointPos;
if ((this->actor.params & 0xF) == 0xF) {
return false;
} else {
path = &globalCtx->setupPathList[this->actor.params & 0xF];
pointPos = SEGMENTED_TO_VIRTUAL(path->points);
pointPos += (path->count - 1);
this->actor.world.pos.x = pointPos->x;
this->actor.world.pos.y = pointPos->y;
this->actor.world.pos.z = pointPos->z;
this->actor.home.pos = this->actor.world.pos;
return true;
}
}
s32 EnGo_SpawnDust(EnGo* this, u8 initialTimer, f32 scale, f32 scaleStep, s32 numDustEffects, f32 radius, f32 xzAccel) {
Vec3f pos = { 0.0f, 0.0f, 0.0f };
Vec3f velocity = { 0.0f, 0.0f, 0.0f };
Vec3f accel = { 0.0f, 0.3f, 0.0f };
s16 angle;
s32 i;
pos = this->actor.world.pos; // Overwrites pos
pos.y = this->actor.floorHeight;
angle = (Rand_ZeroOne() - 0.5f) * 0x10000;
i = numDustEffects;
while (i >= 0) {
accel.x = (Rand_ZeroOne() - 0.5f) * xzAccel;
accel.z = (Rand_ZeroOne() - 0.5f) * xzAccel;
pos.x = (Math_SinS(angle) * radius) + this->actor.world.pos.x;
pos.z = (Math_CosS(angle) * radius) + this->actor.world.pos.z;
EnGo_AddDust(this, &pos, &velocity, &accel, initialTimer, scale, scaleStep);
angle += (s16)(0x10000 / numDustEffects);
i--;
}
return 0;
}
s32 EnGo_IsRollingOnGround(EnGo* this, s16 unkArg1, f32 unkArg2) {
if ((this->actor.bgCheckFlags & 1) == 0 || this->actor.velocity.y > 0.0f) {
return false;
} else if (this->unk_1E0.unk_00 != 0) {
return true;
} else if (DECR(this->unk_21C)) {
if ((this->unk_21C & 1)) {
this->actor.world.pos.y += 1.5f;
} else {
this->actor.world.pos.y -= 1.5f;
}
return true;
} else {
this->unk_21A--;
if (this->unk_21A <= 0) {
if (this->unk_21A == 0) {
this->unk_21C = Rand_S16Offset(60, 30);
this->unk_21A = 0;
this->actor.velocity.y = 0.0f;
return true;
}
this->unk_21A = unkArg1;
}
this->actor.velocity.y = ((f32)this->unk_21A / (f32)unkArg1) * unkArg2;
return true;
}
}
void func_80A3F908(EnGo* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
f32 float1;
s32 isUnkCondition;
if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_GoronLinkRolling ||
this->actionFunc == EnGo_FireGenericActionFunc || this->actionFunc == EnGo_Eyedrops ||
this->actionFunc == func_80A40DCC || this->actionFunc == EnGo_GetItem || this->actionFunc == func_80A40C78 ||
this->actionFunc == func_80A40B1C) {
float1 = (this->collider.dim.radius + 30.0f);
float1 *= (this->actor.scale.x / 0.01f);
if ((this->actor.params & 0xF0) == 0x90) {
float1 *= 4.8f;
}
if ((this->actor.params & 0xF0) == 0x90) {
isUnkCondition =
func_80A3ED24(globalCtx, this, &this->unk_1E0, float1, EnGo_GetTextID, EnGo_SetFlagsGetStates);
} else {
isUnkCondition = func_800343CC(globalCtx, &this->actor, &this->unk_1E0.unk_00, float1, EnGo_GetTextID,
EnGo_SetFlagsGetStates);
}
if (((this->actor.params & 0xF0) == 0x90) && (isUnkCondition == true)) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
if (func_8002F368(globalCtx) == EXCH_ITEM_SWORD_BROKEN) {
if (gSaveContext.infTable[11] & 0x10) {
this->actor.textId = 0x3055;
} else {
this->actor.textId = 0x3054;
}
} else {
this->actor.textId = 0x3053;
}
player->actor.textId = this->actor.textId;
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
if (func_8002F368(globalCtx) == EXCH_ITEM_EYEDROPS) {
this->actor.textId = 0x3059;
} else {
this->actor.textId = 0x3058;
}
player->actor.textId = this->actor.textId;
}
}
}
}
void EnGo_Init(Actor* thisx, GlobalContext* globalCtx) {
EnGo* this = (EnGo*)thisx;
s32 pad;
Vec3f D_80A41B9C = { 0.0f, 0.0f, 0.0f }; // unused
Vec3f D_80A41BA8 = { 0.0f, 0.0f, 0.0f }; // unused
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f);
SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gGoronSkel, NULL, 0, 0, 0);
Collider_InitCylinder(globalCtx, &this->collider);
Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit);
if (!EnGo_IsActorSpawned(this, globalCtx)) {
Actor_Kill(&this->actor);
return;
}
if ((this->actor.params & 0xF0) && ((this->actor.params & 0xF0) != 0x90)) {
this->actor.flags &= ~ACTOR_FLAG_4;
this->actor.flags &= ~ACTOR_FLAG_5;
}
EnGo_ChangeAnim(this, ENGO_ANIM_0);
this->actor.targetMode = 6;
this->unk_1E0.unk_00 = 0;
this->actor.gravity = -1.0f;
switch (this->actor.params & 0xF0) {
case 0x00:
Actor_SetScale(&this->actor, 0.008f);
if (CHECK_OWNED_EQUIP(EQUIP_TUNIC, 1)) {
EnGo_SetMovedPos(this, globalCtx);
EnGo_SetupAction(this, EnGo_CurledUp);
} else {
this->actor.shape.yOffset = 1400.0f;
this->actor.speedXZ = 3.0f;
EnGo_SetupAction(this, EnGo_GoronLinkRolling);
}
break;
case 0x10:
this->skelAnime.curFrame = Animation_GetLastFrame(&gGoronAnim_004930);
Actor_SetScale(&this->actor, 0.01f);
EnGo_SetupAction(this, EnGo_FireGenericActionFunc);
break;
case 0x40:
if (gSaveContext.infTable[14] & 0x800) {
EnGo_SetMovedPos(this, globalCtx);
}
Actor_SetScale(&this->actor, 0.015f);
EnGo_SetupAction(this, EnGo_CurledUp);
break;
case 0x30:
this->actor.shape.yOffset = 1400.0f;
Actor_SetScale(&this->actor, 0.01f);
EnGo_SetupAction(this, func_80A3FEB4);
break;
case 0x90:
this->actor.targetMode = 5;
Actor_SetScale(&this->actor, 0.16f);
EnGo_SetupAction(this, EnGo_CurledUp);
break;
case 0x20:
case 0x50:
case 0x60:
case 0x70:
Actor_SetScale(&this->actor, 0.01f);
EnGo_SetupAction(this, EnGo_CurledUp);
break;
default:
Actor_Kill(&this->actor);
}
}
void EnGo_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnGo* this = (EnGo*)thisx;
SkelAnime_Free(&this->skelAnime, globalCtx);
Collider_DestroyCylinder(globalCtx, &this->collider);
}
void func_80A3FEB4(EnGo* this, GlobalContext* globalCtx) {
if (!(this->actor.xyzDistToPlayerSq > SQ(1200.0f))) {
EnGo_SetupAction(this, EnGo_StopRolling);
}
}
void EnGo_StopRolling(EnGo* this, GlobalContext* globalCtx) {
EnBom* bomb;
if (DECR(this->unk_20E) == 0) {
if (this->collider.base.ocFlags2 & 1) {
this->collider.base.ocFlags2 &= ~1;
globalCtx->damagePlayer(globalCtx, -4);
func_8002F71C(globalCtx, &this->actor, 4.0f, this->actor.yawTowardsPlayer, 6.0f);
this->unk_20E = 0x10;
}
}
this->actor.speedXZ = 3.0f;
if ((EnGo_FollowPath(this, globalCtx) == true) && (this->unk_218 == 0)) {
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;
}
this->actor.speedXZ = 0.0f;
EnGo_SetupAction(this, func_80A4008C);
}
this->actor.shape.rot = this->actor.world.rot;
if (EnGo_IsRollingOnGround(this, 3, 6.0f)) {
EnGo_SpawnDust(this, 12, 0.16f, 0.1f, 1, 10.0f, 20.0f);
}
}
void func_80A4008C(EnGo* this, GlobalContext* globalCtx) {
if (EnGo_IsRollingOnGround(this, 3, 6.0f)) {
if (this->unk_21A == 0) {
this->actor.shape.yOffset = 0.0f;
EnGo_SetupAction(this, EnGo_CurledUp);
} else {
EnGo_SpawnDust(this, 12, 0.16f, 0.1f, 1, 10.0f, 20.0f);
}
}
}
void EnGo_GoronLinkRolling(EnGo* this, GlobalContext* globalCtx) {
if ((EnGo_FollowPath(this, globalCtx) == true) && Flags_GetSwitch(globalCtx, this->actor.params >> 8) &&
(this->unk_218 == 0)) {
this->actor.speedXZ = 0.0f;
EnGo_SetupAction(this, func_80A4008C);
gSaveContext.infTable[16] |= 0x200;
}
this->actor.shape.rot = this->actor.world.rot;
if (EnGo_IsRollingOnGround(this, 3, 6.0f)) {
EnGo_SpawnDust(this, 12, 0.18f, 0.2f, 2, 13.0f, 20.0f);
}
}
void EnGo_FireGenericActionFunc(EnGo* this, GlobalContext* globalCtx) {
}
void EnGo_CurledUp(EnGo* this, GlobalContext* globalCtx) {
if ((DECR(this->unk_210) == 0) && EnGo_IsCameraModified(this, globalCtx)) {
Audio_PlaySoundGeneral(NA_SE_EN_GOLON_WAKE_UP, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
this->skelAnime.playSpeed = 0.1f;
this->skelAnime.playSpeed *= (this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f;
EnGo_SetupAction(this, EnGo_WakeUp);
if ((this->actor.params & 0xF0) == 0x90) {
OnePointCutscene_Init(globalCtx, 4200, -99, &this->actor, MAIN_CAM);
}
}
}
void EnGo_WakeUp(EnGo* this, GlobalContext* globalCtx) {
f32 frame;
if (this->skelAnime.playSpeed != 0.0f) {
Math_SmoothStepToF(&this->skelAnime.playSpeed, ((this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f) * 0.5f, 0.1f,
1000.0f, 0.1f);
frame = this->skelAnime.curFrame;
frame += this->skelAnime.playSpeed;
if (frame <= 12.0f) {
return;
} else {
this->skelAnime.curFrame = 12.0f;
this->skelAnime.playSpeed = 0.0f;
if ((this->actor.params & 0xF0) != 0x90) {
this->unk_212 = 30;
return;
}
}
}
if (DECR(this->unk_212) == 0) {
Audio_PlaySoundGeneral(NA_SE_EN_GOLON_SIT_DOWN, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
EnGo_SetupAction(this, func_80A405CC);
} else if (!EnGo_IsCameraModified(this, globalCtx)) {
EnGo_ReverseAnimation(this);
this->skelAnime.playSpeed = 0.0f;
EnGo_SetupAction(this, func_80A40494);
}
}
void func_80A40494(EnGo* this, GlobalContext* globalCtx) {
f32 frame;
Math_SmoothStepToF(&this->skelAnime.playSpeed, ((this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f) * -0.5f, 0.1f,
1000.0f, 0.1f);
frame = this->skelAnime.curFrame;
frame += this->skelAnime.playSpeed;
if (!(frame >= 0.0f)) {
Audio_PlaySoundGeneral(NA_SE_EN_DODO_M_GND, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
EnGo_SpawnDust(this, 10, 0.4f, 0.1f, 16, 26.0f, 2.0f);
EnGo_ReverseAnimation(this);
this->skelAnime.playSpeed = 0.0f;
this->skelAnime.curFrame = 0.0f;
this->unk_210 = Rand_S16Offset(30, 30);
EnGo_SetupAction(this, EnGo_CurledUp);
}
}
void func_80A405CC(EnGo* this, GlobalContext* globalCtx) {
f32 lastFrame;
f32 frame;
lastFrame = Animation_GetLastFrame(&gGoronAnim_004930);
Math_SmoothStepToF(&this->skelAnime.playSpeed, (this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f, 0.1f, 1000.0f,
0.1f);
frame = this->skelAnime.curFrame;
frame += this->skelAnime.playSpeed;
if (!(frame < lastFrame)) {
this->skelAnime.curFrame = lastFrame;
this->skelAnime.playSpeed = 0.0f;
this->unk_212 = Rand_S16Offset(30, 30);
if (((this->actor.params & 0xF0) == 0x40) && ((gSaveContext.infTable[14] & 0x800) == 0)) {
EnGo_SetupAction(this, func_80A40B1C);
} else {
EnGo_SetupAction(this, EnGo_BiggoronActionFunc);
}
}
}
void EnGo_BiggoronActionFunc(EnGo* this, GlobalContext* globalCtx) {
if (((this->actor.params & 0xF0) == 0x90) && (this->unk_1E0.unk_00 == 2)) {
if (gSaveContext.bgsFlag) {
this->unk_1E0.unk_00 = 0;
} else {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
EnGo_ChangeAnim(this, ENGO_ANIM_2);
this->unk_21E = 100;
this->unk_1E0.unk_00 = 0;
EnGo_SetupAction(this, EnGo_Eyedrops);
globalCtx->msgCtx.msgMode = MSGMODE_PAUSED;
gSaveContext.timer2State = 0;
OnePointCutscene_Init(globalCtx, 4190, -99, &this->actor, MAIN_CAM);
} else {
this->unk_1E0.unk_00 = 0;
EnGo_SetupAction(this, EnGo_GetItem);
Message_CloseTextbox(globalCtx);
EnGo_GetItem(this, globalCtx);
}
}
} else if (((this->actor.params & 0xF0) == 0) && (this->unk_1E0.unk_00 == 2)) {
EnGo_SetupAction(this, EnGo_GetItem);
globalCtx->msgCtx.stateTimer = 4;
globalCtx->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;
} else {
if ((DECR(this->unk_212) == 0) && !EnGo_IsCameraModified(this, globalCtx)) {
EnGo_ReverseAnimation(this);
this->skelAnime.playSpeed = -0.1f;
this->skelAnime.playSpeed *= (this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f;
EnGo_SetupAction(this, func_80A408D8);
}
}
}
void func_80A408D8(EnGo* this, GlobalContext* globalCtx) {
f32 frame;
if (this->skelAnime.playSpeed != 0.0f) {
Math_SmoothStepToF(&this->skelAnime.playSpeed, ((this->actor.params & 0xF0) == 0x90 ? 0.5f : 1.0f) * -1.0f,
0.1f, 1000.0f, 0.1f);
frame = this->skelAnime.curFrame;
frame += this->skelAnime.playSpeed;
if (frame >= 12.0f) {
return;
} else {
this->skelAnime.curFrame = 12.0f;
this->skelAnime.playSpeed = 0.0f;
if ((this->actor.params & 0xF0) != 0x90) {
this->unk_212 = 30;
return;
}
}
}
if (DECR(this->unk_212) == 0) {
EnGo_SetupAction(this, func_80A40494);
} else if (EnGo_IsCameraModified(this, globalCtx)) {
EnGo_ReverseAnimation(this);
Audio_PlaySoundGeneral(NA_SE_EN_GOLON_SIT_DOWN, &this->actor.projectedPos, 4, &D_801333E0, &D_801333E0,
&D_801333E8);
this->skelAnime.playSpeed = 0.0f;
EnGo_SetupAction(this, func_80A405CC);
}
}
void func_80A40A54(EnGo* this, GlobalContext* globalCtx) {
f32 float1 = ((f32)0x8000 / Animation_GetLastFrame(&gGoronAnim_010590));
f32 float2 = this->skelAnime.curFrame * float1;
this->actor.speedXZ = Math_SinS((s16)float2);
if (EnGo_FollowPath(this, globalCtx) && this->unk_218 == 0) {
EnGo_ChangeAnim(this, ENGO_ANIM_1);
this->skelAnime.curFrame = Animation_GetLastFrame(&gGoronAnim_004930);
this->actor.speedXZ = 0.0f;
EnGo_SetupAction(this, EnGo_BiggoronActionFunc);
}
}
void func_80A40B1C(EnGo* this, GlobalContext* globalCtx) {
if (gSaveContext.infTable[14] & 0x800) {
EnGo_ChangeAnim(this, ENGO_ANIM_3);
EnGo_SetupAction(this, func_80A40A54);
} else {
EnGo_BiggoronActionFunc(this, globalCtx);
}
}
void EnGo_GetItem(EnGo* this, GlobalContext* globalCtx) {
f32 xzDist;
f32 yDist;
GetItemEntry getItemEntry = (GetItemEntry)GET_ITEM_NONE;
s32 getItemId;
if (Actor_HasParent(&this->actor, globalCtx)) {
this->unk_1E0.unk_00 = 2;
this->actor.parent = NULL;
EnGo_SetupAction(this, func_80A40C78);
} else {
this->unk_20C = 0;
if ((this->actor.params & 0xF0) == 0x90) {
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
if (!gSaveContext.n64ddFlag) {
getItemId = GI_SWORD_BGS;
} else {
getItemEntry = Randomizer_GetItemFromKnownCheck(RC_DMT_TRADE_CLAIM_CHECK, GI_SWORD_BGS);
getItemId = getItemEntry.getItemId;
}
this->unk_20C = 1;
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_EYEDROPS) {
getItemId = GI_CLAIM_CHECK;
}
if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_SWORD_BROKEN) {
getItemId = GI_PRESCRIPTION;
}
}
if ((this->actor.params & 0xF0) == 0) {
getItemId = GI_TUNIC_GORON;
}
yDist = fabsf(this->actor.yDistToPlayer) + 1.0f;
xzDist = this->actor.xzDistToPlayer + 1.0f;
if (!gSaveContext.n64ddFlag || getItemEntry.getItemId == GI_NONE) {
func_8002F434(&this->actor, globalCtx, getItemId, xzDist, yDist);
} else {
GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, xzDist, yDist);
}
}
}
void func_80A40C78(EnGo* this, GlobalContext* globalCtx) {
if (this->unk_1E0.unk_00 == 3) {
EnGo_SetupAction(this, EnGo_BiggoronActionFunc);
if ((this->actor.params & 0xF0) != 0x90) {
this->unk_1E0.unk_00 = 0;
} else if (this->unk_20C) {
this->unk_1E0.unk_00 = 0;
gSaveContext.bgsFlag = true;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_PRESCRIPTION) {
this->actor.textId = 0x3058;
Message_ContinueTextbox(globalCtx, this->actor.textId);
this->unk_1E0.unk_00 = 1;
} else if (INV_CONTENT(ITEM_TRADE_ADULT) == ITEM_CLAIM_CHECK) {
this->actor.textId = 0x305C;
Message_ContinueTextbox(globalCtx, this->actor.textId);
this->unk_1E0.unk_00 = 1;
Environment_ClearBgsDayCount();
}
}
}
void EnGo_Eyedrops(EnGo* this, GlobalContext* globalCtx) {
if (DECR(this->unk_21E) == 0) {
this->actor.textId = 0x305A;
Message_ContinueTextbox(globalCtx, this->actor.textId);
this->unk_1E0.unk_00 = 1;
EnGo_SetupAction(this, func_80A40DCC);
}
}
void func_80A40DCC(EnGo* this, GlobalContext* globalCtx) {
if (this->unk_1E0.unk_00 == 2) {
EnGo_ChangeAnim(this, ENGO_ANIM_1);
this->skelAnime.curFrame = Animation_GetLastFrame(&gGoronAnim_004930);
Message_CloseTextbox(globalCtx);
EnGo_SetupAction(this, EnGo_GetItem);
EnGo_GetItem(this, globalCtx);
}
}
void EnGo_Update(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnGo* this = (EnGo*)thisx;
Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
SkelAnime_Update(&this->skelAnime);
if (this->actionFunc == EnGo_BiggoronActionFunc || this->actionFunc == EnGo_FireGenericActionFunc ||
this->actionFunc == func_80A40B1C) {
func_80034F54(globalCtx, this->jointTable, this->morphTable, 18);
}
EnGo_UpdateShadow(this);
if (this->unk_1E0.unk_00 == 0) {
Actor_MoveForward(&this->actor);
}
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 0.0f, 0.0f, 0.0f, 4);
func_80A3F0E4(this);
func_80A3F908(this, globalCtx);
this->actionFunc(this, globalCtx);
func_80A3F060(this, globalCtx);
}
void EnGo_DrawCurledUp(EnGo* this, GlobalContext* globalCtx) {
Vec3f D_80A41BB4 = { 0.0f, 0.0f, 0.0f };
OPEN_DISPS(globalCtx->state.gfxCtx);
Matrix_Push();
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);
Matrix_MultVec3f(&D_80A41BB4, &this->actor.focus.pos);
Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void EnGo_DrawRolling(EnGo* this, GlobalContext* globalCtx) {
Vec3f D_80A41BC0 = { 0.0f, 0.0f, 0.0f };
OPEN_DISPS(globalCtx->state.gfxCtx);
Matrix_Push();
func_80093D18(globalCtx->state.gfxCtx);
Matrix_RotateZYX((s16)(globalCtx->state.frames * ((s16)this->actor.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);
Matrix_MultVec3f(&D_80A41BC0, &this->actor.focus.pos);
Matrix_Pop();
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
s32 EnGo_OverrideLimbDraw(GlobalContext* globalCtx, s32 limb, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) {
EnGo* this = (EnGo*)thisx;
Vec3s vec1;
f32 float1;
if (limb == 17) {
Matrix_Translate(2800.0f, 0.0f, 0.0f, MTXMODE_APPLY);
vec1 = this->unk_1E0.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_1E0.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->jointTable[limb]);
rot->y += float1 * 200.0f;
float1 = Math_CosS(this->morphTable[limb]);
rot->z += float1 * 200.0f;
}
return 0;
}
void EnGo_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
EnGo* this = (EnGo*)thisx;
Vec3f D_80A41BCC = { 600.0f, 0.0f, 0.0f };
if (limbIndex == 17) {
Matrix_MultVec3f(&D_80A41BCC, &this->actor.focus.pos);
}
}
void EnGo_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnGo* this = (EnGo*)thisx;
OPEN_DISPS(globalCtx->state.gfxCtx);
EnGo_UpdateDust(this);
Matrix_Push();
EnGo_DrawDust(this, globalCtx);
Matrix_Pop();
if (this->actionFunc == EnGo_CurledUp) {
EnGo_DrawCurledUp(this, globalCtx);
} else if (this->actionFunc == EnGo_GoronLinkRolling || this->actionFunc == func_80A3FEB4 ||
this->actionFunc == EnGo_StopRolling || this->actionFunc == func_80A3FEB4) {
EnGo_DrawRolling(this, globalCtx);
} else {
func_800943C8(globalCtx->state.gfxCtx);
gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(gGoronCsEyeOpenTex));
gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(gGoronCsMouthNeutralTex));
SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, EnGo_OverrideLimbDraw, EnGo_PostLimbDraw, &this->actor);
EnGo_DrawDust(this, globalCtx);
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
void EnGo_AddDust(EnGo* 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->epoch++;
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 EnGo_UpdateDust(EnGo* 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 EnGo_DrawDust(EnGo* this, GlobalContext* globalCtx) {
static void* dustTex[] = { gDust8Tex, gDust7Tex, gDust6Tex, gDust5Tex, gDust4Tex, gDust3Tex, gDust2Tex, gDust1Tex };
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;
}
FrameInterpolation_RecordOpenChild(dustEffect, dustEffect->epoch);
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(dustTex[index]));
gSPDisplayList(POLY_XLU_DISP++, gGoronDL_00FD50);
FrameInterpolation_RecordCloseChild();
}
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}