summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrobojumper <robojumper@gmail.com>2026-01-28 19:18:17 +0100
committerGitHub <noreply@github.com>2026-01-28 19:18:17 +0100
commit734ec3aef89402766b82c14f876cb5c3e0769ed4 (patch)
treef5a4395f7ac2deb358f46f90020a3d05549ff077
parentcffba79e3f0600d54dea3bdbb0506e2fc1c54199 (diff)
parente9033d74d106036da06653d371ad9407188b8c85 (diff)
Merge pull request #292 from robojumper/lastboss
d_a_b_lastboss 99%
-rw-r--r--config/SOUE01/rels/d_a_b_lastbossNP/symbols.txt389
-rw-r--r--config/SOUE01/splits.txt20
-rw-r--r--config/SOUE01/symbols.txt92
-rw-r--r--configure.py7
-rw-r--r--include/d/a/b/d_a_b_lastboss.h428
-rw-r--r--include/d/a/e/d_a_en_base.h19
-rw-r--r--include/d/a/obj/d_a_obj_base.h19
-rw-r--r--include/d/col/c/c_cc_d.h20
-rw-r--r--include/d/col/cc/d_cc_d.h1
-rw-r--r--include/d/d_camera.h2
-rw-r--r--include/d/d_cc.h21
-rw-r--r--include/d/d_light_env.h20
-rw-r--r--include/d/d_player_act.h29
-rw-r--r--include/d/d_sc_game.h4
-rw-r--r--include/d/d_stage_mgr.h23
-rw-r--r--include/d/lyt/d_lyt_boss_caption.h28
-rw-r--r--include/d/snd/d_snd_bgm_mgr.h2
-rw-r--r--include/toBeSorted/d_d3d.h2
-rw-r--r--include/toBeSorted/d_enemy_sword_mdl.h75
-rw-r--r--include/toBeSorted/d_sword_swing_effect.h65
-rw-r--r--include/toBeSorted/d_sword_swing_effect_mgr.h43
-rw-r--r--src/REL/d/a/b/d_a_b_lastboss.cpp3340
-rw-r--r--src/REL/d/a/e/d_a_e_sm.cpp8
-rw-r--r--src/REL/d/a/obj/d_a_obj_warp_hole.cpp2
-rw-r--r--src/d/col/c/c_m3d_g_cps.cpp2
-rw-r--r--src/d/snd/d_snd_source.cpp3
-rw-r--r--src/toBeSorted/d_enemy_sword_mdl.cpp131
-rw-r--r--src/toBeSorted/d_sword_swing_effect.cpp218
-rw-r--r--src/toBeSorted/d_sword_swing_effect_mgr.cpp196
-rw-r--r--src/toBeSorted/dowsing_target.cpp1
30 files changed, 4998 insertions, 212 deletions
diff --git a/config/SOUE01/rels/d_a_b_lastbossNP/symbols.txt b/config/SOUE01/rels/d_a_b_lastbossNP/symbols.txt
index e86f3fc1..5b01a3a5 100644
--- a/config/SOUE01/rels/d_a_b_lastbossNP/symbols.txt
+++ b/config/SOUE01/rels/d_a_b_lastbossNP/symbols.txt
@@ -3,36 +3,36 @@ _epilog = .text:0x00000030; // type:function size:0x2C scope:global
_unresolved = .text:0x00000060; // type:function size:0x4 scope:global
__register_global_object = .text:0x00000070; // type:function size:0x1C scope:global
__destroy_global_chain = .text:0x00000090; // type:function size:0x54 scope:global
-fn_143_F0 = .text:0x000000F0; // type:function size:0x40
+__dt__7mVec3_cFv = .text:0x000000F0; // type:function size:0x40
dAcBlastboss_c_classInit__Fv = .text:0x00000130; // type:function size:0x39C
-fn_143_4D0 = .text:0x000004D0; // type:function size:0x58
-fn_143_530 = .text:0x00000530; // type:function size:0x90
-fn_143_5C0 = .text:0x000005C0; // type:function size:0x90
-fn_143_650 = .text:0x00000650; // type:function size:0x40
+__dt__Q214dAcBlastboss_c10callback_cFv = .text:0x000004D0; // type:function size:0x58
+__dt__15dCcD_Linked_CylFv = .text:0x00000530; // type:function size:0x90
+__dt__15dCcD_Linked_SphFv = .text:0x000005C0; // type:function size:0x90
+__dt__14dScnCallback_cFv = .text:0x00000650; // type:function size:0x40
__dt__27sFState_c<14dAcBlastboss_c>Fv = .text:0x00000690; // type:function size:0x58
__dt__30sFStateFct_c<14dAcBlastboss_c>Fv = .text:0x000006F0; // type:function size:0x6C
__dt__83sStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x00000760; // type:function size:0xA0
__dt__53sFStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c>Fv = .text:0x00000800; // type:function size:0xA4
-fn_143_8B0 = .text:0x000008B0; // type:function size:0x4
-fn_143_8C0 = .text:0x000008C0; // type:function size:0x84
-fn_143_950 = .text:0x00000950; // type:function size:0x58
-fn_143_9B0 = .text:0x000009B0; // type:function size:0x90
-fn_143_A40 = .text:0x00000A40; // type:function size:0xCC
-fn_143_B10 = .text:0x00000B10; // type:function size:0xC0
-fn_143_BD0 = .text:0x00000BD0; // type:function size:0xDC
-fn_143_CB0 = .text:0x00000CB0; // type:function size:0xC0
-fn_143_D70 = .text:0x00000D70; // type:function size:0xDC
-fn_143_E50 = .text:0x00000E50; // type:function size:0x324
-fn_143_1180 = .text:0x00001180; // type:function size:0x3F8
-fn_143_1580 = .text:0x00001580; // type:function size:0x8
+__ct__7mVec3_cFv = .text:0x000008B0; // type:function size:0x4
+__dt__26dSwordSwingEffectProcMgr_cFv = .text:0x000008C0; // type:function size:0x84
+__ct__15dCcD_Linked_CpsFv = .text:0x00000950; // type:function size:0x58
+__dt__15dCcD_Linked_CpsFv = .text:0x000009B0; // type:function size:0x90
+__dt__16dEnemySwordMdl_cFv = .text:0x00000A40; // type:function size:0xCC
+__ct__17UnkLastBossCcSph2Fv = .text:0x00000B10; // type:function size:0xC0
+__dt__17UnkLastBossCcSph2Fv = .text:0x00000BD0; // type:function size:0xDC
+__ct__17UnkLastBossCcSph1Fv = .text:0x00000CB0; // type:function size:0xC0
+__dt__17UnkLastBossCcSph1Fv = .text:0x00000D70; // type:function size:0xDC
+createHeap__14dAcBlastboss_cFv = .text:0x00000E50; // type:function size:0x324
+create__14dAcBlastboss_cFv = .text:0x00001180; // type:function size:0x3F8
+checkInBossRush__15MinigameManagerFv = .text:0x00001580; // type:function size:0x8
changeState__83sStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>FRC12sStateIDIf_c = .text:0x00001590; // type:function size:0x10
-fn_143_15A0 = .text:0x000015A0; // type:function size:0x34
-fn_143_15E0 = .text:0x000015E0; // type:function size:0x17A8
+doDelete__14dAcBlastboss_cFv = .text:0x000015A0; // type:function size:0x34
+actorExecute__14dAcBlastboss_cFv = .text:0x000015E0; // type:function size:0x17A8
executeState__83sStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x00002D90; // type:function size:0x10
getStateID__83sStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>CFv = .text:0x00002DA0; // type:function size:0x10
-fn_143_2DB0 = .text:0x00002DB0; // type:function size:0x48
-fn_143_2E00 = .text:0x00002E00; // type:function size:0x4C
-fn_143_2E50 = .text:0x00002E50; // type:function size:0x85C
+ChkAtHit__10dCcD_CheckFv = .text:0x00002DB0; // type:function size:0x48
+ChkTgHit__10dCcD_CheckFv = .text:0x00002E00; // type:function size:0x4C
+timingB__Q214dAcBlastboss_c10callback_cFUlPQ34nw4r3g3d13WorldMtxManipQ34nw4r3g3d6ResMdl = .text:0x00002E50; // type:function size:0x85C
initializeState_Fight__14dAcBlastboss_cFv = .text:0x000036B0; // type:function size:0xBC
executeState_Fight__14dAcBlastboss_cFv = .text:0x00003770; // type:function size:0x718
finalizeState_Fight__14dAcBlastboss_cFv = .text:0x00003E90; // type:function size:0x4
@@ -75,33 +75,33 @@ finalizeState_Stun__14dAcBlastboss_cFv = .text:0x00006490; // type:function size
initializeState_ThunderWait__14dAcBlastboss_cFv = .text:0x000064A0; // type:function size:0x54
executeState_ThunderWait__14dAcBlastboss_cFv = .text:0x00006500; // type:function size:0x204
finalizeState_ThunderWait__14dAcBlastboss_cFv = .text:0x00006710; // type:function size:0x4
-fn_143_6720 = .text:0x00006720; // type:function size:0xBB4
-fn_143_72E0 = .text:0x000072E0; // type:function size:0x1C
-fn_143_7300 = .text:0x00007300; // type:function size:0x58
-fn_143_7360 = .text:0x00007360; // type:function size:0x50
-fn_143_73B0 = .text:0x000073B0; // type:function size:0x10
-fn_143_73C0 = .text:0x000073C0; // type:function size:0x60
-fn_143_7420 = .text:0x00007420; // type:function size:0x17C
-fn_143_75A0 = .text:0x000075A0; // type:function size:0x218
-fn_143_77C0 = .text:0x000077C0; // type:function size:0x338
-fn_143_7B00 = .text:0x00007B00; // type:function size:0x478
-fn_143_7F80 = .text:0x00007F80; // type:function size:0x674
-fn_143_8600 = .text:0x00008600; // type:function size:0x860
-fn_143_8E60 = .text:0x00008E60; // type:function size:0x5B4
-fn_143_9420 = .text:0x00009420; // type:function size:0x148
-fn_143_9570 = .text:0x00009570; // type:function size:0x9C
-fn_143_9610 = .text:0x00009610; // type:function size:0xAF4
-fn_143_A110 = .text:0x0000A110; // type:function size:0xBC
-fn_143_A1D0 = .text:0x0000A1D0; // type:function size:0x8
-fn_143_A1E0 = .text:0x0000A1E0; // type:function size:0x4
-fn_143_A1F0 = .text:0x0000A1F0; // type:function size:0x4
-fn_143_A200 = .text:0x0000A200; // type:function size:0x8
+checkDamage__14dAcBlastboss_cFv = .text:0x00006720; // type:function size:0xBB4
+calcTimer<Uc>__4sLibFPUc_Uc = .text:0x000072E0; // type:function size:0x1C
+setAnm__14dAcBlastboss_cFPCcf = .text:0x00007300; // type:function size:0x58
+forceSetAnm__14dAcBlastboss_cFPCcf = .text:0x00007360; // type:function size:0x50
+setAnmRate__14dAcBlastboss_cFf = .text:0x000073B0; // type:function size:0x10
+draw__14dAcBlastboss_cFv = .text:0x000073C0; // type:function size:0x60
+checkForCloseRangeAttack__14dAcBlastboss_cFv = .text:0x00007420; // type:function size:0x17C
+checkForRangeAttack__14dAcBlastboss_cFv = .text:0x000075A0; // type:function size:0x218
+checkForCounter__14dAcBlastboss_cFv = .text:0x000077C0; // type:function size:0x338
+updateMainNodeTransforms__14dAcBlastboss_cFv = .text:0x00007B00; // type:function size:0x478
+updateSkirtHairTransforms__14dAcBlastboss_cFv = .text:0x00007F80; // type:function size:0x674
+updateSkirtTransform__14dAcBlastboss_cFl = .text:0x00008600; // type:function size:0x860
+updateHairTransform__14dAcBlastboss_cFl = .text:0x00008E60; // type:function size:0x5B4
+checkForLinkSwordBySwordHit__14dAcBlastboss_cFv = .text:0x00009420; // type:function size:0x148
+classifyAttackDirection__14dAcBlastboss_cFl = .text:0x00009570; // type:function size:0x9C
+executeLightningStrike__14dAcBlastboss_cFv = .text:0x00009610; // type:function size:0xAF4
+setLightningTimerMaybe__14dAcBlastboss_cFl = .text:0x0000A110; // type:function size:0xBC
+vt_0x88__11dAcEnBase_cFi = .text:0x0000A1D0; // type:function size:0x8
+vt_0x84__11dAcEnBase_cFv = .text:0x0000A1E0; // type:function size:0x4
+vt_0x80__11dAcEnBase_cFv = .text:0x0000A1F0; // type:function size:0x4
+getObjectListEntry__11dAcEnBase_cFv = .text:0x0000A200; // type:function size:0x8
__dt__14dAcBlastboss_cFv = .text:0x0000A210; // type:function size:0x398
-fn_143_A5B0 = .text:0x0000A5B0; // type:function size:0x4
-fn_143_A5C0 = .text:0x0000A5C0; // type:function size:0x4
-fn_143_A5D0 = .text:0x0000A5D0; // type:function size:0x4
-fn_143_A5E0 = .text:0x0000A5E0; // type:function size:0x4
-fn_143_A5F0 = .text:0x0000A5F0; // type:function size:0x4
+ExecCallback_DRAW_XLU__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x0000A5B0; // type:function size:0x4
+ExecCallback_DRAW_OPA__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x0000A5C0; // type:function size:0x4
+ExecCallback_CALC_MAT__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x0000A5D0; // type:function size:0x4
+ExecCallback_CALC_WORLD__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x0000A5E0; // type:function size:0x4
+ExecCallback_CALC_VIEW__Q34nw4r3g3d15IScnObjCallbackFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x0000A5F0; // type:function size:0x4
build__30sFStateFct_c<14dAcBlastboss_c>FRC12sStateIDIf_c = .text:0x0000A600; // type:function size:0x60
dispose__30sFStateFct_c<14dAcBlastboss_c>FRP10sStateIf_c = .text:0x0000A660; // type:function size:0xC
initialize__27sFState_c<14dAcBlastboss_c>Fv = .text:0x0000A670; // type:function size:0x1C
@@ -119,36 +119,188 @@ initializeState__29sFStateID_c<14dAcBlastboss_c>CFR14dAcBlastboss_c = .text:0x00
__sinit_\d_a_b_lastboss_cpp = .text:0x0000A7C0; // type:function size:0xA90 scope:local
__dt__29sFStateID_c<14dAcBlastboss_c>Fv = .text:0x0000B250; // type:function size:0x58
isSameName__29sFStateID_c<14dAcBlastboss_c>CFPCc = .text:0x0000B2B0; // type:function size:0x88
-fn_143_B340 = .text:0x0000B340; // type:function size:0x8
-fn_143_B350 = .text:0x0000B350; // type:function size:0x8
-fn_143_B360 = .text:0x0000B360; // type:function size:0x8
+@272@__dt__15dCcD_Linked_CpsFv = .text:0x0000B340; // type:function size:0x8
+@272@__dt__15dCcD_Linked_SphFv = .text:0x0000B350; // type:function size:0x8
+@272@__dt__15dCcD_Linked_CylFv = .text:0x0000B360; // type:function size:0x8
_ctors = .ctors:0x00000000; // type:label scope:global
_dtors = .dtors:0x00000000; // type:label scope:global
__destroy_global_chain_reference = .dtors:0x00000000; // type:object size:0x4 scope:global
lbl_143_rodata_0 = .rodata:0x00000000; // type:object size:0xC data:float
-lbl_143_rodata_C = .rodata:0x0000000C; // type:object size:0x64 align:4 data:float
-lbl_143_rodata_70 = .rodata:0x00000070; // type:object size:0x20 align:4 data:float
+lbl_143_rodata_C = .rodata:0x0000000C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_10 = .rodata:0x00000010; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_14 = .rodata:0x00000014; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_18 = .rodata:0x00000018; // type:object size:0x4
+lbl_143_rodata_1C = .rodata:0x0000001C; // type:object size:0x4
+lbl_143_rodata_20 = .rodata:0x00000020; // type:object size:0x4
+lbl_143_rodata_24 = .rodata:0x00000024; // type:object size:0x4
+lbl_143_rodata_28 = .rodata:0x00000028; // type:object size:0x4
+lbl_143_rodata_2C = .rodata:0x0000002C; // type:object size:0x4 data:float
+lbl_143_rodata_30 = .rodata:0x00000030; // type:object size:0x4
+lbl_143_rodata_38 = .rodata:0x00000038; // type:object size:0x10
+lbl_143_rodata_48 = .rodata:0x00000048; // type:object size:0x4 data:float
+lbl_143_rodata_4C = .rodata:0x0000004C; // type:object size:0x4
+lbl_143_rodata_50 = .rodata:0x00000050; // type:object size:0x4
+lbl_143_rodata_54 = .rodata:0x00000054; // type:object size:0x4 data:float
+lbl_143_rodata_58 = .rodata:0x00000058; // type:object size:0x4
+lbl_143_rodata_5C = .rodata:0x0000005C; // type:object size:0x4
+lbl_143_rodata_60 = .rodata:0x00000060; // type:object size:0x4
+lbl_143_rodata_64 = .rodata:0x00000064; // type:object size:0x4
+lbl_143_rodata_68 = .rodata:0x00000068; // type:object size:0x4
+lbl_143_rodata_6C = .rodata:0x0000006C; // type:object size:0x4 data:float
+lbl_143_rodata_70 = .rodata:0x00000070; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_74 = .rodata:0x00000074; // type:object size:0x4
+lbl_143_rodata_78 = .rodata:0x00000078; // type:object size:0x4
+lbl_143_rodata_7C = .rodata:0x0000007C; // type:object size:0x4
+lbl_143_rodata_80 = .rodata:0x00000080; // type:object size:0x4
+lbl_143_rodata_84 = .rodata:0x00000084; // type:object size:0x4
+lbl_143_rodata_88 = .rodata:0x00000088; // type:object size:0x4 data:float
+lbl_143_rodata_8C = .rodata:0x0000008C; // type:object size:0x4 data:float
lbl_143_rodata_90 = .rodata:0x00000090; // type:object size:0x4 align:4 data:float
-lbl_143_rodata_94 = .rodata:0x00000094; // type:object size:0x10 align:4 data:float
-lbl_143_rodata_A4 = .rodata:0x000000A4; // type:object size:0x44 align:4 data:float
-lbl_143_rodata_E8 = .rodata:0x000000E8; // type:object size:0x18 align:4 data:float
-lbl_143_rodata_100 = .rodata:0x00000100; // type:object size:0x18 align:8 data:double
-lbl_143_rodata_118 = .rodata:0x00000118; // type:object size:0xC align:4 data:float
-lbl_143_rodata_124 = .rodata:0x00000124; // type:object size:0x10 align:4 data:float
-lbl_143_rodata_134 = .rodata:0x00000134; // type:object size:0x7C align:4 data:float
-lbl_143_rodata_1B0 = .rodata:0x000001B0; // type:object size:0x8 align:4 data:float
-lbl_143_rodata_1B8 = .rodata:0x000001B8; // type:object size:0x10 align:4 data:float
-lbl_143_rodata_1C8 = .rodata:0x000001C8; // type:object size:0xC align:4 data:float
-lbl_143_rodata_1D4 = .rodata:0x000001D4; // type:object size:0x3C align:4 data:float
-lbl_143_rodata_210 = .rodata:0x00000210; // type:object size:0x90 align:4 data:float
-g_profile_B_LASTBOSS = .data:0x00000000; // type:object size:0x1A0 data:4byte
+lbl_143_rodata_94 = .rodata:0x00000094; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_98 = .rodata:0x00000098; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_9C = .rodata:0x0000009C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_A0 = .rodata:0x000000A0; // type:object size:0x4
+lbl_143_rodata_A4 = .rodata:0x000000A4; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_A8 = .rodata:0x000000A8; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_AC = .rodata:0x000000AC; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_B0 = .rodata:0x000000B0; // type:object size:0x4 data:float
+lbl_143_rodata_B4 = .rodata:0x000000B4; // type:object size:0x4 data:float
+lbl_143_rodata_B8 = .rodata:0x000000B8; // type:object size:0x4 data:float
+lbl_143_rodata_BC = .rodata:0x000000BC; // type:object size:0x4 data:float
+lbl_143_rodata_C0 = .rodata:0x000000C0; // type:object size:0x4 data:float
+lbl_143_rodata_C4 = .rodata:0x000000C4; // type:object size:0x4 data:float
+lbl_143_rodata_C8 = .rodata:0x000000C8; // type:object size:0x4 data:float
+lbl_143_rodata_CC = .rodata:0x000000CC; // type:object size:0x4 data:float
+lbl_143_rodata_D0 = .rodata:0x000000D0; // type:object size:0x4 data:float
+lbl_143_rodata_D4 = .rodata:0x000000D4; // type:object size:0x4 data:float
+lbl_143_rodata_D8 = .rodata:0x000000D8; // type:object size:0x4 data:float
+lbl_143_rodata_DC = .rodata:0x000000DC; // type:object size:0x4 data:float
+lbl_143_rodata_E0 = .rodata:0x000000E0; // type:object size:0x4 data:float
+lbl_143_rodata_E4 = .rodata:0x000000E4; // type:object size:0x4 data:float
+lbl_143_rodata_E8 = .rodata:0x000000E8; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_EC = .rodata:0x000000EC; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_F0 = .rodata:0x000000F0; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_F4 = .rodata:0x000000F4; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_F8 = .rodata:0x000000F8; // type:object size:0x8 align:8 data:double
+lbl_143_rodata_100 = .rodata:0x00000100; // type:object size:0x8 align:8 data:double
+lbl_143_rodata_108 = .rodata:0x00000108; // type:object size:0x4
+lbl_143_rodata_10C = .rodata:0x0000010C; // type:object size:0x4
+lbl_143_rodata_110 = .rodata:0x00000110; // type:object size:0x4
+lbl_143_rodata_114 = .rodata:0x00000114; // type:object size:0x4
+lbl_143_rodata_118 = .rodata:0x00000118; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_11C = .rodata:0x0000011C; // type:object size:0x4
+lbl_143_rodata_120 = .rodata:0x00000120; // type:object size:0x4
+lbl_143_rodata_124 = .rodata:0x00000124; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_128 = .rodata:0x00000128; // type:object size:0x4
+lbl_143_rodata_12C = .rodata:0x0000012C; // type:object size:0x4
+lbl_143_rodata_130 = .rodata:0x00000130; // type:object size:0x4
+lbl_143_rodata_134 = .rodata:0x00000134; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_138 = .rodata:0x00000138; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_13C = .rodata:0x0000013C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_140 = .rodata:0x00000140; // type:object size:0x4
+lbl_143_rodata_144 = .rodata:0x00000144; // type:object size:0x4
+lbl_143_rodata_148 = .rodata:0x00000148; // type:object size:0x4
+lbl_143_rodata_14C = .rodata:0x0000014C; // type:object size:0x4
+lbl_143_rodata_150 = .rodata:0x00000150; // type:object size:0x4 data:float
+lbl_143_rodata_154 = .rodata:0x00000154; // type:object size:0x4
+lbl_143_rodata_158 = .rodata:0x00000158; // type:object size:0x4 data:float
+lbl_143_rodata_15C = .rodata:0x0000015C; // type:object size:0x4 data:float
+lbl_143_rodata_160 = .rodata:0x00000160; // type:object size:0x4 data:float
+lbl_143_rodata_164 = .rodata:0x00000164; // type:object size:0x4 data:float
+lbl_143_rodata_168 = .rodata:0x00000168; // type:object size:0x4 data:float
+lbl_143_rodata_16C = .rodata:0x0000016C; // type:object size:0x4 data:float
+lbl_143_rodata_170 = .rodata:0x00000170; // type:object size:0x4 data:float
+lbl_143_rodata_174 = .rodata:0x00000174; // type:object size:0x4 data:float
+lbl_143_rodata_178 = .rodata:0x00000178; // type:object size:0x28
+lbl_143_rodata_1A0 = .rodata:0x000001A0; // type:object size:0x4 data:float
+lbl_143_rodata_1A4 = .rodata:0x000001A4; // type:object size:0x4 data:float
+lbl_143_rodata_1A8 = .rodata:0x000001A8; // type:object size:0x4 data:float
+lbl_143_rodata_1AC = .rodata:0x000001AC; // type:object size:0x4
+lbl_143_rodata_1B0 = .rodata:0x000001B0; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1B4 = .rodata:0x000001B4; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1B8 = .rodata:0x000001B8; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1BC = .rodata:0x000001BC; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1C0 = .rodata:0x000001C0; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1C4 = .rodata:0x000001C4; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1C8 = .rodata:0x000001C8; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1CC = .rodata:0x000001CC; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1D0 = .rodata:0x000001D0; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1D4 = .rodata:0x000001D4; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1D8 = .rodata:0x000001D8; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_1E0 = .rodata:0x000001E0; // type:object size:0x10
+lbl_143_rodata_1F0 = .rodata:0x000001F0; // type:object size:0x10
+lbl_143_rodata_200 = .rodata:0x00000200; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_204 = .rodata:0x00000204; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_208 = .rodata:0x00000208; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_20C = .rodata:0x0000020C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_210 = .rodata:0x00000210; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_214 = .rodata:0x00000214; // type:object size:0x24 align:4 data:float
+lbl_143_rodata_238 = .rodata:0x00000238; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_23C = .rodata:0x0000023C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_240 = .rodata:0x00000240; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_244 = .rodata:0x00000244; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_248 = .rodata:0x00000248; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_24C = .rodata:0x0000024C; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_250 = .rodata:0x00000250; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_254 = .rodata:0x00000254; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_258 = .rodata:0x00000258; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_25C = .rodata:0x0000025C; // type:object size:0x4
+lbl_143_rodata_260 = .rodata:0x00000260; // type:object size:0x4
+lbl_143_rodata_264 = .rodata:0x00000264; // type:object size:0x4
+lbl_143_rodata_268 = .rodata:0x00000268; // type:object size:0x4
+lbl_143_rodata_26C = .rodata:0x0000026C; // type:object size:0x4
+lbl_143_rodata_270 = .rodata:0x00000270; // type:object size:0x4
+lbl_143_rodata_274 = .rodata:0x00000274; // type:object size:0x4
+lbl_143_rodata_278 = .rodata:0x00000278; // type:object size:0x4 align:4 data:float
+lbl_143_rodata_27C = .rodata:0x0000027C; // type:object size:0x4
+lbl_143_rodata_280 = .rodata:0x00000280; // type:object size:0x4
+lbl_143_rodata_284 = .rodata:0x00000284; // type:object size:0x4
+lbl_143_rodata_288 = .rodata:0x00000288; // type:object size:0x4
+lbl_143_rodata_28C = .rodata:0x0000028C; // type:object size:0x4
+lbl_143_rodata_290 = .rodata:0x00000290; // type:object size:0x4
+lbl_143_rodata_294 = .rodata:0x00000294; // type:object size:0x4
+lbl_143_rodata_298 = .rodata:0x00000298; // type:object size:0x4
+lbl_143_rodata_29C = .rodata:0x0000029C; // type:object size:0x4
+g_profile_B_LASTBOSS = .data:0x00000000; // type:object size:0x10 data:4byte
+sSrcCyl1 = .data:0x00000010; // type:object size:0x30
+sSrcCyl2 = .data:0x00000040; // type:object size:0x30
+sSrcCyl3 = .data:0x00000070; // type:object size:0x30
+sSrcSph1 = .data:0x000000A0; // type:object size:0x2C
+sSrcSph2 = .data:0x000000CC; // type:object size:0x2C
+sSrcSph = .data:0x000000F8; // type:object size:0x2C
+lbl_143_data_124 = .data:0x00000124; // type:object size:0xA data:string
+lbl_143_data_130 = .data:0x00000130; // type:object size:0x9 data:string
+lbl_143_data_13C = .data:0x0000013C; // type:object size:0x5 data:string
+lbl_143_data_144 = .data:0x00000144; // type:object size:0x5 data:string
+lbl_143_data_14C = .data:0x0000014C; // type:object size:0xE data:string
+lbl_143_data_15C = .data:0x0000015C; // type:object size:0xD data:string
+lbl_143_data_16C = .data:0x0000016C; // type:object size:0x1C data:string
+lbl_143_data_188 = .data:0x00000188; // type:object size:0xC data:string
+lbl_143_data_194 = .data:0x00000194; // type:object size:0xA data:string
lbl_143_data_1A0 = .data:0x000001A0; // type:object size:0x10 data:string
-lbl_143_data_1B0 = .data:0x000001B0; // type:object size:0x28
-lbl_143_data_1D8 = .data:0x000001D8; // type:object size:0x70
+lbl_143_data_1B0 = .data:0x000001B0; // type:object size:0x5 data:string
+lbl_143_data_1B8 = .data:0x000001B8; // type:object size:0x5 data:string
+lbl_143_data_1C0 = .data:0x000001C0; // type:object size:0x7 data:string
+lbl_143_data_1C8 = .data:0x000001C8; // type:object size:0x6 data:string
+lbl_143_data_1D0 = .data:0x000001D0; // type:object size:0x6 data:string
+lbl_143_data_1D8 = .data:0x000001D8; // type:object size:0xC data:string
+lbl_143_data_1E8 = .data:0x000001E8; // type:object size:0x8 data:string
+lbl_143_data_1F0 = .data:0x000001F0; // type:object size:0x8 data:string
+lbl_143_data_1F8 = .data:0x000001F8; // type:object size:0x8 data:string
+lbl_143_data_200 = .data:0x00000200; // type:object size:0x8 data:string
+lbl_143_data_208 = .data:0x00000208; // type:object size:0xE data:string
+lbl_143_data_218 = .data:0x00000218; // type:object size:0xA data:string
+lbl_143_data_224 = .data:0x00000224; // type:object size:0xC data:string
+lbl_143_data_230 = .data:0x00000230; // type:object size:0xC data:string
+lbl_143_data_23C = .data:0x0000023C; // type:object size:0xC data:string
lbl_143_data_248 = .data:0x00000248; // type:object size:0xE data:string
lbl_143_data_258 = .data:0x00000258; // type:object size:0x4 data:4byte
-lbl_143_data_25C = .data:0x0000025C; // type:object size:0x1C
-lbl_143_data_278 = .data:0x00000278; // type:object size:0x20
+lbl_143_data_25C = .data:0x0000025C; // type:object size:0x7 data:string
+lbl_143_data_264 = .data:0x00000264; // type:object size:0x4
+lbl_143_data_268 = .data:0x00000268; // type:object size:0x4
+lbl_143_data_26C = .data:0x0000026C; // type:object size:0xC
+lbl_143_data_278 = .data:0x00000278; // type:object size:0x10 data:string
+lbl_143_data_288 = .data:0x00000288; // type:object size:0xF data:string
lbl_143_data_298 = .data:0x00000298; // type:object size:0x11 data:string
lbl_143_data_2AC = .data:0x000002AC; // type:object size:0x4 data:4byte
lbl_143_data_2B0 = .data:0x000002B0; // type:object size:0x7 data:string
@@ -160,36 +312,87 @@ lbl_143_data_2D8 = .data:0x000002D8; // type:object size:0x8 data:string
lbl_143_data_2E0 = .data:0x000002E0; // type:object size:0x7 data:string
lbl_143_data_2E8 = .data:0x000002E8; // type:object size:0x7 data:string
lbl_143_data_2F0 = .data:0x000002F0; // type:object size:0x7 data:string
-lbl_143_data_2F8 = .data:0x000002F8; // type:object size:0x58
+lbl_143_data_2F8 = .data:0x000002F8; // type:object size:0x7 data:string
+lbl_143_data_300 = .data:0x00000300; // type:object size:0x28
+lbl_143_data_328 = .data:0x00000328; // type:object size:0xD data:string
+lbl_143_data_338 = .data:0x00000338; // type:object size:0xD data:string
+lbl_143_data_348 = .data:0x00000348; // type:object size:0x7 data:string
lbl_143_data_350 = .data:0x00000350; // type:object size:0xB data:string
lbl_143_data_35C = .data:0x0000035C; // type:object size:0xC data:string
lbl_143_data_368 = .data:0x00000368; // type:object size:0x7 data:string
-lbl_143_data_370 = .data:0x00000370; // type:object size:0x64
-lbl_143_data_3D4 = .data:0x000003D4; // type:object size:0x34
+lbl_143_data_370 = .data:0x00000370; // type:object size:0x7 data:string
+lbl_143_data_378 = .data:0x00000378; // type:object size:0xB data:string
+lbl_143_data_384 = .data:0x00000384; // type:object size:0xE data:string
+lbl_143_data_394 = .data:0x00000394; // type:object size:0xE data:string
+lbl_143_data_3A4 = .data:0x000003A4; // type:object size:0xE data:string
+lbl_143_data_3B4 = .data:0x000003B4; // type:object size:0xE data:string
+lbl_143_data_3C4 = .data:0x000003C4; // type:object size:0xE data:string
+lbl_143_data_3D4 = .data:0x000003D4; // type:object size:0xB data:string
+lbl_143_data_3E0 = .data:0x000003E0; // type:object size:0xA data:string
+lbl_143_data_3EC = .data:0x000003EC; // type:object size:0x9 data:string
+lbl_143_data_3F8 = .data:0x000003F8; // type:object size:0x9 data:string
+lbl_143_data_404 = .data:0x00000404; // type:object size:0x4 data:string
lbl_143_data_408 = .data:0x00000408; // type:object size:0x11 data:string
jumptable_143_data_41C = .data:0x0000041C; // type:object size:0x58 scope:local
lbl_143_data_474 = .data:0x00000474; // type:object size:0x9 data:string
lbl_143_data_480 = .data:0x00000480; // type:object size:0xC data:string
-lbl_143_data_48C = .data:0x0000048C; // type:object size:0x34
+lbl_143_data_48C = .data:0x0000048C; // type:object size:0x12 data:string
+lbl_143_data_4A0 = .data:0x000004A0; // type:object size:0x4
+lbl_143_data_4A4 = .data:0x000004A4; // type:object size:0x4
+lbl_143_data_4A8 = .data:0x000004A8; // type:object size:0xC
+lbl_143_data_4B4 = .data:0x000004B4; // type:object size:0xC
lbl_143_data_4C0 = .data:0x000004C0; // type:object size:0x4 data:4byte
-lbl_143_data_4C4 = .data:0x000004C4; // type:object size:0x5C data:4byte
-lbl_143_data_520 = .data:0x00000520; // type:object size:0x90
-lbl_143_data_5B0 = .data:0x000005B0; // type:object size:0x30
-lbl_143_data_5E0 = .data:0x000005E0; // type:object size:0x30
-lbl_143_data_610 = .data:0x00000610; // type:object size:0x18
-lbl_143_data_628 = .data:0x00000628; // type:object size:0x18
-lbl_143_data_640 = .data:0x00000640; // type:object size:0x70
-lbl_143_data_6B0 = .data:0x000006B0; // type:object size:0x18
-lbl_143_data_6C8 = .data:0x000006C8; // type:object size:0x70
-lbl_143_data_738 = .data:0x00000738; // type:object size:0x10
-lbl_143_data_748 = .data:0x00000748; // type:object size:0x70
-lbl_143_data_7B8 = .data:0x000007B8; // type:object size:0x410
-lbl_143_data_BC8 = .data:0x00000BC8; // type:object size:0x34
+lbl_143_data_4C4 = .data:0x000004C4; // type:object size:0x4 data:4byte
+lbl_143_data_4C8 = .data:0x000004C8; // type:object size:0x4 data:4byte
+lbl_143_data_4CC = .data:0x000004CC; // type:object size:0x4 data:4byte
+lbl_143_data_4D0 = .data:0x000004D0; // type:object size:0x4
+lbl_143_data_4D4 = .data:0x000004D4; // type:object size:0x4
+lbl_143_data_4D8 = .data:0x000004D8; // type:object size:0x4
+lbl_143_data_4DC = .data:0x000004DC; // type:object size:0x4
+lbl_143_data_4E0 = .data:0x000004E0; // type:object size:0x4
+lbl_143_data_4E4 = .data:0x000004E4; // type:object size:0x4
+lbl_143_data_4E8 = .data:0x000004E8; // type:object size:0x4
+lbl_143_data_4EC = .data:0x000004EC; // type:object size:0xA data:string
+lbl_143_data_4F8 = .data:0x000004F8; // type:object size:0x8 data:string
+lbl_143_data_500 = .data:0x00000500; // type:object size:0xA data:string
+lbl_143_data_510 = .data:0x00000510; // type:object size:0x10 data:string
+__vt__14dAcBlastboss_c = .data:0x00000520; // type:object size:0x8C
+__vt__53sFStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c> = .data:0x000005B0; // type:object size:0x30
+__vt__83sStateMgr_c<14dAcBlastboss_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c> = .data:0x000005E0; // type:object size:0x30
+__vt__30sFStateFct_c<14dAcBlastboss_c> = .data:0x00000610; // type:object size:0x14
+__vt__27sFState_c<14dAcBlastboss_c> = .data:0x00000628; // type:object size:0x18
+__vt__15dCcD_Linked_Cyl = .data:0x00000640; // type:object size:0x70
+__vt__Q214dAcBlastboss_c10callback_c = .data:0x000006B0; // type:object size:0x18
+__vt__15dCcD_Linked_Sph = .data:0x000006C8; // type:object size:0x70
+__vt__16dEnemySwordMdl_c = .data:0x00000738; // type:object size:0xC
+__vt__15dCcD_Linked_Cps = .data:0x00000748; // type:object size:0x70
+__vt__26dSwordSwingEffectProcMgr_c = .data:0x000007B8; // type:object size:0xC
+__vt__Q34nw4r3g3d15IScnObjCallback = .data:0x000007C8; // type:object size:0x20
+lbl_143_data_7E8 = .data:0x000007E8; // type:object size:0x3E0
+__vt__29sFStateID_c<14dAcBlastboss_c> = .data:0x00000BC8; // type:object size:0x34
__global_destructor_chain = .bss:0x00000000; // type:object size:0x4 scope:global
lbl_143_bss_8 = .bss:0x00000008; // type:object size:0x10 data:4byte
-lbl_143_bss_18 = .bss:0x00000018; // type:object size:0x40 data:4byte
-lbl_143_bss_58 = .bss:0x00000058; // type:object size:0x80 data:4byte
-lbl_143_bss_D8 = .bss:0x000000D8; // type:object size:0x40 data:4byte
-lbl_143_bss_118 = .bss:0x00000118; // type:object size:0x40 data:4byte
-lbl_143_bss_158 = .bss:0x00000158; // type:object size:0x40 data:4byte
-lbl_143_bss_198 = .bss:0x00000198; // type:object size:0x230 data:4byte
+StateID_Fight__14dAcBlastboss_c = .bss:0x00000018; // type:object size:0x30 data:4byte
+StateID_Guard__14dAcBlastboss_c = .bss:0x00000058; // type:object size:0x30 data:4byte
+StateID_GuardBreak__14dAcBlastboss_c = .bss:0x00000098; // type:object size:0x30 data:4byte
+StateID_Attack__14dAcBlastboss_c = .bss:0x000000D8; // type:object size:0x30 data:4byte
+StateID_CounterAttack__14dAcBlastboss_c = .bss:0x00000118; // type:object size:0x30 data:4byte
+StateID_PunchAttack__14dAcBlastboss_c = .bss:0x00000158; // type:object size:0x30 data:4byte
+StateID_DashAttack__14dAcBlastboss_c = .bss:0x00000198; // type:object size:0x30 data:4byte
+StateID_SmallAttack__14dAcBlastboss_c = .bss:0x000001D8; // type:object size:0x30 data:4byte
+StateID_ThunderAttack__14dAcBlastboss_c = .bss:0x00000218; // type:object size:0x30 data:4byte
+StateID_Damage__14dAcBlastboss_c = .bss:0x00000258; // type:object size:0x30 data:4byte
+StateID_SitDamage__14dAcBlastboss_c = .bss:0x00000298; // type:object size:0x30 data:4byte
+StateID_Down__14dAcBlastboss_c = .bss:0x000002D8; // type:object size:0x30 data:4byte
+StateID_Stun__14dAcBlastboss_c = .bss:0x00000318; // type:object size:0x30 data:4byte
+StateID_ThunderWait__14dAcBlastboss_c = .bss:0x00000358; // type:object size:0x30 data:4byte
+lbl_143_bss_388 = .bss:0x00000388; // type:object size:0x1 data:byte
+lbl_143_bss_38C = .bss:0x0000038C; // type:object size:0x6
+lbl_143_bss_392 = .bss:0x00000392; // type:object size:0x1 data:byte
+lbl_143_bss_394 = .bss:0x00000394; // type:object size:0xC
+lbl_143_bss_3A0 = .bss:0x000003A0; // type:object size:0x1 data:byte
+lbl_143_bss_3A4 = .bss:0x000003A4; // type:object size:0x6
+lbl_143_bss_3AA = .bss:0x000003AA; // type:object size:0x1 data:byte
+lbl_143_bss_3AC = .bss:0x000003AC; // type:object size:0xC
+lbl_143_bss_3B8 = .bss:0x000003B8; // type:object size:0x1 data:byte
+lbl_143_bss_3BC = .bss:0x000003BC; // type:object size:0xC
diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt
index 029135b6..02c56d5e 100644
--- a/config/SOUE01/splits.txt
+++ b/config/SOUE01/splits.txt
@@ -91,8 +91,13 @@ toBeSorted/d_shadow.cpp:
.sbss start:0x80575028 end:0x80575038
.sdata2 start:0x80576A78 end:0x80576B08
-toBeSorted/d_unk_mdl_stuff_1.cpp:
- .text start:0x8001BFA0 end:0x8001E444 align:16
+toBeSorted/d_sword_swing_effect.cpp:
+ .text start:0x8001BFA0 end:0x8001CB9C align:16
+ .data start:0x80500AF0 end:0x80500B48
+ .sdata2 start:0x80576B08 end:0x80576B28
+
+toBeSorted/d_unk_mdl_stuff_3.cpp:
+ .text start:0x8001CBA0 end:0x8001E444 align:16
.ctors start:0x804DB654 end:0x804DB658
.sbss start:0x80575038 end:0x80575058
@@ -396,11 +401,14 @@ toBeSorted/actor_info.cpp:
.rodata start:0x804E0FA8 end:0x804E3418
.sdata2 start:0x805779F8 end:0x80579210
-toBeSorted/unk_vec_math.cpp:
- .text start:0x8006A8D0 end:0x8006B3A4 align:16
+toBeSorted/d_sword_swing_effect_mgr.cpp:
+ .text start:0x8006A8D0 end:0x8006B3C0 align:16
+ .sdata2 start:0x80579210 end:0x80579230
-toBeSorted/unk_mdl_cc.cpp:
- .text start:0x8006B3B0 end:0x8006BBD4 align:16
+toBeSorted/d_enemy_sword_mdl.cpp:
+ .text start:0x8006B3C0 end:0x8006BBD4 align:16
+ .data start:0x8050E060 end:0x8050E090
+ .sdata2 start:0x80579230 end:0x80579238
toBeSorted/d_camera.cpp:
.text start:0x8006BBE0 end:0x80083370 align:16
diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt
index 34c5cbef..e86041fb 100644
--- a/config/SOUE01/symbols.txt
+++ b/config/SOUE01/symbols.txt
@@ -600,7 +600,7 @@ remove__Q23d3d12UnkWithWaterFv = .text:0x800190B0; // type:function size:0xB8
apply__Q23d3d16UnkWithWaterNodeFPC9_GXTexObj = .text:0x80019170; // type:function size:0x74
entry__Q23d3d14EggTextureProcFv = .text:0x800191F0; // type:function size:0x9C
fn_80019290 = .text:0x80019290; // type:function size:0x5C
-fn_800192F0 = .text:0x800192F0; // type:function size:0x6C
+fn_800192F0__Q23d3d14EggTextureProcFUcRC6mMtx_cUc = .text:0x800192F0; // type:function size:0x6C
doDraw__Q23d3d14EggTextureProcFv = .text:0x80019360; // type:function size:0x204
doRemove__Q23d3d14EggTextureProcFv = .text:0x80019570; // type:function size:0x44
create__Q23d3d7UnkProcFiiP12mAllocator_c = .text:0x800195C0; // type:function size:0xAC
@@ -657,20 +657,20 @@ fn_8001BE90 = .text:0x8001BE90; // type:function size:0x60
fn_8001BEF0 = .text:0x8001BEF0; // type:function size:0x58
fn_8001BF50 = .text:0x8001BF50; // type:function size:0x40
fn_8001BF90 = .text:0x8001BF90; // type:function size:0x4
-fn_8001BFA0 = .text:0x8001BFA0; // type:function size:0x54
-fn_8001C000 = .text:0x8001C000; // type:function size:0x40
-fn_8001C040 = .text:0x8001C040; // type:function size:0x30C
-fn_8001C350 = .text:0x8001C350; // type:function size:0x14
-fn_8001C370 = .text:0x8001C370; // type:function size:0x44
-fn_8001C3C0 = .text:0x8001C3C0; // type:function size:0xCC
-fn_8001C490 = .text:0x8001C490; // type:function size:0x18
-fn_8001C4B0 = .text:0x8001C4B0; // type:function size:0x78
-fn_8001C530 = .text:0x8001C530; // type:function size:0x94
-fn_8001C5D0 = .text:0x8001C5D0; // type:function size:0x3E4
-fn_8001C9C0 = .text:0x8001C9C0; // type:function size:0x60
-fn_8001CA20 = .text:0x8001CA20; // type:function size:0x7C
-fn_8001CAA0 = .text:0x8001CAA0; // type:function size:0x80
-fn_8001CB20 = .text:0x8001CB20; // type:function size:0x7C
+remove__27dSwordSwingEffectProcBase_cFv = .text:0x8001BFA0; // type:function size:0x54
+__dt__Q227dSwordSwingEffectProcBase_c11swing_entryFv = .text:0x8001C000; // type:function size:0x40
+drawXlu__27dSwordSwingEffectProcBase_cFv = .text:0x8001C040; // type:function size:0x30C
+hasSwings__27dSwordSwingEffectProcBase_cCFv = .text:0x8001C350; // type:function size:0x14
+entry__27dSwordSwingEffectProcBase_cFv = .text:0x8001C370; // type:function size:0x44
+create__27dSwordSwingEffectProcBase_cFlP12mAllocator_c = .text:0x8001C3C0; // type:function size:0xCC
+__ct__Q227dSwordSwingEffectProcBase_c11swing_entryFv = .text:0x8001C490; // type:function size:0x18
+addSwing__27dSwordSwingEffectProcBase_cFRC7mVec3_c6mColorRC7mVec3_c6mColor = .text:0x8001C4B0; // type:function size:0x78
+calc__27dSwordSwingEffectProcBase_cFf = .text:0x8001C530; // type:function size:0x94
+drawXlu__23dSwordSwingEffectProc_cFv = .text:0x8001C5D0; // type:function size:0x3E4
+create__23dSwordSwingEffectProc_cFlP12mAllocator_cPQ23EGG7ResTIMGf = .text:0x8001C9C0; // type:function size:0x60
+set__Q227dSwordSwingEffectProcBase_c11swing_entryFRC7mVec3_c6mColorRC7mVec3_c6mColor = .text:0x8001CA20; // type:function size:0x7C
+__dt__23dSwordSwingEffectProc_cFv = .text:0x8001CAA0; // type:function size:0x80
+__dt__27dSwordSwingEffectProcBase_cFv = .text:0x8001CB20; // type:function size:0x7C
fn_8001CBA0 = .text:0x8001CBA0; // type:function size:0x20C
fn_8001CDB0 = .text:0x8001CDB0; // type:function size:0x308
fn_8001D0C0 = .text:0x8001D0C0; // type:function size:0x35C
@@ -1134,7 +1134,7 @@ fn_8002EA60 = .text:0x8002EA60; // type:function size:0xD0
fn_8002EB30 = .text:0x8002EB30; // type:function size:0x5C
ActorObjectBase__putInODesert = .text:0x8002EB90; // type:function size:0xD8
drawModelType1__12dAcObjBase_cFPQ23m3d6smdl_c = .text:0x8002EC70; // type:function size:0x60
-fn_8002ECD0 = .text:0x8002ECD0; // type:function size:0x50
+fn_8002ECD0__12dAcObjBase_cFPQ23m3d6smdl_ci = .text:0x8002ECD0; // type:function size:0x50
fn_8002ED20 = .text:0x8002ED20; // type:function size:0x88
fn_8002edb0__12dAcObjBase_cFRQ23m3d15mShadowCircle_cRQ23m3d6smdl_cPC7mQuat_cllf = .text:0x8002EDB0; // type:function size:0x8C
drawShadow__12dAcObjBase_cFRQ23m3d15mShadowCircle_cPvRC6mMtx_cPC7mQuat_clllllf = .text:0x8002EE40; // type:function size:0xFC
@@ -1146,10 +1146,10 @@ createInsectActor__12dAcObjBase_cFP9dAcBase_cQ28fProfile14PROFILE_NAME_eUlP7mVec
createActorUnkGroup3__12dAcObjBase_cFQ28fProfile14PROFILE_NAME_eUlUlP7mVec3_cP7mAng3_cP7mVec3_cUl = .text:0x8002F1C0; // type:function size:0x98
createActorUnkGroup3__12dAcObjBase_cFPCcUlUlPC7mVec3_cPC7mAng3_cPC7mVec3_cUlUsSc = .text:0x8002F260; // type:function size:0xA0
__ct__11dAcEnBase_cFv = .text:0x8002F300; // type:function size:0x74
-ActorEnemyBase__dtor = .text:0x8002F380; // type:function size:0x74
-ActorEnemyBase__shouldUpdateMaybe = .text:0x8002F400; // type:function size:0xB4
-ActorEnemyBase__postUpdate = .text:0x8002F4C0; // type:function size:0x7C
-ActorEnemyBase__preDraw = .text:0x8002F540; // type:function size:0x74
+__dt__11dAcEnBase_cFv = .text:0x8002F380; // type:function size:0x74
+preExecute__11dAcEnBase_cFv = .text:0x8002F400; // type:function size:0xB4
+postExecute__11dAcEnBase_cFQ27fBase_c12MAIN_STATE_e = .text:0x8002F4C0; // type:function size:0x7C
+preDraw__11dAcEnBase_cFv = .text:0x8002F540; // type:function size:0x74
fn_8002F5C0 = .text:0x8002F5C0; // type:function size:0x110
checkBeetleActorReferences__17daPlayerActBase_cFl = .text:0x8002F6D0; // type:function size:0x8
getBeetleActorReferencesSize__17daPlayerActBase_cFv = .text:0x8002F6E0; // type:function size:0x8
@@ -1170,7 +1170,7 @@ fn_8002FBC0 = .text:0x8002FBC0; // type:function size:0x4
fn_8002FBD0 = .text:0x8002FBD0; // type:function size:0x18
fn_8002FBF0 = .text:0x8002FBF0; // type:function size:0x20
fn_8002FC10 = .text:0x8002FC10; // type:function size:0xF4
-someEnemyDamageCollisionStuffMaybe = .text:0x8002FD10; // type:function size:0x7C
+someEnemyDamageCollisionStuffMaybe__11dAcEnBase_cFR19dColliderLinkedListPUs = .text:0x8002FD10; // type:function size:0x7C
fn_8002FD90 = .text:0x8002FD90; // type:function size:0x4C
fn_8002FDE0 = .text:0x8002FDE0; // type:function size:0x170
fn_8002FF50 = .text:0x8002FF50; // type:function size:0xD4
@@ -1188,7 +1188,7 @@ fn_80030820 = .text:0x80030820; // type:function size:0x14
fn_80030840 = .text:0x80030840; // type:function size:0x13C
fn_80030980 = .text:0x80030980; // type:function size:0x188
fn_80030B10 = .text:0x80030B10; // type:function size:0x10C
-fn_80030C20 = .text:0x80030C20; // type:function size:0x28
+fn_80030c20__11dAcEnBase_cFUlffff = .text:0x80030C20; // type:function size:0x28
fn_80030C50 = .text:0x80030C50; // type:function size:0x8
fn_80030C60 = .text:0x80030C60; // type:function size:0x4
fn_80030C70 = .text:0x80030C70; // type:function size:0x4
@@ -1290,7 +1290,7 @@ ActorLink__setObjActorFlags0x200 = .text:0x800346B0; // type:function size:0x14
ActorLink__unsetObjActorFlags0x200 = .text:0x800346D0; // type:function size:0x14
fn_800346F0 = .text:0x800346F0; // type:function size:0xDC
vt_0x2AC__17daPlayerActBase_cFv = .text:0x800347D0; // type:function size:0x4
-triggerMoveEventMaybe__17daPlayerActBase_cFUlUlUlR7mVec3_cRC4mAngUlUl = .text:0x800347E0; // type:function size:0x4
+triggerMoveEventMaybe__17daPlayerActBase_cFUlUlUlPC7mVec3_cRC4mAngUlUl = .text:0x800347E0; // type:function size:0x4
vt_0x2C4__17daPlayerActBase_cFv = .text:0x800347F0; // type:function size:0x8
fn_80034800 = .text:0x80034800; // type:function size:0x170
fn_80034970 = .text:0x80034970; // type:function size:0xFC
@@ -3046,23 +3046,23 @@ getNameForProfileId__FUl = .text:0x8006A670; // type:function size:0xB8
getActorName__FPC9ActorInfo = .text:0x8006A730; // type:function size:0x18
getActorInfoByProfileAndSubtype__FUlUl = .text:0x8006A750; // type:function size:0x134
getSoundSourceTypeForName__FPCc = .text:0x8006A890; // type:function size:0x38
-fn_8006A8D0 = .text:0x8006A8D0; // type:function size:0x1DC
-fn_8006AAB0 = .text:0x8006AAB0; // type:function size:0x85C
-fn_8006B310 = .text:0x8006B310; // type:function size:0x94
-fn_8006B3B0 = .text:0x8006B3B0; // type:function size:0x10
-fn_8006B3C0 = .text:0x8006B3C0; // type:function size:0x140
-fn_8006B500 = .text:0x8006B500; // type:function size:0x13C
-fn_8006B640 = .text:0x8006B640; // type:function size:0x20
-fn_8006B660 = .text:0x8006B660; // type:function size:0xB4
-fn_8006B720 = .text:0x8006B720; // type:function size:0x10
+fn_8006A8D0__FRC7mVec2_cRC7mVec2_cRC7mVec2_cRC7mVec2_cR7mVec2_c = .text:0x8006A8D0; // type:function size:0x1DC
+createSwingEntries__26dSwordSwingEffectProcMgr_cFRC7mVec3_cRC7mVec3_c = .text:0x8006AAB0; // type:function size:0x85C
+calc__26dSwordSwingEffectProcMgr_cFRC7mVec3_cRC7mVec3_c = .text:0x8006B310; // type:function size:0x94
+entry__26dSwordSwingEffectProcMgr_cFv = .text:0x8006B3B0; // type:function size:0x10
+create__16dEnemySwordMdl_cFP12mAllocator_cPvPCcUlRC7mVec3_cRC7mVec3_cR9cCcD_SttsPQ23EGG7ResTIMGiPUl = .text:0x8006B3C0; // type:function size:0x140
+create__16dEnemySwordMdl_cFP12mAllocator_cQ34nw4r3g3d7ResFilePCcUlRC7mVec3_cRC7mVec3_cR9cCcD_SttsPQ23EGG7ResTIMGiPUl = .text:0x8006B500; // type:function size:0x13C
+enableAttack__16dEnemySwordMdl_cFv = .text:0x8006B640; // type:function size:0x20
+fn_8006B660__16dEnemySwordMdl_cFiiiiiiiiif = .text:0x8006B660; // type:function size:0xB4
+setDamageMaybe__16dEnemySwordMdl_cFUc = .text:0x8006B720; // type:function size:0x10
fn_8006B730 = .text:0x8006B730; // type:function size:0x5C
fn_8006B790 = .text:0x8006B790; // type:function size:0x10
-fn_8006B7A0 = .text:0x8006B7A0; // type:function size:0x5C
-fn_8006B800 = .text:0x8006B800; // type:function size:0x10
+fn_8006B7A0__16dEnemySwordMdl_cFUl = .text:0x8006B7A0; // type:function size:0x5C
+fn_8006B800__16dEnemySwordMdl_cFUl = .text:0x8006B800; // type:function size:0x10
fn_8006B810 = .text:0x8006B810; // type:function size:0x5C
fn_8006B870 = .text:0x8006B870; // type:function size:0x10
-fn_8006B880 = .text:0x8006B880; // type:function size:0x2A8
-fn_8006BB30 = .text:0x8006BB30; // type:function size:0xA4
+calc__16dEnemySwordMdl_cFRC6mMtx_cRC7mVec3_cb = .text:0x8006B880; // type:function size:0x2A8
+entry__16dEnemySwordMdl_cFP12dAcObjBase_cP15dShadowCircle_cP7mQuat_c = .text:0x8006BB30; // type:function size:0xA4
fn_8006BBE0 = .text:0x8006BBE0; // type:function size:0x70
fn_8006BC50 = .text:0x8006BC50; // type:function size:0x18
fn_8006BC70 = .text:0x8006BC70; // type:function size:0xA8
@@ -10578,7 +10578,7 @@ isSTIFAreaEldin__11dStageMgr_cCFv = .text:0x80199AA0; // type:function size:0x3C
isSTIFAreaLanayru__11dStageMgr_cCFv = .text:0x80199AE0; // type:function size:0x3C
getSTIFunk1__11dStageMgr_cCFv = .text:0x80199B20; // type:function size:0x20
getSTIFRoomType__11dStageMgr_cCFv = .text:0x80199B40; // type:function size:0x1C
-fn_80199B60 = .text:0x80199B60; // type:function size:0xC
+fn_80199B60__11dStageMgr_cFUc = .text:0x80199B60; // type:function size:0xC
fn_80199B70 = .text:0x80199B70; // type:function size:0x1C
fn_80199B90 = .text:0x80199B90; // type:function size:0x3A8
fn_80199F40 = .text:0x80199F40; // type:function size:0x90
@@ -10737,8 +10737,8 @@ fn_8019E890 = .text:0x8019E890; // type:function size:0x40
fn_8019E8D0 = .text:0x8019E8D0; // type:function size:0x54
fn_8019E930 = .text:0x8019E930; // type:function size:0xC
fn_8019E940 = .text:0x8019E940; // type:function size:0xC0
-fn_8019EA00 = .text:0x8019EA00; // type:function size:0x70
-fn_8019EA70 = .text:0x8019EA70; // type:function size:0x11C
+fn_8019EA00__9dCamera_cFRC7mVec3_cRC7mVec3_cff = .text:0x8019EA00; // type:function size:0x70
+fn_8019EA70__9dCamera_cFb = .text:0x8019EA70; // type:function size:0x11C
fn_8019EB90 = .text:0x8019EB90; // type:function size:0xC
fn_8019EBA0 = .text:0x8019EBA0; // type:function size:0x160
fn_8019ED00 = .text:0x8019ED00; // type:function size:0xC
@@ -15768,7 +15768,7 @@ fn_8029FE90 = .text:0x8029FE90; // type:function size:0x21C
fn_802A00B0 = .text:0x802A00B0; // type:function size:0x10
fn_802A00C0 = .text:0x802A00C0; // type:function size:0x10
fn_802A00D0 = .text:0x802A00D0; // type:function size:0x40
-showBossCaption = .text:0x802A0110; // type:function size:0x158
+show__17dLytBossCaption_cFPCci = .text:0x802A0110; // type:function size:0x158
fn_802A0270 = .text:0x802A0270; // type:function size:0x9C
fn_802A0310 = .text:0x802A0310; // type:function size:0x9C
fn_802A03B0 = .text:0x802A03B0; // type:function size:0x4C
@@ -17264,7 +17264,7 @@ ModuleDestructorsX = .text:0x802DFD30; // type:function size:0x44
cLib__memSet = .text:0x802DFD80; // type:function size:0x4
addCalcPos__4cLibFP7mVec3_cRC7mVec3_cfff = .text:0x802DFD90; // type:function size:0x234
addCalcPosXZ__4cLibFP7mVec3_cRC7mVec3_cfff = .text:0x802DFFD0; // type:function size:0x1B8
-cLib__addCalcPos2 = .text:0x802E0190; // type:function size:0x13C
+addCalcPos2__4cLibFP7mVec3_cRC7mVec3_cff = .text:0x802E0190; // type:function size:0x13C
cLib__addCalcPosXZ2 = .text:0x802E02D0; // type:function size:0xF8
cLib__chasePos = .text:0x802E03D0; // type:function size:0x174
chasePosXZ__4cLibFR7mVec3_cR7mVec3_cf = .text:0x802E0550; // type:function size:0x124
@@ -20536,7 +20536,7 @@ getNextInBgmSoundList__12dSndBgmMgr_cFQ212dSndBgmMgr_c14BgmSoundList_eP14dSndBgm
getLastInBgmSoundList__12dSndBgmMgr_cFQ212dSndBgmMgr_c14BgmSoundList_e = .text:0x80372C20; // type:function size:0x28
fn_80372C50 = .text:0x80372C50; // type:function size:0x8C
fn_80372CE0 = .text:0x80372CE0; // type:function size:0x8C
-fn_80372D70 = .text:0x80372D70; // type:function size:0x74
+fn_80372D70__12dSndBgmMgr_cFi = .text:0x80372D70; // type:function size:0x74
fn_80372DF0 = .text:0x80372DF0; // type:function size:0x40
fn_80372E30 = .text:0x80372E30; // type:function size:0x40
fn_80372E70 = .text:0x80372E70; // type:function size:0xB0
@@ -29953,8 +29953,8 @@ __vt__Q23d3d13AnmMdlWrapper = .data:0x80500A20; // type:object size:0x50
@15227 = .data:0x80500AA8; // type:object size:0x10 scope:local data:string
__vt__14dScnCallback_c = .data:0x80500AB8; // type:object size:0x20
lbl_80500AD8 = .data:0x80500AD8; // type:object size:0x18
-lbl_80500AF0 = .data:0x80500AF0; // type:object size:0x2C
-lbl_80500B1C = .data:0x80500B1C; // type:object size:0x2C
+__vt__23dSwordSwingEffectProc_c = .data:0x80500AF0; // type:object size:0x2C
+__vt__27dSwordSwingEffectProcBase_c = .data:0x80500B1C; // type:object size:0x2C
lbl_80500B48 = .data:0x80500B48; // type:object size:0xA data:string
lbl_80500B54 = .data:0x80500B54; // type:object size:0xA data:string
lbl_80500B60 = .data:0x80500B60; // type:object size:0x40
@@ -42586,7 +42586,7 @@ sInstance__21dLytMiniGameScoreSd_c = .sbss:0x80575984; // type:object size:0x4 d
sInstance__14dLytMiniGame_c = .sbss:0x80575988; // type:object size:0x8 data:4byte
lbl_80575990 = .sbss:0x80575990; // type:object size:0x8 data:4byte
lbl_80575998 = .sbss:0x80575998; // type:object size:0x8 data:4byte
-BOSS_CAPTION_PTR = .sbss:0x805759A0; // type:object size:0x8 data:4byte
+sInstance__17dLytBossCaption_c = .sbss:0x805759A0; // type:object size:0x8 data:4byte
sInstance__17dLytDemoDowsing_c = .sbss:0x805759A8; // type:object size:0x8 data:4byte
lbl_805759B0 = .sbss:0x805759B0; // type:object size:0x2 data:2byte
sInstance__10dLytShop_c = .sbss:0x805759B4; // type:object size:0x4 data:4byte
@@ -42661,7 +42661,7 @@ l_lightMgr_pp__Q23m3d8internal = .sbss:0x80575BDC; // type:object size:0x4 data:
l_numFogMgr__Q23m3d8internal = .sbss:0x80575BE0; // type:object size:0x4 data:4byte
l_fogMgr_pp__Q23m3d8internal = .sbss:0x80575BE4; // type:object size:0x4 data:4byte
l_alignment__Q23m3d8internal = .sbss:0x80575BE8; // type:object size:0x4 data:4byte
-lbl_80575BF0 = .sbss:0x80575BF0; // type:object size:0x4 data:4byte
+sInstance__Q23m3d9mShadow_c = .sbss:0x80575BF0; // type:object size:0x4 data:4byte
lbl_80575BF4 = .sbss:0x80575BF4; // type:object size:0x4 data:4byte
lbl_80575BF8 = .sbss:0x80575BF8; // type:object size:0x4 data:4byte
@GUARD@draw__Q23m3d15mCustomShadow_cFRC6mMtx_c@nullMat = .sbss:0x80575BFC; // type:object size:0x1 data:byte
diff --git a/configure.py b/configure.py
index 51409cd2..86ce4cf8 100644
--- a/configure.py
+++ b/configure.py
@@ -427,7 +427,8 @@ config.libs = [
),
Object(NonMatching, "toBeSorted/d_unk_proc.cpp"),
Object(NonMatching, "toBeSorted/d_shadow.cpp"),
- Object(NonMatching, "toBeSorted/d_unk_mdl_stuff_1.cpp"),
+ Object(Matching, "toBeSorted/d_sword_swing_effect.cpp"),
+ Object(NonMatching, "toBeSorted/d_unk_mdl_stuff_3.cpp"),
Object(NonMatching, "toBeSorted/d_unk_mdl_stuff_2.cpp"),
Object(Matching, "d/d_light_env.cpp"),
Object(NonMatching, "toBeSorted/d_emitter.cpp"),
@@ -481,8 +482,8 @@ config.libs = [
Object(Matching, "toBeSorted/arc_managers/layout_arc_manager.cpp"),
Object(NonMatching, "toBeSorted/arc_managers/layout_arc_control.cpp"),
Object(Matching, "toBeSorted/actor_info.cpp"),
- Object(NonMatching, "toBeSorted/unk_vec_math.cpp"),
- Object(NonMatching, "toBeSorted/unk_mdl_cc.cpp"),
+ Object(NonMatching, "toBeSorted/d_sword_swing_effect_mgr.cpp"),
+ Object(NonMatching, "toBeSorted/d_enemy_sword_mdl.cpp"),
Object(NonMatching, "toBeSorted/d_camera.cpp"),
Object(NonMatching, "toBeSorted/d_event_1.cpp"),
Object(NonMatching, "toBeSorted/unk_map_cam.cpp"),
diff --git a/include/d/a/b/d_a_b_lastboss.h b/include/d/a/b/d_a_b_lastboss.h
index 1d01a3f3..e1100d0f 100644
--- a/include/d/a/b/d_a_b_lastboss.h
+++ b/include/d/a/b/d_a_b_lastboss.h
@@ -2,14 +2,286 @@
#define D_A_B_LASTBOSS_H
#include "d/a/e/d_a_en_base.h"
+#include "d/d_cc.h"
+#include "d/d_light_env.h"
+#include "m/m3d/m_anmmatclr.h"
+#include "m/m3d/m_anmtexsrt.h"
+#include "m/m3d/m_mdl.h"
+#include "m/m3d/m_smdl.h"
+#include "m/m_angle.h"
+#include "m/m_vec.h"
#include "s/s_State.hpp"
-#include "s/s_StateMgr.hpp"
+#include "toBeSorted/d_emitter.h"
+#include "toBeSorted/d_enemy_sword_mdl.h"
+#include "toBeSorted/stage_render_stuff.h"
+
+class dTgSwordBattleGame_c;
+
+// TODO this might be a template but what about the offset?
+struct UnkLastBossCcSph1 {
+ /* 0x000 */ u8 _0x000[0x002 - 0x000];
+ /* 0x002 */ s16 field_0x002;
+ /* 0x004 */ s16 field_0x004;
+ /* 0x006 */ s16 field_0x006;
+ /* 0x008 */ mVec3_c field_0x008[5];
+ /* 0x044 */ mVec3_c field_0x044[5];
+ /* 0x080 */ mVec3_c field_0x080[5];
+ /* 0x0BC */ dCcD_Linked_Sph mCc;
+};
+
+struct UnkLastBossCcSph2 {
+ /* 0x000 */ s16 field_0x000;
+ /* 0x002 */ s16 field_0x002;
+ /* 0x004 */ s16 field_0x004;
+ /* 0x006 */ s16 field_0x006;
+ /* 0x008 */ s16 field_0x008;
+ /* 0x00A */ s16 field_0x00A;
+ /* 0x00C */ f32 field_0x00C;
+ /* 0x010 */ f32 field_0x010;
+ /* 0x014 */ mVec3_c field_0x014[10];
+ /* 0x08C */ mVec3_c field_0x08C[10];
+ /* 0x104 */ mVec3_c field_0x104[10];
+ /* 0x17C */ dCcD_Linked_Sph mCc;
+};
class dAcBlastboss_c : public dAcEnBase_c {
+ class callback_c : public m3d::callback_c {
+ public:
+ virtual void timingB(u32, nw4r::g3d::WorldMtxManip *, nw4r::g3d::ResMdl) override;
+
+ /* 0x04 */ mAng field_0x04;
+ /* 0x06 */ mAng field_0x06;
+ /* 0x08 */ mAng field_0x08;
+ /* 0x0A */ mAng field_0x0A;
+ /* 0x0C */ mAng field_0x0C;
+ /* 0x0E */ mAng field_0x0E;
+ /* 0x10 */ mAng field_0x10;
+ /* 0x12 */ mAng field_0x12;
+ /* 0x14 */ mAng field_0x14;
+ /* 0x16 */ mAng field_0x16;
+ /* 0x18 */ mAng field_0x18;
+ /* 0x1A */ mAng field_0x1A;
+ /* 0x1C */ mAng field_0x1C[9];
+ /* 0x2E */ mAng field_0x2E;
+ /* 0x30 */ f32 field_0x30;
+ /* 0x34 */ dAcBlastboss_c *mpOwner;
+ };
+
+ friend class callback_c;
+
+ // BLastBoss.arc > g3d > model.brres > 3DModels(NW4R) > LastBoss > Bones > ...
+ enum BLastBossModelNode_e {
+ B_LAST_BOSS_NODE_center = 0,
+ B_LAST_BOSS_NODE_backbone1 = 1,
+ B_LAST_BOSS_NODE_backbone2 = 2,
+ B_LAST_BOSS_NODE_chest = 3,
+ B_LAST_BOSS_NODE_neck = 4,
+ B_LAST_BOSS_NODE_head = 5,
+ B_LAST_BOSS_NODE_browL = 6,
+ B_LAST_BOSS_NODE_browR = 7,
+ B_LAST_BOSS_NODE_chin = 8,
+ B_LAST_BOSS_NODE_hairA1 = 9,
+ B_LAST_BOSS_NODE_hairA2 = 10,
+ B_LAST_BOSS_NODE_hairA3 = 11,
+ B_LAST_BOSS_NODE_hairA4 = 12,
+ B_LAST_BOSS_NODE_hairBL1 = 13,
+ B_LAST_BOSS_NODE_hairBL2 = 14,
+ B_LAST_BOSS_NODE_hairBL3 = 15,
+ B_LAST_BOSS_NODE_hairBR1 = 16,
+ B_LAST_BOSS_NODE_hairBR2 = 17,
+ B_LAST_BOSS_NODE_hairBR3 = 18,
+ B_LAST_BOSS_NODE_hairC1 = 19,
+ B_LAST_BOSS_NODE_hairC2 = 20,
+ B_LAST_BOSS_NODE_hairC3 = 21,
+ B_LAST_BOSS_NODE_mouthL = 22,
+ B_LAST_BOSS_NODE_mouthR = 23,
+ B_LAST_BOSS_NODE_shoulderL = 24,
+ B_LAST_BOSS_NODE_armL1 = 25,
+ B_LAST_BOSS_NODE_armL2 = 26,
+ B_LAST_BOSS_NODE_assistanceL = 27,
+ B_LAST_BOSS_NODE_wristL = 28,
+ B_LAST_BOSS_NODE_indexL1 = 29,
+ B_LAST_BOSS_NODE_indexL2 = 30,
+ B_LAST_BOSS_NODE_littleL1 = 31,
+ B_LAST_BOSS_NODE_littleL2 = 32,
+ B_LAST_BOSS_NODE_middleL1 = 33,
+ B_LAST_BOSS_NODE_middleL2 = 34,
+ B_LAST_BOSS_NODE_ringL1 = 35,
+ B_LAST_BOSS_NODE_ringL2 = 36,
+ B_LAST_BOSS_NODE_thumbL1 = 37,
+ B_LAST_BOSS_NODE_thumbL2 = 38,
+ B_LAST_BOSS_NODE_shoulderR = 39,
+ B_LAST_BOSS_NODE_armR1 = 40,
+ B_LAST_BOSS_NODE_armR2 = 41,
+ B_LAST_BOSS_NODE_assistanceR = 42,
+ B_LAST_BOSS_NODE_wristR = 43,
+ B_LAST_BOSS_NODE_indexR1 = 44,
+ B_LAST_BOSS_NODE_indexR2 = 45,
+ B_LAST_BOSS_NODE_littleR1 = 46,
+ B_LAST_BOSS_NODE_littleR2 = 47,
+ B_LAST_BOSS_NODE_loc_sword01 = 48,
+ B_LAST_BOSS_NODE_middleR1 = 49,
+ B_LAST_BOSS_NODE_middleR2 = 50,
+ B_LAST_BOSS_NODE_ringR1 = 51,
+ B_LAST_BOSS_NODE_ringR2 = 52,
+ B_LAST_BOSS_NODE_thumbR1 = 53,
+ B_LAST_BOSS_NODE_thumbR2 = 54,
+ B_LAST_BOSS_NODE_belly = 55,
+ B_LAST_BOSS_NODE_waist = 56,
+ B_LAST_BOSS_NODE_legL1 = 57,
+ B_LAST_BOSS_NODE_legL2 = 58,
+ B_LAST_BOSS_NODE_ankleL = 59,
+ B_LAST_BOSS_NODE_toeL = 60,
+ B_LAST_BOSS_NODE_legR1 = 61,
+ B_LAST_BOSS_NODE_legR2 = 62,
+ B_LAST_BOSS_NODE_ankleR = 63,
+ B_LAST_BOSS_NODE_toeR = 64,
+ B_LAST_BOSS_NODE_skirtA1 = 65,
+ B_LAST_BOSS_NODE_skirtA2 = 66,
+ B_LAST_BOSS_NODE_skirtAU1 = 67,
+ B_LAST_BOSS_NODE_skirtB1 = 68,
+ B_LAST_BOSS_NODE_skirtB2 = 69,
+ B_LAST_BOSS_NODE_skirtB3 = 70,
+ B_LAST_BOSS_NODE_skirtB4 = 71,
+ B_LAST_BOSS_NODE_skirtB5 = 72,
+ B_LAST_BOSS_NODE_skirtB6 = 73,
+ B_LAST_BOSS_NODE_skirtB7 = 74,
+ B_LAST_BOSS_NODE_skirtB8 = 75,
+ B_LAST_BOSS_NODE_skirtB9 = 76,
+ B_LAST_BOSS_NODE_skirtBU1 = 77,
+ B_LAST_BOSS_NODE_skirtC1 = 78,
+ B_LAST_BOSS_NODE_skirtC2 = 79,
+ B_LAST_BOSS_NODE_skirtC3 = 80,
+ B_LAST_BOSS_NODE_skirtC4 = 81,
+ B_LAST_BOSS_NODE_skirtC5 = 82,
+ B_LAST_BOSS_NODE_skirtC6 = 83,
+ B_LAST_BOSS_NODE_skirtC7 = 84,
+ B_LAST_BOSS_NODE_skirtC8 = 85,
+ B_LAST_BOSS_NODE_skirtC9 = 86,
+ B_LAST_BOSS_NODE_skirtCU1 = 87,
+ B_LAST_BOSS_NODE_skirtD1 = 88,
+ B_LAST_BOSS_NODE_skirtD2 = 89,
+ B_LAST_BOSS_NODE_skirtD3 = 90,
+ B_LAST_BOSS_NODE_skirtD4 = 91,
+ B_LAST_BOSS_NODE_skirtD5 = 92,
+ B_LAST_BOSS_NODE_skirtD6 = 93,
+ B_LAST_BOSS_NODE_skirtD7 = 94,
+ B_LAST_BOSS_NODE_skirtD8 = 95,
+ B_LAST_BOSS_NODE_skirtD9 = 96,
+ B_LAST_BOSS_NODE_skirtDU1 = 97,
+ B_LAST_BOSS_NODE_skirtE1 = 98,
+ B_LAST_BOSS_NODE_skirtE2 = 99,
+ B_LAST_BOSS_NODE_skirtE3 = 100,
+ B_LAST_BOSS_NODE_skirtE4 = 101,
+ B_LAST_BOSS_NODE_skirtE5 = 102,
+ B_LAST_BOSS_NODE_skirtE6 = 103,
+ B_LAST_BOSS_NODE_skirtE7 = 104,
+ B_LAST_BOSS_NODE_skirtE8 = 105,
+ B_LAST_BOSS_NODE_skirtE9 = 106,
+ B_LAST_BOSS_NODE_skirtEU1 = 107,
+ B_LAST_BOSS_NODE_skirtEU2 = 108,
+ B_LAST_BOSS_NODE_skirtF1 = 109,
+ B_LAST_BOSS_NODE_skirtF2 = 110,
+ B_LAST_BOSS_NODE_skirtF3 = 111,
+ B_LAST_BOSS_NODE_skirtF4 = 112,
+ B_LAST_BOSS_NODE_skirtF5 = 113,
+ B_LAST_BOSS_NODE_skirtF6 = 114,
+ B_LAST_BOSS_NODE_skirtF7 = 115,
+ B_LAST_BOSS_NODE_skirtF8 = 116,
+ B_LAST_BOSS_NODE_skirtF9 = 117,
+ B_LAST_BOSS_NODE_skirtFU1 = 118,
+ B_LAST_BOSS_NODE_skirtG1 = 119,
+ B_LAST_BOSS_NODE_skirtG2 = 120,
+ B_LAST_BOSS_NODE_skirtG3 = 121,
+ B_LAST_BOSS_NODE_skirtG4 = 122,
+ B_LAST_BOSS_NODE_skirtG5 = 123,
+ B_LAST_BOSS_NODE_skirtG6 = 124,
+ B_LAST_BOSS_NODE_skirtG7 = 125,
+ B_LAST_BOSS_NODE_skirtG8 = 126,
+ B_LAST_BOSS_NODE_skirtG9 = 127,
+ B_LAST_BOSS_NODE_skirtGU1 = 128,
+ B_LAST_BOSS_NODE_skirtH1 = 129,
+ B_LAST_BOSS_NODE_skirtH2 = 130,
+ B_LAST_BOSS_NODE_skirtH3 = 131,
+ B_LAST_BOSS_NODE_skirtH4 = 132,
+ B_LAST_BOSS_NODE_skirtH5 = 133,
+ B_LAST_BOSS_NODE_skirtHU1 = 134,
+ };
+
+ // TODO: mFightState probably means different things in
+ // different states, so maybe we need to either remove
+ // this again or split this up further.
+ enum SubState_e {
+ SUB_STATE_0 = 0,
+ SUB_STATE_1,
+ SUB_STATE_2,
+ SUB_STATE_3,
+ SUB_STATE_4,
+ SUB_STATE_5,
+ SUB_STATE_6,
+
+ SUB_STATE_10 = 10,
+ SUB_STATE_11,
+
+ SUB_STATE_20 = 20,
+ SUB_STATE_21,
+
+ SUB_STATE_50 = 50,
+ };
+
+ enum Timer_e {
+ TIMER_0,
+ TIMER_1,
+ TIMER_2,
+ TIMER_3,
+ TIMER_4,
+ TIMER_5,
+
+ TIMER_MAX,
+ };
+
+ // TODO: Maybe reused in other sword fight bosses?
+ // Names taken from the string array
+ enum GuardDirection_e {
+ GUARD_RIGHT,
+ GUARD_UPRIGHT,
+ GUARD_DOWNRIGHT,
+ GUARD_LEFT,
+ GUARD_UPLEFT,
+ GUARD_DOWNLEFT,
+ GUARD_UP,
+ GUARD_DOWN,
+ GUARD_CENTER,
+ GUARD_BT, // not sure
+ };
+
+ enum LightningState_e {
+ LIGHTNING_STRIKE_STATE_NONE = 0,
+
+ LIGHTNING_STRIKE_START_DEMO = 1,
+ LIGHTNING_STRIKE_DEMO,
+ LIGHTNING_STRIKE_WAIT,
+
+ LIGHTNING_STRIKE_TRIGGER_END = 100,
+ LIGHTNING_STRIKE_ENDING,
+
+ LIGHTNING_STRIKE_TRIGGER_START = 200,
+ LIGHTNING_STRIKE_START,
+ LIGHTNING_STRIKE_START_LAST = 299,
+
+ LIGHTNING_STRIKE_FINISH = 1000,
+ };
+
public:
- dAcBlastboss_c() : mStateMgr(*this, sStateID::null) {}
+ dAcBlastboss_c() : mStateMgr(*this, sStateID::null), mScnCallback(this) {}
virtual ~dAcBlastboss_c() {}
+ virtual bool createHeap() override;
+ int create() override;
+ int doDelete() override;
+ int actorExecute() override;
+ int draw() override;
+
STATE_FUNC_DECLARE(dAcBlastboss_c, Fight);
STATE_FUNC_DECLARE(dAcBlastboss_c, Guard);
STATE_FUNC_DECLARE(dAcBlastboss_c, GuardBreak);
@@ -26,7 +298,157 @@ public:
STATE_FUNC_DECLARE(dAcBlastboss_c, ThunderWait);
private:
- /* 0x??? */ STATE_MGR_DECLARE(dAcBlastboss_c);
+ void setAnm(const char *anim, f32 blend);
+ void forceSetAnm(const char *anim, f32 blend);
+ void setAnmRate(f32 rate);
+
+ bool checkDamage();
+ bool checkForCloseRangeAttack();
+ bool checkForRangeAttack();
+ bool checkForCounter();
+ void updateMainNodeTransforms();
+ void updateSkirtHairTransforms();
+ void updateSkirtTransform(s32 level);
+ void updateHairTransform(s32 level);
+ bool checkForLinkSwordBySwordHit();
+ u8 classifyAttackDirection(s32 attackDir);
+ void executeLightningStrike();
+ void setLightningTimerMaybe(s32);
+
+ /* 0x0378 */ d3d::AnmMdlWrapper mMdl;
+ /* 0x03E8 */ m3d::anmTexSrt_c mAnmTexSrt;
+ /* 0x0414 */ m3d::anmMatClr_c mAnmMatClr1;
+ /* 0x0440 */ m3d::smdl_c mThunderMdl;
+ /* 0x045C */ m3d::anmMatClr_c mThunderAnmMatClr;
+ /* 0x0488 */ callback_c mMdlCallback;
+ /* 0x04C0 */ dCcD_Linked_Cyl mCc1;
+ /* 0x0620 */ dCcD_Linked_Cyl mCc2;
+ /* 0x0780 */ dCcD_Linked_Cyl mCc3;
+ /* 0x08E0 */ dCcD_Linked_Sph mCc4;
+ /* 0x0A40 */ dCcD_Linked_Sph mLightningCc;
+ /* 0x0BA0 */ dScnCallback_c mScnCallback;
+ /* 0x0BAC */ STATE_MGR_DECLARE(dAcBlastboss_c);
+ /* 0x0BE8 */ dColliderLinkedList mCcList;
+ /* 0x0BF4 */ dEnemySwordMdl_c mSwordMdl;
+ /* 0x1130 */ u8 mThunderWaitSceneFlag;
+ /* 0x1131 */ u8 field_0x1131;
+ /* 0x1132 */ bool field_0x1132;
+ /* 0x1133 */ u8 field_0x1133;
+ /* 0x1134 */ u8 field_0x1134;
+ /* 0x1135 */ s8 mNumConsecutiveOppositeDirectionAttacks;
+ /* 0x1136 */ s8 mNumConsecutiveSameDirectionAttacks;
+ /* 0x1137 */ u8 field_0x1137;
+ /* 0x1138 */ u8 field_0x1138;
+ /* 0x1139 */ u8 field_0x1139;
+ /* 0x113A */ u8 mChanceAttackCounter;
+ /* 0x113B */ u8 field_0x113B;
+ /* 0x113C */ u8 mChanceCounter;
+ /* 0x113D */ u8 field_0x113D;
+ /* 0x113E */ u8 field_0x113E;
+ /* 0x113F */ u8 field_0x113F;
+ /* 0x1140 */ bool field_0x1140;
+ /* 0x1141 */ bool mIsDown;
+ /* 0x1142 */ u8 field_0x1142;
+ /* 0x1143 */ u8 mInvulnerabilityTimerMaybe;
+ /* 0x1144 */ s8 mGuardDirection;
+ /* 0x1145 */ s8 mLinkCloseRangeShieldTime;
+ /* 0x1146 */ bool mIsSwordEmpowered;
+ /* 0x1147 */ bool mIsThunderBeamAttackActive;
+ /* 0x1148 */ u8 mThunderBeamTimer;
+ /* 0x1149 */ s8 mIsPhaseTwo;
+ /* 0x114A */ u8 mLightingFallSwordTimer;
+ /* 0x114B */ u8 mStunState;
+ /* 0x114C */ u8 field_0x114C;
+ /* 0x114D */ bool mInBossRush;
+ /* 0x114E */ u8 field_0x114E;
+ /* 0x114F */ bool mIsDead;
+ /* 0x1150 */ bool mThunderBeamReflected;
+ /* 0x1152 */ u16 field_0x1152;
+ /* 0x1154 */ u16 mStunCounter;
+ /* 0x1156 */ u16 mTimers[TIMER_MAX];
+ /* 0x1162 */ u16 field_0x1162;
+ /* 0x1164 */ s16 mCounter;
+ /* 0x1166 */ s16 mSubState;
+
+ /* 0x1168 */ u8 _0x1168[0x116A - 0x1168];
+
+ /* 0x116A */ s16 mYAngleToLink;
+
+ /* 0x116C */ u8 _0x116C[0x1170 - 0x116C];
+
+ /* 0x1170 */ s16 field_0x1170;
+ /* 0x1172 */ s16 field_0x1172;
+ /* 0x1174 */ s16 field_0x1174;
+
+ /* 0x1176 */ u8 _0x1176[0x1178 - 0x1176];
+
+ /* 0x1178 */ s16 field_0x1178;
+ /* 0x117A */ s16 field_0x117A;
+ /* 0x117C */ s16 field_0x117C;
+ /* 0x117E */ s16 field_0x117E;
+ /* 0x1180 */ s16 field_0x1180;
+ /* 0x1182 */ s16 field_0x1182;
+ /* 0x1184 */ s16 mLightningTimerMaybe;
+ /* 0x1186 */ s16 mYRotationRelativeToLink;
+ /* 0x1188 */ s16 field_0x1188;
+ /* 0x118A */ mAng field_0x118A;
+ /* 0x118C */ mAng field_0x118C;
+
+ /* 0x118E */ u8 _0x118E[0x1190 - 0x118E];
+
+ /* 0x1190 */ f32 mXZDistanceToLink;
+
+ /* 0x1194 */ u8 _0x1194[0x119C - 0x1194];
+
+ /* 0x119C */ f32 mAttackKnockbackX;
+ /* 0x11A0 */ f32 mAttackKnockbackZ;
+ /* 0x11A4 */ f32 field_0x11A4;
+ /* 0x11A8 */ f32 mAnmRate;
+ /* 0x11AC */ f32 field_0x11AC;
+ /* 0x11B0 */ f32 field_0x11B0;
+ /* 0x11B0 */ f32 field_0x11B4;
+ /* 0x11B8 */ f32 field_0x11B8;
+ /* 0x11BC */ f32 field_0x11BC;
+ /* 0x11C0 */ f32 field_0x11C0;
+ /* 0x11C4 */ f32 field_0x11C4;
+ /* 0x11C8 */ f32 field_0x11C8;
+ /* 0x11CC */ f32 field_0x11CC;
+ /* 0x11D0 */ f32 field_0x11D0;
+ /* 0x11D4 */ s32 mLastAttackDir;
+ /* 0x11D8 */ s32 mSecondLastAttackDirection;
+ /* 0x11DC */ mAng3_c mThunderBeamRotation;
+ /* 0x11E4 */ mVec3_c mThumbL2Translation;
+ /* 0x11F0 */ mVec3_c mBackbone1Translation;
+ /* 0x11FC */ mVec3_c mChestTranslation;
+ /* 0x1208 */ mVec3_c mSwordPosition;
+ /* 0x1214 */ mVec3_c mBugNetPos;
+ /* 0x1220 */ mVec3_c mThunderBeamPosition;
+ /* 0x122C */ mVec3_c mThunderBeamVelocity;
+ /* 0x1238 */ mVec3_c mToeTranslation[2];
+ /* 0x1250 */ mVec3_c field_0x1250[2];
+
+ /* 0x1268 */ UnkLastBossCcSph2 field_0x1268[8];
+ /* 0x2948 */ UnkLastBossCcSph1 field_0x2948[1];
+
+ /* 0x2B64 */ dEmitter_c mWaterEmitter;
+ /* 0x2B98 */ dEmitter_c mEmitter2;
+ /* 0x2BCC */ dEmitter_c mEmitter3;
+ /* 0x2C00 */ dEmitter_c mEmitter4;
+ /* 0x2C34 */ dEmitter_c mEmitter5;
+ /* 0x2C68 */ dEmitter_c mEmitter6;
+ /* 0x2C9C */ dEmitter_c mEmitter7;
+ /* 0x2CD0 */ LIGHT_INFLUENCE mLightInfo;
+ /* 0x2CEC */ s16 mLightingStrikeState;
+ /* 0x2CEE */ s16 field_0x2CEE;
+ /* 0x2CF0 */ s16 field_0x2CF0;
+ /* 0x2CF4 */ f32 field_0x2CF4;
+ /* 0x2CF8 */ u8 _0x2CF8[0x2CFC - 0x2CF8];
+ /* 0x2CFC */ f32 field_0x2CFC;
+ /* 0x2D00 */ f32 field_0x2D00;
+ /* 0x2D04 */ mVec3_c field_0x2D04;
+ /* 0x2D10 */ mVec3_c field_0x2D10;
+ /* 0x2D1C */ const char *mpCurrentAnm;
+ /* 0x2D20 */ dTgSwordBattleGame_c *mpSwordBattleGame;
};
#endif
diff --git a/include/d/a/e/d_a_en_base.h b/include/d/a/e/d_a_en_base.h
index 10cb60d1..328992a1 100644
--- a/include/d/a/e/d_a_en_base.h
+++ b/include/d/a/e/d_a_en_base.h
@@ -4,6 +4,7 @@
#include "common.h"
#include "d/a/obj/d_a_obj_base.h"
#include "d/a/obj/d_a_obj_bomb.h"
+#include "d/d_cc.h"
#include "m/m_angle.h"
#include "m/m_vec.h"
@@ -16,9 +17,21 @@ struct dAcEnData {
// non-official name
class dAcEnBase_c : public dAcObjBase_c {
public:
+ enum InteractionFlags_e {
+ INTERACT_0x1 = (1 << 0),
+ INTERACT_0x4 = (1 << 2),
+ INTERACT_0x40 = (1 << 6),
+ INTERACT_0x1000 = (1 << 12),
+ };
+
+public:
dAcEnBase_c();
virtual ~dAcEnBase_c();
+ virtual int preExecute() override;
+ virtual void postExecute(MAIN_STATE_e state) override;
+ virtual int preDraw() override;
+
virtual void *getObjectListEntry() override {
return &mEnemyLink;
}
@@ -36,7 +49,9 @@ public:
/* 0x33C */ u32 mInteractionFlags;
/* 0x340 */ u16 field_0x338;
/* 0x342 */ u16 mHealth;
- /* 0x344 */ u8 _344[0x374 - 0x344];
+ /* 0x344 */ u8 _344[0x358 - 0x344];
+ /* 0x358 */ mVec3_c mFinalBlowPosition;
+ /* 0x364 */ u8 _364[0x374 - 0x364];
/* 0x374 */ dAcEnData *mpEnemyData;
bool checkInteractionFlags(u32 mask) {
@@ -62,6 +77,8 @@ public:
void fn_80030700();
void fn_80030c20(u32 flags, f32, f32, f32, f32);
+ s32 someEnemyDamageCollisionStuffMaybe(dColliderLinkedList &list, u16 *pOutFlags);
+
bool ChkCrossPlayer(f32 height);
protected:
diff --git a/include/d/a/obj/d_a_obj_base.h b/include/d/a/obj/d_a_obj_base.h
index 6b798af5..57f1222a 100644
--- a/include/d/a/obj/d_a_obj_base.h
+++ b/include/d/a/obj/d_a_obj_base.h
@@ -197,6 +197,7 @@ public:
void fn_8002EA60(void *);
void fn_8002EB30(void *);
void putInODesert(f32 depth, mVec3_c *position);
+ void fn_8002ECD0(m3d::smdl_c *smdl, UNKWORD);
// Disabling makes Items and Link Disappear
void drawModelType1(m3d::smdl_c *smdl);
// Disabling make Lava and other objects Disappear
@@ -220,11 +221,11 @@ public:
fProfile::PROFILE_NAME_e actorId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale, u32 params2,
u32 roomId
);
-
+
// These may not belong here
- static dAcBase_c* createInsectActor(
- dAcBase_c* parent,
- fProfile::PROFILE_NAME_e actorId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale, u32 params2, s32 roomId
+ static dAcBase_c *createInsectActor(
+ dAcBase_c *parent, fProfile::PROFILE_NAME_e actorId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale,
+ u32 params2, s32 roomId
);
static dAcBase_c *createActorUnkGroup3(
fProfile::PROFILE_NAME_e actorId, u32 roomId, u32 params1, mVec3_c *pos, mAng3_c *rot, mVec3_c *scale,
@@ -243,6 +244,16 @@ public:
if (!result) \
return result; \
} while (0)
+
+// Actors' createHeap functions often have patterns that can be matched with this macro
+// `bool result;` needs to be defined in scope prior to use
+#define TRY_CREATE2(thing) \
+ do { \
+ result = (thing); \
+ if (!result) \
+ return result; \
+ } while (0)
+
// Use this in actors' create functions
#define CREATE_ALLOCATOR(className) \
do { \
diff --git a/include/d/col/c/c_cc_d.h b/include/d/col/c/c_cc_d.h
index 7e51421a..b4f7f4f2 100644
--- a/include/d/col/c/c_cc_d.h
+++ b/include/d/col/c/c_cc_d.h
@@ -836,7 +836,14 @@ public:
void OffAtGrp(u32 grp) {
mAt.SetAtFlag(GetAtGrp() & ~grp);
}
+ void SetTgRpm(u32 f) {
+ mTg.SetRPrm(f);
+ }
+ void SetAtRpm(u32 f) {
+ mAt.SetRPrm(f);
+ }
+ // Related to directional attacks?
void SetTgFlag_0xA(u16 flag) {
mTg.SetFlag_0xA(flag);
}
@@ -878,7 +885,9 @@ public:
return mTg.ChkSet();
}
-
+ void ClrAtActorInfo() { mAt.ClrActorInfo(); }
+ void ClrTgActorInfo() { mTg.ClrActorInfo(); }
+ void ClrCoActorInfo() { mCo.ClrActorInfo(); }
bool ChkAtEffCounter() { return mAt.ChkEffCounter(); }
bool ChkTgEffCounter() { return mTg.ChkEffCounter(); }
void ClrAtEffCounter() { mAt.ClrEffCounter(); }
@@ -978,9 +987,18 @@ public:
void OnTgElectric() {
return mTg.OnSPrm(0x40000);
}
+ void OnTg_0x8000000() {
+ return mTg.OnSPrm(0x8000000);
+ }
void ClrTgElectric() {
return mTg.OffSPrm(0x40000);
}
+ void ClrTg_0x10000() {
+ return mTg.OffSPrm(0x10000);
+ }
+ void ClrTg_0x8000000() {
+ return mTg.OffSPrm(0x8000000);
+ }
u32 ChkTgBonk() const {
return mTg.MskSPrm(0x200000);
}
diff --git a/include/d/col/cc/d_cc_d.h b/include/d/col/cc/d_cc_d.h
index 88dff6b7..4af5b6ff 100644
--- a/include/d/col/cc/d_cc_d.h
+++ b/include/d/col/cc/d_cc_d.h
@@ -18,6 +18,7 @@ public:
virtual cCcD_ShapeAttr *GetShapeAttr() override;
using cM3dGCps::Set;
+ using cM3dGLin::Set;
void Set(const dCcD_SrcCps &src);
void unknownCalc();
};
diff --git a/include/d/d_camera.h b/include/d/d_camera.h
index 8f4560a0..059647ba 100644
--- a/include/d/d_camera.h
+++ b/include/d/d_camera.h
@@ -61,9 +61,11 @@ public:
bool isUnderwater() const;
f32 getUnderwaterDepth() const;
+ void fn_8019EA00(const mVec3_c&, const mVec3_c&, f32, f32);
void fn_8019E430();
void fn_8019E410();
mAng fn_8019E3B0() const;
+ void fn_8019EA70(bool);
private:
/* 0x068 */ u8 _0x068[0x6C - 0x068];
diff --git a/include/d/d_cc.h b/include/d/d_cc.h
index c5349190..c06a35e5 100644
--- a/include/d/d_cc.h
+++ b/include/d/d_cc.h
@@ -27,15 +27,14 @@ public:
/* 0x210 */ LinkedColliderNode mNode;
};
-class dCcD_Linked_Cyl : public dCcD_Cyl {
+class dCcD_Linked_Cps : public dCcD_Cps {
public:
- dCcD_Linked_Cyl() : mNode(this) {}
- virtual ~dCcD_Linked_Cyl() {
+ dCcD_Linked_Cps() : mNode(this) {}
+ virtual ~dCcD_Linked_Cps() {
mNode.remove();
}
- /* 0x150 */ LinkedColliderNode mNode;
+ /* 0x170 */ LinkedColliderNode mNode;
};
-
class dCcD_Linked_Sph : public dCcD_Sph {
public:
dCcD_Linked_Sph() : mNode(this) {}
@@ -44,14 +43,13 @@ public:
}
/* 0x150 */ LinkedColliderNode mNode;
};
-
-class dCcD_Linked_Cps : public dCcD_Cps {
+class dCcD_Linked_Cyl : public dCcD_Cyl {
public:
- dCcD_Linked_Cps() : mNode(this) {}
- virtual ~dCcD_Linked_Cps() {
+ dCcD_Linked_Cyl() : mNode(this) {}
+ virtual ~dCcD_Linked_Cyl() {
mNode.remove();
}
- /* 0x170 */ LinkedColliderNode mNode;
+ /* 0x150 */ LinkedColliderNode mNode;
};
class dColliderLinkedList {
@@ -86,7 +84,8 @@ public:
// a ptmf. It's not immediately clear how this works,
// does every actor subclass the LinkedCollider___,
// or are the functions all added here for the other
- // files to implement?
+ // files to implement? d_a_b_lastboss commits a typing crime here
+ // to make it work...
typedef bool (cCcD_Obj::*ccPtmf)();
cCcD_Obj *find(ccPtmf f) const;
diff --git a/include/d/d_light_env.h b/include/d/d_light_env.h
index 8e4cc20b..5e48e39e 100644
--- a/include/d/d_light_env.h
+++ b/include/d/d_light_env.h
@@ -414,6 +414,10 @@ public:
return currentSpf;
}
+ SpfSetting &GetOverrideSpf() {
+ return mOverrideSpfSetting;
+ }
+
const PaletteEAF_smol_entry &getSmallEAF(s32 idx1, s32 idx2) {
return field_0x38E4.field_0x00[idx1].field_0x00[idx2];
}
@@ -430,6 +434,18 @@ public:
return field_0x2F1C;
}
+ s32 getField_0x38DC() const {
+ return field_0x38DC;
+ }
+
+ void setField_0x38DC(s32 v) {
+ field_0x38DC = v;
+ }
+
+ void setField_0x5D48(f32 val) {
+ field_0x5D48 = val;
+ }
+
private:
/* 0x0004 */ Spf currentSpf;
/* 0x020C */ Spf spfs[20];
@@ -487,7 +503,9 @@ private:
/* 0x48E4 */ Bpm4 field_0x48E4;
/* 0x5CE4 */ PaletteDefaultMCF field_0x5CE4;
/* 0x5D04 */ TwoPaletteDefaultMCF field_0x5D04;
- /* 0x5D44 */ u8 field_0x5D44[0x5D59 - 0x5D44];
+ /* 0x5D44 */ u8 field_0x5D44[0x5D48 - 0x5D44];
+ /* 0x5D48 */ f32 field_0x5D48;
+ /* 0x5D4C */ u8 field_0x5D4C[0x5D59 - 0x5D4C];
/* 0x5D59 */ struct { // Anonymous until more is known
bool mEnabled;
u8 mValue;
diff --git a/include/d/d_player_act.h b/include/d/d_player_act.h
index 2a948aa8..4d3b9dc2 100644
--- a/include/d/d_player_act.h
+++ b/include/d/d_player_act.h
@@ -413,7 +413,7 @@ public:
/* vt 0x2A8 */ virtual void lookTowardItem() {}
/* vt 0x2AC */ virtual void vt_0x2AC() {}
/* vt 0x2B0 */ virtual void vt_0x2B0() {}
- /* vt 0x2B4 */ virtual void triggerMoveEventMaybe(u32, u32, u32, mVec3_c &, const mAng &, u32, u32) {}
+ /* vt 0x2B4 */ virtual void triggerMoveEventMaybe(u32, u32, u32, const mVec3_c *, const mAng&, u32, u32) {}
/* vt 0x2B8 */ virtual void setActorRef9() {}
/* vt 0x2BC */ virtual void unlinkActorRef9() {}
/* vt 0x2C0 */ virtual bool vt_0x2C0() {
@@ -463,6 +463,19 @@ public:
ATTACK_FINAL_BLOW = 11,
};
+ enum SpecificPlayerAttackDirection_e {
+ /* 0x000 */ ATTACK_DIRECTION_NONE = 0,
+ /* 0x001 */ ATTACK_DIRECTION_DOWN = 1 << 0,
+ /* 0x002 */ ATTACK_DIRECTION_DOWNRIGHT = 1 << 1,
+ /* 0x004 */ ATTACK_DIRECTION_RIGHT = 1 << 2,
+ /* 0x008 */ ATTACK_DIRECTION_UPRIGHT = 1 << 3,
+ /* 0x010 */ ATTACK_DIRECTION_UP = 1 << 4,
+ /* 0x020 */ ATTACK_DIRECTION_UPLEFT = 1 << 5,
+ /* 0x040 */ ATTACK_DIRECTION_LEFT = 1 << 6,
+ /* 0x080 */ ATTACK_DIRECTION_DOWNLEFT = 1 << 7,
+ /* 0x100 */ ATTACK_DIRECTION_STAB = 1 << 8,
+ };
+
enum ModelUpdateFlags_e {
UPDATE_MODEL_SWORD = 0x20,
UPDATE_MODEL_SHIELD = 0x40,
@@ -625,6 +638,14 @@ public:
return mAttackDirection != ATTACK_NONE;
}
+ bool isAttackingJumpSlash() const {
+ return mAttackDirection == ATTACK_JUMP_SLASH;
+ }
+
+ u16 getSpecificAttackDirection() const {
+ return mSpecificAttackDirection;
+ }
+
inline bool hasvt_0x1C0() const {
return vt_0x1C0() != nullptr;
}
@@ -637,6 +658,9 @@ public:
bool isAttackingStab() const;
bool isAttackingSpinHorizontal() const;
bool isAttackingSpinVertical() const;
+ bool isAttackingSpin() const {
+ return isAttackingSpinHorizontal() || isAttackingSpinVertical();
+ }
void setBonkRelatedAnimFlag(bool b);
void setPosYRot(const mVec3_c &pos, mAng rot, bool force = false, UNKWORD = 0, UNKWORD = 0);
void setTransform(const mMtx_c &mtx, bool force, UNKWORD, UNKWORD);
@@ -668,7 +692,8 @@ protected:
/* 0x334 */ f32 field_0x334;
/* 0x338 */ u8 mAttackDirection;
/* 0x339 */ u8 mRidingActorType;
- /* 0x33A */ u8 unk_0x33A[0x340 - 0x33A];
+ /* 0x33A */ u16 mSpecificAttackDirection;
+ /* 0x33C */ u8 unk_0x33C[0x340 - 0x33C];
/* 0x340 */ u32 someFlags_0x340;
/* 0x344 */ u32 mFaceUpdateFlags;
/* 0x348 */ u32 mSwordAndMoreStates;
diff --git a/include/d/d_sc_game.h b/include/d/d_sc_game.h
index b1ba5573..67bbddb4 100644
--- a/include/d/d_sc_game.h
+++ b/include/d/d_sc_game.h
@@ -172,6 +172,10 @@ public:
sUpdateFrameCount = 0;
}
+ static u32 getUpdateFrameCount() {
+ return sUpdateFrameCount;
+ }
+
bool savePromptFlag() const {
return mSavePromptFlag;
}
diff --git a/include/d/d_stage_mgr.h b/include/d/d_stage_mgr.h
index de4d0b47..f20c541d 100644
--- a/include/d/d_stage_mgr.h
+++ b/include/d/d_stage_mgr.h
@@ -5,6 +5,7 @@
#include "d/col/cc/d_cc_s.h"
#include "d/d_base.h"
#include "d/d_bzs_types.h"
+#include "d/d_cursor_hit_check.h"
#include "d/d_dylink.h"
#include "d/d_fader.h"
#include "egg/gfx/eggCpuTexture.h"
@@ -12,6 +13,7 @@
#include "m/m_allocator.h"
#include "m/m_dvd.h"
#include "m/m_fader_base.h"
+#include "m/m_mtx.h"
#include "nw4r/g3d/g3d_camera.h"
#include "s/s_FPhase.h"
#include "s/s_State.hpp"
@@ -103,6 +105,9 @@ public:
s32 getMapNameId() const;
bool fn_80199250();
+ void procfn_800192F0(u8 a1, const mMtx_c &mtx, u8 a2) {
+ mProc1.fn_800192F0(a1, mtx, a2);
+ }
static dStageMgr_c *GetInstance() {
return sInstance;
@@ -169,6 +174,8 @@ public:
nw4r::g3d::Camera getCamera(s32 idx);
+ void fn_80199B60(u8);
+
dFader_c *getFader() {
return &mFader;
}
@@ -202,11 +209,19 @@ private:
/* 0x0580 */ LayoutArcControl mLayoutArcCtrl2;
/* 0x058C */ dBgS mBg;
// ...
- u8 _0x00001[0x778];
+ u8 _0x00001[0x6C8];
+
+ /* 0x3E38 */ // ...
+
/* 0x3E40 */ dCcS mCc;
+
+ /* 0x75D8 */ dCursorHitCheckCC_c mCsHitCheck;
// ...
/* 0x7814 */ dParticle::tex_c mParticleTex[2];
- // ...
+ /* 0x7898 */ d3d::EggTextureProc mProc1;
+ /* 0x78EC */ d3d::XluProc mProc2;
+ u8 _0x00002[0x28];
+ /* 0x790C */ // ...
/* 0x7930 */ dFader_c mFader;
/* 0x7954 */ u16 mPcamCount;
@@ -218,6 +233,8 @@ private:
/* 0x7964 */ const STIF *mpStif;
/* 0x7968 */ const RMPL *mpRmpl;
+ u8 _0x00003[0x30];
+
/* 0x799C */ mDvd_callback_c *mpDvdCallback;
/* 0x79A0 */ mDvd_callback_c *mpDvdCallback2;
@@ -227,7 +244,7 @@ private:
/* 0x8694 */ dTimeAreaMgr_c mTimeAreaMgr;
// ...
- u8 ___[438];
+ u8 ___[390];
/* 0x8898 */ EGG::CpuTexture *field_0x8898;
u8 _0x889C[4];
diff --git a/include/d/lyt/d_lyt_boss_caption.h b/include/d/lyt/d_lyt_boss_caption.h
new file mode 100644
index 00000000..65436c12
--- /dev/null
+++ b/include/d/lyt/d_lyt_boss_caption.h
@@ -0,0 +1,28 @@
+#ifndef D_LYT_BOSS_CAPTION_H
+#define D_LYT_BOSS_CAPTION_H
+
+#include "common.h"
+
+class dLytBossCaption_c {
+public:
+ static dLytBossCaption_c *GetInstance() {
+ return sInstance;
+ }
+
+ void show(const char *label, UNKWORD);
+
+ // I believe this is the inline that causes all the Rev0 -> Rev1 pain in RELs...
+ void unk_inline() {
+ field_0x645 = 0;
+ field_0x646 = 0;
+ }
+
+private:
+ static dLytBossCaption_c *sInstance;
+
+ u8 _0x00[0x645 - 0x00];
+ u8 field_0x645;
+ u8 field_0x646;
+};
+
+#endif
diff --git a/include/d/snd/d_snd_bgm_mgr.h b/include/d/snd/d_snd_bgm_mgr.h
index ff8a31d7..3ff73f12 100644
--- a/include/d/snd/d_snd_bgm_mgr.h
+++ b/include/d/snd/d_snd_bgm_mgr.h
@@ -101,6 +101,8 @@ public:
// always returns false
bool weirdCheckAlwaysFalse();
+ void fn_80372D70(UNKWORD);
+
dSndBgmSound_c *getActiveBgmSound();
// I don't love this inline but it fixes one regswap
// TODO look into getting rid of this one
diff --git a/include/toBeSorted/d_d3d.h b/include/toBeSorted/d_d3d.h
index ebfeafd2..e565ddf2 100644
--- a/include/toBeSorted/d_d3d.h
+++ b/include/toBeSorted/d_d3d.h
@@ -203,6 +203,8 @@ public:
doDraw();
}
+ void fn_800192F0(u8, const mMtx_c&, u8);
+
private:
void doRemove();
void doDraw();
diff --git a/include/toBeSorted/d_enemy_sword_mdl.h b/include/toBeSorted/d_enemy_sword_mdl.h
new file mode 100644
index 00000000..40883513
--- /dev/null
+++ b/include/toBeSorted/d_enemy_sword_mdl.h
@@ -0,0 +1,75 @@
+#ifndef D_ENEMY_SWORD_MDL_H
+#define D_ENEMY_SWORD_MDL_H
+
+#include "common.h"
+#include "d/a/obj/d_a_obj_base.h"
+#include "d/d_cc.h"
+#include "d/d_shadow.h"
+#include "egg/gfx/eggTexture.h"
+#include "m/m3d/m_smdl.h"
+#include "m/m_allocator.h"
+#include "m/m_angle.h"
+#include "m/m_mtx.h"
+#include "m/m_quat.h"
+#include "m/m_vec.h"
+#include "nw4r/types_nw4r.h"
+#include "toBeSorted/d_sword_swing_effect_mgr.h"
+
+class dEnemySwordMdl_c {
+public:
+ /* 0x000 */ m3d::smdl_c mMdl;
+ /* 0x01C */ dSwordSwingEffectProcMgr_c mProc;
+
+private:
+ /* 0x070 */ bool mIsActive;
+ /* 0x071 */ bool mFirstFramePassed;
+ /* 0x074 */ mVec3_c field_0x074;
+ /* 0x080 */ mVec3_c field_0x080;
+ /* 0x08C */ mVec3_c field_0x08C;
+ /* 0x098 */ mVec3_c field_0x098;
+ /* 0x0A4 */ f32 field_0x0A4;
+ /* 0x0A8 */ f32 field_0x0A8;
+ /* 0x0AC */ dCcD_Linked_Cps mCcs[3];
+
+public:
+ /* 0x52C */ dColliderLinkedList mCcList;
+
+public:
+ dEnemySwordMdl_c() {}
+ virtual ~dEnemySwordMdl_c() {}
+
+ bool create(
+ mAllocator_c *alloc, void *pData, const char *mdlName, u32 bufferOption, const mVec3_c &v1, const mVec3_c &v2,
+ cCcD_Stts &stts, EGG::ResTIMG *pImg, int nView, u32 *pSize
+ );
+ bool create(
+ mAllocator_c *alloc, nw4r::g3d::ResFile resFile, const char *mdlName, u32 bufferOption, const mVec3_c &v1,
+ const mVec3_c &v2, cCcD_Stts &stts, EGG::ResTIMG *pImg, int nView, u32 *pSize
+ );
+
+ void calc(const mMtx_c &mtx, const mVec3_c &v1, bool mass);
+ void calc(const mMtx_c &mtx, mAng angle, bool mass) {
+ // A bit of a wild inline but this vector is very low on the dAcBlastboss_c::actorExecute stack
+ mVec3_c v1 = mVec3_c(angle.sin(), 0.0f, angle.cos());
+ calc(mtx, v1, mass);
+ }
+ bool entry(dAcObjBase_c *obj, dShadowCircle_c *shadow, mQuat_c *quat);
+
+ void enableAttack();
+ void fn_8006B660(UNKWORD, UNKWORD, UNKWORD, UNKWORD, UNKWORD, UNKWORD, UNKWORD, UNKWORD, UNKWORD, f32);
+ void setDamageMaybe(u8 damage);
+ void fn_8006B7A0(u32);
+ void fn_8006B800(u32);
+
+ void enable() {
+ enableAttack();
+ mProc.setActive(true);
+ }
+
+ void disable() {
+ mIsActive = false;
+ mProc.setActive(false);
+ }
+};
+
+#endif
diff --git a/include/toBeSorted/d_sword_swing_effect.h b/include/toBeSorted/d_sword_swing_effect.h
new file mode 100644
index 00000000..1a97f0cd
--- /dev/null
+++ b/include/toBeSorted/d_sword_swing_effect.h
@@ -0,0 +1,65 @@
+#ifndef D_SWORD_SWING_EFFECT_H
+#define D_SWORD_SWING_EFFECT_H
+
+#include "common.h"
+#include "egg/gfx/eggTexture.h"
+#include "m/m3d/m_proc.h"
+#include "m/m_allocator.h"
+#include "m/m_color.h"
+#include "m/m_vec.h"
+
+class dSwordSwingEffectProcBase_c : public m3d::proc_c {
+protected:
+ struct swing_entry {
+ swing_entry() {
+ mLifetime = 0.0f;
+ }
+ ~swing_entry() {}
+
+ void set(const mVec3_c &pos1, const mColor &c1, const mVec3_c &pos2, const mColor &c2);
+
+ /* 0x00 */ f32 mLifetime;
+ /* 0x04 */ mVec3_c mv1;
+ /* 0x10 */ mVec3_c mv2;
+ /* 0x1C */ mColor mc1;
+ /* 0x20 */ mColor mc2;
+ };
+
+public:
+ dSwordSwingEffectProcBase_c() : mpEntries(nullptr), mCount(0), mHead(0) {}
+ virtual ~dSwordSwingEffectProcBase_c() {
+ remove();
+ }
+
+ virtual int entry() override;
+ virtual void remove() override;
+ virtual void drawXlu() override;
+
+ bool create(s32 num, mAllocator_c *alloc);
+ void addSwing(const mVec3_c &pos1, const mColor c1, const mVec3_c &pos2, const mColor c2);
+ void calc(f32 f);
+
+protected:
+ bool hasSwings() const;
+
+ /* 0x18 */ swing_entry *mpEntries;
+ /* 0x1C */ u16 mNum;
+ /* 0x1E */ u16 mCount;
+ /* 0x20 */ u16 mHead;
+};
+
+class dSwordSwingEffectProc_c : public dSwordSwingEffectProcBase_c {
+public:
+ dSwordSwingEffectProc_c() : mpImg(nullptr) {}
+ virtual ~dSwordSwingEffectProc_c() {}
+
+ virtual void drawXlu() override;
+
+ bool create(s32 num, mAllocator_c *alloc, EGG::ResTIMG *pImg, f32 scale);
+
+private:
+ /* 0x24 */ EGG::ResTIMG *mpImg;
+ /* 0x28 */ f32 mTexScale;
+};
+
+#endif
diff --git a/include/toBeSorted/d_sword_swing_effect_mgr.h b/include/toBeSorted/d_sword_swing_effect_mgr.h
new file mode 100644
index 00000000..e14600ad
--- /dev/null
+++ b/include/toBeSorted/d_sword_swing_effect_mgr.h
@@ -0,0 +1,43 @@
+#ifndef D_SWORD_SWING_EFFECT_MGR_H
+#define D_SWORD_SWING_EFFECT_MGR_H
+
+#include "m/m_color.h"
+#include "m/m_vec.h"
+#include "toBeSorted/d_sword_swing_effect.h"
+
+// TODO better name
+class dSwordSwingEffectProcMgr_c {
+private:
+ /* 0x00 */ dSwordSwingEffectProc_c mProc;
+ /* 0x2C */ bool mIsActive;
+ /* 0x30 */ mColor mC1;
+ /* 0x34 */ mColor mC2;
+ /* 0x38 */ mVec3_c field_0x38;
+ /* 0x44 */ mVec3_c field_0x44;
+
+ void createSwingEntries(const mVec3_c &v1, const mVec3_c &v2);
+
+public:
+ dSwordSwingEffectProcMgr_c() : mC1(0xFF, 0xFF, 0xFF, 0x40), mC2(0xFF, 0xFF, 0xFF, 0x20) {}
+ virtual ~dSwordSwingEffectProcMgr_c() {}
+
+ void setColor1(mColor c1) {
+ mC1 = c1;
+ }
+
+ void setColor2(mColor c1) {
+ mC2 = c1;
+ }
+
+ void setActive(bool v) {
+ mIsActive = v;
+ }
+
+ bool create(s32 num, mAllocator_c *alloc, EGG::ResTIMG *pImg, f32 scale) {
+ return mProc.create(num, alloc, pImg, scale);
+ }
+ void calc(const mVec3_c &v1, const mVec3_c &v2);
+ void entry();
+};
+
+#endif
diff --git a/src/REL/d/a/b/d_a_b_lastboss.cpp b/src/REL/d/a/b/d_a_b_lastboss.cpp
index af5d73b5..875845d1 100644
--- a/src/REL/d/a/b/d_a_b_lastboss.cpp
+++ b/src/REL/d/a/b/d_a_b_lastboss.cpp
@@ -1,5 +1,44 @@
#include "d/a/b/d_a_b_lastboss.h"
+#include "c/c_lib.h"
+#include "c/c_math.h"
+#include "common.h"
+#include "d/a/d_a_player.h"
+#include "d/a/obj/d_a_obj_base.h"
+#include "d/col/c/c_cc_d.h"
+#include "d/col/cc/d_cc_s.h"
+#include "d/d_base.h"
+#include "d/d_camera.h"
+#include "d/d_cc.h"
+#include "d/d_light_env.h"
+#include "d/d_player_act.h"
+#include "d/d_rumble.h"
+#include "d/d_sc_game.h"
+#include "d/d_stage.h"
+#include "d/d_stage_mgr.h"
+#include "d/flag/sceneflag_manager.h"
+#include "d/flag/storyflag_manager.h"
+#include "d/lyt/d_lyt_boss_caption.h"
+#include "d/snd/d_snd_bgm_mgr.h"
+#include "d/snd/d_snd_wzsound.h"
+#include "d/t/d_t_sword_battle_game.h"
+#include "f/f_base.h"
+#include "f/f_manager.h"
+#include "f/f_profile_name.h"
+#include "m/m3d/m_fanm.h"
+#include "m/m_angle.h"
+#include "m/m_mtx.h"
+#include "m/m_vec.h"
+#include "nw4r/g3d/res/g3d_resfile.h"
+#include "nw4r/g3d/res/g3d_resmdl.h"
+#include "nw4r/math/math_arithmetic.h"
+#include "rvl/MTX/mtxvec.h"
+#include "s/s_Math.h"
+#include "toBeSorted/d_emitter.h"
+#include "toBeSorted/event.h"
+#include "toBeSorted/event_manager.h"
+#include "toBeSorted/minigame_mgr.h"
+
SPECIAL_ACTOR_PROFILE(B_LASTBOSS, dAcBlastboss_c, fProfile::B_LASTBOSS, 0xBA, 0, 0);
STATE_DEFINE(dAcBlastboss_c, Fight);
@@ -17,45 +56,3286 @@ STATE_DEFINE(dAcBlastboss_c, Down);
STATE_DEFINE(dAcBlastboss_c, Stun);
STATE_DEFINE(dAcBlastboss_c, ThunderWait);
-void dAcBlastboss_c::initializeState_Fight() {}
-void dAcBlastboss_c::executeState_Fight() {}
+static dCcD_SrcCyl sSrcCyl1 = {
+ /* mObjInf */
+ {/* mObjAt */ {0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {~(AT_TYPE_BUGNET | AT_TYPE_0x80000 | AT_TYPE_BELLOWS | AT_TYPE_BEETLE | AT_TYPE_WIND | AT_TYPE_0x8000),
+ 0x4103,
+ {0, 0x4, 0x407},
+ 0x0,
+ 0x0},
+ /* mObjCo */ {0x0}},
+ /* mCylInf */
+ {40.f, 300.f}
+};
+
+static dCcD_SrcCyl sSrcCyl2 = {
+ /* mObjInf */
+ {/* mObjAt */ {0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {AT_TYPE_BELLOWS, 0x103, {0, 0x4, 0x407}, 0x0, 0x0},
+ /* mObjCo */ {0x0}},
+ /* mCylInf */
+ {70.f, 30.f}
+};
+
+static dCcD_SrcCyl sSrcCyl3 = {
+ /* mObjInf */
+ {/* mObjAt */ {0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {0x0, 0x0, {0, 0x0, 0x407}, 0x0, 0x0},
+ /* mObjCo */ {0xE5}},
+ /* mCylInf */
+ {100.f, 250.f}
+};
+
+static dCcD_SrcSph sSrcSph1 = {
+ /* mObjInf */
+ {/* mObjAt */ {AT_TYPE_DAMAGE, 0x2008D, {0, 0, 0}, 4, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {0, 0, {0, 0x0, 0x407}, 0, 0},
+ /* mObjCo */ {0}},
+ /* mSphInf */
+ {100.0f}
+};
+
+static dCcD_SrcSph sSrcSph2 = {
+ /* mObjInf */
+ {/* mObjAt */ {AT_TYPE_DAMAGE, 0x22008D, {0, 0, 4}, 8, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {AT_TYPE_0x800000 | AT_TYPE_BUGNET, 0x103, {0, 0x19, 0x407}, 0, 0},
+ /* mObjCo */ {0}},
+ /* mSphInf */
+ {100.0f}
+};
+
+static dCcD_SrcSph sSrcSph = {
+ /* mObjInf */
+ {/* mObjAt */ {0, 0, {0, 0, 0}, 0, 0, 0, 0, 0, 0},
+ /* mObjTg */
+ {AT_TYPE_BELLOWS, 0x4103, {0, 0x0, 0x40F}, 0, 0},
+ /* mObjCo */ {0}},
+ /* mSphInf */
+ {30.0f}
+};
+
+s32 useUnused() {
+ static const f32 a1[] = {
+ 0.95f,
+ 1.05f,
+ 0.0f,
+ };
+ return (s32)a1;
+}
+
+bool dAcBlastboss_c::createHeap() {
+ bool result;
+ void *pData = getOarcResFile("BLastBoss");
+
+ TRY_CREATE2(mMdl.create3(*this, pData, "LastBoss", "Wait", 0x334));
+ mScnCallback.attach(mMdl.getModel());
+
+ nw4r::g3d::ResFile res(pData);
+
+ TRY_CREATE2(mAnmTexSrt.create(mMdl.getModel().getResMdl(), res.GetResAnmTexSrt("Hair"), &mAllocator, nullptr, 1));
+ mMdl.getModel().setAnm(mAnmTexSrt);
+
+ TRY_CREATE2(mAnmMatClr1.create(mMdl.getModel().getResMdl(), res.GetResAnmClr("Wait"), &mAllocator, nullptr, 2));
+ mAnmMatClr1.setAnm(mMdl.getModel(), res.GetResAnmClr("Hair"), 1, m3d::PLAY_MODE_0);
+ mMdl.getModel().setAnm(mAnmMatClr1);
+
+ mMdl.getModel().setCallback(&mMdlCallback);
+ mMdlCallback.mpOwner = this;
+
+ TRY_CREATE2(mSwordMdl.create(
+ &mAllocator, pData, "LastBossSword", 0x130, mVec3_c(0.0f, 0.0f, 0.0f), mVec3_c(0.0f, -230.0f, 0.0f), mStts,
+ nullptr, 1, nullptr
+ ));
+ // TODO I'm not going to try and make sense of this for now
+ mSwordMdl.fn_8006B660(4, 1, 0, 0x10000, 0, 0, 0, 0x400, 0xc, 60.0f);
+ mSwordMdl.mProc.setColor1(mColor(0xFF, 0xFF, 0xFF, 0x14));
+ mSwordMdl.mProc.setColor2(mColor(0xFF, 0xFF, 0xFF, 0x14));
+
+ TRY_CREATE2(mThunderMdl.create(res.GetResMdl("FX_LBThunder"), &mAllocator, 0x120));
+
+ TRY_CREATE2(
+ mThunderAnmMatClr.create(mThunderMdl.getResMdl(), res.GetResAnmClr("FX_LBThunder"), &mAllocator, nullptr, 1)
+ );
+ mThunderMdl.setAnm(mThunderAnmMatClr);
+
+ dBase_c::createBase(fProfile::LYT_BOSS_CAPTION, this, 0, OTHER);
+
+ return result;
+}
+
+int dAcBlastboss_c::create() {
+ mThunderWaitSceneFlag = getFromParams(0, 0xFF);
+ if (MinigameManager::GetInstance()->checkInBossRush()) {
+ mInBossRush = true;
+ }
+ CREATE_ALLOCATOR(dAcBlastboss_c);
+
+ mStts.SetRank(10);
+ mCcList.addCc(mCc1, sSrcCyl1);
+ mCcList.addCc(mCc2, sSrcCyl2);
+ mCcList.addCc(mCc3, sSrcCyl3);
+
+ for (int i = 0; i < (int)ARRAY_LENGTH(field_0x1268); i++) {
+ field_0x1268[i].field_0x000 = i;
+ field_0x1268[i].field_0x002 = cM::rndF(65536.0f);
+ mCcList.addCc(field_0x1268[i].mCc, sSrcSph);
+ for (int j = 0; j < (int)ARRAY_LENGTH(field_0x1268[j].field_0x014); j++) {
+ field_0x1268[i].field_0x014[j] = mPosition;
+ }
+ field_0x1268[i].field_0x008 = i * 15000;
+ }
+
+ // TODO loop of length 1 might not exist
+ for (int i = 0; i < (int)ARRAY_LENGTH(field_0x2948); i++) {
+ mCcList.addCc(field_0x2948[i].mCc, sSrcSph);
+ for (int j = 0; j < (int)ARRAY_LENGTH(field_0x2948[j].field_0x008); j++) {
+ field_0x2948[i].field_0x008[j] = mPosition;
+ }
+ }
+
+ mCcList.SetStts(mStts);
+
+ mCc4.Set(sSrcSph1);
+ mCc4.SetStts(mStts);
+
+ mLightningCc.Set(sSrcSph2);
+ mLightningCc.mTg.Set_0x4C(-1);
+ mLightningCc.SetStts(mStts);
+
+ mAcceleration = -5.0f;
+ mMaxSpeed = -80.0f;
+
+ mBoundingBox.Set(mVec3_c(-200.0f, -300.0f, -200.0f), mVec3_c(200.0f, 300.0f, 200.0f));
+ mStateMgr.changeState(StateID_Fight);
+
+ field_0x1132 = true;
+ mCounter = cM::rndF(65536.0f);
+
+ mHealth = 400;
+ mPositionCopy3 = mPosition;
+
+ mLastAttackDir = mSecondLastAttackDirection = -1;
+
+ mWaterEmitter.init(this);
+ mEmitter2.init(this);
+ // mEmitter3.init(this); // TODO why not this one...
+ mEmitter4.init(this);
+ mEmitter5.init(this);
+ mEmitter6.init(this);
+ mEmitter7.init(this);
+
+ mLightInfo.SetPosition(mPosition);
+ mLightInfo.mClr.Set(100, 150, 255, 255);
+ dLightEnv_c::GetPInstance()->plight_set(&mLightInfo);
+ setLightningTimerMaybe(100);
+
+ if (!mInBossRush) {
+ mLightingStrikeState = LIGHTNING_STRIKE_TRIGGER_START;
+ setActorProperty(AC_PROP_0x4);
+ }
+
+ return SUCCEEDED;
+}
+
+// why are these up here?
+static const s16 moreAngs[] = {0xA000, 0xC000, 0xE000, 0xF000, 0x0000, 0x1000, 0x2000, 0x4000};
+
+int dAcBlastboss_c::doDelete() {
+ dLightEnv_c::GetPInstance()->plight_cut(&mLightInfo);
+ return SUCCEEDED;
+}
+
+int dAcBlastboss_c::actorExecute() {
+ if (mInBossRush && mpSwordBattleGame == nullptr) {
+ mpSwordBattleGame = static_cast<dTgSwordBattleGame_c *>(
+ fManager_c::searchBaseByProfName(fProfile::TAG_SWORD_BATTLE_GAME, mpSwordBattleGame)
+ );
+ }
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+
+ mCounter++;
+
+ field_0x1133 = 0;
+ field_0x1131 = 0;
+ mIsDown = false;
+ field_0x114E = 0;
+
+ field_0x11A4 = 0.0f;
+ mLightInfo.mScale = 0.0f;
+ field_0x11B0 = 0.7f;
+
+ for (int i = 0; i < TIMER_MAX; i++) {
+ if (mTimers[i] != 0) {
+ mTimers[i]--;
+ }
+ }
+
+ if (mMdlCallback.field_0x04.mVal != 0) {
+ mMdlCallback.field_0x04.mVal--;
+ }
+
+ if (field_0x117C != 0) {
+ field_0x117C--;
+ }
+
+ if (field_0x113D != 0) {
+ field_0x113D--;
+ }
+
+ if (field_0x113F != 0) {
+ field_0x113F--;
+ }
+
+ if (field_0x113E != 0) {
+ field_0x113E--;
+ }
+
+ mVec3_c vEff;
+ mVec3_c linkPos = link->getPosition();
+ mYAngleToLink = cLib::targetAngleY(mPosition, linkPos);
+ mXZDistanceToLink = link->getPosition().absXZTo(mPosition);
+
+ mYRotationRelativeToLink = mYAngleToLink - mRotation.y;
+ mSwordMdl.disable();
+
+ mCc4.ClrAtSet();
+ mLightningCc.ClrAtSet();
+
+ checkDamage();
+ if (mpSwordBattleGame == nullptr || mpSwordBattleGame->checkFightStarted() == true) {
+ mStateMgr.executeState();
+ }
+
+ mRotation.x = mAngle.x;
+ mRotation.z = mAngle.z;
+ sLib::addCalcAngle(mRotation.y.ref(), mAngle.y, 2, 0x800);
+
+ mMdl.play();
+ if (!mIsDead) {
+ mAnmMatClr1.play();
+ }
+
+ calcVelocity();
+ mPosition += mVelocity;
+ mPosition += mStts.GetCcMove();
+ mPosition.x += mAttackKnockbackX;
+ mPosition.z += mAttackKnockbackZ;
+
+ mAttackKnockbackX *= 0.6f;
+ mAttackKnockbackZ *= 0.6f;
+
+ f32 f5 = 0.0f;
+ if (mRotation.x != 0) {
+ f5 += field_0x11C0 * mRotation.x.sin();
+ }
+
+ field_0x1140 = false;
+ if (mPosition.y <= f5) {
+ mPosition.y = f5;
+ field_0x11BC = mVelocity.y;
+ mVelocity.y = 0.0f;
+ field_0x1140 = true;
+ }
+
+ updateMainNodeTransforms();
+
+ mWorldMtx.transS(mPosition);
+ mWorldMtx.ZXYrotM(mRotation);
+ mScale.set(0.95f, 0.95f, 0.95f);
+ mMdl.getModel().setScale(mScale);
+ mMdl.getModel().setLocalMtx(mWorldMtx);
+ if (!mIsDown) {
+ mAnmTexSrt.play();
+ }
+
+ mMdl.getModel().calc(false);
+
+ nw4r::g3d::ResMdl resMdl = mMdl.getModel().getResMdl();
+ // TODO: These very deliberately placed matrices might work better with
+ // inlines but I haven't found an inline that places rotMtx where it needs
+ // to be.
+ mMtx_c nodeMtx;
+ mMtx_c rotMtx;
+ mMtx_c scaleMtx;
+ mMdl.getModel().getNodeWorldMtx(resMdl.GetResNode("loc_sword01").GetID(), nodeMtx);
+ scaleMtx.scaleS(1.05f, 1.05f, 1.05f);
+ MTXConcat(nodeMtx, scaleMtx, nodeMtx);
+
+ mSwordMdl.calc(nodeMtx, mRotation.y, false);
+
+ vEff.set(0.0f, -120.0f, 0.0f);
+ if (mGuardDirection == GUARD_BT) {
+ vEff.y = -80.0f;
+ if (mXZDistanceToLink > 300.0f) {
+ vEff.y -= (mXZDistanceToLink - 300.0f);
+ if (vEff.y < -280.0f) {
+ vEff.y = -280.0f;
+ }
+ }
+ }
+ MTXMultVec(nodeMtx, vEff, mSwordPosition);
+
+ if (mIsSwordEmpowered) {
+ mEmitter4.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_619_, nodeMtx, nullptr, nullptr);
+ mLightInfo.mPos = mSwordPosition;
+ if (dScGame_c::getUpdateFrameCount() & 2) {
+ mLightInfo.SetScale(300.0f);
+ } else {
+ mLightInfo.SetScale(200.0f);
+ }
+ holdSound(SE_BLasBos_SwordEnpowered);
+ }
+
+ if (mStunState != 0) {
+ if (mStunState == 1) {
+ mEmitter7.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_852_, nodeMtx, nullptr, nullptr);
+ mMdl.getModel().getNodeWorldMtx(resMdl.GetResNode("backbone2").GetID(), nodeMtx);
+ mEmitter6.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_853_, nodeMtx, nullptr, nullptr);
+ holdSound(SE_BLasBos_UnderElecShock);
+ } else if (mStunState == 2) {
+ mMdl.getModel().getNodeWorldMtx(resMdl.GetResNode("backbone2").GetID(), nodeMtx);
+ dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_851_, nodeMtx, nullptr, nullptr, 0, 0);
+ mMtx_c transMtx;
+ transMtx.transS(0.0f, -100000.0f, 0.0f);
+ MTXConcat(nodeMtx, transMtx, nodeMtx);
+ mEmitter7.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_852_, nodeMtx, nullptr, nullptr);
+ mEmitter6.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_853_, nodeMtx, nullptr, nullptr);
+ holdSound(SE_BLasBos_KillOffElecShock);
+ }
+ mLightInfo.mPos = mSwordPosition;
+ if (dScGame_c::getUpdateFrameCount() & 2) {
+ mLightInfo.SetScale(400.0f);
+ } else {
+ mLightInfo.SetScale(300.0f);
+ }
+ mStunState = 0;
+ }
+
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_thumbL2, nodeMtx);
+ nodeMtx.getTranslation(mThumbL2Translation);
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_backbone1, nodeMtx);
+ nodeMtx.getTranslation(mBackbone1Translation);
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_chest, nodeMtx);
+ nodeMtx.getTranslation(mChestTranslation);
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_toeL, nodeMtx);
+ nodeMtx.getTranslation(mToeTranslation[0]);
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_toeR, nodeMtx);
+ nodeMtx.getTranslation(mToeTranslation[1]);
+
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_head, nodeMtx);
+ mVec3_c tmp1(0.0f, 0.0f, 0.0f);
+ MTXMultVec(nodeMtx, tmp1, mPositionCopy2);
+ mVec3_c v3;
+ v3.x = mPositionCopy2.x;
+ v3.y = mPositionCopy2.y + 50.0f;
+ v3.z = mPositionCopy2.z;
+ mPositionCopy3 = v3;
+
+ if (field_0x1132) {
+ fn_80030c20(0, 1500.0f, 50.0f, -200.0f, 200.0f);
+ }
+
+ nodeMtx.YrotS(mRotation.y);
+
+ mVec3_c tmpCc;
+ if (link->isAttacking() && mStateMgr.isState(StateID_Guard)) {
+ if (mGuardDirection == GUARD_BT) {
+ tmpCc.x = 0.0f;
+ tmpCc.y = 0.0f;
+ tmpCc.z = 100.0f;
+ if (mXZDistanceToLink > 300.0f) {
+ tmpCc.z = (mXZDistanceToLink - 300.0f) + 100.0f;
+ if (tmpCc.z > 300) {
+ tmpCc.z = 300.0f;
+ }
+ }
+ } else {
+ tmpCc.x = 0.0f;
+ tmpCc.y = 0.0f;
+ tmpCc.z = 130.0f;
+ }
+ mCc1.SetR(20.0f);
+ } else if (mStateMgr.isState(StateID_ThunderWait)) {
+ tmpCc.set(0.0f, 0.0f, 0.0f);
+ mCc1.SetR(150.0f);
+ } else {
+ tmpCc.set(0.0f, 0.0f, 80.0f);
+ mCc1.SetR(55.0f);
+ }
+
+ MTXMultVec(nodeMtx, tmpCc, tmpCc);
+ tmpCc += mPosition;
+
+ if (link->isAttacking() && mXZDistanceToLink < 400.0f) {
+ tmpCc.y += 100.0f;
+ mCc1.SetH(100.0f);
+ } else {
+ mCc1.SetH(250.0f);
+ }
+ mCc1.SetC(tmpCc);
+
+ tmpCc.x = mChestTranslation.x;
+ tmpCc.y = mChestTranslation.y;
+ tmpCc.z = mChestTranslation.z;
+ tmpCc.y = mPosition.y;
+
+ if (!mIsDown) {
+ mCc3.SetR(100.0f);
+ } else {
+ mCc3.SetR(200.0f);
+ }
+ mCc3.SetC(tmpCc);
+
+ tmpCc.x = mPosition.x;
+ tmpCc.y = mPosition.y + 150.0f;
+ tmpCc.z = mPosition.z;
+
+ mCc2.SetC(tmpCc);
+
+ field_0x1250[0] = mToeTranslation[0] + (mToeTranslation[1] - mToeTranslation[0]) * 0.5f;
+ // UB: this should use string comparison functions for robustness, but
+ // probably works fine in MWCC
+ if ((mpCurrentAnm == "CatchThunderEnd" || mpCurrentAnm == "Stan") && mMdl.getAnm().getFrame() <= 3.0f) {
+ field_0x11A4 = 25.0f;
+ }
+
+ updateSkirtHairTransforms();
+
+ if (!link->isAttacking()) {
+ mInvulnerabilityTimerMaybe = 1;
+ }
+
+ if (mInvulnerabilityTimerMaybe == 0) {
+ mCc1.SetTg_0x4B(1);
+ // TODO
+ mCc1.mTg.field_0x6C = mSwordPosition;
+ } else {
+ mInvulnerabilityTimerMaybe--;
+ tmpCc.set(0.0f, -10000.0f, 0.0);
+ mCc1.SetTg_0x4B(1);
+ // TODO
+ mCc1.mTg.field_0x6C = tmpCc;
+ }
+
+ mCc1.ClrTg_0x10000();
+
+ if (field_0x1142 != 0) {
+ field_0x1142--;
+ mCcList.ClrTg();
+ } else {
+ mCcList.TgSet();
+ }
+ mCcList.registerColliders();
+
+ if (field_0x1139 != 0) {
+ mCc4.OnAtSet();
+ if (field_0x1139 == 1) {
+ mCc4.setCenter(mThumbL2Translation);
+ field_0x1139 = 2;
+ } else {
+ mCc4.moveCenter(mThumbL2Translation);
+ }
+ dCcS::GetInstance()->Set(&mCc4);
+ }
+
+ static mAng3_c sEffRot(0, 0, 0);
+ static mVec3_c sEffScale(1.5f, 1.5f, 1.5f);
+ mVec3_c effPos(mPosition.x, 10.0f, mPosition.z);
+ // Basically the same code as in dWaterEffect_c::execute
+ mWaterEmitter.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_127_, effPos, &sEffRot, &sEffScale, nullptr, nullptr);
+ f32 rate = nw4r::math::FAbs(mSpeed) * 0.02f;
+ rate = rate > 0.95f ? 0.95f : rate;
+ mWaterEmitter.setRate(rate + 0.05f);
+
+ bool footSplash[2] = {false, false};
+ // UB: this should use string comparison functions for robustness, but
+ // probably works fine in MWCC
+ if (mpCurrentAnm == "Walk" || mpCurrentAnm == "WalkBt") {
+ if (mMdl.getAnm().checkFrame(22.0f)) {
+ footSplash[0] = true;
+ } else if (mMdl.getAnm().checkFrame(48.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "TurnR") {
+ if (mMdl.getAnm().checkFrame(31.0f)) {
+ footSplash[0] = true;
+ } else if (mMdl.getAnm().checkFrame(19.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "TurnL") {
+ if (mMdl.getAnm().checkFrame(31.0f)) {
+ footSplash[1] = true;
+ } else if (mMdl.getAnm().checkFrame(19.0f)) {
+ footSplash[0] = true;
+ }
+ } else if (mpCurrentAnm == "AttackBreak") {
+ if (mMdl.getAnm().checkFrame(16.0f)) {
+ footSplash[0] = true;
+ }
+ } else if (mpCurrentAnm == "AttackL") {
+ if (mMdl.getAnm().checkFrame(26.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "AttackR") {
+ if (mMdl.getAnm().checkFrame(24.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "AttackU") {
+ if (mMdl.getAnm().checkFrame(10.0f)) {
+ footSplash[1] = true;
+ } else if (mMdl.getAnm().checkFrame(24.0f)) {
+ footSplash[0] = true;
+ }
+ } else if (mpCurrentAnm == "Counter") {
+ if (mMdl.getAnm().checkFrame(21.0f)) {
+ footSplash[0] = true;
+ } else if (mMdl.getAnm().checkFrame(45.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "AttackJumpEnd") {
+ if (mMdl.getAnm().checkFrame(6.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "DownGetUp") {
+ if (mMdl.getAnm().checkFrame(137.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "DownEscapeL") {
+ if (mMdl.getAnm().checkFrame(15.0f)) {
+ footSplash[0] = true;
+ } else if (mMdl.getAnm().checkFrame(17.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "DownEscapeR") {
+ if (mMdl.getAnm().checkFrame(15.0f)) {
+ footSplash[1] = true;
+ } else if (mMdl.getAnm().checkFrame(17.0f)) {
+ footSplash[0] = true;
+ }
+ } else if (mpCurrentAnm == "ThunderDemo") {
+ if (mMdl.getAnm().checkFrame(18.0f)) {
+ footSplash[1] = true;
+ }
+ } else if (mpCurrentAnm == "AttackThunder") {
+ if (mMdl.getAnm().checkFrame(25.0f)) {
+ footSplash[0] = true;
+ }
+ }
+
+ // Spawn splash effects
+ for (int i = 0; i < 2; i++) {
+ if (footSplash[i]) {
+ mToeTranslation[i].y = 10.0f;
+ dJEffManager_c::spawnEffect(
+ PARTICLE_RESOURCE_ID_MAPPING_855_, mToeTranslation[i], nullptr, nullptr, nullptr, nullptr, 0, 0
+ );
+ }
+ }
+
+ if (mIsPhaseTwo != 0) {
+ if (!link->checkSwordAndMoreStates(0x400000) && (mIsPhaseTwo < 0 || !mIsSwordEmpowered)) {
+ if (mLightningTimerMaybe == 0) {
+ if (dLightEnv_c::GetPInstance()->getField_0x38DC() == 0) {
+ dLightEnv_c::GetPInstance()->setField_0x38DC(1);
+ setLightningTimerMaybe(100);
+ }
+ } else if (!mIsSwordEmpowered || (dScGame_c::getUpdateFrameCount() & 0b11) == 0) {
+ mLightningTimerMaybe--;
+ }
+ } else {
+ setLightningTimerMaybe(100);
+ }
+ sLib::addCalcScaledDiff(&field_0x11CC, 1.0f, 1.0f, 0.01f);
+ }
+
+ // TODO: inline doesn't work :(
+ dLightEnv_c::GetInstance().GetOverrideSpf().mIdxStart = 1;
+ dLightEnv_c::GetInstance().GetOverrideSpf().mIdxEnd = 2;
+ dLightEnv_c::GetInstance().GetOverrideSpf().mRatio = field_0x11CC;
+
+ if (mIsThunderBeamAttackActive && mThunderBeamTimer != 0) {
+ mThunderBeamTimer--;
+ mThunderBeamPosition += mThunderBeamVelocity;
+ nodeMtx.transS(mThunderBeamPosition);
+ nodeMtx.ZXYrotM(mThunderBeamRotation);
+
+ if (!mThunderBeamReflected) {
+ if (mLightningCc.ChkAtHit() || mLightningCc.ChkTgHit()) {
+ dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_850_, nodeMtx, nullptr, nullptr, 0, 0);
+ if (mLightningCc.ChkTgHit() && mLightningCc.ChkTgAtHitType(AT_TYPE_BUGNET)) {
+ // Reflect thunder beam attack with Bug Net
+ getSoundSource()->startSoundAtPosition2(SE_BLasBos_EmitThunderBeam, mThunderBeamPosition);
+ mThunderBeamTimer = 0x3C;
+ mThunderBeamVelocity *= -1.0f;
+ dRumble_c::start(dRumble_c::sRumblePreset2, dRumble_c::FLAG_SLOT0);
+ dStageMgr_c::GetInstance()->fn_80199B60(3);
+ mThunderBeamReflected = true;
+ } else {
+ mIsThunderBeamAttackActive = false;
+ mMtx_c mtx;
+ mtx.transS(0.0f, -100000.0f, 0.0f);
+ MTXConcat(nodeMtx, mtx, nodeMtx);
+ getSoundSource()->startSoundAtPosition2(SE_BLasBos_BeamCrossCrush, mThunderBeamPosition);
+ }
+ mLightningCc.SetTgRpm(0);
+ mLightningCc.ClrTgActorInfo();
+ mLightningCc.SubtractTgEffCounter();
+ mLightningCc.SetAtRpm(0);
+ mLightningCc.ClrAtActorInfo();
+ mLightningCc.SubtractAtEffCounter();
+ }
+ } else {
+ if ((mThunderBeamPosition - mPosition).absXZ() < 150.0f) {
+ // Boss hit by bug net reflected attack
+ dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_850_, nodeMtx, nullptr, nullptr, 0, 0);
+ mIsThunderBeamAttackActive = false;
+ mMtx_c mtx;
+ mtx.transS(0.0f, -100000.0f, 0.0f);
+ MTXConcat(nodeMtx, mtx, nodeMtx);
+ getSoundSource()->startSoundAtPosition2(SE_BLasBos_BeamCrossCrush, mThunderBeamPosition);
+ v3.set(0.0f, 0.0f, 20.0f);
+ rotMtx.YrotS(link->mRotation.y);
+ MTXMultVec(rotMtx, v3, v3);
+ mAttackKnockbackX = v3.x;
+ mAttackKnockbackZ = v3.z;
+ mStateMgr.changeState(StateID_Stun);
+ }
+ }
+ mLightInfo.mPos = mThunderBeamPosition;
+ if ((dScGame_c::getUpdateFrameCount() & 2) != 0) {
+ mLightInfo.SetScale(300.0f);
+ } else {
+ mLightInfo.SetScale(200.0f);
+ }
+
+ if (mThunderBeamTimer <= 10) {
+ // TODO: lightning timer?
+ if (mThunderBeamTimer == 10) {
+ mEmitter5.setFading(10);
+ }
+ if (mThunderBeamTimer == 0) {
+ mIsThunderBeamAttackActive = false;
+ }
+ mLightningCc.ClrAtSet();
+ } else {
+ if (!mThunderBeamReflected) {
+ mLightningCc.OnAtSet();
+ mLightningCc.SetR(100.0f);
+ mLightningCc.moveCenter(mThunderBeamPosition);
+ dCcS::GetInstance()->Set(&mLightningCc);
+ }
+ getSoundSource()->holdSoundAtPosition(SE_BLasBos_ThunderBeamFly, mThunderBeamPosition);
+ }
+ mEmitter5.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_618_, nodeMtx, nullptr, nullptr);
+ }
+
+ if (mLightingFallSwordTimer != 0) {
+ mLightingFallSwordTimer--;
+ mLightningCc.OnAtSet();
+ mLightningCc.SetC(mPosition);
+ mLightningCc.SetR(300.0f - mLightingFallSwordTimer * 30.0f);
+ mLightningCc.SetAtVec(link->getPosition() - mPosition);
+ dCcS::GetInstance()->Set(&mLightningCc);
+ if (mLightingFallSwordTimer == 8) {
+ vEff.x = mPosition.x;
+ vEff.y = 10.0f;
+ vEff.z = mPosition.z;
+ dJEffManager_c::spawnEffect(
+ PARTICLE_RESOURCE_ID_MAPPING_842_, vEff, nullptr, nullptr, nullptr, nullptr, 0, 0
+ );
+ }
+ }
+ executeLightningStrike();
+
+ SceneflagManager *mgr = SceneflagManager::sInstance;
+ if (mgr != nullptr) {
+ if (mStateMgr.isState(StateID_ThunderWait)) {
+ mgr->setFlag(getRoomId(), mThunderWaitSceneFlag);
+ } else {
+ mgr->unsetFlag(getRoomId(), mThunderWaitSceneFlag);
+ }
+ }
+
+ if (mIsPhaseTwo != 0) {
+ // "Target lock: Demise" (Phase 2)
+ mTargetFiTextID = 0x38;
+ } else {
+ // "Target lock: Demise" (Phase 1)
+ mTargetFiTextID = 0x37;
+ }
+
+ return SUCCEEDED;
+}
+
+struct dCcD_Check : public cCcD_Obj {
+ bool ChkAtHit();
+ bool ChkTgHit();
+};
+
+bool dCcD_Check::ChkAtHit() {
+ if (cCcD_Obj::ChkAtHit()) {
+ return true;
+ }
+ return false;
+}
+
+bool dCcD_Check::ChkTgHit() {
+ if (cCcD_Obj::ChkTgHit()) {
+ return true;
+ }
+ return false;
+}
+
+void dAcBlastboss_c::callback_c::timingB(u32 nodeId, nw4r::g3d::WorldMtxManip *manip, nw4r::g3d::ResMdl mdl) {
+ u32 baseNodeIdSkirt = 0;
+ u32 baseNodeIdHair = 0;
+ int r27;
+ int param_4;
+
+ if (nodeId >= B_LAST_BOSS_NODE_skirtA1 && nodeId < B_LAST_BOSS_NODE_skirtAU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtA1;
+ param_4 = 0;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtB1 && nodeId < B_LAST_BOSS_NODE_skirtBU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtB1;
+ param_4 = 1;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtC1 && nodeId < B_LAST_BOSS_NODE_skirtCU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtC1;
+ param_4 = 2;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtD1 && nodeId < B_LAST_BOSS_NODE_skirtDU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtD1;
+ param_4 = 3;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtE1 && nodeId < B_LAST_BOSS_NODE_skirtEU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtE1;
+ param_4 = 4;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtF1 && nodeId < B_LAST_BOSS_NODE_skirtFU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtF1;
+ param_4 = 5;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtG1 && nodeId < B_LAST_BOSS_NODE_skirtGU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtG1;
+ param_4 = 6;
+ } else if (nodeId >= B_LAST_BOSS_NODE_skirtH1 && nodeId < B_LAST_BOSS_NODE_skirtHU1) {
+ baseNodeIdSkirt = B_LAST_BOSS_NODE_skirtH1;
+ param_4 = 7;
+ }
+
+ if (baseNodeIdSkirt != 0) {
+ u32 nodeOffset = nodeId - baseNodeIdSkirt;
+
+ mMtx_c mtx;
+ mtx.transS(mpOwner->field_0x1268[param_4].field_0x014[nodeOffset]);
+ mtx.XrotM(mpOwner->field_0x1268[param_4].field_0x08C[nodeOffset].x);
+ mtx.YrotM(mpOwner->field_0x1268[param_4].field_0x08C[nodeOffset].y);
+ mtx.ZrotM(-mpOwner->field_0x1268[param_4].field_0x08C[nodeOffset].z);
+ mtx.scaleM(0.95f, 0.95f, 1.0f);
+ mtx.YrotM(-0x4000);
+ manip->SetMtx(mtx);
+ }
+
+ if (nodeId >= B_LAST_BOSS_NODE_hairA1 && nodeId < B_LAST_BOSS_NODE_hairBL1) {
+ baseNodeIdHair = B_LAST_BOSS_NODE_hairA1;
+ r27 = 0;
+ }
+
+ if (baseNodeIdHair != 0) {
+ u32 nodeOffset = nodeId - baseNodeIdHair;
+ mMtx_c mtx;
+ mtx.transS(mpOwner->field_0x2948[r27].field_0x008[nodeOffset]);
+ mtx.YrotM(mpOwner->field_0x2948[r27].field_0x044[nodeOffset].y);
+ mtx.XrotM(mpOwner->field_0x2948[r27].field_0x044[nodeOffset].x);
+ mtx.ZrotM(-mpOwner->field_0x2948[r27].field_0x044[nodeOffset].z);
+ mtx.scaleM(0.95f, 0.95f, 1.0f);
+ mtx.YrotM(-0x4000);
+ manip->SetMtx(mtx);
+ }
+
+ if (nodeId == B_LAST_BOSS_NODE_center) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.XrotM(-field_0x0E.mVal / 2);
+ mtx.ZrotM(-field_0x10.mVal / 2);
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_backbone1 || nodeId == B_LAST_BOSS_NODE_backbone2) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.YrotM(field_0x0E);
+ mtx.XrotM(field_0x2E - field_0x0E);
+ mtx.ZrotM(-field_0x10);
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_head) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.YrotM(field_0x0E * 2 + field_0x08 + field_0x06);
+ mtx.ZrotM(field_0x0A - field_0x10 * 2);
+ mtx.XrotM(field_0x0C);
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_chin) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.ZrotM(field_0x12);
+ manip->SetMtx(mtx);
+ } else if (nodeId >= B_LAST_BOSS_NODE_hairBL1 && nodeId <= B_LAST_BOSS_NODE_hairC3) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+
+ if (nodeId >= B_LAST_BOSS_NODE_hairC1) {
+ mtx.XrotM(field_0x1C[nodeId - B_LAST_BOSS_NODE_hairBL1]);
+ mtx.ZrotM(field_0x1C[nodeId - B_LAST_BOSS_NODE_hairBL1]);
+ } else {
+ mtx.YrotM(field_0x1C[nodeId - B_LAST_BOSS_NODE_hairBL1]);
+ mtx.XrotM(field_0x1C[nodeId - B_LAST_BOSS_NODE_hairBL1]);
+ }
+
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_armR1) {
+ int blah = field_0x04 * mAng(field_0x04 * 0x4300).sin() * 80.0f;
+
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+
+ mtx.XrotM(blah + (int)(300.0f * field_0x30));
+ mtx.ZrotM(blah + (int)(200.0f * field_0x30));
+
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_armR2) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.ZrotM(field_0x30 * 200.0f);
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_wristR) {
+ // unused
+ int blah = field_0x04 * (f32)mAng(field_0x04 * 0x4300).sin();
+
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+
+ int i2 = 0;
+ if (field_0x30 > 0.0f) {
+ i2 = field_0x30 * -200.0f;
+ }
+
+ mtx.XrotM(i2 + field_0x18);
+ mtx.ZrotM(i2 + field_0x1A);
+
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_legR1 || nodeId == B_LAST_BOSS_NODE_legR2) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.XrotM(field_0x14);
+ if (nodeId == B_LAST_BOSS_NODE_legR2) {
+ mtx.XrotM(field_0x14);
+ }
+ manip->SetMtx(mtx);
+ } else if (nodeId == B_LAST_BOSS_NODE_legL1 || nodeId == B_LAST_BOSS_NODE_legL2) {
+ mMtx_c mtx;
+ manip->GetMtx(mtx);
+ mtx.XrotM(field_0x16);
+ if (nodeId == B_LAST_BOSS_NODE_legL2) {
+ mtx.XrotM(field_0x16);
+ }
+ manip->SetMtx(mtx);
+ }
+}
+
+void dAcBlastboss_c::initializeState_Fight() {
+ setAnm("WaitBt", 20.0f);
+ mAnmRate = 1.0f;
+ mSubState = SUB_STATE_0;
+ field_0x118A = 0;
+ if (mIsPhaseTwo == 0) {
+ mTimers[TIMER_2] = cM::rndF(50.0f) + 50.0f;
+ } else {
+ mTimers[TIMER_2] = cM::rndF(20.0f) + 10.0f;
+ }
+ mGuardDirection = GUARD_BT;
+}
+void dAcBlastboss_c::executeState_Fight() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ field_0x1131 = 1;
+ f32 targetSpeed = 0.0f;
+ f32 targetAnmRate = 1.5f;
+ f32 puVar2 = 0.0f;
+
+ bool b = false;
+ s16 diff = mAngle.y - mYAngleToLink;
+
+ if (mLightingStrikeState >= LIGHTNING_STRIKE_TRIGGER_START && mLightingStrikeState <= LIGHTNING_STRIKE_START_LAST) {
+ puVar2 = -100.0f;
+ mTimers[TIMER_2] = cM::rndF(50.0f) + 100.0f;
+ }
+
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ b = true;
+ field_0x118C = 0;
+ targetAnmRate = 1.0f;
+ field_0x117E = 0;
+ if (mXZDistanceToLink > puVar2 + 450.0f) {
+ mSubState = SUB_STATE_2;
+ break;
+ } else if (mXZDistanceToLink < puVar2 + 250.0f + 100.0f) {
+ mSubState = SUB_STATE_1;
+ mTimers[TIMER_0] = 8;
+ mAnmRate = -1.0f;
+ field_0x1180 = 0;
+ // fall-through...
+ } else {
+ setAnm("WaitBt", 20.0f);
+ mAnmRate = 1.0f;
+ if (diff < -0x1000 || diff > 0x1000) {
+ mSubState = SUB_STATE_4;
+ if (diff < 0) {
+ setAnm("TurnL", 10.0f);
+ } else {
+ setAnm("TurnR", 10.0f);
+ }
+ }
+ break;
+ }
+ }
+ case SUB_STATE_1: {
+ b = true;
+ setAnm("WalkBt", 20.0f);
+ targetSpeed = -5.0f;
+ targetAnmRate = -2.5f;
+ if (mXZDistanceToLink < 200.0f) {
+ field_0x1180++;
+ if (field_0x1180 > 40) {
+ mStateMgr.changeState(StateID_PunchAttack);
+ return;
+ }
+ } else if (mXZDistanceToLink >= puVar2 + 200.0f && mTimers[TIMER_0] == 0) {
+ mSubState = SUB_STATE_0;
+ }
+ break;
+ }
+ case SUB_STATE_2: {
+ b = true;
+ field_0x117E = 0;
+ if (mXZDistanceToLink > puVar2 + 850.0f) {
+ mSubState = SUB_STATE_3;
+ } else {
+ setAnm("WalkBt", 20.0f);
+ if (mMdl.getAnm().getFrame() >= 25.0f && mMdl.getAnm().getFrame() <= 50.0f) {
+ targetSpeed = 5.0f;
+ }
+ field_0x11A4 = 5.0f;
+ targetAnmRate = 1.5f;
+ }
+ if (mXZDistanceToLink < puVar2 + 400.0f) {
+ mSubState = SUB_STATE_0;
+ if (mIsPhaseTwo == 0) {
+ mTimers[TIMER_2] = cM::rndF(50.0f) + 50.0f;
+ } else {
+ mTimers[TIMER_2] = cM::rndF(20.0f) + 10.0f;
+ }
+ }
+ break;
+ }
+ case SUB_STATE_3: {
+ setAnm("Walk", 20.0f);
+ targetSpeed = 7.5f;
+ field_0x11A4 = 7.5f;
+ targetAnmRate = 1.0f;
+ if (mXZDistanceToLink < puVar2 + 750.0f) {
+ mSubState = SUB_STATE_2;
+ } else if (!link->isRecovering()) {
+ field_0x117E++;
+ if (field_0x117E > 70) {
+ mStateMgr.changeState(StateID_DashAttack);
+ return;
+ }
+ } else {
+ field_0x117E = 0;
+ }
+ break;
+ }
+ case SUB_STATE_4: {
+ field_0x117E = 0;
+ b = true;
+ if (mMdl.getAnm().isStop()) {
+ mSubState = SUB_STATE_0;
+ }
+ break;
+ }
+ }
+
+ sLib::addCalcScaledDiff(&mAnmRate, targetAnmRate, 1.0f, 0.5f);
+ setAnmRate(mAnmRate);
+ sLib::addCalcScaledDiff(&mSpeed, targetSpeed, 1.0f, 2.0f);
+
+ if (mSubState != SUB_STATE_0) {
+ sLib::addCalcAngle(field_0x118C.ref(), 0x800, 1, 100);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, field_0x118C);
+ }
+
+ if (b) {
+ if (diff > 0x1000) {
+ diff = 0x1000;
+ } else if (diff < -0x1000) {
+ diff = -0x1000;
+ }
+ field_0x1172 = diff / 2;
+ // approx. 160/65536, but maybe hardcoded?
+ sLib::addCalcScaledDiff(&mMdlCallback.field_0x30, diff * (1.0f / 409.59937f), 0.5f, 1.0f);
+ if (mLightingStrikeState == LIGHTNING_STRIKE_STATE_NONE && !link->isUsingShield() && link->isUsingSword()) {
+ mMtx_c rotMtx;
+ rotMtx.YrotS(-mYAngleToLink);
+ mVec3_c v = mVec3_c(link->getSwordPos() - mPosition);
+ MTXMultVec(rotMtx, v, v);
+ if (v.x > 150.0f) {
+ v.x = 150.0f;
+ } else if (v.x < -150.0f) {
+ v.x = -150.0f;
+ }
+ sLib::addCalcAngle(field_0x118A.ref(), 400, 1, 20);
+ sLib::addCalcAngle(mMdlCallback.field_0x18.ref(), mAng(v.x * -40.0f), 2, field_0x118A);
+ v.y -= 270.0f;
+ if (v.y > 100.0f) {
+ v.y = 100.0f;
+ } else if (v.y < -150.0f) {
+ v.y = -150.0f;
+ }
+ sLib::addCalcAngle(mMdlCallback.field_0x1A.ref(), mAng(v.y * -40.0f), 2, field_0x118A);
+ } else {
+ field_0x118A = 0;
+ sLib::addCalcAngle(mMdlCallback.field_0x18.ref(), 0, 4, 400);
+ sLib::addCalcAngle(mMdlCallback.field_0x1A.ref(), 0, 4, 400);
+ }
+ field_0x1133 = 1;
+ }
+
+ if (field_0x117C == 0) {
+ if (!checkForRangeAttack()) {
+ checkForCloseRangeAttack();
+ checkForCounter();
+ }
+ mCc1.SetTgFlag_0xA(0x1FF);
+ } else {
+ // TODO
+ mCc1.SetTgFlag_0xA(0);
+ }
+
+ if (mTimers[TIMER_4] == 1) {
+ field_0x1178 = 40;
+ } else if (mTimers[TIMER_4] <= 10) {
+ mNumConsecutiveSameDirectionAttacks = 0;
+ mNumConsecutiveOppositeDirectionAttacks = 0;
+ mChanceAttackCounter = 0;
+ mLastAttackDir = mSecondLastAttackDirection = -1;
+ }
+}
void dAcBlastboss_c::finalizeState_Fight() {}
-void dAcBlastboss_c::initializeState_Guard() {}
-void dAcBlastboss_c::executeState_Guard() {}
-void dAcBlastboss_c::finalizeState_Guard() {}
-void dAcBlastboss_c::initializeState_GuardBreak() {}
-void dAcBlastboss_c::executeState_GuardBreak() {}
-void dAcBlastboss_c::finalizeState_GuardBreak() {}
-void dAcBlastboss_c::initializeState_Attack() {}
-void dAcBlastboss_c::executeState_Attack() {}
+
+void dAcBlastboss_c::initializeState_Attack() {
+ f32 rnd = cM::rnd();
+ mSubState = SUB_STATE_0;
+ if (rnd < 0.3333f) {
+ setAnm("AttackU", 5.0f);
+ } else if (rnd < 0.6666f) {
+ setAnm("AttackR", 5.0f);
+ } else {
+ setAnm("AttackL", 5.0f);
+ }
+
+ if (mIsSwordEmpowered) {
+ mSwordMdl.setDamageMaybe(8);
+ } else {
+ mSwordMdl.setDamageMaybe(4);
+ }
+ mSwordMdl.fn_8006B7A0(0x20000);
+}
+void dAcBlastboss_c::executeState_Attack() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ field_0x1131 = 1;
+ f32 speed = 0.0f;
+ // TODO major typing crime here but I'm not sure how this actually works
+ cCcD_Obj *atHit = mSwordMdl.mCcList.find((dColliderLinkedList::ccPtmf)&dCcD_Check::ChkAtHit);
+
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (field_0x1152 >= 15 && mMdl.getAnm().checkFrame(7.0f) && cM::rnd() < 0.1f) {
+ mStateMgr.changeState(StateID_Fight);
+ field_0x113F = 20;
+ } else {
+ if (mMdl.getAnm().getFrame() < 20.0f) {
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x800);
+ }
+
+ if (mMdl.getAnm().getFrame() >= 25.0f && mMdl.getAnm().getFrame() <= 28.0f) {
+ mSwordMdl.enable();
+ speed = 20.0f;
+ field_0x11A4 = 20.0f;
+ field_0x113D = 10;
+ }
+ if (atHit != nullptr) {
+ mSubState = SUB_STATE_1;
+ } else {
+ if (mMdl.getAnm().getFrame() > 28.0f) {
+ mSubState = SUB_STATE_1;
+ if (field_0x113E != 0) {
+ setAnmRate(0.5f);
+ }
+ }
+ }
+ }
+ break;
+ }
+ case SUB_STATE_1: {
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ break;
+ }
+ }
+
+ mSpeed = speed;
+ if (!mIsPhaseTwo && link->checkCurrentAction(/* BACKFLIP */ 0x62)) {
+ field_0x113E = 20;
+ }
+ if (field_0x113E != 0) {
+ if (mIsPhaseTwo) {
+ mSubState = SUB_STATE_0;
+ mStateMgr.changeState(StateID_CounterAttack);
+ return;
+ }
+ mCc1.SetTgFlag_0xA(0);
+ } else {
+ if (mpCurrentAnm == "AttackR") {
+ mCc1.SetTgFlag_0xA(0xE);
+ } else if (mpCurrentAnm == "AttackL") {
+ mCc1.SetTgFlag_0xA(0xE0);
+ } else {
+ mCc1.SetTgFlag_0xA(0x1);
+ }
+ }
+ checkForCounter();
+}
void dAcBlastboss_c::finalizeState_Attack() {}
-void dAcBlastboss_c::initializeState_CounterAttack() {}
-void dAcBlastboss_c::executeState_CounterAttack() {}
+
+void dAcBlastboss_c::initializeState_CounterAttack() {
+ mSwordMdl.fn_8006B7A0(0x20000);
+ if (mSubState == 0) {
+ setAnm("Counter", 5.0f);
+ } else {
+ f32 rnd = cM::rnd();
+ if (rnd < 0.3333f) {
+ setAnm("AttackU", 5.0f);
+ } else if (rnd < 0.6666f) {
+ setAnm("AttackR", 5.0f);
+ } else {
+ setAnm("AttackL", 5.0f);
+ }
+ mMdl.setFrame(5.0f);
+ }
+
+ mNumConsecutiveSameDirectionAttacks = 0;
+ mNumConsecutiveOppositeDirectionAttacks = 0;
+ mLastAttackDir = mSecondLastAttackDirection = -1;
+}
+void dAcBlastboss_c::executeState_CounterAttack() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ f32 speed = 0.0f;
+ bool b = false;
+ field_0x1131 = 1;
+ if (mSubState == SUB_STATE_0) {
+ if (mMdl.getAnm().getFrame() < 15.0f) {
+ speed = -10.0f;
+ }
+ if (mMdl.getAnm().getFrame() < 10.0f ||
+ (mMdl.getAnm().getFrame() > 30.0f && mMdl.getAnm().getFrame() < 40.0f)) {
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x800);
+ }
+
+ if ((mMdl.getAnm().getFrame() >= 20.0f && mMdl.getAnm().getFrame() <= 23.0f) ||
+ (mMdl.getAnm().getFrame() >= 43.0f && mMdl.getAnm().getFrame() <= 47.0f)) {
+ mSwordMdl.enable();
+ speed = 30.0f;
+ field_0x11A4 = 20.0f;
+ }
+
+ int targetFrame = 42;
+ if (mMdl.getAnm().checkFrame(targetFrame) && mXZDistanceToLink > 400.0f) {
+ mStateMgr.changeState(StateID_Fight);
+ return;
+ }
+ if (mMdl.getAnm().getFrame() >= 52.0f) {
+ b = true;
+ }
+ } else {
+ if (mMdl.getAnm().getFrame() < 20.0f) {
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x800);
+ }
+ if (mMdl.getAnm().getFrame() >= 25.0f && mMdl.getAnm().getFrame() <= 28.0f) {
+ mSwordMdl.enable();
+ speed = 10.0f;
+ field_0x11A4 = 20.0f;
+ field_0x113D = 5;
+ }
+ if (mMdl.getAnm().getFrame() >= 33.0f) {
+ b = true;
+ }
+ }
+
+ if (link->checkCurrentAction(/* BACKFLIP */ 0x62)) {
+ field_0x113E = 20;
+ }
+ mCc1.SetTgFlag_0xA(0);
+ if (field_0x113E != 0) {
+ field_0x1142 = 0;
+ field_0x1134 = 0;
+ } else if (b) {
+ mCc1.SetTgFlag_0xA(0x1FF);
+ field_0x1142 = 0;
+ checkForCounter();
+ }
+
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ mSpeed = speed;
+}
void dAcBlastboss_c::finalizeState_CounterAttack() {}
-void dAcBlastboss_c::initializeState_PunchAttack() {}
-void dAcBlastboss_c::executeState_PunchAttack() {}
+
+void dAcBlastboss_c::initializeState_PunchAttack() {
+ setAnm("AttackBreak", 5.0f);
+ mSwordMdl.fn_8006B7A0(0x20000);
+ mSubState = 0;
+}
+void dAcBlastboss_c::executeState_PunchAttack() {
+ f32 speed = 0.0f;
+ field_0x1131 = 1;
+ mCc1.SetTgFlag_0xA(0);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x800);
+ if (mMdl.getAnm().getFrame() < 15.0f) {
+ speed = -10.0f;
+ }
+ if (mMdl.getAnm().getFrame() >= 15.0f && mMdl.getAnm().getFrame() <= 23.0f) {
+ speed = 40.0f;
+ }
+ if (mMdl.getAnm().checkFrame(15.0f)) {
+ field_0x1139 = 1;
+ }
+ if (mMdl.getAnm().checkFrame(23.0f)) {
+ field_0x1139 = 0;
+ }
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ mSpeed = speed;
+}
void dAcBlastboss_c::finalizeState_PunchAttack() {}
-void dAcBlastboss_c::initializeState_DashAttack() {}
-void dAcBlastboss_c::executeState_DashAttack() {}
+
+void dAcBlastboss_c::initializeState_DashAttack() {
+ mSubState = 0;
+ mSwordMdl.setDamageMaybe(8);
+ mSwordMdl.fn_8006B7A0(0x20000);
+}
+void dAcBlastboss_c::executeState_DashAttack() {
+ field_0x1131 = 1;
+ f32 targetSpeed = 0.0f;
+ f32 stepSize = 40.0f; // never set differently
+ mCc1.SetTgFlag_0xA(0x1FF);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x1000);
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mXZDistanceToLink < 400.0f) {
+ mStateMgr.changeState(StateID_CounterAttack);
+ return;
+ }
+ setAnm("AttackJumpStart", 5.0f);
+ mSwordMdl.fn_8006B7A0(0x20000);
+ mSubState = SUB_STATE_1;
+ // fall-through
+ }
+ case SUB_STATE_1: {
+ if (mMdl.getAnm().getFrame() >= 23.0f) {
+ field_0x11A4 = 30.0f;
+ targetSpeed = 40.0f;
+ }
+ if (mMdl.getAnm().isStop()) {
+ setAnm("AttackJumpLoop", 0.0f);
+ mSubState = SUB_STATE_2;
+ mTimers[TIMER_0] = 200;
+ }
+ break;
+ }
+ case SUB_STATE_2: {
+ field_0x11A4 = 30.0f;
+ targetSpeed = 80.0f;
+ field_0x11B8 = 5.0f;
+ if (mXZDistanceToLink < 750.0f) {
+ setAnm("AttackJumpEnd", 0.0f);
+ mSubState = SUB_STATE_3;
+ } else if (mTimers[TIMER_0] == 0) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ break;
+ }
+ case SUB_STATE_3: {
+ if (mXZDistanceToLink > 300.0f && mMdl.getAnm().getFrame() <= 6.0f) {
+ targetSpeed = 80.0f;
+ } else {
+ stepSize = 40.0f;
+ }
+ if (mMdl.getAnm().getFrame() >= 6.0f && mMdl.getAnm().getFrame() <= 9.0f) {
+ mSwordMdl.enable();
+ field_0x113D = 10;
+ }
+
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ break;
+ }
+ }
+
+ sLib::addCalcScaledDiff(&mSpeed, targetSpeed, 1.0f, stepSize);
+ if (mSpeed > 50.0f) {
+ // @bug: effect rotation never updated due to static...
+ static mAng3_c sEffRot(0, mRotation.y, 0);
+ static mVec3_c sEffScale(1.0f, 1.0f, 1.0f);
+ mVec3_c effPos(mPosition.x, 10.0f, mPosition.z);
+ mEmitter2.holdEffect(PARTICLE_RESOURCE_ID_MAPPING_858_, effPos, &sEffRot, &sEffScale, nullptr, nullptr);
+ }
+}
void dAcBlastboss_c::finalizeState_DashAttack() {}
-void dAcBlastboss_c::initializeState_SmallAttack() {}
-void dAcBlastboss_c::executeState_SmallAttack() {}
+
+void dAcBlastboss_c::initializeState_SmallAttack() {
+ setAnm("AttackSwordBreak", 5.0f);
+ mSubState = SUB_STATE_0;
+}
+void dAcBlastboss_c::executeState_SmallAttack() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ field_0x1131 = 1;
+ f32 targetSpeed = 0.0f;
+
+ mCc1.SetTgFlag_0xA(0);
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mMdl.getAnm().getFrame() >= 31.0f && mMdl.getAnm().getFrame() <= 33.0f) {
+ field_0x11A4 = 15.0f;
+ if (checkForLinkSwordBySwordHit()) {
+ mVec3_c effPos;
+
+ effPos = link->vt_0x278() + (link->getSwordPos() - link->vt_0x278()) * 0.4f;
+ dJEffManager_c::spawnEffect(
+ PARTICLE_RESOURCE_ID_MAPPING_388_, effPos, &mRotation, nullptr, nullptr, nullptr, 0, 0
+ );
+ dRumble_c::start(dRumble_c::sRumblePreset4, dRumble_c::FLAG_SLOT0);
+ startSound(SE_BLasBos_SwordBySword);
+ link->onForceOrPreventActionFlags(0x80000);
+ mSubState = SUB_STATE_1;
+ }
+ }
+ break;
+ }
+ }
+
+ if (mMdl.getAnm().checkFrame(44.0f) && mSubState != SUB_STATE_1) {
+ mStateMgr.changeState(StateID_Fight);
+ mpCurrentAnm = nullptr;
+ setAnm("WaitBt", 40.0f);
+ field_0x113E = 10;
+ field_0x1134 = 0;
+ }
+
+ if (mMdl.getAnm().getFrame() >= 55.0f && mMdl.getAnm().getFrame() <= 59.0f) {
+ mSwordMdl.enable();
+ targetSpeed = 40.0f;
+ field_0x11A4 = 20.0f;
+ }
+
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+
+ sLib::addCalcScaledDiff(&mSpeed, targetSpeed, 1.0f, 20.0f);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x200);
+}
void dAcBlastboss_c::finalizeState_SmallAttack() {}
-void dAcBlastboss_c::initializeState_ThunderAttack() {}
-void dAcBlastboss_c::executeState_ThunderAttack() {}
+
+void dAcBlastboss_c::initializeState_ThunderAttack() {
+ setAnm("AttackThunder", 5.0f);
+ mSubState = SUB_STATE_0;
+}
+void dAcBlastboss_c::executeState_ThunderAttack() {
+ field_0x1131 = 1;
+ f32 targetSpeed = 0.0f;
+ mCc1.SetTgFlag_0xA(0);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x400);
+ if (mMdl.getAnm().getFrame() >= 21.0f && mMdl.getAnm().getFrame() <= 25.0f) {
+ mSwordMdl.enable();
+ field_0x11A4 = 20.0f;
+ if (mMdl.getAnm().checkFrame(23.0f)) {
+ mIsSwordEmpowered = false;
+ mCc1.ClrTg_0x8000000();
+ mSwordMdl.fn_8006B800(0);
+ mIsThunderBeamAttackActive = true;
+ mThunderBeamTimer = 60;
+ mThunderBeamReflected = false;
+ mThunderBeamRotation = mRotation;
+ mVec3_c v(0.0f, 100.0f, 300.0f);
+ mMtx_c mtx;
+ mtx.YrotS(mRotation.y);
+ MTXMultVec(mtx, v, mThunderBeamPosition);
+ mThunderBeamPosition += mPosition;
+
+ v.set(0.0f, 0.0f, 50.0f);
+ MTXMultVec(mtx, v, mThunderBeamVelocity);
+ mLightningCc.setCenter(mThunderBeamPosition);
+ setLightningTimerMaybe(30);
+ startSound(SE_BLasBos_EmitThunderBeam);
+ }
+ }
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+
+ sLib::addCalcScaledDiff(&mSpeed, targetSpeed, 1.0f, 5.0f);
+}
void dAcBlastboss_c::finalizeState_ThunderAttack() {}
-void dAcBlastboss_c::initializeState_Damage() {}
-void dAcBlastboss_c::executeState_Damage() {}
+
+void dAcBlastboss_c::initializeState_Guard() {
+ mSubState = SUB_STATE_0;
+ mMdlCallback.field_0x30 = 0.0f;
+ mMdlCallback.field_0x18 = 0;
+}
+void dAcBlastboss_c::executeState_Guard() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ field_0x1131 = 1;
+ f32 targetSpeed = 0.0f;
+
+ static const char *sGuardNames[] = {
+ "GuardR", "GuardRU", "GuardRD", "GuardL", "GuardLU", "GuardLD", "GuardU", "GuardD", "GuardC", "WaitBt",
+ };
+
+ static const u32 sGuardFlags[] = {
+ 0x8 | 0x4 | 0x2,
+ 0x8 | 0x4 | 0x2,
+ 0x10 | 0x8 | 0x4 | 0x2,
+ 0x80 | 0x40 | 0x20,
+ 0x80 | 0x40 | 0x20,
+ 0x80 | 0x40 | 0x20 | 0x10,
+ 0x80 | 0x2 | 0x1,
+ 0x20 | 0x10 | 0x8,
+ 0x100,
+ 0x100 | 0x80 | 0x40 | 0x20 | 0x10 | 0x8 | 0x4 | 0x2 | 0x1,
+ };
+
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (link->isAttackingJumpSlash()) {
+ mSubState = SUB_STATE_2;
+ setAnm("WalkBt", 2.0f);
+ setAnmRate(-2.0f);
+ mTimers[TIMER_0] = 5;
+ break;
+ } else {
+ if (mGuardDirection == GUARD_BT) {
+ setAnm(sGuardNames[mGuardDirection], 3.0f);
+ mTimers[TIMER_0] = 14;
+ } else {
+ forceSetAnm(sGuardNames[mGuardDirection], 3.0f);
+ }
+ mSubState = SUB_STATE_1;
+ // fall-through
+ }
+ }
+ case SUB_STATE_1: {
+ if (link->isAttackingSpin()) {
+ mTimers[TIMER_0] = 5;
+ }
+
+ if (mGuardDirection == GUARD_BT) {
+ field_0x1133 = 1;
+ if (mTimers[TIMER_0] == 0) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+ } else if (mMdl.getAnm().getFrame() >= 13.0f) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+
+ if (!link->isAttackingJumpSlash()) {
+ checkForCounter();
+ }
+ break;
+ }
+ case SUB_STATE_2: {
+ field_0x11A4 = 20.0f;
+ targetSpeed = -30.0f;
+ if (mTimers[TIMER_0] == 0) {
+ mGuardDirection = GUARD_UP;
+ forceSetAnm(sGuardNames[mGuardDirection], 3.0);
+ mSubState = SUB_STATE_1;
+ }
+ break;
+ }
+ case SUB_STATE_10: {
+ if (mGuardDirection == GUARD_RIGHT) {
+ setAnm("AttackRGuard", 3.0f);
+ } else if (mGuardDirection == GUARD_LEFT) {
+ setAnm("AttackLGuard", 3.0f);
+ } else {
+ setAnm("GuardU", 3.0f);
+ }
+ mSubState = SUB_STATE_11;
+ // fall-through
+ }
+ case SUB_STATE_11: {
+ if (mMdl.getAnm().getFrame() >= 13.0f) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+ break;
+ }
+ }
+
+ sLib::addCalcScaledDiff(&mSpeed, targetSpeed, 1.0f, 5.0f);
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x1000);
+
+ if (field_0x113E != 0) {
+ setAnmRate(0.2f);
+ } else {
+ setAnmRate(1.0f);
+ if (link->isAttacking()) {
+ switch (dAcPy_c::GetLinkM()->getSpecificAttackDirection()) {
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWN: mGuardDirection = GUARD_UP; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_LEFT: mGuardDirection = GUARD_LEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT: mGuardDirection = GUARD_UPLEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT: mGuardDirection = GUARD_DOWNLEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_RIGHT: mGuardDirection = GUARD_RIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT: mGuardDirection = GUARD_UPRIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT: mGuardDirection = GUARD_DOWNRIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UP: mGuardDirection = GUARD_DOWN; break;
+ default: mGuardDirection = GUARD_CENTER; break;
+ }
+ setAnm(sGuardNames[mGuardDirection], 3.0);
+ }
+ }
+
+ mCc1.SetTgFlag_0xA(sGuardFlags[mGuardDirection]);
+ checkForRangeAttack();
+}
+void dAcBlastboss_c::finalizeState_Guard() {}
+
+void dAcBlastboss_c::initializeState_GuardBreak() {
+ s32 side;
+ s32 attackDir = dAcPy_c::GetLinkM()->getSpecificAttackDirection();
+ if (attackDir == daPlayerActBase_c::ATTACK_DIRECTION_LEFT ||
+ attackDir == daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT ||
+ attackDir == daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT) {
+ side = 0;
+ } else if (attackDir == daPlayerActBase_c::ATTACK_DIRECTION_RIGHT ||
+ attackDir == daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT ||
+ attackDir == daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT) {
+ side = 1;
+ } else {
+ side = (s32)cM::rndF(1.99f);
+ }
+
+ if (side == 0) {
+ setAnm("GuardBreak", 5.0f);
+ } else {
+ setAnm("GuardBreakB", 5.0f);
+ }
+ mSubState = 0;
+ mTimers[TIMER_0] = 3;
+}
+void dAcBlastboss_c::executeState_GuardBreak() {
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+
+ if (mTimers[TIMER_0] == 1) {
+ mSpeed = -30.0f;
+ }
+ sLib::addCalcScaled(&mSpeed, 1.0f, 4.0f);
+ mCc1.SetTgFlag_0xA(0x1FF);
+ checkForCounter();
+}
+void dAcBlastboss_c::finalizeState_GuardBreak() {}
+
+void dAcBlastboss_c::initializeState_Damage() {
+ forceSetAnm("Damage", 5.0f);
+ mSubState = SUB_STATE_0;
+ mSpeed = -20.0f;
+ mChanceAttackCounter++;
+ field_0x1142 = 5;
+ startSound(SE_BLasBos_VO_DamageNormal);
+}
+void dAcBlastboss_c::executeState_Damage() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ sLib::addCalcScaled(&mSpeed, 1.0f, 2.0f);
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ mTimers[TIMER_2] = 0;
+ }
+ field_0x113E = 0;
+ if (mIsPhaseTwo == 0 && !link->isAttackingSpin()) {
+ mCc1.SetTgFlag_0xA(0x1FF);
+ }
+ checkForCounter();
+}
void dAcBlastboss_c::finalizeState_Damage() {}
-void dAcBlastboss_c::initializeState_SitDamage() {}
-void dAcBlastboss_c::executeState_SitDamage() {}
+
+void dAcBlastboss_c::initializeState_SitDamage() {
+ setAnm("Chance", 5.0f);
+ mSubState = 0;
+ mSpeed = -20.0f;
+ mChanceAttackCounter = 0;
+ mTimers[TIMER_0] = 80;
+ field_0x1142 = 5;
+ mChanceCounter++;
+}
+void dAcBlastboss_c::executeState_SitDamage() {
+ sLib::addCalcScaled(&mSpeed, 1.0f, 2.0f);
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mMdl.getAnm().isStop()) {
+ setAnm("ChanceLoop", 0.0f);
+ mSubState = SUB_STATE_1;
+ }
+ break;
+ }
+ case SUB_STATE_1: {
+ if (mTimers[TIMER_0] == 0 || mChanceAttackCounter >= 5) {
+ setAnm("ChanceReverse", 5.0f);
+ mSubState = SUB_STATE_2;
+ // fall-through
+ } else {
+ break;
+ }
+ }
+ case SUB_STATE_2: {
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+ checkForCounter();
+ mCc1.SetTgFlag_0xA(0x1FF);
+ return;
+ }
+ case SUB_STATE_5: {
+ if (field_0x1137 == 0) {
+ forceSetAnm("ChanceDamageU", 2.0f);
+ } else if (field_0x1137 == 1) {
+ forceSetAnm("ChanceDamageR", 2.0f);
+ } else if (field_0x1137 == 2) {
+ forceSetAnm("ChanceDamageL", 2.0f);
+ } else {
+ forceSetAnm("ChanceDamageD", 2.0f);
+ }
+ mSubState = SUB_STATE_6;
+ break;
+ }
+ case SUB_STATE_6: {
+ if (mTimers[TIMER_0] == 0 || mChanceAttackCounter >= 5) {
+ setAnm("ChanceReverse", 5.0f);
+ mSubState = SUB_STATE_2;
+ // fall-through
+ } else if (mMdl.getAnm().isStop()) {
+ setAnm("ChanceLoop", 0.0f);
+ mSubState = SUB_STATE_1;
+ }
+ }
+ }
+ mCc1.SetTgFlag_0xA(0);
+}
void dAcBlastboss_c::finalizeState_SitDamage() {}
-void dAcBlastboss_c::initializeState_Down() {}
-void dAcBlastboss_c::executeState_Down() {}
+
+void dAcBlastboss_c::initializeState_Down() {
+ setAnm("DownBStart", 5.0f);
+ mSubState = SUB_STATE_0;
+ mSpeed = -20.0f;
+ mAcceleration = -5.0f;
+ mVelocity.y = 60.0f;
+ mIsSwordEmpowered = false;
+ mCc1.ClrTg_0x8000000();
+ mSwordMdl.fn_8006B800(0);
+}
+void dAcBlastboss_c::executeState_Down() {
+ mVec3_c v;
+ mMtx_c mtx;
+
+ mIsDown = true;
+ field_0x1142 = 5;
+ bool b = false;
+ setLightningTimerMaybe(30);
+ mGuardDirection = -1;
+
+ // TODO: Are all these fall-throughs intentional??????
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mMdl.getAnm().isStop()) {
+ mSubState = SUB_STATE_1;
+ setAnm("DownBLoop", 0.0f);
+ field_0x11C0 = 20.0f;
+ }
+ // fall-through
+ }
+ case SUB_STATE_1: {
+ sLib::addCalcAngle(mAngle.x.ref(), -0x4000, 2, 0x300);
+ if (field_0x11BC <= -10.0f && field_0x1140) {
+ mSubState = SUB_STATE_2;
+ b = true;
+ setAnm("DownBEnd", 2.0f);
+ mVelocity.y = 30.0f;
+ } else {
+ field_0x11A4 = -30.0f;
+ break;
+ }
+ // fall-through
+ }
+ case SUB_STATE_2: {
+ if (mVelocity.y < 0.0f) {
+ field_0x11C0 = -35.0f;
+ }
+ sLib::addCalcAngle(mAngle.x.ref(), -0x4000, 2, 0x300);
+ if (field_0x11BC <= -10.0f && field_0x1140) {
+ b = true;
+ }
+ if (mMdl.getAnm().isStop()) {
+ setAnm("DownLoop", 0.0f);
+ mSubState = SUB_STATE_3;
+ if (field_0x113B >= 3 || mLightingStrikeState != LIGHTNING_STRIKE_STATE_NONE) {
+ mTimers[TIMER_0] = 70;
+ } else if (field_0x113B == 2) {
+ mTimers[TIMER_0] = 40;
+ } else {
+ mTimers[TIMER_0] = 25;
+ }
+ field_0x113B++;
+ } else {
+ sLib::addCalcScaled(&mSpeed, 1.0f, 1.0f);
+ if (mSpeed < 1.0f) {
+ mFinalBlowPosition.set(mChestTranslation.x, mChestTranslation.y, mChestTranslation.z);
+ setInteractionFlags(INTERACT_0x1);
+ }
+ break;
+ }
+ // fall-through
+ }
+ case SUB_STATE_3: {
+ mFinalBlowPosition.set(mChestTranslation.x, mChestTranslation.y, mChestTranslation.z);
+ sLib::addCalcScaled(&mSpeed, 1.0f, 1.0f);
+ if (checkInteractionFlags(INTERACT_0x1000)) {
+ setAnm("End", 3.0f);
+ mSubState = SUB_STATE_50;
+ mLightingStrikeState = LIGHTNING_STRIKE_TRIGGER_END;
+ startSound(SE_BLasBos_LastHit);
+ mIsDead = true;
+ resetInteractionFlags(INTERACT_0x1000);
+ resetInteractionFlags(INTERACT_0x1);
+ } else if (mTimers[TIMER_0] == 0) {
+ if (cM::rnd() < 0.5f || mLightingStrikeState != LIGHTNING_STRIKE_STATE_NONE) {
+ setAnm("DownEscapeR", 10.0f);
+ } else {
+ setAnm("DownEscapeL", 10.0f);
+ }
+ setAnmRate(0.65f);
+ mSubState = SUB_STATE_5;
+ field_0x11C8 = 0.0f;
+ resetInteractionFlags(INTERACT_0x1);
+ if (mLightingStrikeState != LIGHTNING_STRIKE_STATE_NONE) {
+ mLightingStrikeState = LIGHTNING_STRIKE_WAIT;
+ field_0x2D00 = 0.0f;
+ dLightEnv_c::GetPInstance()->setField_0x38DC(1);
+ }
+ }
+ break;
+ }
+ case SUB_STATE_4: {
+ if (mMdl.getAnm().getFrame() >= 52.0f) {
+ mIsDown = false;
+ sLib::addCalcAngle(mAngle.x.ref(), 0, 1, 910);
+ }
+ if (mMdl.getAnm().getFrame() >= 170.0f) {
+ field_0x1131 = 2;
+ }
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+ break;
+ }
+ case SUB_STATE_5: {
+ sLib::addCalcAngle(mAngle.x.ref(), 0, 1, 0x400);
+ if ((int)mMdl.getAnm().getFrame() <= 14) {
+ sLib::addCalcScaledDiff(&field_0x11C8, 15.0f, 1.0f, 5.0f);
+ field_0x11A4 = 20.0f;
+ } else {
+ mIsDown = false;
+ sLib::addCalcAngle(mAngle.y.ref(), mYAngleToLink, 2, 0x800);
+ sLib::addCalcScaled(&field_0x11C8, 1.0f, 5.0f);
+ }
+ mtx.YrotS(mRotation.y);
+ if (mpCurrentAnm == "DownEscapeR") {
+ v.set(-field_0x11C8, 0.0f, 0.0f);
+ } else {
+ v.set(field_0x11C8, 0.0f, 0.0f);
+ }
+ MTXMultVec(mtx, v, v);
+ mPosition.x += v.x;
+ mPosition.z += v.z;
+
+ if (mMdl.getAnm().isStop()) {
+ if (mLightingStrikeState != LIGHTNING_STRIKE_STATE_NONE) {
+ setAnm("ThunderDemo", 10.0f);
+ mSubState = SUB_STATE_20;
+ } else {
+ if (field_0x113B >= 3 && mXZDistanceToLink < 500.0f) {
+ mStateMgr.changeState(StateID_Attack);
+ mMdl.setFrame(10.0f);
+ } else {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ }
+ }
+ }
+ break;
+ }
+ case SUB_STATE_10: {
+ // TODO: Is this state ever set?
+ if (mMdl.getAnm().isStop()) {
+ setAnm("DownGetUp", 10.0f);
+ mSubState = SUB_STATE_4;
+ }
+ break;
+ }
+ case SUB_STATE_20: {
+ mIsDown = 0;
+ if (mMdl.getAnm().isStop()) {
+ mSubState = SUB_STATE_21;
+ setAnm("CatchThunderLoop", 0.0f);
+ }
+ break;
+ }
+ case SUB_STATE_21: {
+ mIsDown = false;
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ mTimers[TIMER_4] = 15;
+ mLightingStrikeState = LIGHTNING_STRIKE_FINISH;
+ }
+ break;
+ }
+ }
+
+ if (b) {
+ v.set(0.0f, 0.0f, -100.0f);
+ mtx.YrotS(mRotation.y);
+ MTXMultVec(mtx, v, v);
+ v.x += mBackbone1Translation.x;
+ v.z += mBackbone1Translation.z;
+ v.y = 10.0f;
+
+ static mVec3_c sScale(3.0f, 3.0f, 3.0f);
+ dJEffManager_c::spawnEffect(PARTICLE_RESOURCE_ID_MAPPING_91_, v, nullptr, &sScale, nullptr, nullptr, 0, 0);
+ }
+}
void dAcBlastboss_c::finalizeState_Down() {}
-void dAcBlastboss_c::initializeState_Stun() {}
-void dAcBlastboss_c::executeState_Stun() {}
+
+void dAcBlastboss_c::initializeState_Stun() {
+ setAnm("Stan", 3.0f);
+ mSubState = SUB_STATE_0;
+ mChanceAttackCounter = 0;
+ mInvulnerabilityTimerMaybe = 10;
+ mStunCounter++;
+ mIsSwordEmpowered = false;
+ mCc1.ClrTg_0x8000000();
+ mSwordMdl.fn_8006B800(0);
+ startSound(SE_BLasBos_HitThunderBeam);
+}
+void dAcBlastboss_c::executeState_Stun() {
+ setLightningTimerMaybe(40);
+ mStunState = 1;
+ int frame = mMdl.getAnm().getFrame();
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mMdl.getAnm().isStop()) {
+ mSubState = SUB_STATE_1;
+ setAnm("StanLoop", 0.0f);
+ mTimers[TIMER_0] = 100;
+ }
+ break;
+ }
+ case SUB_STATE_1: {
+ if (mTimers[TIMER_0] == 0) {
+ mSubState = SUB_STATE_2;
+ setAnm("StanReverse", 10.0f);
+ }
+ break;
+ }
+ case SUB_STATE_2: {
+ if (frame <= 58) {
+ if (frame == 58) {
+ mStunState = 2;
+ }
+ } else {
+ mStunState = 0;
+ if (frame <= 61) {
+ field_0x11A4 = 25.0f;
+ }
+ }
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ break;
+ }
+ }
+
+ sLib::addCalcScaled(&mSpeed, 1.0f, 10.0f);
+ if (mChanceAttackCounter >= 7) {
+ mCc1.SetTgFlag_0xA(0x1FF);
+ checkForCounter();
+ } else {
+ if (mInvulnerabilityTimerMaybe != 0) {
+ mCc1.SetTgFlag_0xA(0x1FF);
+ } else {
+ mCc1.SetTgFlag_0xA(0);
+ }
+ }
+}
void dAcBlastboss_c::finalizeState_Stun() {}
-void dAcBlastboss_c::initializeState_ThunderWait() {}
-void dAcBlastboss_c::executeState_ThunderWait() {}
+
+void dAcBlastboss_c::initializeState_ThunderWait() {
+ setAnm("CatchThunderStart", 10.0f);
+ mSubState = SUB_STATE_0;
+ mGuardDirection = -1;
+ mTimers[TIMER_0] = 30;
+}
+void dAcBlastboss_c::executeState_ThunderWait() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ mCc1.SetTgFlag_0xA(0);
+
+ switch (mSubState) {
+ case SUB_STATE_0: {
+ if (mMdl.getAnm().isStop()) {
+ mSubState = SUB_STATE_1;
+ setAnm("CatchThunderLoop", 0.0f);
+ }
+ // fall-through
+ }
+ case SUB_STATE_1: {
+ if (link->checkSwordAndMoreStates(0x400000)) {
+ mStateMgr.changeState(StateID_Fight);
+ } else if (mTimers[TIMER_0] == 0) {
+ dLightEnv_c::GetPInstance()->setField_0x38DC(7);
+ mSubState = SUB_STATE_5;
+ setAnm("CatchThunderEnd", 5.0f);
+ mVec3_c vEff;
+ vEff.x = mSwordPosition.x;
+ vEff.y = mSwordPosition.y + 110.0f;
+ vEff.z = mSwordPosition.z;
+ dJEffManager_c::spawnEffect(
+ PARTICLE_RESOURCE_ID_MAPPING_624_, vEff, nullptr, nullptr, nullptr, nullptr, 0, 0
+ );
+ mTimers[TIMER_3] = cM::rndF(100.0f) + 900.0f;
+ mIsSwordEmpowered = true;
+ mSwordMdl.fn_8006B800(4);
+ mCc1.OnTg_0x8000000();
+ mLightingFallSwordTimer = 10;
+ startSound(SE_BLasBos_ThunderFallSword);
+ }
+ break;
+ }
+ case SUB_STATE_5: {
+ if (mMdl.getAnm().getFrame() >= 20.0f) {
+ mCc1.SetTgFlag_0xA(0x1FF);
+ checkForCounter();
+ }
+ if (mMdl.getAnm().isStop()) {
+ mStateMgr.changeState(StateID_Fight);
+ }
+ break;
+ }
+ }
+ sLib::addCalcScaled(&mSpeed, 1.0f, 4.0f);
+}
void dAcBlastboss_c::finalizeState_ThunderWait() {}
+
+bool dAcBlastboss_c::checkDamage() {
+ mVec3_c v;
+ mVec3_c v2;
+ mMtx_c mtx;
+
+ mHealth = 400;
+ // TODO: typing crime
+ cCcD_Obj *atHit = mSwordMdl.mCcList.find((dColliderLinkedList::ccPtmf)&dCcD_Check::ChkAtHit);
+ if (atHit != nullptr && atHit->GetAtFlag0x8()) {
+ field_0x113E = 20;
+ }
+
+ if (sLib::calcTimer(&field_0x1134) == 0) {
+ // TODO: regswap between unk and link.
+ // Making this a u16 or s16 fixes regalloc but breaks instructions...
+ s32 unk = someEnemyDamageCollisionStuffMaybe(mCcList, nullptr);
+
+ // TODO: typing crime
+ cCcD_Obj *tgHit = mCcList.find((dColliderLinkedList::ccPtmf)&dCcD_Check::ChkTgHit);
+ if (tgHit == nullptr) {
+ return false;
+ }
+
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ s32 mLastAttackDirection = link->getSpecificAttackDirection();
+
+ // TODO: enum?
+ switch (unk) {
+ case 0: {
+ break;
+ }
+ case 6: {
+ startSound(SE_BLasBos_SwordBySword);
+ // TODO inline?
+ if (tgHit->GetTgDamageFlags() & 0x4) {
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = 20.0f;
+ mtx.YrotS(link->mRotation.y);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ mStateMgr.changeState(StateID_Stun);
+ break;
+ }
+
+ if (tgHit->ChkTgAtHitType(AT_TYPE_0x800000)) {
+ mGuardDirection = GUARD_UP;
+ mStateMgr.changeState(StateID_Guard);
+ break;
+ }
+ mMdlCallback.field_0x04.set(7);
+ if (field_0x113F != 0) {
+ mSubState = SUB_STATE_1;
+ mStateMgr.changeState(StateID_CounterAttack);
+ break;
+ } else if (mGuardDirection == GUARD_BT) {
+ if (classifyAttackDirection(mLastAttackDirection) == classifyAttackDirection(mLastAttackDir)) {
+ mNumConsecutiveOppositeDirectionAttacks++;
+ } else {
+ mNumConsecutiveSameDirectionAttacks++;
+ }
+ if (mNumConsecutiveSameDirectionAttacks >= 2) {
+ mSubState = SUB_STATE_1;
+ mStateMgr.changeState(StateID_CounterAttack);
+ break;
+ }
+
+ if (classifyAttackDirection(mLastAttackDirection) == 0) {
+ // Left
+ mMdlCallback.field_0x30 += 3.0f;
+ mMdlCallback.field_0x18 += 0x7D0;
+ } else if (classifyAttackDirection(mLastAttackDirection) == 1) {
+ // Right
+ mMdlCallback.field_0x30 -= 3.0f;
+ mMdlCallback.field_0x18 -= 0x7D0;
+ }
+ if (mNumConsecutiveOppositeDirectionAttacks >= 1) {
+ mStateMgr.changeState(StateID_GuardBreak);
+ }
+ } else if (mLastAttackDir >= 0) {
+ if (classifyAttackDirection(mLastAttackDirection) == classifyAttackDirection(mLastAttackDir)) {
+ mNumConsecutiveSameDirectionAttacks++;
+ } else {
+ mNumConsecutiveOppositeDirectionAttacks++;
+ }
+ s8 x = 3;
+ if (classifyAttackDirection(mLastAttackDirection) == classifyAttackDirection(mLastAttackDir)) {
+ x = 1;
+ }
+ if (mNumConsecutiveSameDirectionAttacks >= x ||
+ (mSecondLastAttackDirection >= 0 && (classifyAttackDirection(mSecondLastAttackDirection) & 2) ==
+ (classifyAttackDirection(mLastAttackDirection) & 2))) {
+ mSubState = SUB_STATE_0;
+ mStateMgr.changeState(StateID_CounterAttack);
+ } else {
+ if (mNumConsecutiveOppositeDirectionAttacks >= 1) {
+ field_0x113E = 25;
+ mNumConsecutiveOppositeDirectionAttacks = 1;
+ field_0x1182 = 20;
+ }
+ }
+ }
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = -5.0f;
+ mtx.YrotS(mYAngleToLink);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ mLastAttackDir = mLastAttackDirection;
+ break;
+ }
+ case 7: {
+ break;
+ }
+ default: {
+ if (tgHit != nullptr &&
+ (tgHit->ChkTgAtHitType(AT_TYPE_SLINGSHOT) || tgHit->ChkTgAtHitType(AT_TYPE_CLAWSHOT) ||
+ tgHit->ChkTgAtHitType(AT_TYPE_BOMB) || tgHit->ChkTgAtHitType(AT_TYPE_ARROW) ||
+ tgHit->ChkTgAtHitType(AT_TYPE_WHIP) || tgHit->ChkTgAtHitType(AT_TYPE_0x40))) {
+ mGuardDirection = GUARD_UP;
+ mStateMgr.changeState(StateID_Guard);
+
+ if (tgHit->ChkTgAtHitType(AT_TYPE_BOMB)) {
+ field_0x11A4 = 30.0f;
+ field_0x11B8 = 15.0f;
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = -10.0f;
+ mtx.YrotS(mRotation.y);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ }
+
+ break;
+ }
+
+ // TODO inline?
+ if (tgHit->GetTgDamageFlags() & 4) {
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = 20.0f;
+ mtx.YrotS(link->mRotation.y);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ mStateMgr.changeState(StateID_Stun);
+ break;
+ }
+
+ field_0x1152++;
+ if (field_0x1152 == 15) {
+ dSndBgmMgr_c::GetInstance()->fn_80372D70(3);
+ }
+
+ if (mIsPhaseTwo >= 0) {
+ if (field_0x1152 == 30) {
+ dStageMgr_c::GetInstance()->fn_80199B60(4);
+ mStateMgr.changeState(StateID_Down);
+ mLightingStrikeState = LIGHTNING_STRIKE_START_DEMO;
+ startSound(SE_BLasBos_DownHit);
+ break;
+ }
+ } else {
+ if (field_0x1152 == 50) {
+ mStateMgr.changeState(StateID_Down);
+ field_0x1152 = 45;
+ break;
+ }
+ }
+
+ if ((!field_0x113E && (mStateMgr.isState(StateID_Attack) || mStateMgr.isState(StateID_SmallAttack) ||
+ mStateMgr.isState(StateID_CounterAttack))) ||
+ mStateMgr.isState(StateID_ThunderWait)) {
+ field_0x1188 = 10;
+ break;
+ }
+
+ if (field_0x113E != 0 && mIsPhaseTwo != 0) {
+ field_0x1188 = 10;
+ break;
+ }
+
+ if (mStateMgr.isState(StateID_Stun)) {
+ mNumConsecutiveSameDirectionAttacks = 0;
+ mSecondLastAttackDirection = mLastAttackDirection;
+ mChanceAttackCounter++;
+
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = -20.0f;
+ mtx.YrotS(mYAngleToLink);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ field_0x1138 = 10;
+ field_0x11B8 = 5.0f;
+ field_0x11A4 = 7.0f;
+ if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_LEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT) {
+ field_0x1137 = 1;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_RIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT) {
+ field_0x1137 = 2;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_STAB) {
+ field_0x1137 = 3;
+ } else {
+ field_0x1137 = 0;
+ }
+ startSound(SE_BLasBos_VO_DamageChance);
+ break;
+ }
+
+ if (mStateMgr.isState(StateID_SitDamage)) {
+ mNumConsecutiveSameDirectionAttacks = 0;
+ mSecondLastAttackDirection = mLastAttackDirection;
+ mChanceAttackCounter++;
+
+ if (mChanceAttackCounter >= 5 && mChanceCounter >= 3) {
+ if (mIsPhaseTwo >= 0) {
+ mChanceAttackCounter = 0;
+ field_0x1152 = 30;
+ dStageMgr_c::GetInstance()->fn_80199B60(4);
+ mStateMgr.changeState(StateID_Down);
+ mLightingStrikeState = LIGHTNING_STRIKE_START_DEMO;
+ startSound(SE_BLasBos_DownHit);
+ break;
+ }
+ mStateMgr.changeState(StateID_Down);
+ field_0x1152 = 45;
+ break;
+ }
+
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = -20.0f;
+ mtx.YrotS(mYAngleToLink);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ field_0x11B8 = 5.0f;
+ field_0x11A4 = 7.0f;
+ if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_LEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT) {
+ field_0x1137 = 1;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_RIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT) {
+ field_0x1137 = 2;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWN) {
+ field_0x1137 = 3;
+ } else {
+ field_0x1137 = 0;
+ }
+ mSubState = SUB_STATE_5;
+ startSound(SE_BLasBos_VO_DamageChance);
+ break;
+ }
+
+ if (mChanceAttackCounter >= 3) {
+ mStateMgr.changeState(StateID_SitDamage);
+ mChanceAttackCounter = 0;
+ } else {
+ mStateMgr.changeState(StateID_Damage);
+ }
+
+ mNumConsecutiveSameDirectionAttacks = -1;
+ mSecondLastAttackDirection = mLastAttackDirection;
+ v.x = 0.0f;
+ v.y = 0.0f;
+ v.z = -20.0f;
+ mtx.YrotS(mYAngleToLink);
+ MTXMultVec(mtx, v, v2);
+ mAttackKnockbackX = v2.x;
+ mAttackKnockbackZ = v2.z;
+ field_0x1138 = 10;
+ field_0x11B8 = 5.0f;
+ field_0x11A4 = 7.0f;
+ if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_LEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT) {
+ field_0x1137 = 1;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_RIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT ||
+ mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT) {
+ field_0x1137 = 2;
+ } else if (mLastAttackDirection == daPlayerActBase_c::ATTACK_DIRECTION_STAB) {
+ field_0x1137 = 3;
+ } else {
+ field_0x1137 = 0;
+ }
+ break;
+ }
+ }
+ }
+
+ return true;
+}
+
+void dAcBlastboss_c::setAnm(const char *name, f32 blend) {
+ if (mpCurrentAnm != name) {
+ mMdl.setAnm(name, m3d::PLAY_MODE_4, blend);
+ mpCurrentAnm = name;
+ }
+}
+
+void dAcBlastboss_c::forceSetAnm(const char *name, f32 blend) {
+ mMdl.setAnm(name, m3d::PLAY_MODE_4, blend);
+ mpCurrentAnm = name;
+}
+
+void dAcBlastboss_c::setAnmRate(f32 rate) {
+ mMdl.setRate(rate);
+}
+
+int dAcBlastboss_c::draw() {
+ drawModelType1(&mMdl.getModel());
+ mSwordMdl.entry(this, nullptr, nullptr);
+ if (field_0x114C) {
+ drawModelType1(&mThunderMdl);
+ }
+ return SUCCEEDED;
+}
+
+bool dAcBlastboss_c::checkForCloseRangeAttack() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+
+ bool ret = false;
+ if (mXZDistanceToLink < 500.0f) {
+ if (mIsPhaseTwo != 0) {
+ if (mTimers[TIMER_2] == 0) {
+ mStateMgr.changeState(StateID_Attack);
+ ret = true;
+ }
+ } else {
+ if (link->isUsingShield()) {
+ mLinkCloseRangeShieldTime++;
+ } else {
+ mLinkCloseRangeShieldTime = 0;
+ }
+ if (mLinkCloseRangeShieldTime > 40) {
+ mStateMgr.changeState(StateID_PunchAttack);
+ ret = true;
+ } else if (mTimers[TIMER_2] == 0) {
+ if (checkForLinkSwordBySwordHit() && cM::rnd() < 0.35f) {
+ mStateMgr.changeState(StateID_SmallAttack);
+ ret = true;
+ } else {
+ mStateMgr.changeState(StateID_Attack);
+ ret = true;
+ }
+ mLinkCloseRangeShieldTime = 0;
+ }
+ }
+
+ } else {
+ mLinkCloseRangeShieldTime = 0;
+ }
+
+ return ret;
+}
+
+bool dAcBlastboss_c::checkForRangeAttack() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+
+ bool ret = false;
+
+ if (mIsPhaseTwo != 0 && !link->isRecovering() && mStunCounter != 0 && link->getSwordPos().y > 270.0f) {
+ field_0x1162++;
+ } else {
+ field_0x1162 = 0;
+ }
+
+ if (mIsPhaseTwo != 0) {
+ if (field_0x1162 >= 20) {
+ mStateMgr.changeState(StateID_DashAttack);
+ return true;
+ } else if (mIsSwordEmpowered) {
+ if ((link->checkSwordAndMoreStates(0x400000) && mStunCounter != 0) ||
+ (mXZDistanceToLink < 1500.0f && mTimers[TIMER_3] == 0)) {
+ mStateMgr.changeState(StateID_ThunderAttack);
+ ret = true;
+ }
+ } else {
+ if (link->checkSwordAndMoreStates(0x400000)) {
+ if ((mCounter & 0x7) == 0 && mStunCounter != 0) {
+ mStateMgr.changeState(StateID_DashAttack);
+ ret = true;
+ }
+ } else {
+ if (mXZDistanceToLink < 1500.0f && dLightEnv_c::GetPInstance()->getField_0x38DC() == 6) {
+ if (field_0x1162 > 10) {
+ mStateMgr.changeState(StateID_DashAttack);
+ ret = true;
+ } else {
+ mStateMgr.changeState(StateID_ThunderWait);
+ ret = true;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+bool dAcBlastboss_c::checkForCounter() {
+ bool ret = false;
+
+ if (field_0x113E != 0) {
+ return false;
+ }
+
+ f32 attackRange = 450.0f;
+ if (dAcPy_c::GetLinkM()->isAttackingJumpSlash()) {
+ attackRange = 750.0f;
+ }
+
+ if (mXZDistanceToLink < attackRange) {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ if (link->checkFlags0x354(0x04)) {
+ if (link->isAttackingSpin()) {
+ field_0x11A4 = 15.0f;
+ } else if (link->isAttacking()) {
+ field_0x11A4 = 7.0f;
+ }
+
+ s32 attackDir = link->getSpecificAttackDirection();
+
+ if (mStateMgr.isState(StateID_Attack)) {
+ if (mpCurrentAnm == "AttackR" &&
+ (attackDir == dAcPy_c::ATTACK_DIRECTION_RIGHT || attackDir == dAcPy_c::ATTACK_DIRECTION_UPRIGHT ||
+ attackDir == dAcPy_c::ATTACK_DIRECTION_DOWNRIGHT)) {
+ mGuardDirection = GUARD_RIGHT;
+ } else if (mpCurrentAnm == "AttackL" && (attackDir == dAcPy_c::ATTACK_DIRECTION_LEFT ||
+ attackDir == dAcPy_c::ATTACK_DIRECTION_UPLEFT ||
+ attackDir == dAcPy_c::ATTACK_DIRECTION_DOWNLEFT)) {
+ mGuardDirection = GUARD_LEFT;
+ } else if (mpCurrentAnm == "AttackU" && attackDir == daPlayerActBase_c::ATTACK_DIRECTION_DOWN) {
+ mGuardDirection = GUARD_UP;
+ } else {
+ return false;
+ }
+
+ mStateMgr.changeState(StateID_Guard);
+ mSubState = SUB_STATE_10;
+ } else {
+ if ((mIsPhaseTwo > 0 || mXZDistanceToLink < 200.0f) && mNumConsecutiveOppositeDirectionAttacks < 1) {
+ mNumConsecutiveOppositeDirectionAttacks = 1;
+ }
+
+ switch (attackDir) {
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWN: mGuardDirection = GUARD_UP; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_LEFT: mGuardDirection = GUARD_LEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT: mGuardDirection = GUARD_UPLEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT: mGuardDirection = GUARD_DOWNLEFT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_RIGHT: mGuardDirection = GUARD_RIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT: mGuardDirection = GUARD_UPRIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT: mGuardDirection = GUARD_DOWNRIGHT; break;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UP: mGuardDirection = GUARD_DOWN; break;
+ default: mGuardDirection = GUARD_CENTER; break;
+ }
+ if (!mStateMgr.isState(StateID_Guard)) {
+ mStateMgr.changeState(StateID_Guard);
+ }
+
+ mSubState = SUB_STATE_0;
+ }
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+void dAcBlastboss_c::updateMainNodeTransforms() {
+ if (field_0x1131 != 0) {
+ s16 ang = 0x800;
+ if (field_0x1131 == 2) {
+ ang = 0x300;
+ }
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+ mVec3_c attentionTarget = link->getPosition();
+ attentionTarget.y += 250.0f;
+ if (link->isUsingBugnet() && mXZDistanceToLink < 400.0f) {
+ field_0x117C = 5;
+ mBugNetPos = link->getBugNetPos();
+ }
+
+ s16 diff;
+ if (field_0x117C != 0) {
+ attentionTarget = mBugNetPos;
+ mAng targetAngle = cLib::targetAngleY(mPosition, attentionTarget);
+ diff = targetAngle - mRotation.y;
+ } else {
+ diff = mYAngleToLink - mRotation.y;
+ }
+ if (diff > 0x1800) {
+ diff = 0x1800;
+ } else if (diff < -0x1800) {
+ diff = -0x1800;
+ }
+ sLib::addCalcAngle(mMdlCallback.field_0x06.ref(), -diff, 2, ang);
+
+ s16 diff2 = cLib::targetAngleX(attentionTarget, mPositionCopy2);
+ if (diff2 > 0x1000) {
+ diff2 = 0x1000;
+ } else if (diff2 < -0x1000) {
+ diff2 = -0x1000;
+ }
+ sLib::addCalcAngle(mMdlCallback.field_0x0A.ref(), diff2, 2, ang);
+
+ if ((mCounter & 0xF) == 0 && cM::rnd() < 0.5f) {
+ field_0x1170 = cM::rndFX(2000.0f);
+ }
+ sLib::addCalcAngle(mMdlCallback.field_0x0C.ref(), field_0x1170, 8, 0x200);
+ } else {
+ mMdlCallback.field_0x06 = mMdlCallback.field_0x0A = mMdlCallback.field_0x0C = 0;
+ if (mLightingStrikeState == LIGHTNING_STRIKE_ENDING) {
+ mMdlCallback.field_0x0A = 2000;
+ }
+ }
+
+ if (field_0x1178 != 0) {
+ field_0x1178--;
+ s16 target = mAng(field_0x1178 * 0xE00).sin() * 1500.0f;
+ sLib::addCalcAngle(mMdlCallback.field_0x08.ref(), target, 2, 200);
+ } else {
+ sLib::addCalcAngle(mMdlCallback.field_0x08.ref(), 0, 2, 100);
+ }
+
+ s16 t3 = 0;
+ if (field_0x1182 != 0) {
+ field_0x1182--;
+ t3 = 4000;
+ }
+ sLib::addCalcAngle(mMdlCallback.field_0x12.ref(), t3, 4, 200);
+ sLib::addCalcAngle(mMdlCallback.field_0x14.ref(), field_0x1172, 2, 0x200);
+ sLib::addCalcAngle(mMdlCallback.field_0x16.ref(), field_0x1174, 2, 0x200);
+
+ field_0x1172 = 0;
+ field_0x1174 = 0;
+
+ if (field_0x1138 != 0) {
+ field_0x1138--;
+
+ field_0x117A = 2000;
+ s16 t4 = 0, t5 = 0;
+ if (field_0x1137 == 0) {
+ field_0x117A = 3000;
+ t5 = 5000;
+ } else if (field_0x1137 == 1) {
+ t5 = 3000;
+ t4 = 3000;
+ } else if (field_0x1137 == 2) {
+ t5 = 3000;
+ t4 = -3000;
+ } else if (field_0x1137 == 3) {
+ field_0x117A = 3000;
+ t5 = -5000;
+ }
+
+ sLib::addCalcAngle(mMdlCallback.field_0x0E.ref(), t4, 2, field_0x117A);
+ sLib::addCalcAngle(mMdlCallback.field_0x10.ref(), t5, 2, field_0x117A);
+ } else if (field_0x1188 != 0) {
+ field_0x1188--;
+ s16 target = mAng(mCounter * 0x6510).sin() * 300.0f;
+ mMdlCallback.field_0x2E = target;
+ } else {
+ sLib::addCalcAngle(mMdlCallback.field_0x0E.ref(), 0, 4, field_0x117A / 4);
+ sLib::addCalcAngle(mMdlCallback.field_0x10.ref(), 0, 4, field_0x117A / 4);
+ }
+
+ if (field_0x1133 == 0) {
+ sLib::addCalcScaled(&mMdlCallback.field_0x30, 0.5f, 0.5f);
+ sLib::addCalcAngle(mMdlCallback.field_0x18.ref(), 0, 4, 400);
+ sLib::addCalcAngle(mMdlCallback.field_0x1A.ref(), 0, 4, 400);
+ }
+}
+
+void dAcBlastboss_c::updateSkirtHairTransforms() {
+ static const u16 sNodeIds[] = {
+ B_LAST_BOSS_NODE_skirtAU1, B_LAST_BOSS_NODE_skirtBU1, B_LAST_BOSS_NODE_skirtCU1, B_LAST_BOSS_NODE_skirtDU1,
+ B_LAST_BOSS_NODE_skirtEU1, B_LAST_BOSS_NODE_skirtFU1, B_LAST_BOSS_NODE_skirtGU1, B_LAST_BOSS_NODE_skirtHU1,
+ };
+
+ static const s16 sAngs[] = {
+ 0x2000, 0x2000, 0x4000, 0x6000, 0x8000, 0xA000, 0xC000, 0xE000,
+ };
+
+ f32 f = 80.0f;
+
+ if (mpCurrentAnm == "AttackU") {
+ if (mMdl.getAnm().getFrame() >= 18.0f && mMdl.getAnm().getFrame() <= 40.0f) {
+ f = 150.0f;
+ }
+ } else if (mpCurrentAnm == "Counter") {
+ if (mMdl.getAnm().getFrame() >= 17.0f && mMdl.getAnm().getFrame() <= 68.0f) {
+ f = 120.0f;
+ }
+ } else if (mpCurrentAnm == "TurnR") {
+ if (mMdl.getAnm().getFrame() >= 19.0f && mMdl.getAnm().getFrame() <= 30.0f) {
+ f = 100.0f;
+ }
+ } else if (mpCurrentAnm == "AttackJumpEnd") {
+ if (mMdl.getAnm().getFrame() <= 18.0f) {
+ f = 120.0f;
+ }
+ } else if (mpCurrentAnm == "AttackJumpStart" || mpCurrentAnm == "AttackJumpLoop") {
+ f = 120.0f;
+ } else if (mpCurrentAnm == "DownGetUp") {
+ // same value
+ f = 80.0f;
+ }
+ sLib::addCalcScaledDiff(&field_0x11B4, f, 0.5f, 20.0f);
+
+ mMtx_c mtx;
+ mVec3_c v;
+ mVec3_c t(0.0f, 0.0f, 12.0f);
+ for (int i = 0; i < (int)ARRAY_LENGTH(field_0x1268); i++) {
+ field_0x1268[i].field_0x002++;
+ field_0x1268[i].field_0x004 = sAngs[i] + mRotation.y;
+ mMdl.getModel().getNodeWorldMtx(sNodeIds[i], mtx);
+ mtx.getTranslation(v);
+ mtx.YrotS(field_0x1268[i].field_0x004);
+ MTXMultVec(mtx, t, field_0x1268[i].field_0x014[0]);
+ field_0x1268[i].field_0x014[0] += v;
+ if (nw4r::math::FAbs(field_0x1268[i].field_0x010) < 1.0f) {
+ // TODO - regswaps between tmp and abs result
+ f32 tmp = field_0x1268[(i + 1) & 7].field_0x010;
+ if (nw4r::math::FAbs(tmp) > 1.0f) {
+ field_0x1268[i].field_0x010 = tmp * 0.5f;
+ }
+ tmp = field_0x1268[(i - 1) & 7].field_0x010;
+ if (nw4r::math::FAbs(tmp) > 1.0f) {
+ field_0x1268[i].field_0x010 = tmp * 0.5f;
+ }
+ }
+
+ f32 f4 = field_0x1268[i].field_0x010 + field_0x11A4;
+ if (nw4r::math::FAbs(f4) > 0.1f) {
+ if (field_0x11A4 > 0.1f) {
+ field_0x1268[i].field_0x006 = mRotation.y + 0x8000 + moreAngs[i];
+ } else if (field_0x11A4 < -0.1f) {
+ field_0x1268[i].field_0x006 = mRotation.y + 0x8000 - moreAngs[i];
+ }
+
+ if (nw4r::math::FAbs(field_0x11A4) > 25.0f) {
+ field_0x1268[i].field_0x00A = 8000;
+ } else {
+ field_0x1268[i].field_0x00A = 5000;
+ }
+
+ if (i >= 2 && i <= 6) {
+ field_0x1268[i].field_0x00C = f4;
+ } else {
+ field_0x1268[i].field_0x00C = 0.75f * f4;
+ }
+ field_0x11B0 = 0.0f;
+ } else {
+ sLib::addCalcScaled(&field_0x1268[i].field_0x00C, 0.05f, 2.0f);
+ sLib::addCalcAngle(&field_0x1268[i].field_0x00A, 1000, 4, 200);
+ }
+ field_0x1268[i].field_0x008 += field_0x1268[i].field_0x00A;
+ updateSkirtTransform(i);
+ }
+
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_head, mtx);
+ mtx.fn_802F1C40(0, 1);
+ mAng3_c ang;
+ mtx.toRot(ang);
+ ang.y += 0x4000;
+ ang.x += 0;
+ ang.z += 6500;
+ t.set(-20.0f, -20.0f, 0.0f);
+ for (int i = 0; i < 1; i++) {
+ field_0x2948[i].field_0x002 = ang.y;
+ field_0x2948[i].field_0x004 = -ang.z;
+ field_0x2948[i].field_0x006 = -ang.x;
+ mMdl.getModel().getNodeWorldMtx(B_LAST_BOSS_NODE_head, mtx);
+ MTXMultVec(mtx, t, field_0x2948[i].field_0x008[0]);
+ updateHairTransform(i);
+ }
+
+ if (!mIsDown) {
+ for (int i = 0; i < 9; i++) {
+ f32 f = (i % 3) * 3 + 1;
+ if (i < 3) {
+ mMdlCallback.field_0x1C[i] = (s16)(f * 500.0f * mAng(mCounter * 0x2600 - (i * 24000)).sin());
+ } else if (i < 6) {
+ mMdlCallback.field_0x1C[i] = -(s16)(f * 500.0f * mAng(mCounter * 0x2800 - (i * 25000)).sin());
+ } else {
+ mMdlCallback.field_0x1C[i] = -(s16)(f * 500.0f * mAng(mCounter * 0x2A00 - (i * 26000)).sin());
+ }
+ }
+ }
+
+ if (field_0x114E != 0) {
+ holdSound(SE_BLasBos_SkirtAir);
+ }
+}
+
+void dAcBlastboss_c::updateSkirtTransform(s32 level) {
+ // NONMATCHING but probably equivalent
+
+ UnkLastBossCcSph2 &cc = field_0x1268[level];
+ mVec3_c *v1 = &cc.field_0x014[1];
+ mVec3_c *v2 = &cc.field_0x08C[0];
+ mVec3_c *v3 = &cc.field_0x104[1];
+
+ mVec3_c t1(0.0f, 0.0f, 33.25f);
+
+ s32 offset1 = 0;
+
+ mVec3_c d1;
+
+ d1 = mToeTranslation[0] - mBackbone1Translation;
+
+ mMtx_c mtx;
+ mtx.YrotS(-mRotation.y);
+ MTXMultVec(mtx, d1, d1);
+ if (d1.z > 0.0f) {
+ offset1 = -1;
+ }
+
+ d1 = mToeTranslation[1] - mBackbone1Translation;
+ MTXMultVec(mtx, d1, d1);
+ if (d1.z > 20.0f) {
+ offset1 = 1;
+ }
+
+ // hmm yes
+ mVec3_c p3;
+ mVec3_c v4;
+ mVec3_c p2;
+ mVec3_c v5;
+ mVec3_c p1;
+
+ p1.set(0.0f, 0.0f, 0.0f);
+ p2.set(0.0f, 0.0f, 0.0f);
+ bool isAttackJumpStart = false;
+ if (mpCurrentAnm == "AttackJumpStart") {
+ isAttackJumpStart = true;
+ }
+ f32 f;
+ if (level == 7 && offset1 > 0) {
+ f = 10.0f;
+ } else if (level >= 0 && level <= 1 && offset1 < 0) {
+ f = 50.0f;
+ } else {
+ f = -3.0f;
+ }
+ if (level >= 0 && level < 2 && isAttackJumpStart) {
+ p1.y = 500.0f;
+ f = 50.0f;
+ }
+
+ sLib::addCalcScaledDiff(&field_0x11D0, f, 1.0f, 2.0f);
+ p1.z = field_0x11D0;
+
+ p3.set(0.0f, 0.0f, 2.0f);
+ mtx.YrotS(cc.field_0x004);
+ MTXMultVec(mtx, p3, v4);
+ MTXMultVec(mtx, p1, v5);
+ mtx.YrotS(mRotation.y);
+ MTXMultVec(mtx, p2, p2);
+
+ f32 fAdd = -15.0f;
+ f32 f1 = cc.field_0x00C;
+ sLib::addCalcScaledDiff(&field_0x11AC, field_0x11B0, 1.0f, 0.02f);
+
+ s32 offset2 = 0;
+ if (offset1 < 0 && (level == 0) || level == 1 || level == 2 || level == 7) {
+ offset2 = 1;
+ }
+
+ f32 f2 = field_0x11B4;
+ u32 u12 = (cc.field_0x002 & 1) + 1;
+ if (level >= 2 && level <= 6) {
+ u12 += 2;
+ cc.mCc.SetR(30.0f);
+ } else {
+ cc.mCc.SetR(50.0f);
+ }
+
+ if (mIsDown) {
+ offset2 = 0;
+ v4.set(0.0f, 0.0f, 0.0f);
+ p2.set(0.0f, 0.0f, 0.0f);
+ }
+
+ f1 *= 0.75f;
+
+ static const f32 sFloats[] = {
+ 15.0f, 15.0f, 15.0f, 15.0f, 13.0f, 11.0f, 9.0f, 7.0f, 5.0f,
+ };
+
+ s32 actual = offset2 - 1;
+
+ for (u32 i = 1; i < 10; i++, v1++, v2++, v3++) {
+ mtx.YrotS(cc.field_0x006);
+ d1.x = 0.0f;
+ d1.y = mAng(cc.field_0x008 - i * 8000).sin() * f1;
+ d1.z = f1;
+ mVec3_c v6;
+ MTXMultVec(mtx, d1, v6);
+ s32 zero = 0;
+ f1 = f1 * (zero * 0.01f + 1.1f);
+
+ f32 fY = fAdd + v1[0].y + v4.y + v3[0].y + v6.y + v5.y;
+ if (i >= 1) {
+ v5.y = 0.0f;
+ } else {
+ // @bug unreachable
+ v5.y *= 0.5f;
+ }
+
+ f32 f4;
+ if (mIsDown) {
+ f4 = 5.0f;
+ } else {
+ f4 = sFloats[i - 1];
+ }
+
+ if (fY <= f4) {
+ fY = f4;
+ }
+
+ f32 fX = v1[0].x + v4.x + p2.x + v3[0].x + v6.x + v5.x;
+ f32 fZ = v1[0].z + v4.z + p2.z + v3[0].z + v6.z + v5.z;
+ if (offset2 != 0) {
+ f32 dX = fX - field_0x1250[actual].x;
+ f32 dZ = fZ - field_0x1250[actual].z;
+ f32 f11 = nw4r::math::FSqrt(dX * dX + dZ * dZ);
+ if (f11 < f2) {
+ mtx.YrotS(cM::atan2s(dX, dZ));
+ d1.set(0.0f, 0.0f, f2);
+ MTXMultVec(mtx, d1, d1);
+ fX = d1.x + field_0x1250[actual].x;
+ fZ = d1.z + field_0x1250[actual].z;
+ }
+ }
+
+ fX -= v1[-1].x;
+ fY -= v1[-1].y;
+ fZ -= v1[-1].z;
+ v5.x *= 0.4f;
+ v5.z *= 0.4f;
+ v2[0].x = -cM::atan2s(fY, fZ);
+ f32 f8 = nw4r::math::FSqrt(fY * fY + fZ * fZ);
+
+ v2[0].y = cM::atan2s(fX, f8);
+ v2[0].z = mRotation.y;
+
+ mtx.XrotS(v2[0].x);
+ mtx.YrotM(v2[0].y);
+ MTXMultVec(mtx, t1, d1);
+ v3[0] = v1[0];
+ v1[0] = v1[-1] + d1;
+ v3[0] = (v1[0] - v3[0]) * field_0x11AC;
+ if (i == u12) {
+ cc.field_0x010 = 0.0f;
+ cc.mCc.SetC(v1[0]);
+ if (cc.mCc.ChkTgHit()) {
+ cc.field_0x006 = moreAngs[level] + dAcPy_c::GetLinkM()->mRotation.y;
+ cc.field_0x010 = 25.0f;
+ field_0x114E = 1;
+ }
+ }
+ }
+}
+
+void dAcBlastboss_c::updateHairTransform(s32 level) {
+ // NONMATCHING but probably equivalent
+
+ UnkLastBossCcSph1 &cc = field_0x2948[level];
+ mVec3_c *v1 = &cc.field_0x008[1];
+ mVec3_c *v2 = &cc.field_0x044[0];
+ mVec3_c *v3 = &cc.field_0x080[1];
+
+ mMtx_c mtx2;
+ mMtx_c mtx;
+ mVec3_c t1(0.0f, 0.0f, 47.5f);
+ mVec3_c v;
+ mVec3_c t2(0.0f, 0.0f, -10.0f);
+
+ mtx.YrotS(cc.field_0x002);
+ mtx.XrotM(cc.field_0x004);
+ MTXMultVec(mtx, t2, t2);
+
+ f32 f1 = field_0x11B8;
+ f32 f2 = -field_0x11B8;
+ f32 f4 = 0.9f;
+ f32 fAdd = -5.0f;
+ f32 fScale = 1.0f;
+
+ for (u32 i = 1; i < 5; i++, v1++, v2++, v3++) {
+ v.x = f1 * mAng(mCounter * 12000 - (i * 20000)).sin();
+ v.y = f1 * mAng(mCounter * 10000 - (i * 20000)).sin();
+ v.z = f2;
+ v.x += mAng(mCounter * 10000 - (i * 20000)).sin() * fScale;
+ v.y += mAng(mCounter * 12000 - (i * 20000)).sin() * fScale;
+ MTXMultVec(mtx, v, v);
+
+ f1 *= 1.6f;
+
+ f32 f13;
+ if (field_0x113D != 0) {
+ f13 = fAdd + v1[0].y + t2.y + v3[0].y + v.y;
+ if (f13 < mPositionCopy2.y) {
+ f13 = mPositionCopy2.y;
+ }
+ f13 = f13 - v1[-1].y;
+ } else if (mIsDown) {
+ f13 = fAdd + v1[0].y + v3[0].y;
+ if (f13 <= 0.0f) {
+ f13 = 0.0f;
+ }
+ f13 = f13 - v1[-1].y;
+ v.set(0.0f, 0.0f, 0.0f);
+ } else {
+ f13 = fAdd + (v1[0].y - v1[-1].y) + t2.y + v3[0].y + v.y;
+ }
+
+ f32 fX2 = (v1[0].x - v1[-1].x) + t2.x + v3[0].x + v.x;
+ f32 fZ2 = (v1[0].z - v1[-1].z) + t2.z + v3[0].z + v.z;
+
+ t2.x *= 0.6f;
+ t2.y *= 0.6f;
+ t2.z *= 0.6f;
+ v2[0].y = cM::atan2s(fX2, fZ2);
+ f32 f8 = nw4r::math::FSqrt(fX2 * fX2 + fZ2 * fZ2);
+ v2[0].x = -cM::atan2s(f13, f8);
+ v2[0].z = cc.field_0x006;
+
+ mtx2.YrotS(v2[0].y);
+ mtx2.XrotM(v2[0].x);
+ MTXMultVec(mtx2, t1, v);
+
+ v3[0] = v1[0];
+ v1[0] = v1[-1] + v;
+ v3[0] = (v1[0] - v3[0]) * f4;
+ }
+
+ f32 target = 0.0f;
+ cc.mCc.SetC(mPositionCopy2);
+ cc.mCc.SetR(30.0f);
+ if (cc.mCc.ChkTgHit()) {
+ target = 7.0f;
+ holdSound(SE_BLasBos_HairAir);
+ if (field_0x1178 == 0) {
+ field_0x1178 = 18;
+ }
+ }
+ sLib::addCalcScaledDiff(&field_0x11B8, target, 0.2f, 0.7f);
+}
+
+bool dAcBlastboss_c::checkForLinkSwordBySwordHit() {
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+
+ bool ret = !link->isUsingShield();
+ if (ret) {
+ ret = link->isUsingSword();
+ }
+ if (ret) {
+ ret = link->getSwordPos().y > 100.0f;
+ }
+ if (ret) {
+ ret = link->getSwordPos().y < 230.0f;
+ }
+ if (ret) {
+ ret = (mPosition - link->getSwordPos()).absXZ() < 260.0f;
+ }
+
+ return ret;
+}
+
+u8 dAcBlastboss_c::classifyAttackDirection(s32 attackDir) {
+ switch (attackDir) {
+ case daPlayerActBase_c::ATTACK_DIRECTION_LEFT:
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNLEFT:
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPLEFT: return 0;
+
+ case daPlayerActBase_c::ATTACK_DIRECTION_RIGHT:
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWNRIGHT:
+ case daPlayerActBase_c::ATTACK_DIRECTION_UPRIGHT: return 1;
+
+ case daPlayerActBase_c::ATTACK_DIRECTION_DOWN: return 2;
+ case daPlayerActBase_c::ATTACK_DIRECTION_UP: return 3;
+
+ case daPlayerActBase_c::ATTACK_DIRECTION_STAB: return 4;
+
+ default: return -1;
+ }
+}
+
+void dAcBlastboss_c::executeLightningStrike() {
+ dCamera_c *cam = dScGame_c::getCamera();
+ dAcPy_c *link = dAcPy_c::GetLinkM();
+
+ mMtx_c mtx;
+ mMtx_c mtx1;
+ mVec3_c v;
+ mVec3_c effPos;
+
+ bool b1 = false;
+ bool b2 = false;
+ bool spawnEffect = false;
+ dLightEnv_c &lightEnv = dLightEnv_c::GetInstance();
+
+ switch (mLightingStrikeState) {
+ case LIGHTNING_STRIKE_START_DEMO: {
+ {
+ // this works but I don't like it
+ static volatile u32 FLAGS_1 = 0x00000001;
+ static u32 FLAGS_2 = 0x00100001;
+ u32 f1 = FLAGS_1;
+ u32 f2 = FLAGS_2;
+ Event e = Event("BLS_demo2", 100, f2 & ~f1, nullptr, nullptr);
+ EventManager::alsoSetAsCurrentEvent(this, &e, nullptr);
+ }
+ if (EventManager::isInEvent(this, "BLS_demo2")) {
+ field_0x2CEE = 0;
+ field_0x2D00 = 0.0f;
+ field_0x2CFC = 60.0f;
+ mLightingStrikeState = LIGHTNING_STRIKE_DEMO;
+ // huh
+ field_0x2D10.x = cam->getField_0x78().x;
+ field_0x2D10.y = cam->getField_0x78().y;
+ field_0x2D10.z = cam->getField_0x78().z;
+ field_0x2D04.x = cam->getPositionMaybe().x;
+ field_0x2D04.y = cam->getPositionMaybe().y;
+ field_0x2D04.z = cam->getPositionMaybe().z;
+ mIsPhaseTwo = -1;
+ // fall-through
+ } else {
+ break;
+ }
+ }
+ case LIGHTNING_STRIKE_DEMO: {
+ if (field_0x2CEE < 30) {
+ b2 = true;
+ }
+ mtx.YrotS((s16)field_0x2CF4 + mRotation.y);
+ v.set(0.0f, 100.0f, 400.0f);
+ MTXMultVec(mtx, v, v);
+ v += mPosition;
+ cLib::addCalcPos2(&field_0x2D04, v, 0.1f, 30.0f);
+ if (field_0x2CEE > 5) {
+ sLib::addCalcScaledDiff(&field_0x2D00, 1.0f, 1.0f, 0.1f);
+ sLib::addCalcScaledDiff(&field_0x2CF4, 6000.0f, 0.05f, field_0x2D00 * 100.0f);
+ }
+ // fall-through
+ }
+ case LIGHTNING_STRIKE_WAIT: {
+ b1 = true;
+ if (field_0x2CEE > 205) {
+ sLib::addCalcScaledDiff(&field_0x2D00, 1.0f, 1.0f, 0.1f);
+ if (field_0x2CEE >= 290) {
+ if (field_0x2CEE == 290) {
+ field_0x2D00 = 0.0f;
+ }
+ sLib::addCalcScaledDiff(&field_0x2CFC, 50.0f, 0.05f, field_0x2D00);
+ sLib::addCalcScaledDiff(&field_0x2D10.y, 290.0f, 0.1f, field_0x2D00 * 5.0f);
+ } else {
+ sLib::addCalcScaledDiff(&field_0x2CFC, 70.0f, 0.05f, field_0x2D00);
+ sLib::addCalcScaledDiff(&field_0x2D10.y, 420.0f, 0.1f, field_0x2D00 * 100.0f);
+ if (field_0x2CEE == 0xFA) {
+ dLightEnv_c::GetPInstance()->setField_0x38DC(7);
+ setAnm("CatchThunderEnd", 5.0f);
+ spawnEffect = true;
+ effPos.set(mSwordPosition.x, mSwordPosition.y + 110.0f, mSwordPosition.z);
+ mIsSwordEmpowered = true;
+ mSwordMdl.fn_8006B800(4);
+ mCc1.OnTg_0x8000000();
+ startSound(SE_BLasBos_ThunderFallSword);
+ mSubState = SUB_STATE_21;
+ mTimers[TIMER_3] = cM::rndF(30.0f) + 200.0f;
+ dRumble_c::start(dRumble_c::sRumblePreset4, dRumble_c::FLAG_ACTIVE | dRumble_c::FLAG_SLOT0);
+ field_0x2CF0 = 15;
+ }
+ if (field_0x2CEE >= 200 && field_0x2CEE <= 250) {
+ b2 = true;
+ }
+ }
+ } else {
+ cLib::addCalcPos2(&field_0x2D10, mChestTranslation, 0.1f, 50.0f);
+ }
+ break;
+ }
+ case LIGHTNING_STRIKE_TRIGGER_END: {
+ {
+ // this works but I don't like it
+ static volatile u32 FLAGS_1 = 0x00000001;
+ static u32 FLAGS_2 = 0x00100001;
+ u32 f1 = FLAGS_1;
+ u32 f2 = FLAGS_2;
+ Event e = Event("BLS_end", 100, f2 & ~f1, nullptr, nullptr);
+ EventManager::alsoSetAsCurrentEvent(this, &e, nullptr);
+ }
+ if (EventManager::isInEvent(this, "BLS_end")) {
+ field_0x2CEE = 0;
+ field_0x2D00 = 0.0f;
+ field_0x2CFC = 50.0f;
+ mLightingStrikeState = LIGHTNING_STRIKE_ENDING;
+ link->onFlags_0x360(0x200);
+ if (mpSwordBattleGame != nullptr) {
+ mpSwordBattleGame->notifyBossDeath(false);
+ }
+ StoryflagManager::sInstance->setFlagOrCounterToValue(STORYFLAG_692, 0);
+ dStage_c::GetInstance()->getRoom(0)->someLastBossThing(false);
+ // fall-through
+ } else {
+ break;
+ }
+ }
+ case LIGHTNING_STRIKE_ENDING: {
+ b1 = true;
+ if (field_0x2CEE < 30) {
+ b2 = true;
+ }
+ mtx.YrotS(mRotation.y - 0x4000);
+ v.set(0.0f, 100.0f, 1500.0f);
+ MTXMultVec(mtx, v, v);
+ field_0x2D04 = mBackbone1Translation + v;
+ field_0x2D10.x = mBackbone1Translation.x;
+ field_0x2D10.y = 400.0f;
+ field_0x2D10.z = mBackbone1Translation.z;
+ sLib::addCalcScaledDiff(&field_0x2CFC, 60.0f, 0.035f, 0.1f);
+ if (field_0x2CEE == 160) {
+ field_0x114C = 1;
+ }
+
+ if (field_0x2CEE >= 159) {
+ if (field_0x2CEE < 170) {
+ sLib::addCalcScaledDiff(&field_0x11C4, cM::rndF(0.3f) + 0.7f, 1.0f, 0.4f);
+ } else {
+ sLib::addCalcScaled(&field_0x11C4, 1.0f, 0.02f);
+ }
+ } else {
+ if (field_0x2CEE < 10) {
+ sLib::addCalcScaledDiff(&field_0x11C4, 0.7f, 1.0f, 0.35f);
+ } else {
+ sLib::addCalcScaled(&field_0x11C4, 1.0f, 0.035f);
+ }
+ }
+
+ if (field_0x2CEE == 230) {
+ link->offFlags_0x360(0x200);
+ }
+
+ if (field_0x2CEE == 270 && mpSwordBattleGame != nullptr) {
+ mLightingStrikeState = LIGHTNING_STRIKE_FINISH;
+ } else {
+ lightEnv.setField_0x5D48(field_0x11C4);
+ if (field_0x2CEE == 360) {
+ dScGame_c::GetInstance()->triggerExit(mRoomID, 1);
+ }
+ }
+ break;
+ }
+ case LIGHTNING_STRIKE_TRIGGER_START: {
+ {
+ // this works but I don't like it
+ static volatile u32 FLAGS_1 = 0x00000001;
+ static u32 FLAGS_2 = 0x00100001;
+ u32 f1 = FLAGS_1;
+ u32 f2 = FLAGS_2;
+ Event e = Event("BLS_start", 100, f2 & ~f1, nullptr, nullptr);
+ EventManager::alsoSetAsCurrentEvent(this, &e, nullptr);
+ }
+ if (EventManager::isInEvent(this, "BLS_start")) {
+ field_0x2CEE = 0;
+ field_0x2D00 = 0.0f;
+ field_0x2CFC = 60.0f;
+ mLightingStrikeState = LIGHTNING_STRIKE_START;
+ field_0x2D10.set(0.0f, 200.0f, -587.0f);
+ field_0x2D04.set(0.0f, 197.0f, -207.0f);
+ dAcPy_c::GetLinkM()->vt_0x2AC();
+ dLytBossCaption_c::GetInstance()->show("BOSS_11_caption", 0);
+ // fall-through
+ } else {
+ break;
+ }
+ }
+ case LIGHTNING_STRIKE_START: {
+ b1 = true;
+ sLib::addCalcScaledDiff(&field_0x2D00, 1.0f, 1.0f, 0.05f);
+ cLib::addCalcPos2(&field_0x2D10, mVec3_c(-2.6f, 118.0f, 298.0f), 0.1f, field_0x2D00 * 80.0f);
+ cLib::addCalcPos2(&field_0x2D04, mVec3_c(-132.0f, 89.0f, 654.0f), 0.1f, field_0x2D00 * 80.0f);
+
+ if (field_0x2CEE >= 20) {
+ sLib::addCalcScaledDiff(&field_0x2CFC, 40.0f, 0.05f, 0.1f);
+ }
+
+ if (field_0x2CEE == 40) {
+ dAcPy_c::GetLinkM()->triggerMoveEventMaybe(4, 0, 0, nullptr, 0, 1, 0);
+ }
+
+ if (field_0x2CEE == 110) {
+ dLytBossCaption_c::GetInstance()->unk_inline();
+ }
+
+ if (field_0x2CEE >= 140) {
+ EventManager::finishEvent(this, nullptr);
+ dScGame_c::getCamera()->fn_8019EA70(true);
+ mLightingStrikeState = LIGHTNING_STRIKE_STATE_NONE;
+ unsetActorProperty(AC_PROP_0x4);
+ }
+ break;
+ }
+ case LIGHTNING_STRIKE_FINISH: {
+ EventManager::finishEvent(this, nullptr);
+ dScGame_c::getCamera()->fn_8019EA70(true);
+ mLightingStrikeState = LIGHTNING_STRIKE_STATE_NONE;
+ break;
+ }
+ }
+
+ if (spawnEffect) {
+ dJEffManager_c::spawnEffect(
+ PARTICLE_RESOURCE_ID_MAPPING_624_, effPos, nullptr, nullptr, nullptr, nullptr, 0, 0
+ );
+ mLightingFallSwordTimer = 10;
+ }
+
+ if (b1) {
+ field_0x2CEE++;
+ mVec3_c tmp1 = field_0x2D10;
+ if (field_0x2CF0 != 0) {
+ field_0x2CF0--;
+ s16 val = field_0x2CF0;
+ f32 fac = val * 3.0f;
+ tmp1.y += mAng(val * 0x1C20).cos() * fac;
+ }
+ cam->fn_8019EA00(tmp1, field_0x2D04, field_0x2CFC, 0.0f);
+ if (b2) {
+ mtx1.transS(0.5f, 0.5f, 0.0f);
+ // REGSWAP
+ s32 scale = 95;
+ mtx1.scaleM(scale / 100.0f, scale / 100.0f, 0.0f);
+ mtx1.transM(-0.5f, -0.5f, 0.0f);
+ dStageMgr_c::GetInstance()->procfn_800192F0(0x96, mtx1, 0x32);
+ }
+ }
+
+ if (field_0x114C != 0) {
+ mtx.YrotS(cam->fn_8019E3B0());
+ v.set(0.0f, 10.0f, 10000.0f);
+ MTXMultVec(mtx, v, v);
+ v.x += cam->getPositionMaybe().x;
+ v.z += cam->getPositionMaybe().z;
+ mtx.transS(v);
+ v.set(0.7f, 0.7f, 0.7f);
+ mThunderMdl.setScale(v);
+ mThunderMdl.setLocalMtx(mtx);
+ mThunderAnmMatClr.play();
+ }
+}
+
+void dAcBlastboss_c::setLightningTimerMaybe(s32 arg) {
+ f32 f = arg + cM::rndF(arg * 0.5f);
+
+ if (mStunCounter >= 2) {
+ f *= 0.5f;
+ } else if (mStunCounter == 1) {
+ f *= 0.75f;
+ }
+
+ mLightningTimerMaybe = f;
+}
diff --git a/src/REL/d/a/e/d_a_e_sm.cpp b/src/REL/d/a/e/d_a_e_sm.cpp
index 7616f56e..01fb52ae 100644
--- a/src/REL/d/a/e/d_a_e_sm.cpp
+++ b/src/REL/d/a/e/d_a_e_sm.cpp
@@ -265,7 +265,7 @@ int dAcEsm_c::actorCreate() {
mAnmTexPat.setFrame(anim_frame, 0);
- setInteractionFlags(0x40);
+ setInteractionFlags(INTERACT_0x40);
fn_187_44C0();
@@ -369,7 +369,7 @@ int dAcEsm_c::actorExecute() {
if (timeCheck != 0) {
if (field_0xBBF == 3) {
- if (checkInteractionFlags(4)) {
+ if (checkInteractionFlags(INTERACT_0x4)) {
fn_800306d0();
}
return SUCCEEDED;
@@ -400,7 +400,7 @@ int dAcEsm_c::actorExecute() {
}
if (field_0xBBF == 3 && mTimeArea.isNearZero()) {
- if (checkInteractionFlags(4)) {
+ if (checkInteractionFlags(INTERACT_0x4)) {
fn_800306d0();
}
return SUCCEEDED;
@@ -1430,7 +1430,7 @@ void dAcEsm_c::fn_187_6C20(bool param0) {
mSph.SetAtFlagsUpper(0);
sTimer = 0;
- setInteractionFlags(4);
+ setInteractionFlags(INTERACT_0x4);
fn_187_44C0();
field_0xBAC = 60;
diff --git a/src/REL/d/a/obj/d_a_obj_warp_hole.cpp b/src/REL/d/a/obj/d_a_obj_warp_hole.cpp
index 73228b42..d0ee7416 100644
--- a/src/REL/d/a/obj/d_a_obj_warp_hole.cpp
+++ b/src/REL/d/a/obj/d_a_obj_warp_hole.cpp
@@ -86,7 +86,7 @@ int dAcOwarpHole_c::actorExecuteInEvent() {
if (EventManager::isCurrentEvent("BeforeLastBossBattleChicken")) {
dAcPy_c* player = dAcPy_c::GetLinkM();
player->vt_0x2AC();
- player->triggerMoveEventMaybe(2, 0, 0, mLinkPos, 0, 0, 0);
+ player->triggerMoveEventMaybe(2, 0, 0, &mLinkPos, 0, 0, 0);
}
}
if (dAcPy_c::GetLinkM()->mPosition.absXZTo(mLinkPos) < 10.0f) {
diff --git a/src/d/col/c/c_m3d_g_cps.cpp b/src/d/col/c/c_m3d_g_cps.cpp
index 4457e2fb..6fbcfc3d 100644
--- a/src/d/col/c/c_m3d_g_cps.cpp
+++ b/src/d/col/c/c_m3d_g_cps.cpp
@@ -16,7 +16,7 @@ void cM3dGCps::SetR(f32 r) {
r = 0.0f;
}
mRadius = r;
- field_0x1C = (double)r; // huh
+ field_0x1C = mRadius;
}
void cM3dGCps::Set_0x1C(f32 f) {
diff --git a/src/d/snd/d_snd_source.cpp b/src/d/snd/d_snd_source.cpp
index f71dfb3a..00ddbbee 100644
--- a/src/d/snd/d_snd_source.cpp
+++ b/src/d/snd/d_snd_source.cpp
@@ -472,8 +472,7 @@ bool dSoundSource_c::startBgHitSound(
return startBgHitSound(soundLabelToSoundId(label), polyAttr0, polyAttr1, position);
}
-// exact copy of startSoundAtPosition - used only for when the hookshot
-// hits the water level
+// exact copy of startSoundAtPosition
bool dSoundSource_c::startSoundAtPosition2(u32 soundId, const nw4r::math::VEC3 *position) {
if (!d_s_vt_0x1AC(soundId)) {
return false;
diff --git a/src/toBeSorted/d_enemy_sword_mdl.cpp b/src/toBeSorted/d_enemy_sword_mdl.cpp
new file mode 100644
index 00000000..0c030dcd
--- /dev/null
+++ b/src/toBeSorted/d_enemy_sword_mdl.cpp
@@ -0,0 +1,131 @@
+#include "toBeSorted/d_enemy_sword_mdl.h"
+
+#include "common.h"
+#include "d/col/cc/d_cc_s.h"
+#include "d/d_sc_game.h"
+#include "m/m3d/m_shadow.h"
+#include "m/m_vec.h"
+#include "nw4r/g3d/res/g3d_resfile.h"
+#include "nw4r/g3d/res/g3d_resmdl.h"
+
+dCcD_SrcCps sCcSrc = {
+ {
+ {AT_TYPE_DAMAGE, 0x8D, {1, 0, 0}, 1, 0, 0, 0, 0, 0},
+ {0, 0, {0, 0, 0x407}, 0, 0},
+ {0},
+ },
+ {30.0f},
+};
+
+// Yeah these two functions do the same thing. Could've made one call the other...
+
+bool dEnemySwordMdl_c::create(
+ mAllocator_c *alloc, void *pData, const char *mdlName, u32 bufferOption, const mVec3_c &v1, const mVec3_c &v2,
+ cCcD_Stts &stts, EGG::ResTIMG *pImg, int nView, u32 *pSize
+) {
+ nw4r::g3d::ResMdl mdl = nw4r::g3d::ResFile(pData).GetResMdl(mdlName);
+ if (!mMdl.create(mdl, alloc, bufferOption, nView, pSize)) {
+ return false;
+ }
+
+ if (!mProc.create(100, alloc, pImg, 0.015f)) {
+ mMdl.remove();
+ return false;
+ }
+
+ field_0x074.set(v1.x, v1.y, v1.z);
+ field_0x080.set(v2.x, v2.y, v2.z);
+
+ for (int i = 0; i < 3; i++) {
+ mCcList.addCc(mCcs[i], sCcSrc);
+ }
+ mCcList.SetStts(stts);
+ mCcList.ClrAt();
+ return true;
+}
+
+bool dEnemySwordMdl_c::create(
+ mAllocator_c *alloc, nw4r::g3d::ResFile resFile, const char *mdlName, u32 bufferOption, const mVec3_c &v1,
+ const mVec3_c &v2, cCcD_Stts &stts, EGG::ResTIMG *pImg, int nView, u32 *pSize
+) {
+ nw4r::g3d::ResMdl mdl = resFile.GetResMdl(mdlName);
+ if (!mMdl.create(mdl, alloc, bufferOption, nView, pSize)) {
+ return false;
+ }
+
+ if (!mProc.create(100, alloc, pImg, 0.015f)) {
+ mMdl.remove();
+ return false;
+ }
+
+ field_0x074.set(v1.x, v1.y, v1.z);
+ field_0x080.set(v2.x, v2.y, v2.z);
+
+ for (int i = 0; i < 3; i++) {
+ mCcList.addCc(mCcs[i], sCcSrc);
+ }
+ mCcList.SetStts(stts);
+ mCcList.ClrAt();
+ return true;
+}
+
+void dEnemySwordMdl_c::enableAttack() {
+ mCcs[0].OnAtSet();
+ mIsActive = true;
+ mFirstFramePassed = false;
+}
+
+// TODO - ...
+
+void dEnemySwordMdl_c::calc(const mMtx_c &mtx, const mVec3_c &v1, bool mass) {
+ mMdl.setLocalMtx(mtx);
+ mMdl.calc(false);
+ MTXMultVec(mtx, field_0x074, field_0x08C);
+ MTXMultVec(mtx, field_0x080, field_0x098);
+
+ if (mIsActive) {
+ mVec3_c v = field_0x098 - field_0x08C;
+ v.normalize();
+
+ mVec3_c hi = field_0x098 + v * field_0x0A8;
+
+ mCcs[1].Set(mCcs[0].mEnd, hi);
+ mCcs[2].Set(mCcs[0].mStart, hi);
+ mCcs[0].Set(field_0x08C - v * field_0x0A4, hi);
+
+ mCcs[0].SetAtVec(v1);
+ mCcs[1].SetAtVec(v1);
+ mCcs[2].SetAtVec(v1);
+
+ if (mFirstFramePassed && !mCcs[1].ChkAtSet()) {
+ mCcs[1].OnAtSet();
+ mCcs[2].OnAtSet();
+ } else {
+ mFirstFramePassed = true;
+ }
+
+ mCcList.registerColliders();
+ if (mass) {
+ dCcS::GetInstance()->GetMassMng().SetObj(&mCcs[0], 2);
+ }
+ } else {
+ mFirstFramePassed = false;
+ if (mCcs[0].ChkAtSet()) {
+ mCcList.ClrAt();
+ }
+ }
+ mProc.calc(field_0x098, field_0x08C);
+}
+
+bool dEnemySwordMdl_c::entry(dAcObjBase_c *obj, dShadowCircle_c *shadow, mQuat_c *quat) {
+ if (dScGame_c::currentSpawnInfo.getTrial() == SpawnInfo::TRIAL) {
+ obj->fn_8002ECD0(&mMdl, 7);
+ } else {
+ obj->drawModelType1(&mMdl);
+ }
+ mProc.entry();
+ if (shadow != nullptr && quat != nullptr) {
+ m3d::mShadow_c::GetInstance()->addMdlToCircle(shadow, mMdl, *quat);
+ }
+ return true;
+}
diff --git a/src/toBeSorted/d_sword_swing_effect.cpp b/src/toBeSorted/d_sword_swing_effect.cpp
new file mode 100644
index 00000000..20d8b97f
--- /dev/null
+++ b/src/toBeSorted/d_sword_swing_effect.cpp
@@ -0,0 +1,218 @@
+#include "toBeSorted/d_sword_swing_effect.h"
+
+#include "d/d_stage_mgr.h"
+#include "egg/gfx/eggDrawGX.h"
+#include "m/m3d/m3d.h"
+#include "m/m3d/m_proc.h"
+#include "m/m3d/m_scnleaf.h"
+#include "nw4r/g3d/g3d_scnobj.h"
+#include "nw4r/math/math_types.h"
+
+void dSwordSwingEffectProcBase_c::remove() {
+ if (mpEntries != nullptr) {
+ delete[] mpEntries;
+ mpEntries = nullptr;
+ }
+ m3d::scnLeaf_c::remove();
+}
+
+void dSwordSwingEffectProcBase_c::drawXlu() {
+ m3d::resetMaterial();
+ GXSetNumChans(1);
+ GXSetChanCtrl(GX_COLOR0A0, GX_FALSE, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
+ GXSetNumTexGens(0);
+ GXSetNumTevStages(1);
+ GXSetNumIndStages(0);
+ GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
+ GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0);
+ GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_RASC);
+ GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_RASA);
+ GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV);
+ GXSetZCompLoc(1);
+ GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR);
+ GXSetZMode(GX_TRUE, GX_LEQUAL, GX_FALSE);
+ GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
+ GXSetFog(GX_FOG_NONE, mColor(0), 0.0, 0.0, 0.0, 0.0);
+ GXSetFogRangeAdj(0, 0, 0);
+ GXSetCullMode(GX_CULL_NONE);
+ nw4r::math::MTX34 mtx;
+ nw4r::g3d::Camera cam = m3d::getCurrentCamera();
+ cam.GetCameraMtx(&mtx);
+ GXLoadPosMtxImm(mtx, 0);
+ GXSetCurrentMtx(0);
+ GXClearVtxDesc();
+ GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
+ GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, mCount * 2);
+
+ swing_entry *entry = &mpEntries[mHead];
+ for (u16 i = 0; i < mCount; i++) {
+ if (entry == &mpEntries[0]) {
+ entry = &mpEntries[mNum];
+ }
+ entry--;
+
+ GXPosition3f32(entry->mv1.x, entry->mv1.y, entry->mv1.z);
+ GXColor4u8(entry->mc1.r, entry->mc1.g, entry->mc1.b, entry->mc1.a * entry->mLifetime);
+ GXPosition3f32(entry->mv2.x, entry->mv2.y, entry->mv2.z);
+ GXColor4u8(entry->mc2.r, entry->mc2.g, entry->mc2.b, entry->mc2.a * entry->mLifetime);
+ }
+
+ GXEnd();
+}
+
+bool dSwordSwingEffectProcBase_c::hasSwings() const {
+ return mCount != 0;
+}
+
+int dSwordSwingEffectProcBase_c::entry() {
+ if (hasSwings()) {
+ return m3d::pushBack(mpScnLeaf);
+ }
+ return 0;
+}
+
+bool dSwordSwingEffectProcBase_c::create(s32 num, mAllocator_c *alloc) {
+ if (!m3d::proc_c::create(alloc, nullptr)) {
+ return false;
+ }
+
+ mpEntries = new (alloc->getHeap()) swing_entry[num]();
+ if (mpEntries == nullptr) {
+ remove();
+ return false;
+ }
+
+ mNum = num;
+ setOption(nw4r::g3d::ScnObj::OPTION_DISABLE_DRAW_OPA, true);
+ return true;
+}
+
+void dSwordSwingEffectProcBase_c::addSwing(
+ const mVec3_c &pos1, mColor c1, const mVec3_c &pos2, mColor c2
+) {
+ mpEntries[mHead].set(pos1, c1, pos2, c2);
+ mHead++;
+ if (mHead >= mNum) {
+ mHead = 0;
+ }
+ if (mCount < mNum) {
+ mCount++;
+ }
+}
+
+void dSwordSwingEffectProcBase_c::calc(f32 f) {
+ s32 count = mCount;
+ if (count == 0) {
+ return;
+ }
+
+ swing_entry *entry = &mpEntries[mHead];
+ for (u16 i = 0; i < mCount; i++) {
+ if (entry == &mpEntries[0]) {
+ entry = &mpEntries[mNum];
+ }
+ entry--;
+ entry->mLifetime -= f;
+ if (entry->mLifetime <= 0.0f) {
+ entry->mLifetime = 0.0f;
+ count--;
+ }
+ }
+ if (mCount != 0 && count == 0) {
+ mHead = 0;
+ }
+ mCount = count;
+}
+
+void dSwordSwingEffectProc_c::drawXlu() {
+ if (mpImg == nullptr) {
+ dSwordSwingEffectProcBase_c::drawXlu();
+ } else {
+ EGG::DrawGX::LoadTexture(mpImg, GX_TEXMAP0);
+ GXSetNumChans(1);
+ GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_VTX, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE);
+ GXSetNumTexGens(1);
+ GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, 0x3c, 0, 0x7d);
+ GXSetNumTevStages(1);
+ GXSetNumIndStages(0);
+ GXSetTevSwapMode(GX_TEVSTAGE0, GX_TEV_SWAP0, GX_TEV_SWAP0);
+ GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0);
+ GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_RASC, GX_CC_TEXC, GX_CC_ZERO);
+ GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, 1, GX_TEVPREV);
+ GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_RASA, GX_CA_TEXA, GX_CA_ZERO);
+ GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV);
+ GXSetZCompLoc(0);
+ GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_OR);
+ GXSetZMode(true, GX_LEQUAL, false);
+ GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0);
+ GXSetFog(GX_FOG_NONE, mColor(0), 0.0, 0.0, 0.0, 0.0);
+ GXSetFogRangeAdj(0, 0, 0);
+ GXSetCullMode(GX_CULL_NONE);
+ nw4r::math::MTX34 mtx;
+ nw4r::g3d::Camera cam = m3d::getCurrentCamera();
+ cam.GetCameraMtx(&mtx);
+ GXLoadPosMtxImm(mtx, 0);
+ GXSetCurrentMtx(0);
+ GXClearVtxDesc();
+ GXSetVtxDesc(GX_VA_POS, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT);
+ GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0);
+ GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_TEX_ST, GX_F32, 0);
+ GXBegin(GX_TRIANGLESTRIP, GX_VTXFMT0, mCount * 2);
+
+ u8 alpha = dStageMgr_c::GetInstance()->getGlobalAlpha();
+ f32 fAlpha = alpha * (1.0f / 255.0f);
+
+ s32 idx = mHead - mCount;
+ if (idx < 0) {
+ idx += mNum;
+ }
+
+ f32 texCoordOffset = mTexScale * idx;
+
+ swing_entry *entry = &mpEntries[idx];
+ swing_entry *last = &mpEntries[mNum];
+
+ for (u16 i = 0; i < mCount; i++) {
+ GXPosition3f32(entry->mv1.x, entry->mv1.y, entry->mv1.z);
+ GXColor4u8(entry->mc1.r, entry->mc1.g, entry->mc1.b, entry->mc1.a * entry->mLifetime * fAlpha);
+ GXTexCoord2f32(texCoordOffset, 0.0f);
+
+ GXPosition3f32(entry->mv2.x, entry->mv2.y, entry->mv2.z);
+ GXColor4u8(entry->mc2.r, entry->mc2.g, entry->mc2.b, entry->mc2.a * entry->mLifetime * fAlpha);
+ GXTexCoord2f32(texCoordOffset, 1.0f);
+
+ texCoordOffset += mTexScale;
+ entry++;
+ if (entry == last) {
+ entry = &mpEntries[0];
+ }
+ }
+ }
+}
+
+bool dSwordSwingEffectProc_c::create(s32 num, mAllocator_c *alloc, EGG::ResTIMG *pImg, f32 scale) {
+ if (!dSwordSwingEffectProcBase_c::create(num, alloc)) {
+ return false;
+ }
+
+ mpImg = pImg;
+ mTexScale = scale;
+ return true;
+}
+
+void dSwordSwingEffectProcBase_c::swing_entry::set(
+ const mVec3_c &pos1, const mColor &c1, const mVec3_c &pos2, const mColor &c2
+) {
+ mLifetime = 1.0f;
+ mv1 = pos1;
+ mv2 = pos2;
+ mc1 = c1;
+ mc2 = c2;
+}
diff --git a/src/toBeSorted/d_sword_swing_effect_mgr.cpp b/src/toBeSorted/d_sword_swing_effect_mgr.cpp
new file mode 100644
index 00000000..1d0339c3
--- /dev/null
+++ b/src/toBeSorted/d_sword_swing_effect_mgr.cpp
@@ -0,0 +1,196 @@
+#include "toBeSorted/d_sword_swing_effect_mgr.h"
+
+#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)
+ );
+}
+
+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;
+ mVec2_c t2 = v4 - v3;
+
+ if (cM::isZero(t1.x)) {
+ if (cM::isZero(t2.x)) {
+ return false;
+ } else {
+ result.x = v1.x;
+ result.y = v3.y + (t2.y / t2.x) * (v1.x - v3.x);
+ }
+ } else {
+ if (cM::isZero(t2.x)) {
+ result.x = v3.x;
+ } else {
+ f32 tmp = t1.y / t1.x - t2.y / t2.x;
+ if (cM::isZero(tmp)) {
+ return false;
+ }
+ result.x = (v3.x + (((t1.y / t1.x) * v1.x - v1.y) - (t2.y / t2.x) * v3.x)) / tmp;
+ }
+ result.y = v1.y + (t1.y / t1.x) * (result.x - v1.x);
+ }
+
+ mVec2_c diff = result - v1;
+ if (diff.x * t1.x + diff.y * t1.y >= 0.0f) {
+ return false;
+ }
+
+ diff = result - v3;
+ if (diff.x * t2.x + diff.y * t2.y >= 0.0f) {
+ return false;
+ }
+
+ return true;
+}
+
+void dSwordSwingEffectProcMgr_c::createSwingEntries(const mVec3_c &v1, const mVec3_c &v2) {
+ mVec3_c lastDiff = field_0x44 - field_0x38;
+ mVec3_c diff = v1 - v2;
+
+ mVec3_c cross_;
+ cross(cross_, lastDiff, diff);
+
+ f32 diffMag = diff.mag();
+
+ lastDiff.normalize();
+
+ diff /= diffMag;
+
+ cross_.normalize();
+
+ // Same code as in dowsing_target...
+ f32 dot = lastDiff.dot(diff);
+ dot = cM::minMaxLimit(dot, -1.0f, 1.0f);
+ f32 a = 1.0f - dot * dot <= 0.0f ? 0.0f : nw4r::math::FrSqrt(1.0f - dot * dot) * (1.0f - dot * dot);
+ EGG::Matrix34f mat;
+ mat.setAxisRotation(cross_, cM::atan2f(a, dot) * 0.1f);
+
+ mVec2_c p1, p2, p3, p4;
+ mVec2_c res1, res2, res3;
+
+ p1.set(field_0x38.x, field_0x38.y);
+ p2.set(field_0x44.x, field_0x44.y);
+ p3.set(v2.x, v2.y);
+ p4.set(v1.x, v1.y);
+ bool b1 = fn_8006A8D0(p1, p2, p3, p4, res1);
+
+ p1.set(field_0x38.y, field_0x38.z);
+ p2.set(field_0x44.y, field_0x44.z);
+ p3.set(v2.y, v2.z);
+ p4.set(v1.y, v1.z);
+ bool b2 = fn_8006A8D0(p1, p2, p3, p4, res2);
+
+ p1.set(field_0x38.z, field_0x38.x);
+ p2.set(field_0x44.z, field_0x44.x);
+ p3.set(v2.z, v2.x);
+ p4.set(v1.z, v1.x);
+ bool b3 = fn_8006A8D0(p1, p2, p3, p4, res3);
+
+ bool b;
+ mVec3_c local_124 = (v2 + field_0x38) * 0.5f;
+ mVec3_c diff1;
+ mVec3_c v;
+ f32 f_29;
+ f32 f_28;
+ EGG::Matrix34f mat2;
+ int i = 0;
+ if (!b1) {
+ i += 1;
+ }
+ if (!b2) {
+ i += 1;
+ }
+
+ if (!b3) {
+ i += 1;
+ }
+
+ if (i >= 2) {
+ v = (v2 - field_0x38) * 0.1f;
+ b = false;
+ } else {
+ if (b1 && b3) {
+ local_124.x = (res1.x + res3.y) * 0.5f;
+ } else if (b1) {
+ local_124.x = res1.x;
+ } else if (b3) {
+ local_124.x = res3.y;
+ }
+
+ if (b2 && b1) {
+ local_124.y = (res2.x + res1.y) * 0.5f;
+ } else if (b2) {
+ local_124.y = res2.x;
+ } else if (b1) {
+ local_124.y = res1.y;
+ }
+
+ if (b3 && b2) {
+ local_124.z = (res3.x + res2.y) * 0.5f;
+ } else if (b3) {
+ local_124.z = res3.x;
+ } else if (b2) {
+ local_124.z = res2.y;
+ }
+
+ diff1 = field_0x38 - local_124;
+ mVec3_c diff2 = v2 - local_124;
+
+ f_29 = diff1.mag();
+ f_28 = (diff2.mag() - f_29) * 0.1f;
+
+ diff2.normalize();
+ diff1.normalize();
+
+ cross(cross_, diff1, diff2);
+ cross_.normalize();
+
+ // Same code as in dowsing_target...
+ f32 dot = diff1.dot(diff2);
+ dot = cM::minMaxLimit(dot, -1.0f, 1.0f);
+ f32 a = 1.0f - dot * dot <= 0.0f ? 0.0f : nw4r::math::FrSqrt(1.0f - dot * dot) * (1.0f - dot * dot);
+ mat2.setAxisRotation(cross_, cM::atan2f(a, dot) * 0.1f);
+
+ b = true;
+ }
+
+ f32 blub = 0.1f;
+ for (int i = 1; i <= 10; i++) {
+ mVec3_c a;
+ mVec3_c t;
+ if (b) {
+ MTXMultVecSR(mat2.m, diff1, diff1);
+ t = local_124 + (diff1 * (f_29 + (f_28 * i)));
+ } else {
+ t = field_0x38 + v * i;
+ }
+
+ MTXMultVecSR(mat.m, lastDiff, lastDiff);
+ a = t + lastDiff * diffMag;
+
+ mProc.addSwing(a, mC1, t, mC2);
+ // Unused
+ blub += 0.1f;
+ }
+}
+
+void dSwordSwingEffectProcMgr_c::calc(const mVec3_c &v1, const mVec3_c &v2) {
+ mProc.calc(0.1f);
+ if (mIsActive) {
+ createSwingEntries(v1, v2);
+ }
+ field_0x44 = v1;
+ field_0x38 = v2;
+}
+
+void dSwordSwingEffectProcMgr_c::entry() {
+ mProc.entry();
+}
diff --git a/src/toBeSorted/dowsing_target.cpp b/src/toBeSorted/dowsing_target.cpp
index 5969bf73..35311efb 100644
--- a/src/toBeSorted/dowsing_target.cpp
+++ b/src/toBeSorted/dowsing_target.cpp
@@ -174,6 +174,7 @@ DowsingTarget *DowsingTarget::getDowsingInfo(
targetDir.normalize();
+ // Same code as in d_sword_swing_effect_mgr...
f32 dot = dwsDir.dot(targetDir);
dot = cM::minMaxLimit(dot, -1.0f, 1.0f);
f32 a = 1.0f - dot * dot <= 0.0f ? 0.0f : nw4r::math::FrSqrt(1.0f - dot * dot) * (1.0f - dot * dot);