From fbd1a79942dc1af21959757ee9eec5d0ef22f0be Mon Sep 17 00:00:00 2001 From: Tom Overton Date: Thu, 30 Sep 2021 06:34:45 -0700 Subject: [PATCH] Arrow_Ice OK (#314) * Migrate data and ArrowIce_Init OK * ArrowIce_Destroy OK (also define func_80115D5C in functions.h, maybe a bad thing???) * ArrowIce_SetupAction OK * func_809224DC OK * ArrowIce_Update OK * func_809227F4 OK (but with hacky float constant) * func_809225D0 OK and use float constant in func_809227F4 * func_80922628 OK * ArrowIce_Draw OK * Migrate D_80924200.s to C * Apply better names in ice_gfx, and document Draw slightly * Name struct vars to match OoT * Update function names to match OoT * Explain that arrow's timer and hitFlags came from OoT * Update spec + "migrate" bss to C * Do a hex -> decimal conversion I missed * Remove blank line in-between headers * Remove extraneous forward declare * Move initialization of arrow up one line * Remove parentheses * Use else if * Use decrement operation * Use decimal for an alpha calculation * Switch func_80115D5C to take GameState* * Put pad on the top of Draw * Move initialization of arrow up (again) * Early return from Update if we're killed * Extract assets instead of putting them in the repo * Add explanatory comment to top of file * += 1 -> ++ * Use VEC3F_LERPIMPDST macro * Force a jenkins rerun by adding a space * Remove the space from the last commit * Move literal to the back of the conditional * Respond to review feedback * Add ArrowIce_LerpFiredPosition to functions.txt --- assets/xml/overlays/ovl_Arrow_Ice.xml | 11 + include/functions.h | 2 +- spec | 4 +- .../actors/ovl_Arrow_Ice/z_arrow_ice.c | 222 ++++++++++++++++-- .../actors/ovl_Arrow_Ice/z_arrow_ice.h | 7 +- src/overlays/actors/ovl_En_Arrow/z_en_arrow.h | 5 +- tools/disasm/functions.txt | 8 +- 7 files changed, 229 insertions(+), 30 deletions(-) create mode 100644 assets/xml/overlays/ovl_Arrow_Ice.xml diff --git a/assets/xml/overlays/ovl_Arrow_Ice.xml b/assets/xml/overlays/ovl_Arrow_Ice.xml new file mode 100644 index 0000000000..e130bdd055 --- /dev/null +++ b/assets/xml/overlays/ovl_Arrow_Ice.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/include/functions.h b/include/functions.h index 4cfd6cfe28..d682431cee 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2162,7 +2162,7 @@ void func_801159c0(s16 param_1); void func_801159EC(s16 arg0); void func_80115A14(s32 arg0, s16 arg1); // void Parameter_AddMagic(void); -// void func_80115D5C(void); +void func_80115D5C(GameState* gamestate); // void func_80115DB4(void); // void func_80116088(void); // void func_80116114(void); diff --git a/spec b/spec index 18ce776d04..cdaf81c06c 100644 --- a/spec +++ b/spec @@ -1414,9 +1414,7 @@ beginseg name "ovl_Arrow_Ice" compress include "build/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.o" - include "build/data/ovl_Arrow_Ice/ovl_Arrow_Ice.data.o" - include "build/data/ovl_Arrow_Ice/ovl_Arrow_Ice.bss.o" - include "build/data/ovl_Arrow_Ice/ovl_Arrow_Ice.reloc.o" + include "build/src/overlays/actors/ovl_Arrow_Ice/ovl_Arrow_Ice_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c b/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c index a4dad87701..9d61ca2926 100644 --- a/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c +++ b/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.c @@ -1,4 +1,11 @@ +/* + * File: z_arrow_ice.c + * Overlay: ovl_Arrow_Ice + * Description: Ice Arrow. Spawned as a child of a normal arrow. + */ + #include "z_arrow_ice.h" +#include "overlays/actors/ovl_En_Arrow/z_en_arrow.h" #define FLAGS 0x02000010 @@ -9,13 +16,14 @@ void ArrowIce_Destroy(Actor* thisx, GlobalContext* globalCtx); void ArrowIce_Update(Actor* thisx, GlobalContext* globalCtx); void ArrowIce_Draw(Actor* thisx, GlobalContext* globalCtx); -void func_809224DC(ArrowIce* this, GlobalContext* globalCtx); -void func_80922628(ArrowIce* this, GlobalContext* globalCtx); -void func_809227F4(ArrowIce* this, GlobalContext* globalCtx); +void ArrowIce_Charge(ArrowIce* this, GlobalContext* globalCtx); +void ArrowIce_Hit(ArrowIce* this, GlobalContext* globalCtx); +void ArrowIce_Fly(ArrowIce* this, GlobalContext* globalCtx); -void ArrowIce_SetupAction(ArrowIce* this, ArrowIceActionFunc actionFunc); +#include "overlays/ovl_Arrow_Ice/ovl_Arrow_Ice.c" + +s32 unused; // Needed for bss -#if 0 const ActorInit Arrow_Ice_InitVars = { ACTOR_ARROW_ICE, ACTORCAT_ITEMACTION, @@ -28,33 +36,207 @@ const ActorInit Arrow_Ice_InitVars = { (ActorFunc)ArrowIce_Draw, }; -// static InitChainEntry sInitChain[] = { -static InitChainEntry D_809241F0[] = { +static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneForward, 2000, ICHAIN_STOP), }; -#endif +extern Gfx D_0E0002E0[]; -extern InitChainEntry D_809241F0[]; +void ArrowIce_SetupAction(ArrowIce* this, ArrowIceActionFunc actionFunc) { + this->actionFunc = actionFunc; +} -extern UNK_TYPE D_0E0002E0; +void ArrowIce_Init(Actor* thisx, GlobalContext* globalCtx) { + ArrowIce* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/D_80924200.s") + Actor_ProcessInitChain(&this->actor, sInitChain); + this->radius = 0; + this->height = 1.0f; + ArrowIce_SetupAction(this, ArrowIce_Charge); + Actor_SetScale(&this->actor, 0.01f); + this->alpha = 100; + this->timer = 0; + this->blueingEffectMagnitude = 0.0f; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/ArrowIce_SetupAction.s") +void ArrowIce_Destroy(Actor* thisx, GlobalContext* globalCtx) { + func_80115D5C(&globalCtx->state); + (void)"消滅"; // Unreferenced in retail, means "Disappearance" +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/ArrowIce_Init.s") +void ArrowIce_Charge(ArrowIce* this, GlobalContext* globalCtx) { + EnArrow* arrow = (EnArrow*)this->actor.parent; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/ArrowIce_Destroy.s") + if ((arrow == NULL) || (arrow->actor.update == NULL)) { + Actor_MarkForDeath(&this->actor); + return; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/func_809224DC.s") + if (this->radius < 10) { + this->radius++; + } + // copy position and rotation from arrow + this->actor.world.pos = arrow->actor.world.pos; + this->actor.shape.rot = arrow->actor.shape.rot; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/func_809225D0.s") + func_800B9010(&this->actor, NA_SE_PL_ARROW_CHARGE_ICE - SFX_FLAG); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/func_80922628.s") + // if arrow has no parent, player has fired the arrow + if (arrow->actor.parent == NULL) { + this->firedPos = this->actor.world.pos; + this->radius = 10; + ArrowIce_SetupAction(this, ArrowIce_Fly); + this->alpha = 255; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/func_809227F4.s") +void ArrowIce_LerpFiredPosition(Vec3f* firedPos, Vec3f* icePos, f32 scale) { + VEC3F_LERPIMPDST(firedPos, firedPos, icePos, scale); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/ArrowIce_Update.s") +void ArrowIce_Hit(ArrowIce* this, GlobalContext* globalCtx) { + f32 scale; + f32 offset; + u16 timer; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Arrow_Ice/ArrowIce_Draw.s") + if (this->actor.projectedW < 50.0f) { + scale = 10.0f; + } else if (this->actor.projectedW > 950.0f) { + scale = 310.0f; + } else { + scale = this->actor.projectedW; + scale = (scale - 50.0f) * (1.0f / 3.0f) + 10.0f; + } + + timer = this->timer; + if (timer != 0) { + this->timer--; + + if (this->timer >= 8) { + offset = ((this->timer - 8) * (1.0f / 24.0f)); + offset = SQ(offset); + this->radius = (((1.0f - offset) * scale) + 10.0f); + this->height += ((2.0f - this->height) * 0.1f); + if (this->timer < 16) { + if (1) {} + this->alpha = ((this->timer * 35) - 280); + } + } + } + + if (this->timer >= 9) { + if (this->blueingEffectMagnitude < 1.0f) { + this->blueingEffectMagnitude += 0.25f; + } + } else { + if (this->blueingEffectMagnitude > 0.0f) { + this->blueingEffectMagnitude -= 0.125f; + } + } + + if (this->timer < 8) { + this->alpha = 0; + } + + if (this->timer == 0) { + this->timer = 255; + Actor_MarkForDeath(&this->actor); + } +} + +void ArrowIce_Fly(ArrowIce* this, GlobalContext* globalCtx) { + EnArrow* arrow = (EnArrow*)this->actor.parent; + f32 distanceScaled; + s32 pad; + + if ((arrow == NULL) || (arrow->actor.update == NULL)) { + Actor_MarkForDeath(&this->actor); + return; + } + // copy position and rotation from arrow + this->actor.world.pos = arrow->actor.world.pos; + this->actor.shape.rot = arrow->actor.shape.rot; + distanceScaled = Math_Vec3f_DistXYZ(&this->firedPos, &this->actor.world.pos) * (1.0f / 24.0f); + this->height = distanceScaled; + if (distanceScaled < 1.0f) { + this->height = 1.0f; + } + ArrowIce_LerpFiredPosition(&this->firedPos, &this->actor.world.pos, 0.05f); + + if (arrow->unk_261 & 1) { + Audio_PlayActorSound2(&this->actor, NA_SE_IT_EXPLOSION_ICE); + ArrowIce_SetupAction(this, ArrowIce_Hit); + this->timer = 32; + this->alpha = 255; + } else if (arrow->unk_260 < 34) { + if (this->alpha < 35) { + Actor_MarkForDeath(&this->actor); + } else { + this->alpha -= 25; + } + } +} + +void ArrowIce_Update(Actor* thisx, GlobalContext* globalCtx) { + ArrowIce* this = THIS; + + if ((globalCtx->msgCtx.unk11F22 == 0xE) || (globalCtx->msgCtx.unk11F22 == 0x12)) { + Actor_MarkForDeath(&this->actor); + return; + } else { + this->actionFunc(this, globalCtx); + } +} + +void ArrowIce_Draw(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; + ArrowIce* this = THIS; + Actor* transform; + u32 stateFrames = globalCtx->state.frames; + EnArrow* arrow = (EnArrow*)this->actor.parent; + + if ((arrow != NULL) && (arrow->actor.update != NULL) && (this->timer < 255)) { + transform = (arrow->unk_261 & 2) ? &this->actor : &arrow->actor; + + OPEN_DISPS(globalCtx->state.gfxCtx); + + SysMatrix_InsertTranslation(transform->world.pos.x, transform->world.pos.y, transform->world.pos.z, + MTXMODE_NEW); + Matrix_RotateY(transform->shape.rot.y, MTXMODE_APPLY); + SysMatrix_InsertXRotation_s(transform->shape.rot.x, MTXMODE_APPLY); + SysMatrix_InsertZRotation_s(transform->shape.rot.z, MTXMODE_APPLY); + Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY); + + // Draw blue effect over the screen when arrow hits + if (this->blueingEffectMagnitude > 0.0f) { + POLY_XLU_DISP = func_8012BFC4(POLY_XLU_DISP); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, (s32)(this->blueingEffectMagnitude * 10.0f) & 0xFF, + (s32)(50.0f * this->blueingEffectMagnitude) & 0xFF, + (s32)(150.0f * this->blueingEffectMagnitude) & 0xFF); + gDPSetAlphaDither(POLY_XLU_DISP++, G_AD_DISABLE); + gDPSetColorDither(POLY_XLU_DISP++, G_CD_DISABLE); + gSPDisplayList(POLY_XLU_DISP++, D_0E0002E0); + } + + // Draw ice on the arrow + func_8012C2DC(globalCtx->state.gfxCtx); + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 170, 255, 255, (s32)(this->alpha * 0.5f) & 0xFF); + gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 255, 128); + SysMatrix_InsertRotation(0x4000, 0, 0, MTXMODE_APPLY); + if (this->timer != 0) { + SysMatrix_InsertTranslation(0.0f, 0.0f, 0.0f, MTXMODE_APPLY); + } else { + SysMatrix_InsertTranslation(0.0f, 1500.0f, 0.0f, MTXMODE_APPLY); + } + Matrix_Scale(this->radius * 0.2f, this->height * 3.0f, this->radius * 0.2f, MTXMODE_APPLY); + SysMatrix_InsertTranslation(0.0f, -700.0f, 0.0f, MTXMODE_APPLY); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, sIceArrowDL); + gSPDisplayList(POLY_XLU_DISP++, + Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 511 - (stateFrames * 5) % 512, 0, 128, 32, 1, + 511 - (stateFrames * 10) % 512, 511 - (stateFrames * 10) % 512, 4, 16)); + gSPDisplayList(POLY_XLU_DISP++, sIceArrowVtxDL); + + CLOSE_DISPS(globalCtx->state.gfxCtx); + } +} diff --git a/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.h b/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.h index 44a5ed9451..a731d9d447 100644 --- a/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.h +++ b/src/overlays/actors/ovl_Arrow_Ice/z_arrow_ice.h @@ -9,7 +9,12 @@ typedef void (*ArrowIceActionFunc)(struct ArrowIce*, GlobalContext*); typedef struct ArrowIce { /* 0x0000 */ Actor actor; - /* 0x0144 */ char unk_144[0x1C]; + /* 0x0144 */ s16 radius; + /* 0x0146 */ u16 timer; + /* 0x0148 */ u8 alpha; + /* 0x014C */ Vec3f firedPos; + /* 0x0158 */ f32 height; + /* 0x015C */ f32 blueingEffectMagnitude; /* 0x0160 */ ArrowIceActionFunc actionFunc; } ArrowIce; // size = 0x164 diff --git a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h index e022d21a0c..119507d4d0 100644 --- a/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h +++ b/src/overlays/actors/ovl_En_Arrow/z_en_arrow.h @@ -11,7 +11,10 @@ typedef struct EnArrow { /* 0x0000 */ Actor actor; /* 0x0144 */ char unk_144[0x7C]; /* 0x01C0 */ s32 unk_1C0; - /* 0x01C4 */ char unk_1C4[0xB0]; + /* 0x01C4 */ char unk_1C4[0x9C]; + /* 0x0260 */ u8 unk_260; // timer in OoT + /* 0x0261 */ u8 unk_261; // hitFlags in OoT + /* 0x0262 */ char unk_262[0x12]; /* 0x0274 */ EnArrowActionFunc actionFunc; } EnArrow; // size = 0x278 diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index b64e05c56b..918da5570e 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -7014,10 +7014,10 @@ 0x80922430:("ArrowIce_SetupAction",), 0x8092243C:("ArrowIce_Init",), 0x809224B8:("ArrowIce_Destroy",), - 0x809224DC:("func_809224DC",), - 0x809225D0:("func_809225D0",), - 0x80922628:("func_80922628",), - 0x809227F4:("func_809227F4",), + 0x809224DC:("ArrowIce_Charge",), + 0x809225D0:("ArrowIce_LerpFiredPosition",), + 0x80922628:("ArrowIce_Hit",), + 0x809227F4:("ArrowIce_Fly",), 0x80922948:("ArrowIce_Update",), 0x8092299C:("ArrowIce_Draw",), 0x80924300:("ArrowLight_SetupAction",),