From 916f07e2867eb7b4e5276dea5692f8d1ab67f9ec Mon Sep 17 00:00:00 2001 From: robojumper Date: Sat, 23 May 2026 22:58:30 +0200 Subject: [PATCH] dAcArrow_c 99% --- config/SOUE01/splits.txt | 6 +- config/SOUE01/symbols.txt | 116 +-- include/d/a/d_a_player.h | 13 +- include/d/a/obj/d_a_obj_arrow.h | 92 +- include/d/col/c/c_cc_d.h | 20 + include/d/d_linkage.h | 19 + include/d/d_player_mdl.h | 13 + include/d/d_vec.h | 14 + include/m/m_vec.h | 3 + include/rvl/MTX/vec.h | 4 + src/d/a/obj/d_a_obj_arrow.cpp | 902 +++++++++++++++++++- src/toBeSorted/d_sword_swing_effect_mgr.cpp | 15 +- 12 files changed, 1098 insertions(+), 119 deletions(-) diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index c8a60407..4aa9b4e0 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -1514,6 +1514,8 @@ d/a/obj/d_a_obj_bomb.cpp: .data start:0x80534490 end:0x805347A8 .sdata start:0x805739B0 end:0x805739C8 .sbss start:0x805758E0 end:0x805758F0 + .sdata2 start:0x8057BF80 end:0x8057C058 + .bss start:0x805B48A8 end:0x805B49E8 d/a/obj/d_a_obj_arrow.cpp: .text start:0x8025D5E0 end:0x80260D38 align:16 @@ -1522,6 +1524,8 @@ d/a/obj/d_a_obj_arrow.cpp: .data start:0x805347A8 end:0x80534AD0 .sdata start:0x805739C8 end:0x805739D8 .sbss start:0x805758F0 end:0x80575900 + .sdata2 start:0x8057C058 end:0x8057C0F8 + .bss start:0x805B49E8 end:0x805B4BE0 d/a/obj/d_a_obj_boomerang.cpp: .text start:0x80260D40 end:0x80265618 align:16 @@ -1531,7 +1535,7 @@ d/a/obj/d_a_obj_boomerang.cpp: .sdata start:0x805739D8 end:0x80573A30 .sbss start:0x80575900 end:0x80575908 .sdata2 start:0x8057C0F8 end:0x8057C180 - .bss start:0x805B4BF0 end:0x805B4DD8 + .bss start:0x805B4BE0 end:0x805B4DD8 d/a/obj/d_a_obj_fairy.cpp: .text start:0x80265620 end:0x80268598 align:16 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 4b9c307a..dfe94f37 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -12484,7 +12484,7 @@ fn_802097E0 = .text:0x802097E0; // type:function size:0x104 ActorLink__isChargingWeapon = .text:0x802098F0; // type:function size:0x14 ActorLink__isWeaponChargedFully = .text:0x80209910; // type:function size:0x14 ActorLink__isArrowShot = .text:0x80209930; // type:function size:0x78 -fn_802099B0 = .text:0x802099B0; // type:function size:0x10 +getStateID__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x802099B0; // type:function size:0x10 fn_802099C0 = .text:0x802099C0; // type:function size:0x68 isUsingBow_inner = .text:0x80209A30; // type:function size:0x38 isUsingBow = .text:0x80209A70; // type:function size:0x54 @@ -14045,53 +14045,53 @@ create__10dAcArrow_cFv = .text:0x8025D9D0; // type:function size:0x184 changeState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x8025DB60; // type:function size:0x10 __dt__10dAcArrow_cFv = .text:0x8025DB70; // type:function size:0x110 hitCallback__10dAcArrow_cFP8cCcD_ObjP12dAcObjBase_cP8cCcD_Obj = .text:0x8025DC80; // type:function size:0xA0 -fn_8025DD20 = .text:0x8025DD20; // type:function size:0x1AC -fn_8025DED0 = .text:0x8025DED0; // type:function size:0x288 -fn_8025E160 = .text:0x8025E160; // type:function size:0x480 -fn_8025E5E0 = .text:0x8025E5E0; // type:function size:0x60 -fn_8025E640 = .text:0x8025E640; // type:function size:0xD8 -fn_8025E720 = .text:0x8025E720; // type:function size:0x94 -fn_8025E7C0 = .text:0x8025E7C0; // type:function size:0x120 -fn_8025E8E0 = .text:0x8025E8E0; // type:function size:0x80 -fn_8025E960 = .text:0x8025E960; // type:function size:0x1BC -fn_8025EB20 = .text:0x8025EB20; // type:function size:0x4C -fn_8025EB70 = .text:0x8025EB70; // type:function size:0xA8 -AcArrow__stateWaitEnter = .text:0x8025EC20; // type:function size:0x4 -AcArrow__stateWaitUpdate = .text:0x8025EC30; // type:function size:0x6C -AcArrow__stateWaitLeave = .text:0x8025ECA0; // type:function size:0x4 -AcArrow__stateMoveEnter = .text:0x8025ECB0; // type:function size:0x114 -AcArrow__stateMoveUpdate = .text:0x8025EDD0; // type:function size:0xAF8 -AcArrow__stateMoveLeave = .text:0x8025F8D0; // type:function size:0x4 -AcArrow__stateBoundEnter = .text:0x8025F8E0; // type:function size:0x138 -AcArrow__stateBoundUpdate = .text:0x8025FA20; // type:function size:0x1BC -AcArrow__stateBoundLeave = .text:0x8025FBE0; // type:function size:0x4 -AcArrow__stateBgStopEnter = .text:0x8025FBF0; // type:function size:0x218 -AcArrow__stateBgStopUpdate = .text:0x8025FE10; // type:function size:0x11C -AcArrow__stateBgStopLeave = .text:0x8025FF30; // type:function size:0x4 -AcArrow__stateActorStopEnter = .text:0x8025FF40; // type:function size:0x8C -AcArrow__stateActorStopUpdate = .text:0x8025FFD0; // type:function size:0x6C -AcArrow__stateActorStopLeave = .text:0x80260040; // type:function size:0x10 -fn_80260050 = .text:0x80260050; // type:function size:0x80 -fn_802600D0 = .text:0x802600D0; // type:function size:0xE8 -fn_802601C0 = .text:0x802601C0; // type:function size:0x90 -fn_80260250 = .text:0x80260250; // type:function size:0x78 -AcArrow__update = .text:0x802602D0; // type:function size:0x260 -fn_80260530 = .text:0x80260530; // type:function size:0x10 -AcArrow__draw = .text:0x80260540; // type:function size:0xB8 -fn_80260600 = .text:0x80260600; // type:function size:0x60 -fn_80260660 = .text:0x80260660; // type:function size:0xC -fn_80260670 = .text:0x80260670; // type:function size:0x1C -fn_80260690 = .text:0x80260690; // type:function size:0x1C -fn_802606B0 = .text:0x802606B0; // type:function size:0x1C -fn_802606D0 = .text:0x802606D0; // type:function size:0x10 -fn_802606E0 = .text:0x802606E0; // type:function size:0x10 -fn_802606F0 = .text:0x802606F0; // type:function size:0x10 -fn_80260700 = .text:0x80260700; // type:function size:0x10 -fn_80260710 = .text:0x80260710; // type:function size:0x10 -fn_80260720 = .text:0x80260720; // type:function size:0x10 -fn_80260730 = .text:0x80260730; // type:function size:0x30 -fn_80260760 = .text:0x80260760; // type:function size:0x30 -fn_80260790 = .text:0x80260790; // type:function size:0x30 +fn_8025DD20__10dAcArrow_cFRC7mVec3_cR7mVec3_cb = .text:0x8025DD20; // type:function size:0x1AC +fn_8025DED0__10dAcArrow_cFf = .text:0x8025DED0; // type:function size:0x288 +fn_8025E160__10dAcArrow_cFv = .text:0x8025E160; // type:function size:0x480 +updateRoomId__10dAcArrow_cFv = .text:0x8025E5E0; // type:function size:0x60 +fn_8025E640__10dAcArrow_cFv = .text:0x8025E640; // type:function size:0xD8 +fn_8025E720__10dAcArrow_cFP12dAcObjBase_cRC7mVec3_c = .text:0x8025E720; // type:function size:0x94 +updateMtx__10dAcArrow_cFv = .text:0x8025E7C0; // type:function size:0x120 +setInitialPosition__10dAcArrow_cFv = .text:0x8025E8E0; // type:function size:0x80 +fn_8025E960__10dAcArrow_cFv = .text:0x8025E960; // type:function size:0x1BC +initPickupCc__10dAcArrow_cFv = .text:0x8025EB20; // type:function size:0x4C +checkPickup__10dAcArrow_cFv = .text:0x8025EB70; // type:function size:0xA8 +initializeState_Wait__10dAcArrow_cFv = .text:0x8025EC20; // type:function size:0x4 +executeState_Wait__10dAcArrow_cFv = .text:0x8025EC30; // type:function size:0x6C +finalizeState_Wait__10dAcArrow_cFv = .text:0x8025ECA0; // type:function size:0x4 +initializeState_Move__10dAcArrow_cFv = .text:0x8025ECB0; // type:function size:0x114 +executeState_Move__10dAcArrow_cFv = .text:0x8025EDD0; // type:function size:0xAF8 +finalizeState_Move__10dAcArrow_cFv = .text:0x8025F8D0; // type:function size:0x4 +initializeState_Bound__10dAcArrow_cFv = .text:0x8025F8E0; // type:function size:0x138 +executeState_Bound__10dAcArrow_cFv = .text:0x8025FA20; // type:function size:0x1BC +finalizeState_Bound__10dAcArrow_cFv = .text:0x8025FBE0; // type:function size:0x4 +initializeState_BgStop__10dAcArrow_cFv = .text:0x8025FBF0; // type:function size:0x218 +executeState_BgStop__10dAcArrow_cFv = .text:0x8025FE10; // type:function size:0x11C +finalizeState_BgStop__10dAcArrow_cFv = .text:0x8025FF30; // type:function size:0x4 +initializeState_ActorStop__10dAcArrow_cFv = .text:0x8025FF40; // type:function size:0x8C +executeState_ActorStop__10dAcArrow_cFv = .text:0x8025FFD0; // type:function size:0x6C +finalizeState_ActorStop__10dAcArrow_cFv = .text:0x80260040; // type:function size:0x10 +fn_80260050__10dAcArrow_cFRC7mVec3_cb = .text:0x80260050; // type:function size:0x80 +fn_802600D0__10dAcArrow_cFb = .text:0x802600D0; // type:function size:0xE8 +fn_802601C0__10dAcArrow_cFv = .text:0x802601C0; // type:function size:0x90 +fn_80260250__10dAcArrow_cFP12dAcObjBase_cP12dAcObjBase_c = .text:0x80260250; // type:function size:0x78 +actorExecute__10dAcArrow_cFv = .text:0x802602D0; // type:function size:0x260 +executeState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x80260530; // type:function size:0x10 +draw__10dAcArrow_cFv = .text:0x80260540; // type:function size:0xB8 +build__26sFStateFct_c<10dAcArrow_c>FRC12sStateIDIf_c = .text:0x80260600; // type:function size:0x60 +dispose__26sFStateFct_c<10dAcArrow_c>FRP10sStateIf_c = .text:0x80260660; // type:function size:0xC +initialize__23sFState_c<10dAcArrow_c>Fv = .text:0x80260670; // type:function size:0x1C +execute__23sFState_c<10dAcArrow_c>Fv = .text:0x80260690; // type:function size:0x1C +finalize__23sFState_c<10dAcArrow_c>Fv = .text:0x802606B0; // type:function size:0x1C +initializeState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x802606D0; // type:function size:0x10 +finalizeState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x802606E0; // type:function size:0x10 +refreshState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x802606F0; // type:function size:0x10 +getState__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x80260700; // type:function size:0x10 +getNewStateID__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x80260710; // type:function size:0x10 +getOldStateID__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x80260720; // type:function size:0x10 +finalizeState__25sFStateID_c<10dAcArrow_c>CFR10dAcArrow_c = .text:0x80260730; // type:function size:0x30 +executeState__25sFStateID_c<10dAcArrow_c>CFR10dAcArrow_c = .text:0x80260760; // type:function size:0x30 +initializeState__25sFStateID_c<10dAcArrow_c>CFR10dAcArrow_c = .text:0x80260790; // type:function size:0x30 __sinit_\d_a_obj_arrow_cpp = .text:0x802607C0; // type:function size:0x490 scope:local __dt__25sFStateID_c<10dAcArrow_c>Fv = .text:0x80260C50; // type:function size:0x58 isSameName__25sFStateID_c<10dAcArrow_c>CFPCc = .text:0x80260CB0; // type:function size:0x88 @@ -28544,7 +28544,7 @@ AcItem__SHOULD_DEMO_FUNCS = .rodata:0x804ED2D0; // type:object size:0x30 sCb1s__15dAcItem_0xB3C_2 = .rodata:0x804ED300; // type:object size:0x18 sCb2s__15dAcItem_0xB3C_2 = .rodata:0x804ED318; // type:object size:0x24 lbl_804ED340 = .rodata:0x804ED340; // type:object size:0x10 align:4 data:float -lbl_804ED350 = .rodata:0x804ED350; // type:object size:0x30 +sCc2__10dAcArrow_c = .rodata:0x804ED350; // type:object size:0x30 lbl_804ED380 = .rodata:0x804ED380; // type:object size:0x30 AcTbox__ARC_NAMES = .rodata:0x804ED3B0; // type:object size:0x10 AcTbox__OPEN_EVENT_NAMES = .rodata:0x804ED3C0; // type:object size:0x38 @@ -36292,17 +36292,19 @@ __vt__77sStateMgr_c<9dAcBomb_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDC __vt__24sFStateFct_c<9dAcBomb_c> = .data:0x805345F0; // type:object size:0x18 __vt__21sFState_c<9dAcBomb_c> = .data:0x80534608; // type:object size:0x168 lbl_80534770 = .data:0x80534770; // type:object size:0x38 -g_profile_ARROW = .data:0x805347A8; // type:object size:0x38 -lbl_805347E0 = .data:0x805347E0; // type:object size:0x2C data:4byte +g_profile_ARROW = .data:0x805347A8; // type:object size:0x10 +sCcSrcInf__10dAcArrow_c = .data:0x805347B8; // type:object size:0x28 +sCc1__10dAcArrow_c = .data:0x805347E0; // type:object size:0x2C data:4byte lbl_8053480C = .data:0x8053480C; // type:object size:0x14 data:string lbl_80534820 = .data:0x80534820; // type:object size:0xB data:string lbl_80534830 = .data:0x80534830; // type:object size:0x18 data:string -AcArrow__vtable = .data:0x80534848; // type:object size:0x80 -lbl_805348C8 = .data:0x805348C8; // type:object size:0x30 -lbl_805348F8 = .data:0x805348F8; // type:object size:0x30 -lbl_80534928 = .data:0x80534928; // type:object size:0x18 -lbl_80534940 = .data:0x80534940; // type:object size:0x15C -lbl_80534A9C = .data:0x80534A9C; // type:object size:0x34 +__vt__10dAcArrow_c = .data:0x80534848; // type:object size:0x80 +__vt__49sFStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c> = .data:0x805348C8; // type:object size:0x30 +__vt__79sStateMgr_c<10dAcArrow_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c> = .data:0x805348F8; // type:object size:0x30 +__vt__26sFStateFct_c<10dAcArrow_c> = .data:0x80534928; // type:object size:0x18 +__vt__23sFState_c<10dAcArrow_c> = .data:0x80534940; // type:object size:0x18 +lbl_80534958 = .data:0x80534958; // type:object size:0x144 +__vt__25sFStateID_c<10dAcArrow_c> = .data:0x80534A9C; // type:object size:0x34 AcBoomerang__colliderInit = .data:0x80534AD0; // type:object size:0x30 g_profile_BOOMERANG = .data:0x80534B00; // type:object size:0x10 lbl_80534B10 = .data:0x80534B10; // type:object size:0xC data:string diff --git a/include/d/a/d_a_player.h b/include/d/a/d_a_player.h index d56631eb..c1d45efd 100644 --- a/include/d/a/d_a_player.h +++ b/include/d/a/d_a_player.h @@ -62,7 +62,18 @@ public: // Item select/equip/use functions [0x801E3160 - 0x801E7AD0] ? static s32 calcItemWheelSelection(bool reset, s32 numOptions); - static void addDigInteractionTarget(dAcBase_c*, f32); + static void addDigInteractionTarget(dAcBase_c *, f32); + static void fn_801E2FC0(const mVec3_c &v1, cBgS_PolyInfo &, f32); + + // Slingshot, Bow functions [0x80208CA0 - 0x8020AC30] + mAng fn_80208CA0(); + f32 fn_80208CE0(); // 50.0f + f32 fn_80208CF0(); // 3.0f + void fn_80209700(f32 &, f32 &, bool); + const mVec3_c *fn_802097E0(mAng &, mAng &); + f32 fn_802097B0(); // 50.0f + f32 fn_802097C0(); // 1000.0f + f32 fn_802097D0(); // 4000.0f public: f32 getField_0x4564() const { diff --git a/include/d/a/obj/d_a_obj_arrow.h b/include/d/a/obj/d_a_obj_arrow.h index b3d68cda..a1a17b4b 100644 --- a/include/d/a/obj/d_a_obj_arrow.h +++ b/include/d/a/obj/d_a_obj_arrow.h @@ -6,19 +6,18 @@ #include "d/col/c/c_cc_d.h" #include "d/col/cc/d_cc_d.h" #include "m/m3d/m_smdl.h" +#include "m/m_vec.h" #include "nw4r/g3d/res/g3d_resfile.h" #include "s/s_State.hpp" -#include "s/s_StateID.hpp" #include "toBeSorted/d_emitter.h" class dAcArrow_c : public dAcObjBase_c { public: - dAcArrow_c() : mPolyInfo(), mStateMgr(*this) {} + dAcArrow_c() : mPolyInfo(), mStateMgr(*this), mEffects(this) {} virtual ~dAcArrow_c(); virtual bool createHeap() override; virtual int create() override; - virtual int doDelete() override; virtual int actorExecute() override; virtual int draw() override; @@ -30,11 +29,70 @@ public: void hitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB); -public: +private: static cCcD_SrcGObj sCcSrcInf; static dCcD_SrcCps sCc1; static const dCcD_SrcSph sCc2; + static const u8 sDamageArrMaybe[]; + static u16 sCounter; + + bool fn_8025DD20(const mVec3_c &v1, mVec3_c &v2, bool noEffect); + void fn_8025DED0(f32 f); + void fn_8025E160(); + void updateRoomId(); + s16 fn_8025E640(); + void fn_8025E720(dAcObjBase_c *obj, const mVec3_c &v); + void updateMtx(); + void setInitialPosition(); + dAcObjBase_c *fn_8025E960(); + void initPickupCc(); + bool checkPickup(); + void fn_80260050(const mVec3_c &v, bool); + void fn_802600D0(bool); + void fn_802601C0(); + bool fn_80260250(dAcObjBase_c *o1, dAcObjBase_c *o2); + + enum ArrowFlag_e { + ARROW_0x1 = 1 << 0, + ARROW_0x2 = 1 << 1, + ARROW_INITIAL_SPAWN = 1 << 2, + ARROW_0x8 = 1 << 3, + ARROW_0x10 = 1 << 4, + ARROW_0x20 = 1 << 5, + ARROW_0x40 = 1 << 6, + ARROW_0x80 = 1 << 7, + ARROW_0x100 = 1 << 8, + ARROW_0x200 = 1 << 9, + ARROW_0x400 = 1 << 10, + ARROW_0x800 = 1 << 11, + ARROW_0x1000 = 1 << 12, + ARROW_0x2000 = 1 << 13, + ARROW_0x4000 = 1 << 14, + ARROW_0x8000 = 1 << 15, + ARROW_0x10000 = 1 << 16, + }; + + void setArrowFlag(u32 f) { + mArrowFlags |= f; + } + + void unsetArrowFlag(u32 f) { + mArrowFlags &= ~f; + } + + bool checkArrowFlag (u32 f) const { + return (mArrowFlags & f) != 0; + } + + enum ArrowType_e { + TYPE_MSK_SLINGSHOT = 0x10, + }; + + bool isSlingshotProjectile() const { + return (mArrowType & TYPE_MSK_SLINGSHOT) != 0; + } + /* 0x330 */ nw4r::g3d::ResFile mResFile; /* 0x334 */ m3d::smdl_c mModel; /* 0x350 */ dAcRef_c mRef1; @@ -42,17 +100,31 @@ public: /* 0x4CC */ dCcD_Sph mCcSph; /* 0x61C */ cBgS_PolyInfo mPolyInfo; // ?? /* 0x648 */ dEmitter_c mEffects; - /* 0x67C */ u32 field_0x67C; - /* 0x680 */ u8 mSubType; + /* 0x67C */ u32 mArrowFlags; + /* 0x680 */ u8 mArrowType; /* 0x681 */ u8 field_0x681; /* 0x682 */ u8 mDespawnTimer; + /* 0x683 */ u8 field_0x683; /* 0x684 */ s16 field_0x684; /* 0x686 */ u8 field_0x686[0x688 - 0x686]; - /* 0x688 */ u16 field_0x688; - /* 0x68A */ u16 field_0x68A; - /* 0x68C */ u8 field_0x68C[0x6A8 - 0x68C]; + /* 0x688 */ s16 field_0x688; + /* 0x68A */ s16 field_0x68A; + /* 0x68C */ u16 mEffectId; + /* 0x68E */ mAng field_0x68E; + /* 0x690 */ mAng field_0x690; + /* 0x692 */ mAng3_c field_0x692; + /* 0x698 */ UNKWORD field_0x698; + /* 0x69C */ f32 field_0x69C; + /* 0x6A0 */ f32 field_0x6A0; + /* 0x6A4 */ f32 field_0x6A4; /* 0x6A8 */ f32 field_0x6A8; - /* 0x6AC */ u8 field_0x6AC[0x6F8 - 0x6AC]; + /* 0x6AC */ f32 field_0x6AC; + /* 0x6B0 */ mVec3_c field_0x6B0; + /* 0x6BC */ mVec3_c field_0x6BC; + /* 0x6C8 */ mVec3_c field_0x6C8; + /* 0x6D4 */ mVec3_c field_0x6D4; + /* 0x6E0 */ mVec3_c field_0x6E0; + /* 0x6EC */ mVec3_c field_0x6EC; /* 0x6F8 */ dAcRef_c mRef2; /* 0x704 */ STATE_MGR_DECLARE(dAcArrow_c); }; diff --git a/include/d/col/c/c_cc_d.h b/include/d/col/c/c_cc_d.h index edd178ee..384d253d 100644 --- a/include/d/col/c/c_cc_d.h +++ b/include/d/col/c/c_cc_d.h @@ -552,6 +552,10 @@ public: return mSrc.mDamage; } + void SetInfo_0x0(u8 val) { + mSrc.mInfo.field_0x0 = val; + } + const cCcD_SrcGObjAt &GetSrc() const { return mSrc; } @@ -605,6 +609,9 @@ public: void Set_0x4C(u32 f) { field_0x4C = f; } + bool Chk_0x4C(u32 f) const { + return field_0x4C & f; + } u32 MskType(u32 mask) const { return mSrc.mType & mask; @@ -930,6 +937,10 @@ public: mTg.Set_0x4C(f); } + bool ChkTg_0x4C(u32 f) const { + return mTg.Chk_0x4C(f); + } + void SetAtCallback(cCcD_HitCallback cb) { mAt.SetCallback(cb); } @@ -981,12 +992,21 @@ public: void OnAt_0x40() { mAt.OnSPrm(0x40); } + void OnAt_0x1000() { + mAt.OnSPrm(0x1000); + } + void OnAt_0x2000() { + mAt.OnSPrm(0x2000); + } // Related to Beetle (no hook) void OnAt_0x4000() { mAt.OnSPrm(0x4000); } + void SetAtInfo_0x0(u8 amount) { + mAt.SetInfo_0x0(amount); + } void SetAtDamage(u8 amount) { mAt.SetAtDamage(amount); diff --git a/include/d/d_linkage.h b/include/d/d_linkage.h index 720f1769..2739ab49 100644 --- a/include/d/d_linkage.h +++ b/include/d/d_linkage.h @@ -55,6 +55,10 @@ public: return mState; } + f32 getField_0x1C() const { + return field_0x1C; + } + bool checkState(State_e state) const { return mState == state; } @@ -68,6 +72,21 @@ public: return (checkState(STATE_ACTIVE) && mType == type); } + bool hasJntCol() const { + return field_0xA0 != nullptr; + } + + dJntCol_c *getJntCol() { + return field_0xA0; + } + + // TODO - can we get rid of this inline? + int getArrowOffsetPosAndAngle( + mVec3_c const *param_1, mAng3_c const *param_2, mVec3_c *param_3, mVec3_c *param_4, bool param_5 + ) const { + return field_0xA0->getArrowOffsetPosAndAngle(param_1, param_2, param_3, param_4, param_5); + } + public: void set(u32 flags, f32, f32, f32, void *unk); bool tryAttach(dAcObjBase_c *, dAcObjBase_c *, dAcRefBase_c *, ConnectionType_e, bool); diff --git a/include/d/d_player_mdl.h b/include/d/d_player_mdl.h index a01d0a5a..65e5b594 100644 --- a/include/d/d_player_mdl.h +++ b/include/d/d_player_mdl.h @@ -914,6 +914,19 @@ public: static mColor sGuideColor2; static mColor sGuideColor3; + // Really not sure about these - there exist virtual functions for these use cases... + const mAng& getField_0x1268() const { + return field_0x1268; + } + + const mAng& getField_0x126A() const { + return field_0x126A; + } + + void getWeaponLMtx(mMtx_c &mtx) const { + mMainMdl.getNodeWorldMtx(PLAYER_MAIN_NODE_WEAPON_L, mtx); + } + protected: /* 0x370 */ mHeapAllocator_c mModelAllocator; /* 0x38C */ mHeapAllocator_c mSwordAllocator; diff --git a/include/d/d_vec.h b/include/d/d_vec.h index 18fdd628..5c9dbfda 100644 --- a/include/d/d_vec.h +++ b/include/d/d_vec.h @@ -26,4 +26,18 @@ inline mVec3_c vec2ToVec3XY(const mVec2_c &v) { return mVec3_c(v.x, v.y, 0.0f); } +/** + * @brief Computes left x right + * + * @param result the result + * @param left left operant + * @param right right operand + */ +inline void vecCross(mVec3_c &result, const mVec3_c &left, const mVec3_c &right) { + result.set( + (left.y * right.z) - (left.z * right.y), (left.z * right.x) - (left.x * right.z), + (left.x * right.y) - (left.y * right.x) + ); +} + #endif diff --git a/include/m/m_vec.h b/include/m/m_vec.h index 6f0047b9..bd4cc4b0 100644 --- a/include/m/m_vec.h +++ b/include/m/m_vec.h @@ -265,6 +265,9 @@ public: s16 atan2sX_Z() const { return cM::atan2s(x, z); } + s16 atan2snX_nZ() const { + return cM::atan2s(-x, -z); + } s16 atan2snY_XZ() const { return cM::atan2s(-y, absXZ()); } diff --git a/include/rvl/MTX/vec.h b/include/rvl/MTX/vec.h index e220fa40..70e0c58b 100644 --- a/include/rvl/MTX/vec.h +++ b/include/rvl/MTX/vec.h @@ -29,6 +29,10 @@ f32 PSVECDistance(const Vec *, const Vec *); #define VECDistance PSVECDistance void C_VECHalfAngle(const Vec *, const Vec *, Vec *); +void C_VECReflect(const Vec *, const Vec *, Vec *); + +#define VECHalfAngle C_VECHalfAngle +#define VECReflect C_VECReflect #ifdef __cplusplus } diff --git a/src/d/a/obj/d_a_obj_arrow.cpp b/src/d/a/obj/d_a_obj_arrow.cpp index f17c71bc..a52f5daf 100644 --- a/src/d/a/obj/d_a_obj_arrow.cpp +++ b/src/d/a/obj/d_a_obj_arrow.cpp @@ -1,11 +1,63 @@ #include "d/a/obj/d_a_obj_arrow.h" +#include "c/c_lib.h" #include "c/c_math.h" +#include "common.h" +#include "d/a/d_a_item.h" +#include "d/a/d_a_itembase.h" +#include "d/a/d_a_player.h" +#include "d/a/obj/d_a_obj_base.h" +#include "d/col/bg/d_bg_pc.h" +#include "d/col/bg/d_bg_s.h" +#include "d/col/bg/d_bg_s_gnd_chk.h" +#include "d/col/bg/d_bg_s_lin_chk.h" +#include "d/col/c/c_bg_s_poly_info.h" #include "d/col/c/c_cc_d.h" +#include "d/col/c/c_m3d_g_pla.h" +#include "d/col/cc/d_cc_s.h" +#include "d/d_angle.h" +#include "d/d_jnt_col.h" +#include "d/d_light_env.h" +#include "d/d_linkage.h" +#include "d/d_vec.h" +#include "d/snd/d_snd_source_if.h" +#include "d/snd/d_snd_wzsound.h" +#include "f/f_profile_name.h" +#include "m/m_mtx.h" +#include "m/m_vec.h" +#include "nw4r/math/math_types.h" #include "nw4r/types_nw4r.h" +#include "s/s_Math.h" +#include "toBeSorted/d_emitter.h" SPECIAL_ACTOR_PROFILE(ARROW, dAcArrow_c, fProfile::ARROW, 0x126, 0, 0x80); +static dBgS_ArrowLinChk sArrowLinChk; +u16 dAcArrow_c::sCounter; + +inline static u32 getDamage1() { + return 16; +} + +inline static u32 getDamage2() { + return 16; +} + +inline static u32 getDamage3() { + return 24; +} + +inline static u32 getDamage4() { + return 32; +} + +const u8 dAcArrow_c::sDamageArrMaybe[] = { + getDamage1(), + getDamage2(), + getDamage3(), + getDamage4(), +}; + STATE_DEFINE(dAcArrow_c, Wait); STATE_DEFINE(dAcArrow_c, Move); STATE_DEFINE(dAcArrow_c, ActorStop); @@ -15,7 +67,7 @@ STATE_DEFINE(dAcArrow_c, Bound); // clang-format off cCcD_SrcGObj dAcArrow_c::sCcSrcInf = { - {AT_TYPE_ARROW, 0x8BB, {0x15,0, 0}, 0, 0, 0, 0, 0, 0}, + {AT_TYPE_ARROW, 0x8BB, {0x15,0, 0}, sDamageArrMaybe[0], 0, 0, 0, 0, 0}, { ~(AT_TYPE_BUGNET | AT_TYPE_BEETLE | AT_TYPE_GLITTERING_SPORES | AT_TYPE_0x8000 | AT_TYPE_ARROW | AT_TYPE_0x100 | AT_TYPE_WIND | AT_TYPE_SLINGSHOT), 0x210, {0, 0, 0x407}, 0, 0 @@ -45,12 +97,13 @@ bool dAcArrow_atHitCallback(dAcObjBase_c *i_actorA, cCcD_Obj *i_objInfA, dAcObjB bool dAcArrow_c::createHeap() { mResFile = nw4r::g3d::ResFile(getOarcResFile("Alink")); nw4r::g3d::ResMdl mdl(nullptr); - if ((mSubType & 0x10) != 0) { + if ((isSlingshotProjectile()) != 0) { mdl = mResFile.GetResMdl("EquipPachinkoBullet"); } else { mdl = mResFile.GetResMdl("EquipArrow"); } - // ? + // Looks weird; the more likely explanation here is that they did an `if (!create) return false;` + // forgetting the `return true;` case, but this matches without UB so let's keep it that way? bool ok = mModel.create(mdl, &mAllocator, 0x120); if (!ok) { ok = false; @@ -58,22 +111,20 @@ bool dAcArrow_c::createHeap() { return ok; } -extern "C" void fn_8025E5E0(void *); - int dAcArrow_c::create() { - mSubType = mParams & 0xFF; + mArrowType = mParams & 0xFF; CREATE_ALLOCATOR(dAcArrow_c); - field_0x67C |= 4; + setArrowFlag(ARROW_INITIAL_SPAWN); mStts.SetRank(2); mCcCps.Set(sCc1); mCcCps.SetStts(mStts); - mCcCps.SetAtFlag(0x2000); + mCcCps.OnAt_0x2000(); mCcCps.SetAtCallback(dAcArrow_atHitCallback); mCcSph.Set(sCc2); mCcSph.SetStts(mStts); - if (mSubType == 0x11) { + if (mArrowType == 17) { mStateMgr.changeState(StateID_Move); } else { mStateMgr.changeState(StateID_Wait); @@ -82,52 +133,827 @@ int dAcArrow_c::create() { mBoundingBox.Set(mVec3_c(-6.0f, -6.0f, 0.0f), mVec3_c(6.0f, 6.0f, 110.0f)); field_0x684 = -1; field_0x68A = 300; - f32 rnd = cM::rndF(20.0f); - field_0x688 = 50.0f - rnd; + field_0x688 = 50.0f - cM::rndF(20.0f); field_0x6A8 = 80.0f; mDespawnTimer = 10; - fn_8025E5E0(this); + updateRoomId(); return SUCCEEDED; } dAcArrow_c::~dAcArrow_c() {} -void dAcArrow_c::hitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) {} +void dAcArrow_c::hitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, cCcD_Obj *i_objInfB) { + dJntCol_c *col = i_actorB->getLinkage().getJntCol(); + if (col != nullptr) { + field_0x698 = col->getArrowOffsetPosAndAngle( + &i_objInfA->GetAtHitPos(), &mRotation, &field_0x6B0, &field_0x6BC, i_objInfB->ChkTg_0x4C(0x2000) + ); -int dAcArrow_c::doDelete() { - // TODO + if (field_0x698 >= 0) { + mRef1.link(i_actorB); + } else { + mRef1.unlink(); + } + } +} - return SUCCEEDED; +bool dAcArrow_c::fn_8025DD20(const mVec3_c &v1, mVec3_c &v2, bool noEffect) { + if (dBgS_WtrLinChk::SetIsWater(&v1, &v2, this)) { + const mVec3_c &end = dBgS_WtrLinChk::GetInstance().GetLinEnd(); + if (isSlingshotProjectile()) { + v2 = end; + } else { + mVec3_c t1 = v2 - end; + f32 sc; + f32 dist = v2.distance(v1); + if (dist > 0.0001f) { + sc = t1.mag() / dist; + } else { + sc = 1.0f; + } + t1.normalize(); + v2 = end + t1 * field_0x6A8 * sc; + } + + if (!noEffect) { + dAcPy_c::fn_801E2FC0(end, dBgS_WtrLinChk::GetInstance(), 0.5f); + startSound(SE_AW_HIT_WATER); + } + return true; + } + + return false; +} + +void dAcArrow_c::fn_8025DED0(f32 f) { + f32 f1; + dAcPy_c *link = dAcPy_c::GetLink2(); + if (isSlingshotProjectile()) { + f1 = 12.0f; + } else { + f1 = 5.0f; + f32 f2 = link->fn_802097C0(); + if (f > f2) { + f32 f3 = link->fn_802097D0(); + if (f3 <= f2) { + f1 += link->fn_802097B0(); + } else { + f32 f4 = (f - f2) / (f3 - f2); + if (f4 > 1.0f) { + f4 = 1.0f; + } + f1 += f4 * link->fn_802097B0(); + } + } + } + + mVec3_c next = mVec3_c(mPosition + mVelocity * (field_0x6A0 + 1.0f)); + mCcCps.OnAtSet(); + + if (!checkArrowFlag(ARROW_0x20)) { + if (!isSlingshotProjectile()) { + holdSound(SE_AW_FLY_LV); + } + fb: + fn_8025DD20(mPosition, next, true); + } else { + f32 diff = next.y - field_0x6D4.y; + if (diff < -300.0f) { + diff = -300.0f - diff; + f32 diff2 = next.y - mPosition.y; + diff2 = nw4r::math::FAbs(diff2); + if (diff2 > diff) { + next = mPosition + mVelocity * ((field_0x6A0 + 1.0f) * ((diff2 - diff) / diff2)); + } + } + } + + sArrowLinChk.Set(&mPosition, &next, this); + if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) { + next = sArrowLinChk.GetLinEnd(); + } + mCcCps.Set(mPosition, next, f1); + mCcCps.unknownCalc(); + dCcS::GetInstance()->Set(&mCcCps); + dCcS::GetInstance()->GetMassMng().SetObj(&mCcCps, 1); +} + +void dAcArrow_c::fn_8025E160() { + // NONMATCHING + dAcPy_c *link = dAcPy_c::GetLink2(); + if (isSlingshotProjectile()) { + field_0x6A0 = 0.0f; + if (mArrowType != 17) { + // TODO - this inline is not certain anyway... + setRotXY(mAngle, -link->getField_0x1268(), link->getField_0x126A() + link->getRotation().y); + } else { + mAngle.y = mRotation.y; + mAngle.x = -mRotation.x; + } + link->fn_80209700(field_0x6A4, field_0x69C, false); + } else { + link->fn_80209700(field_0x6A4, field_0x69C, false); + if (checkArrowFlag(ARROW_0x80)) { + const mVec3_c *v = link->fn_802097E0(mRotation.x, mRotation.y); + if (v != nullptr) { + mPosition = *v; + mAngle.x = -mRotation.x; + mAngle.y = mRotation.y; + } + } + field_0x683 = 30; + field_0x6A0 = 90.0f / field_0x69C; + startSound(SE_AW_FLY); + } + + if (checkArrowFlag(ARROW_0x40)) { + unsetArrowFlag(ARROW_0x40); + mVec3_c tmp = field_0x6EC - mPosition; + mAngle.x = tmp.atan2sY_XZ() + field_0x6AC * cM::rndFX(400.0f); + mAngle.y = tmp.atan2sX_Z() + field_0x6AC * cM::rndFX(400.0f); + mRotation.x = -mAngle.x; + mRotation.y = mAngle.y; + } + + // Spawn additional projectiles for Mighty Scattershot + if (isSlingshotProjectile() && checkArrowFlag(ARROW_0x80)) { + mVec3_c tmp = mVec3_c::Ez; + tmp.rotX(mAngle.x); + tmp.rotY(mAngle.y); + + mAng3_c ang(0, 0, 0); + + for (int i = 0; i < 8; i++) { + mVec3_c tmp2 = mVec3_c::Ez; + // TODO eliminate temps? + mAng a1 = link->fn_80208CA0(); + mAng a2 = mAng::fromDeg(cM::rndF(2.5f)); + tmp2.rotX(mAngle.x + a1 - a2); + tmp2.rotY(mAngle.y); + + mMtx_c mtx; + mtx.setAxisRotation(tmp, i * mAng::s2r_c(0x2000) + mAng::d2r_c(cM::rndF(2.5f))); + MTXMultVecSR(mtx, tmp2, tmp2); + ang.x = tmp2.atan2sY_XZ(); + ang.y = tmp2.atan2sX_Z(); + dAcObjBase_c::create(fProfile::ARROW, -1, 17, &mPosition, &ang, 0, -1); + } + } + + mSpeed = 100.0f; + field_0x6C8 = mPosition; + mVelocity.fromXY(mAngle.x, mAngle.y, field_0x69C); + if (!isSlingshotProjectile()) { + field_0x684 = sCounter; + sCounter++; + if (sCounter == 6) { + sCounter = 0; + } + } + fn_8025DED0(0.0f); +} + +void dAcArrow_c::updateRoomId() { + if (dBgS_ObjGndChk::CheckPos(mPosition)) { + mRoomID = dBgS_ObjGndChk::GetRoomID(); + } else if (mRoomID == -1) { + mRoomID = dAcPy_c::GetLink2()->getRoomId(); + } +} + +s16 dAcArrow_c::fn_8025E640() { + if (sLib::calcTimer(&field_0x688)) { + field_0x690 += (s16)(21243.0f - cM::rndF(0x1000)); + f32 a = field_0x688 * 0.02f; + return a * 0x400 * a * field_0x690.sin(); + } else { + return 0; + } +} + +void dAcArrow_c::fn_8025E720(dAcObjBase_c *obj, const mVec3_c &v) { + // NONMATCHING + mRef1.link(obj); + mMtx_c mtx; + // TODO argument order + mtx.inverseTo(obj->mWorldMtx); + MTXMultVec(mtx, v, field_0x6B0); + mVec3_c v1 = mVec3_c::createProjectionXZ(mRotation, 1.0f); + v1.y *= -1.0f; + MTXMultVecSR(mtx, v1, field_0x6BC); +} + +void dAcArrow_c::updateMtx() { + mWorldMtx.transS(mPosition); + mWorldMtx.XYZrotM(mRotation); + if (mStateMgr.isState(StateID_BgStop)) { + mMtx_c mtx; + mtx.transS(0.0f, 0.0f, -90.0f); + MTXConcat(mWorldMtx, mtx, mWorldMtx); + } else if (mStateMgr.isState(StateID_Bound)) { + mMtx_c mtx; + mtx.transS(0.0f, 0.0f, -45.0f); + MTXConcat(mWorldMtx, mtx, mWorldMtx); + } + mModel.setLocalMtx(mWorldMtx); +} + +void dAcArrow_c::setInitialPosition() { + dAcPy_c::GetLink2()->getWeaponLMtx(mWorldMtx); + mModel.setLocalMtx(mWorldMtx); + mWorldMtx.getTranslation(mPosition); + mWorldMtx.toRot(mRotation); + mAngle.y = mRotation.y; + mAngle.x = -mRotation.x; +} + +dAcObjBase_c *dAcArrow_c::fn_8025E960() { + s16 a1 = fn_8025E640(); + dAcObjBase_c *o1 = mRef1.get(); + if (o1 == nullptr || o1->checkObjectProperty(OBJ_PROP_0x100)) { + return nullptr; + } else if (checkArrowFlag(ARROW_0x2000)) { + if (checkArrowFlag(ARROW_0x10000)) { + mWorldMtx.getTranslation(mPosition); + mWorldMtx.toRot(mRotation); + mMtx_c mtx; + mtx.transS(0.0f, 0.0f, -90.0f); + MTXConcat(mWorldMtx, mtx, mWorldMtx); + mModel.setLocalMtx(mWorldMtx); + } + return o1; + } else { + dJntCol_c *col = o1->getLinkage().getJntCol(); + if (col != nullptr) { + col->setArrowPosAndAngle(&field_0x6B0, &field_0x6BC, field_0x698, &mPosition, &mRotation); + } else { + MTXMultVec(o1->mWorldMtx, field_0x6B0, mPosition); + mVec3_c tmp; + MTXMultVecSR(o1->mWorldMtx, field_0x6BC, tmp); + mRotation.x = tmp.atan2snY_XZ(); + mRotation.y = tmp.atan2sX_Z(); + } + mWorldMtx.transS(mPosition); + mWorldMtx.ZXYrotM(mRotation.x + a1, mRotation.y, mRotation.z); + mMtx_c mtx; + mtx.transS(0.0f, 0.0f, -90.0f); + MTXConcat(mWorldMtx, mtx, mWorldMtx); + mModel.setLocalMtx(mWorldMtx); + return o1; + } +} + +void dAcArrow_c::initPickupCc() { + mCcSph.SetR(25.0f); + mCcSph.ClrTgSet(); + mCcSph.OnCoSet(); +} + +bool dAcArrow_c::checkPickup() { + if (dAcPy_c::getCurrentBowType() != 0) { + if (mCcSph.ChkCoHit()) { + dAcItem_c::giveItem(ITEM_SINGLE_ARROW, 0, -1); + setArrowFlag(ARROW_0x2); + return true; + } + mCcSph.SetC(mPosition); + dCcS::GetInstance()->Set(&mCcSph); + } + + return false; +} + +void dAcArrow_c::initializeState_Wait() { + setInitialPosition(); +} + +void dAcArrow_c::executeState_Wait() { + setInitialPosition(); + if (checkArrowFlag(ARROW_0x800)) { + mStateMgr.changeState(StateID_Move); + } else if (isSlingshotProjectile()) { + field_0x681 = 1; + } +} + +void dAcArrow_c::finalizeState_Wait() {} + +void dAcArrow_c::initializeState_Move() { + setArrowFlag(ARROW_0x1000); + setActorProperty(AC_PROP_0x4); + if (isSlingshotProjectile()) { + mCcCps.SetAtType(AT_TYPE_SLINGSHOT); + mCcCps.SetAtInfo_0x0(20); + mCcCps.SetAtDamage(0); + mEffectId = PARTICLE_RESOURCE_ID_MAPPING_207_; + } else { + u8 dmg = sDamageArrMaybe[dAcPy_c::getCurrentBowType()]; + if (checkArrowFlag(ARROW_0x80)) { + mCcCps.SetAtFlagsUpper(0x2000000); + mEffectId = PARTICLE_RESOURCE_ID_MAPPING_2_; + dmg = (s32)dmg * 1.5f + 0.5f; + } else { + mEffectId = PARTICLE_RESOURCE_ID_MAPPING_1_; + } + mCcCps.SetAtDamage(dmg); + mCcCps.OnAt_0x1000(); + } + mCcCps.OnTgSet(); + fn_8025E160(); + updateMtx(); +} + +void dAcArrow_c::executeState_Move() { + mPosition += mVelocity; + mVec3_c next = mVec3_c(mPosition + mVelocity * field_0x6A0); + if (!checkArrowFlag(ARROW_0x20)) { + sArrowLinChk.Set(&mOldPosition, &next, this); + mVec3_c t; + if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) { + t = sArrowLinChk.GetLinEnd(); + } else { + t = next; + } + + if (fn_8025DD20(mOldPosition, t, false)) { + setArrowFlag(ARROW_0x20); + unsetArrowFlag(ARROW_0x200); + field_0x6D4 = dBgS_WtrLinChk::GetInstance().GetLinEnd(); + mVelocity.normalize(); + mPosition = t - mVelocity * 90.0f; + mVelocity *= field_0x6A8; + + if (!isSlingshotProjectile()) { + field_0x6A0 = 90.0f / field_0x6A8; + } + next = t; + } + } + + sArrowLinChk.Set(&mOldPosition, &next, this); + bool isCross = dBgS::GetInstance()->LineCross(&sArrowLinChk); + // TODO the constness here is probably a bit messed up + const cCcD_Obj *obj = nullptr; + s32 flags = -1; + if (mCcCps.ChkTgHit()) { + obj = &mCcCps; + } + + if (obj != nullptr) { + flags = obj->GetTgDamageFlags(); + } + + // TODO magic numbers + if (flags == 8) { + mPosition = obj->GetTgHitPos(); + const mVec3_c &hitDir = obj->GetTgAtHitDir(); + if (hitDir.squareMagXZ() < 1.0f) { + // TODO constness + mAngle.y = cLib::targetAngleY(mPosition, const_cast(obj)->GetTgActor()->mPosition); + } else { + mAngle.y = hitDir.atan2snX_nZ(); + } + + mRotation.y = mAngle.y; + setArrowFlag(ARROW_0x400); + mStateMgr.changeState(StateID_Bound); + } else if (obj != nullptr) { + mPosition = obj->GetTgHitPos(); + mStateMgr.changeState(StateID_Bound); + startSound(SE_AW_FLIP); + } else { + dAcObjBase_c *atActor; + s32 what; + + if (mCcCps.ChkAtHit()) { + if (mCcCps.GetAtActor()->mProfileName == fProfile::PUMPKIN) { + field_0x683 = 0; + } + dLightEnv_c::GetPInstance()->setBPM8_Type6(&mCcCps.GetAtHitPos()); + if (isSlingshotProjectile()) { + fn_80260050(mCcCps.GetAtHitPos(), 0); + return; + } + atActor = mCcCps.GetAtActor(); + what = 1; + if (atActor != nullptr && atActor->getLinkage().hasJntCol()) { + bool b = false; + if (atActor != mRef1.get()) { + field_0x698 = atActor->getLinkage().getArrowOffsetPosAndAngle( + &mCcCps.GetAtHitPos(), &mRotation, &field_0x6B0, &field_0x6BC, mCcCps.GetAtFlag0x2() + ); + b = true; + } + + if (field_0x698 >= 0) { + what = 4; + if (b) { + mRef1.link(atActor); + } + } else if (field_0x698 == -2 || mCcCps.GetAtFlag0x2()) { + what = 2; + } + } else { + if (mCcCps.GetAtFlag0x2()) { + what = 2; + } else if (mCcCps.ChkAtArrowStick()) { + fn_8025E720(atActor, mCcCps.GetAtHitPos()); + what = 4; + } + } + + if (what == 1 && atActor != nullptr && atActor->getLinkage().checkFlag(0x1000) && + !isSlingshotProjectile()) { + if (!mRef2.isLinked()) { + atActor->getLinkage().tryAttach(atActor, this, &mRef2, dLinkage_c::CONNECTION_8, false); + } + what = 0; + } + } else { + what = 0; + } + + switch (what) { + default: { + if (what == 2) { + if (checkArrowFlag(ARROW_0x20)) { + setArrowFlag(ARROW_0x2); + } else { + if (mCcCps.ChkAtHit()) { + mPosition = mCcCps.GetAtHitPos(); + } + mStateMgr.changeState(StateID_Bound); + } + } else if (what == 4) { + mStateMgr.changeState(StateID_ActorStop); + } else { + setArrowFlag(ARROW_0x2); + if (!checkArrowFlag(ARROW_0x20) && mCcCps.ChkAtHit()) { + mPosition = mCcCps.GetAtHitPos(); + } + } + break; + } + case 0: + case 3: { + if (isCross) { + mPosition = sArrowLinChk.GetLinEnd(); + if (checkArrowFlag(ARROW_0x20) && + (isSlingshotProjectile() || mPosition.y - field_0x6D4.y < -300.0f)) { + setArrowFlag(ARROW_0x2); + } else { + s32 polyAtt0 = dBgS::GetInstance()->GetPolyAtt0(sArrowLinChk); + s32 polyAtt1 = dBgS::GetInstance()->GetPolyAtt1(sArrowLinChk); + s32 specialCode = dBgS::GetInstance()->GetSpecialCode(sArrowLinChk); + if (isSlingshotProjectile() || specialCode == 19 || specialCode == 20 || specialCode == 16 || + specialCode == 10 || specialCode == 11 || polyAtt0 == 6 || polyAtt0 == POLY_ATT_0_ROCK || + polyAtt0 == POLY_ATT_0_NONE || polyAtt0 == POLY_ATT_0_NUMA || + polyAtt0 == POLY_ATT_0_STONE || polyAtt0 == POLY_ATT_0_METAL || + (polyAtt0 == POLY_ATT_0_LIFE && (polyAtt1 == 2 || polyAtt1 == 3))) { + if (checkArrowFlag(ARROW_0x20)) { + setArrowFlag(ARROW_0x2); + } else { + dAcPy_c::fn_801E2FC0(mPosition, sArrowLinChk, 0.5f); + if (isSlingshotProjectile()) { + fn_80260050(mPosition, polyAtt0 == POLY_ATT_0_LAVA); + } else { + startBgHitSound(SE_AW_HIT, sArrowLinChk, nullptr); + if (polyAtt0 == POLY_ATT_0_LAVA || polyAtt0 == POLY_ATT_0_NUMA || + polyAtt0 == POLY_ATT_0_NONE || specialCode == 16 || specialCode == 10 || + specialCode == 11) { + setArrowFlag(ARROW_0x2); + } else { + mStateMgr.changeState(StateID_Bound); + } + } + } + } else { + mStateMgr.changeState(StateID_BgStop); + } + } + } else if (checkArrowFlag(ARROW_0x20)) { + if (isSlingshotProjectile()) { + mPosition = next; + setArrowFlag(ARROW_0x2); + } else { + f32 diff = mPosition.y - field_0x6D4.y; + if (diff < -300.0f) { + mCcCps.ClrAtSet(); + mCcCps.ClrAtHit(); + if (sLib::chase(&mScale.x, 0.0f, 0.1f)) { + setArrowFlag(ARROW_0x2); + } else { + mScale.y = mScale.z = mScale.x; + mModel.setScale(mScale); + } + } else if (diff > 90.0f) { + setArrowFlag(ARROW_0x2); + } else { + fn_8025DED0(mPosition.distance(field_0x6C8)); + } + } + } else { + f32 diff = mPosition.distance(field_0x6C8); + if (diff > field_0x6A4 || mAcceleration < 0.0f) { + if (isSlingshotProjectile()) { + mAcceleration = -5.0f; + } else { + mAcceleration = -2.0f; + } + mVelocity.y += mAcceleration; + if (isSlingshotProjectile()) { + dAcPy_c *link = dAcPy_c::GetLink2(); + f32 xz = mVelocity.absXZ(); + f32 t1 = link->fn_80208CE0(); + if (xz > t1) { + f32 orig = xz; + sLib::chase(&xz, t1, link->fn_80208CF0()); + xz /= orig; + mVelocity.x *= xz; + mVelocity.z *= xz; + } + } + if (field_0x68A != 0) { + field_0x68A--; + } else { + setArrowFlag(ARROW_0x2); + return; + } + mRotation.x = mVelocity.atan2snY_XZ(); + mAngle.x = -mRotation.x; + if (!isSlingshotProjectile()) { + field_0x6A0 = 90.0f / mVelocity.mag(); + } + } + fn_8025DED0(diff); + } + break; + } + } + } +} + +void dAcArrow_c::finalizeState_Move() {} + +void dAcArrow_c::initializeState_Bound() { + if (isSlingshotProjectile()) { + fn_80260050(mPosition, false); + } else { + mSpeed = 0.0f; + fn_802601C0(); + f32 rnd = cM::rndFX(0x2000); + f32 ang = mAngle.y + 0x8000; + mAng ay = ang + rnd; + mAng ax; + if (checkArrowFlag(ARROW_0x400)) { + ax = 0x2000 - cM::rndF(0x1000); + } else { + ax = -cM::rndF(0x1000); + } + mVelocity.fromXY(ax, ay, 15.0f + cM::rndF(15.0f)); + field_0x690 = 0x2C00 - cM::rndF(0x1000); + setArrowFlag(ARROW_0x100); + unsetArrowFlag(ARROW_0x200); + updateMtx(); + } +} + +void dAcArrow_c::executeState_Bound() { + mVelocity.y -= 2.0f; + mPosition += mVelocity; + mRotation.x += field_0x690; + + mVec3_c next = mPosition + mVelocity * field_0x6A0; + + sArrowLinChk.Set(&mOldPosition, &next, this); + if (dBgS::GetInstance()->LineCross(&sArrowLinChk)) { + cM3dGPla pla; + dBgS::GetInstance()->GetTriPla(sArrowLinChk, &pla); + f32 halfMag = mVelocity.mag() * 0.5f; + + VECReflect(mVelocity, pla.mNormal, mVelocity); + mVelocity *= halfMag; + field_0x690.mVal >>= 1; + if (dBgS_CheckBGroundPoly(sArrowLinChk)) { + setArrowFlag(ARROW_0x1); + } + } else if ((checkArrowFlag(ARROW_0x1) && mVelocity.y <= 0.0f) || field_0x6C8.y - 5000.0f > mPosition.y) { + setArrowFlag(ARROW_0x2); + } + + updateMtx(); +} + +void dAcArrow_c::finalizeState_Bound() {} + +void dAcArrow_c::initializeState_BgStop() { + fn_802601C0(); + cM3dGPla pla; + dBgS::GetInstance()->GetTriPla(sArrowLinChk, &pla); + mVec3_c vz; + mWorldMtx.getBase(2, vz); + if (pla.mNormal.dot(vz) > mAng(19115).cos()) { + mVec3_c c; + vecCross(c, pla.mNormal, vz); + if (nw4r::math::VEC3LenSq(c) > 0.1f) { + mMtx_c mtx; + mtx.setAxisRotation(c, mAng::s2r_c(19115)); + MTXMultVecSR(mtx.m, pla.mNormal, vz); + mRotation.y = vz.atan2sX_Z(); + mRotation.x = vz.atan2snY_XZ(); + } + } + + unsetArrowFlag(ARROW_0x200); + setArrowFlag(ARROW_0x100); + mSpeed = 0.0f; + mAngle.x = -mRotation.x; + field_0x68A = 300; + updateMtx(); + mPolyInfo.SetPolyInfo(sArrowLinChk); + startBgHitSound(SE_AW_STICK, sArrowLinChk, nullptr); + // TODO - constness + dBgS::GetInstance()->ArrowStickCallBack(sArrowLinChk, this, const_cast(sArrowLinChk.GetLinEnd())); + initPickupCc(); + dLightEnv_c::GetPInstance()->setBPM8_Type6(&mPosition); + const dAcObjBase_c *ac = dBgS::GetInstance()->GetActorPointer(sArrowLinChk); + if (ac != nullptr) { + // TODO - constness + fn_8025E720(const_cast(ac), mPosition); + setArrowFlag(ARROW_0x8000); + } +} + +void dAcArrow_c::executeState_BgStop() { + checkPickup(); + dAcObjBase_c *ref = this; + if (checkArrowFlag(ARROW_0x8000)) { + ref = fn_8025E960(); + } + + if (checkArrowFlag(ARROW_0x10) || ref == nullptr || + ((!ref->checkObjectProperty(OBJ_PROP_0x10000) || !checkArrowFlag(ARROW_0x8000)) && + !dBgS::GetInstance()->ChkPolySafe(mPolyInfo))) { + setArrowFlag(ARROW_0x2); + } else if (!checkArrowFlag(ARROW_0x8000)) { + bool b = false; + s16 s1 = fn_8025E640(); + if (field_0x688 != 0) { + b = true; + } + if (dBgS::GetInstance()->ChkMoveBG(mPolyInfo, true)) { + dBgS::GetInstance()->MoveBgTransPos(mPolyInfo, true, &mPosition, &mAngle, &mRotation); + b = true; + } + + if (b != 0) { + mRotation.x = s1 - mAngle.x; + updateMtx(); + } + } +} + +void dAcArrow_c::finalizeState_BgStop() {} + +void dAcArrow_c::initializeState_ActorStop() { + fn_802601C0(); + unsetArrowFlag(ARROW_0x200); + mSpeed = 0.0f; + dAcObjBase_c *obj = fn_8025E960(); + if (obj != nullptr) { + getSoundSource()->startObjHitSound(SE_AW_STICK, obj->getSoundSource(), mPosition); + } + initPickupCc(); +} + +void dAcArrow_c::executeState_ActorStop() { + dAcObjBase_c *obj = fn_8025E960(); + checkPickup(); + if (checkArrowFlag(ARROW_0x10) || obj == nullptr) { + setArrowFlag(ARROW_0x2); + } + unsetArrowFlag(ARROW_0x10000); +} + +void dAcArrow_c::finalizeState_ActorStop() { + unsetArrowFlag(ARROW_0x10000); +} + +void dAcArrow_c::fn_80260050(const mVec3_c &v, bool b) { + if (b) { + startSound(SE_PC_HIT_LAVA); + } else { + startSound(SE_PC_HIT); + } + setArrowFlag(ARROW_0x2); + setArrowFlag(ARROW_0x100); + dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_538_, v, nullptr, nullptr, nullptr, nullptr, 0, 0); +} + +void dAcArrow_c::fn_802600D0(bool b) { + // NONMATCHING + if (b) { + mWorldMtx.getTranslation(field_0x6E0); + field_0x692.x.mVal = 0; + field_0x692.y.mVal = mRotation.y; + field_0x692.z.mVal = field_0x68E; + if (mEffectId == PARTICLE_RESOURCE_ID_MAPPING_2_) { + field_0x68E += 0x888; + } + mMtx_c mtx; + mtx.transS(field_0x6E0); + mtx.ZXYrotM(field_0x692); + mEffects.holdEffect(mEffectId, mtx, nullptr, nullptr); + } else { + mEffects.setFading(5); + unsetArrowFlag(ARROW_0x1000); + } + unsetArrowFlag(ARROW_0x100); +} + +void dAcArrow_c::fn_802601C0() { + if (field_0x683 != 0) { + if (!(mCcCps.ChkAtHit() && mCcCps.GetAtActor()->mProfileName == fProfile::PUMPKIN)) { + setArrowFlag(ARROW_0x4000); + } + field_0x683 = 0; + } +} + +bool dAcArrow_c::fn_80260250(dAcObjBase_c *o1, dAcObjBase_c *o2) { + dAcObjBase_c *o = mRef2.get(); + if (o == nullptr || o1 == o) { + o1->getLinkage().forceRemove(o1); + o2->getLinkage().tryAttach(o2, this, &mRef2, dLinkage_c::CONNECTION_8, false); + return true; + } else { + return false; + } } int dAcArrow_c::actorExecute() { - mStateMgr.executeState(); + unsetArrowFlag(ARROW_0x4000); + if (field_0x683 != 0) { + field_0x683--; + if (field_0x683 == 0) { + setArrowFlag(ARROW_0x4000); + } + } - // TODO + if (checkArrowFlag(ARROW_0x2)) { + // TODO - works but maybe temps or inlines? + if (mRef2.isLinked()) { + mRef2.get()->getLinkage().forceRemove(mRef2.get()); + } + fn_802601C0(); + if (mDespawnTimer != 0) { + mDespawnTimer--; + + } else { + deleteRequest(); + return SUCCEEDED; + } + } else { + if (field_0x684 == sCounter) { + setArrowFlag(ARROW_0x10); + } + if (field_0x681 != 0) { + field_0x681--; + } + mStateMgr.executeState(); + if (mStateMgr.isState(StateID_Move)) { + updateMtx(); + } + } + + mPositionCopy2 = mPositionCopy3 = mPosition; + if (checkArrowFlag(ARROW_0x1000)) { + fn_802600D0(mStateMgr.isState(StateID_Move) && !checkArrowFlag(ARROW_0x2) || checkArrowFlag(ARROW_0x100)); + } + updateRoomId(); + dAcObjBase_c *obj = mRef2.get(); + if (obj != nullptr) { + static const mVec3_c v(0.0f, 0.0f, 45.0f); + mVec3_c v2; + MTXMultVec(mWorldMtx, v, v2); + obj->mPosition = v2; + obj->mPosition.y -= obj->getLinkage().getField_0x1C(); + } return SUCCEEDED; } int dAcArrow_c::draw() { + if (field_0x681 != 0) { + return SUCCEEDED; + } + if (checkArrowFlag(ARROW_0x2)) { + return SUCCEEDED; + } + if (mStateMgr.isState(StateID_Wait) && checkArrowFlag(ARROW_INITIAL_SPAWN)) { + setInitialPosition(); + unsetArrowFlag(ARROW_INITIAL_SPAWN); + } + drawModelType1(&mModel); return SUCCEEDED; } - -void dAcArrow_c::initializeState_Wait() {} -void dAcArrow_c::executeState_Wait() {} -void dAcArrow_c::finalizeState_Wait() {} - -void dAcArrow_c::initializeState_Move() {} -void dAcArrow_c::executeState_Move() {} -void dAcArrow_c::finalizeState_Move() {} - -void dAcArrow_c::initializeState_ActorStop() {} -void dAcArrow_c::executeState_ActorStop() {} -void dAcArrow_c::finalizeState_ActorStop() {} - -void dAcArrow_c::initializeState_BgStop() {} -void dAcArrow_c::executeState_BgStop() {} -void dAcArrow_c::finalizeState_BgStop() {} - -void dAcArrow_c::initializeState_Bound() {} -void dAcArrow_c::executeState_Bound() {} -void dAcArrow_c::finalizeState_Bound() {} diff --git a/src/toBeSorted/d_sword_swing_effect_mgr.cpp b/src/toBeSorted/d_sword_swing_effect_mgr.cpp index 1d0339c3..b1558788 100644 --- a/src/toBeSorted/d_sword_swing_effect_mgr.cpp +++ b/src/toBeSorted/d_sword_swing_effect_mgr.cpp @@ -3,16 +3,7 @@ #include "c/c_math.h" #include "egg/math/eggMatrix.h" #include "m/m_vec.h" - -// TODO: can't use EGG::Vector3f::cross because the Vector3f -> mVec3_c conversion -// forces additional stack stores. An open-coded cross function works too in this -// file but maybe pattern comes up in more files and then we can move it to d_vec? -inline void cross(mVec3_c &result, const mVec3_c &left, const mVec3_c &right) { - result.set( - (left.y * right.z) - (left.z * right.y), (left.z * right.x) - (left.x * right.z), - (left.x * right.y) - (left.y * right.x) - ); -} +#include "d/d_vec.h" static bool fn_8006A8D0(const mVec2_c &v1, const mVec2_c &v2, const mVec2_c &v3, const mVec2_c &v4, mVec2_c &result) { mVec2_c t1 = v2 - v1; @@ -56,7 +47,7 @@ void dSwordSwingEffectProcMgr_c::createSwingEntries(const mVec3_c &v1, const mVe mVec3_c diff = v1 - v2; mVec3_c cross_; - cross(cross_, lastDiff, diff); + vecCross(cross_, lastDiff, diff); f32 diffMag = diff.mag(); @@ -150,7 +141,7 @@ void dSwordSwingEffectProcMgr_c::createSwingEntries(const mVec3_c &v1, const mVe diff2.normalize(); diff1.normalize(); - cross(cross_, diff1, diff2); + vecCross(cross_, diff1, diff2); cross_.normalize(); // Same code as in dowsing_target...