From bb6fd66745a19426066f4c664fc0972634d09462 Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 18 May 2025 12:41:12 +0200 Subject: [PATCH] More player model --- config/SOUE01/symbols.txt | 138 +-- include/d/a/d_a_player.h | 753 ++++++++++------ include/d/d_rawarchive.h | 3 + include/d/d_sc_game.h | 1 + include/d/lyt/meter/d_lyt_meter.h | 12 + .../d/lyt/meter/d_lyt_meter_shield_gauge.h | 10 +- include/egg/core/eggAllocator.h | 5 + include/egg/core/eggHeap.h | 19 +- include/m/m3d/m_anmchr.h | 4 + include/m/m3d/m_anmchrblend.h | 4 + include/m/m3d/m_mdl.h | 2 +- include/m/m_mtx.h | 6 + include/nw4r/g3d/g3d_calcworld.h | 5 + include/nw4r/g3d/res/g3d_resshp.h | 9 + include/toBeSorted/cx_util.h | 8 + include/toBeSorted/stage_render_stuff.h | 1 - src/REL/d/a/obj/d_a_obj_seat_sword.cpp | 6 +- src/REL/d/t/d_t_reaction.cpp | 5 +- src/d/a/obj/d_a_obj_tbox.cpp | 1 + src/d/d_player_mdl.cpp | 828 +++++++++++++++++- src/d/lyt/meter/d_lyt_meter_cross_btn.cpp | 3 +- src/d/lyt/meter/d_lyt_meter_shield_gauge.cpp | 8 +- src/egg/core/eggHeap.cpp | 2 +- src/m/m_allocator.cpp | 13 +- src/toBeSorted/special_item_drop_mgr.cpp | 7 +- 25 files changed, 1489 insertions(+), 364 deletions(-) create mode 100644 include/toBeSorted/cx_util.h diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index d7c6b37b..0a953cd1 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -2486,10 +2486,10 @@ unsetRegionBasedFlagsMaybe = .text:0x8005BEA0; // type:function size:0x100 getEarringsColor__17daPlayerActBase_cFv = .text:0x8005BFA0; // type:function size:0xB0 getLinkTunicSubtype = .text:0x8005C050; // type:function size:0xC getCurrentSwordType = .text:0x8005C060; // type:function size:0xAC -updateCurrentSword = .text:0x8005C110; // type:function size:0x24 +updateCurrentSword__17daPlayerActBase_cFv = .text:0x8005C110; // type:function size:0x24 doesPlayerHaveSword = .text:0x8005C140; // type:function size:0x1C -getSwordName = .text:0x8005C160; // type:function size:0x14 -getCurrentlyEquippedShieldType__7dAcPy_cFv = .text:0x8005C180; // type:function size:0x44 +getSwordName__17daPlayerActBase_cFl = .text:0x8005C160; // type:function size:0x14 +getCurrentlyEquippedShieldType__17daPlayerActBase_cFv = .text:0x8005C180; // type:function size:0x44 getCurrentSlingshotType__7dAcPy_cFv = .text:0x8005C1D0; // type:function size:0x48 getCurrentBugNetType__7dAcPy_cFv = .text:0x8005C220; // type:function size:0x48 getCurrentBeetleType__7dAcPy_cFv = .text:0x8005C270; // type:function size:0x78 @@ -2627,42 +2627,42 @@ set0x439F__17daPlayerActBase_cFP9dAcBase_ci = .text:0x8005CE10; // type:function vt_0x084__17daPlayerActBase_cFP9dAcBase_ci = .text:0x8005CE20; // type:function size:0x8 IfCurrentActionToActor__17daPlayerActBase_cFP9dAcBase_ci = .text:0x8005CE30; // type:function size:0x8 __sinit_\d_player_act_cpp = .text:0x8005CE40; // type:function size:0x4C -fn_8005CE90 = .text:0x8005CE90; // type:function size:0x134 -fn_8005CFD0 = .text:0x8005CFD0; // type:function size:0x10 -fn_8005CFE0 = .text:0x8005CFE0; // type:function size:0x134 -fn_8005D120 = .text:0x8005D120; // type:function size:0xD4 -fn_8005D200 = .text:0x8005D200; // type:function size:0x4 -fn_8005D210 = .text:0x8005D210; // type:function size:0x38 -fn_8005D250 = .text:0x8005D250; // type:function size:0x60 -fn_8005D2B0 = .text:0x8005D2B0; // type:function size:0x8 -fn_8005D2C0 = .text:0x8005D2C0; // type:function size:0x8 -fn_8005D2D0 = .text:0x8005D2D0; // type:function size:0x8 -fn_8005D2E0 = .text:0x8005D2E0; // type:function size:0x34 -isAnimationWaitingMaybe = .text:0x8005D320; // type:function size:0x80 -fn_8005D3A0 = .text:0x8005D3A0; // type:function size:0x8 +ExecCallback_DRAW_OPA__24daPlBaseScnObjCallback_cFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x8005CE90; // type:function size:0x134 +ExecCallback_CALC_MAT__24daPlBaseScnObjCallback_cFQ44nw4r3g3d6ScnObj6TimingPQ34nw4r3g3d6ScnObjUlPv = .text:0x8005CFD0; // type:function size:0x10 +ExecCallbackA__21daPlBaseMdlCallback_cFPQ34nw4r3g3d12ChrAnmResultQ34nw4r3g3d6ResMdlPQ34nw4r3g3d16FuncObjCalcWorld = .text:0x8005CFE0; // type:function size:0x134 +create__13daPlBaseMdl_cFP19daPlayerModelBase_cQ34nw4r3g3d6ResMdlP12mAllocator_cUlUlPUl = .text:0x8005D120; // type:function size:0xD4 +setAnm__13daPlBaseMdl_cFRQ23m3d6banm_c = .text:0x8005D200; // type:function size:0x4 +remove__13daPlBaseMdl_cFv = .text:0x8005D210; // type:function size:0x38 +setBlendNodeRange__13daPlBaseMdl_cFUsUsf = .text:0x8005D250; // type:function size:0x60 +timingA__22daPlBaseMainCallback_cFUlPQ34nw4r3g3d12ChrAnmResultQ34nw4r3g3d6ResMdl = .text:0x8005D2B0; // type:function size:0x8 +timingB__22daPlBaseMainCallback_cFUlPQ34nw4r3g3d13WorldMtxManipQ34nw4r3g3d6ResMdl = .text:0x8005D2C0; // type:function size:0x8 +timingC__22daPlBaseMainCallback_cFPQ34nw4r4math5MTX34Q34nw4r3g3d6ResMdl = .text:0x8005D2D0; // type:function size:0x8 +play__16daPlBaseAnmChr_cFv = .text:0x8005D2E0; // type:function size:0x34 +isFinished__16daPlBaseAnmChr_cFv = .text:0x8005D320; // type:function size:0x80 +timingB__22daPlBaseHeadCallback_cFUlPQ34nw4r3g3d13WorldMtxManipQ34nw4r3g3d6ResMdl = .text:0x8005D3A0; // type:function size:0x8 ExecCallbackC__27daPlBaseCalcWorldCallback_cFPQ34nw4r4math5MTX34Q34nw4r3g3d6ResMdlPQ34nw4r3g3d16FuncObjCalcWorld = .text:0x8005D3B0; // type:function size:0x30 fn_8005D3E0 = .text:0x8005D3E0; // type:function size:0x28 -fn_8005D410 = .text:0x8005D410; // type:function size:0x60 -InitLinkItemHeap = .text:0x8005D470; // type:function size:0x58 -ActorLink__allocateExternalDataBuffers = .text:0x8005D4D0; // type:function size:0x9C -InitSomeModelHeaps = .text:0x8005D570; // type:function size:0x78 -ActorLink__updateSwordShieldIfNeeded = .text:0x8005D5F0; // type:function size:0x58 -fn_8005D650 = .text:0x8005D650; // type:function size:0xDC -ActorLink__setEarringColor = .text:0x8005D730; // type:function size:0x74 -ActorLink__LoadLinkModels = .text:0x8005D7B0; // type:function size:0x32C -ActorLink__initBodyModels = .text:0x8005DAE0; // type:function size:0x360 -LoadHands = .text:0x8005DE40; // type:function size:0x250 -fn_8005E090 = .text:0x8005E090; // type:function size:0x64 -ActorLink__initSwordModels = .text:0x8005E100; // type:function size:0x1F0 -ActorLink__updateSword = .text:0x8005E2F0; // type:function size:0xA8 +freeFrmHeap__19daPlayerModelBase_cFP16mHeapAllocator_c = .text:0x8005D410; // type:function size:0x60 +allocFrmHeap__19daPlayerModelBase_cFP16mHeapAllocator_cUlPCc = .text:0x8005D470; // type:function size:0x58 +allocExternalDataBuffers__19daPlayerModelBase_cFv = .text:0x8005D4D0; // type:function size:0x9C +initModelHeaps__19daPlayerModelBase_cFv = .text:0x8005D570; // type:function size:0x78 +updateSwordShieldModelsIfNeeded__19daPlayerModelBase_cFv = .text:0x8005D5F0; // type:function size:0x58 +createAnmTexSrt__19daPlayerModelBase_cFPCcRQ23m3d6bmdl_c = .text:0x8005D650; // type:function size:0xDC +updateEarringsColor__19daPlayerModelBase_cFv = .text:0x8005D730; // type:function size:0x74 +loadBodyModels__19daPlayerModelBase_cFv = .text:0x8005D7B0; // type:function size:0x32C +loadBody__19daPlayerModelBase_cFv = .text:0x8005DAE0; // type:function size:0x360 +loadHandsModels__19daPlayerModelBase_cFv = .text:0x8005DE40; // type:function size:0x250 +setSwordAnm__19daPlayerModelBase_cFPCc = .text:0x8005E090; // type:function size:0x64 +initSwordModel__19daPlayerModelBase_cFv = .text:0x8005E100; // type:function size:0x1F0 +updateSwordModel__19daPlayerModelBase_cFv = .text:0x8005E2F0; // type:function size:0xA8 getCurrentShieldPouchSlot = .text:0x8005E3A0; // type:function size:0x50 isInBambooCuttingMinigame__7dAcPy_cFv = .text:0x8005E3F0; // type:function size:0x8 getCurrentlyEquippedShieldId = .text:0x8005E400; // type:function size:0x4C getShieldSubtype = .text:0x8005E450; // type:function size:0x3C -ActorLink__initShieldModels = .text:0x8005E490; // type:function size:0x2C0 -ActorLink__updateShieldModels = .text:0x8005E750; // type:function size:0xC8 -ActorLink__createModelAndSetDrawPriority = .text:0x8005E820; // type:function size:0x68 -createModelAndSetPriorityDraw = .text:0x8005E890; // type:function size:0x68 +initShieldModel__19daPlayerModelBase_cFv = .text:0x8005E490; // type:function size:0x2C0 +updateShieldModel__19daPlayerModelBase_cFv = .text:0x8005E750; // type:function size:0xC8 +createGenericSmdl__19daPlayerModelBase_cFQ34nw4r3g3d6ResMdlRQ23m3d6smdl_cP12mAllocator_cUl = .text:0x8005E820; // type:function size:0x68 +createGenericMdl__19daPlayerModelBase_cFQ34nw4r3g3d6ResMdlRQ23m3d5mdl_cP12mAllocator_cUl = .text:0x8005E890; // type:function size:0x68 fn_8005E900 = .text:0x8005E900; // type:function size:0x11C fn_8005EA20 = .text:0x8005EA20; // type:function size:0xA0 fn_8005EAC0__19daPlayerModelBase_cFv = .text:0x8005EAC0; // type:function size:0x274 @@ -2682,19 +2682,19 @@ vt_0x2E8__19daPlayerModelBase_cFv = .text:0x8005FB50; // type:function size:0x8 vt_0x304__19daPlayerModelBase_cCFv = .text:0x8005FB60; // type:function size:0xC isOnClawTargetMaybe__19daPlayerModelBase_cFiR4mAngR4mAng = .text:0x8005FB70; // type:function size:0x14 fn_8005FB90 = .text:0x8005FB90; // type:function size:0x220 -fn_8005FDB0 = .text:0x8005FDB0; // type:function size:0x4 -fn_8005FDC0 = .text:0x8005FDC0; // type:function size:0x78 -fn_8005FE40 = .text:0x8005FE40; // type:function size:0x4C +mainModeltimingA__19daPlayerModelBase_cFUlPQ34nw4r3g3d12ChrAnmResultRQ34nw4r3g3d6ResMdl = .text:0x8005FDB0; // type:function size:0x4 +mainModeltimingB__19daPlayerModelBase_cFUlPQ34nw4r3g3d13WorldMtxManipRQ34nw4r3g3d6ResMdl = .text:0x8005FDC0; // type:function size:0x78 +mainModelTimingC__19daPlayerModelBase_cFPQ34nw4r4math5MTX34RQ34nw4r3g3d6ResMdl = .text:0x8005FE40; // type:function size:0x4C fn_8005FE90 = .text:0x8005FE90; // type:function size:0xA8 fn_8005FF40 = .text:0x8005FF40; // type:function size:0x118 -UnkModel__setMatrix = .text:0x80060060; // type:function size:0x40 +setTransformAndCalc__19daPlayerModelBase_cFRQ23m3d9scnLeaf_cPC6mMtx_c = .text:0x80060060; // type:function size:0x40 fn_800600A0 = .text:0x800600A0; // type:function size:0xD4 fn_80060180 = .text:0x80060180; // type:function size:0xB0 -getItemResFile__7dAcPy_cFPCcR12mAllocator_c = .text:0x80060230; // type:function size:0xD4 -ActorLink__GetResCompressedFileFromExternalData = .text:0x80060310; // type:function size:0x94 -getAnmChrFromExternal = .text:0x800603B0; // type:function size:0x94 -ActorLink__BindAnmTexPatToArcALink2 = .text:0x80060450; // type:function size:0xD4 -getAnmTexSrtFromExternal = .text:0x80060530; // type:function size:0x94 +getItemResFile__19daPlayerModelBase_cFPCcR12mAllocator_c = .text:0x80060230; // type:function size:0xD4 +getExternalCompressedFile__19daPlayerModelBase_cFPCcPCcPvUl = .text:0x80060310; // type:function size:0x94 +getExternalAnmChr__19daPlayerModelBase_cFPCcPvUl = .text:0x800603B0; // type:function size:0x94 +getExternalAnmTexPat__19daPlayerModelBase_cFPCcPvUl = .text:0x80060450; // type:function size:0xD4 +getExternalAnmTexSrt__19daPlayerModelBase_cFPCcPvUl = .text:0x80060530; // type:function size:0x94 fn_800605D0 = .text:0x800605D0; // type:function size:0x30 ActorLink__SetFaceTexPat = .text:0x80060600; // type:function size:0xEC fn_800606F0 = .text:0x800606F0; // type:function size:0x38 @@ -2713,26 +2713,26 @@ fn_80061050 = .text:0x80061050; // type:function size:0x1B0 fn_80061200 = .text:0x80061200; // type:function size:0x210 fn_80061410__19daPlayerModelBase_cFv = .text:0x80061410; // type:function size:0x6C alwaysRet0__19daPlayerModelBase_cFv = .text:0x80061480; // type:function size:0x8 -fn_80061490 = .text:0x80061490; // type:function size:0x1C -fn_800614B0 = .text:0x800614B0; // type:function size:0xC -fn_800614C0 = .text:0x800614C0; // type:function size:0xC -ActorLink__getSwordModelMatrix = .text:0x800614D0; // type:function size:0x8 -ActorLink__getShieldModelMatrix = .text:0x800614E0; // type:function size:0x8 -fn_800614F0 = .text:0x800614F0; // type:function size:0x14 -ActorLink__getCurrentCarriedActor = .text:0x80061510; // type:function size:0x8 -fn_80061520 = .text:0x80061520; // type:function size:0x8 -fn_80061530 = .text:0x80061530; // type:function size:0x8 -ActorLink__getHeadTranslation = .text:0x80061540; // type:function size:0x8 -fn_80061550 = .text:0x80061550; // type:function size:0x8 -ActorLink__getCenterTranslation = .text:0x80061560; // type:function size:0x8 -fn_80061570 = .text:0x80061570; // type:function size:0x8 +somethingWithCarriedActorFlags__19daPlayerModelBase_cFv = .text:0x80061490; // type:function size:0x1C +vt_0x19C__19daPlayerModelBase_cFv = .text:0x800614B0; // type:function size:0xC +vt_0x198__19daPlayerModelBase_cFv = .text:0x800614C0; // type:function size:0xC +getSwordModelMatrix__19daPlayerModelBase_cFP6mMtx_c = .text:0x800614D0; // type:function size:0x8 +getSheathModelMatrix__19daPlayerModelBase_cFP6mMtx_c = .text:0x800614E0; // type:function size:0x8 +getBodyMtx__19daPlayerModelBase_cFP6mMtx_ci = .text:0x800614F0; // type:function size:0x14 +getCurrentCarriedActor__19daPlayerModelBase_cFv = .text:0x80061510; // type:function size:0x8 +vt_0x0F4__19daPlayerModelBase_cCFv = .text:0x80061520; // type:function size:0x8 +vt_0x0F0__19daPlayerModelBase_cCFv = .text:0x80061530; // type:function size:0x8 +vt_0x0EC__19daPlayerModelBase_cCFv = .text:0x80061540; // type:function size:0x8 +vt_0x0E8__19daPlayerModelBase_cCFv = .text:0x80061550; // type:function size:0x8 +getCenterTranslation__19daPlayerModelBase_cCFv = .text:0x80061560; // type:function size:0x8 +canBlockAttack__19daPlayerModelBase_cFv = .text:0x80061570; // type:function size:0x8 __dt__19daPlayerModelBase_cFv = .text:0x80061580; // type:function size:0x254 __dt__16daPlBaseAnmChr_cFv = .text:0x800617E0; // type:function size:0x58 __dt__24daPlBaseScnObjCallback_cFv = .text:0x80061840; // type:function size:0x40 __dt__27daPlBaseCalcWorldCallback_cFv = .text:0x80061880; // type:function size:0x40 __dt__Q34nw4r3g3d18ICalcWorldCallbackFv = .text:0x800618C0; // type:function size:0x40 -__dt__19daPlBaseCallback2_cFv = .text:0x80061900; // type:function size:0x58 -__dt__19daPlBaseCallback1_cFv = .text:0x80061960; // type:function size:0x58 +__dt__22daPlBaseHeadCallback_cFv = .text:0x80061900; // type:function size:0x58 +__dt__22daPlBaseMainCallback_cFv = .text:0x80061960; // type:function size:0x58 __dt__13daPlBaseMdl_cFv = .text:0x800619C0; // type:function size:0x6C __dt__21daPlBaseMdlCallback_cFv = .text:0x80061A30; // type:function size:0x58 ExecCallbackB__Q34nw4r3g3d18ICalcWorldCallbackFPQ34nw4r3g3d13WorldMtxManipQ34nw4r3g3d6ResMdlPQ34nw4r3g3d16FuncObjCalcWorld = .text:0x80061A90; // type:function size:0x4 @@ -2898,7 +2898,7 @@ fn_80066DA0 = .text:0x80066DA0; // type:function size:0x5C fn_80066E00 = .text:0x80066E00; // type:function size:0x44 fn_80066E50 = .text:0x80066E50; // type:function size:0x108 fn_80066F60 = .text:0x80066F60; // type:function size:0x50 -lzSafeDecompress = .text:0x80066FB0; // type:function size:0x64 +lzSafeDecompress__FPCvUlPv = .text:0x80066FB0; // type:function size:0x64 matrixCreateFromPosRotYScale__FR6mMtx_cRC7mVec3_c4mAngRC7mVec3_cP6mMtx_cf = .text:0x80067020; // type:function size:0x138 checkIfVec3fInMatrix__FRC6mMtx_cRC7mVec3_c = .text:0x80067160; // type:function size:0x88 fn_800671F0 = .text:0x800671F0; // type:function size:0x84 @@ -11198,7 +11198,7 @@ getCamera__9dScGame_cFl = .text:0x801BB6F0; // type:function size:0x10 fn_801BB700 = .text:0x801BB700; // type:function size:0x4C fn_801BB750 = .text:0x801BB750; // type:function size:0x4C fn_801BB7A0 = .text:0x801BB7A0; // type:function size:0xC4 -isHeroMode = .text:0x801BB870; // type:function size:0x44 +isHeroMode__9dScGame_cFv = .text:0x801BB870; // type:function size:0x44 startNewGameFile = .text:0x801BB8C0; // type:function size:0x100 fn_801BB9C0 = .text:0x801BB9C0; // type:function size:0x3C unsetFlagsAfterStart = .text:0x801BBA00; // type:function size:0x110 @@ -12655,7 +12655,7 @@ ActorLink__dealsWithShield = .text:0x80214110; // type:function size:0xA0 fn_802141B0 = .text:0x802141B0; // type:function size:0x108 fn_802142C0 = .text:0x802142C0; // type:function size:0x11C fn_802143E0 = .text:0x802143E0; // type:function size:0x148 -fn_80214530 = .text:0x80214530; // type:function size:0x78 +onShieldUpdate__7dAcPy_cFv = .text:0x80214530; // type:function size:0x78 handleShieldStatusEffects = .text:0x802145B0; // type:function size:0x200 fn_802147B0 = .text:0x802147B0; // type:function size:0x2D4 ActorLink__ShieldBlock = .text:0x80214A90; // type:function size:0x128 @@ -13079,7 +13079,7 @@ ActorLink__finishPlayingHarp = .text:0x80236CF0; // type:function size:0x20 ActorLink__doHarpPlayAnim = .text:0x80236D10; // type:function size:0xE0 fn_80236DF0 = .text:0x80236DF0; // type:function size:0x22C __ct__7dAcPy_cFv = .text:0x80237020; // type:function size:0xAC8 -__ct__10daPlBase_cFv = .text:0x80237AF0; // type:function size:0x34C +__ct__19daPlayerModelBase_cFv = .text:0x80237AF0; // type:function size:0x34C __ct__16daPlBaseAnmChr_cFv = .text:0x80237E40; // type:function size:0x48 ActorLink__create16EmptyActorReferences = .text:0x80237E90; // type:function size:0x48 fn_80237EE0 = .text:0x80237EE0; // type:function size:0x80 @@ -28150,7 +28150,11 @@ lbl_804DF2E0 = .rodata:0x804DF2E0; // type:object size:0x10 lbl_804DF2F0 = .rodata:0x804DF2F0; // type:object size:0xC LINK_ANIMATIONS = .rodata:0x804DF2FC; // type:object size:0x14C4 SHIELD_DURABILITIES = .rodata:0x804E07C0; // type:object size:0xC -SHIELD_REGEN_TIME = .rodata:0x804E07CC; // type:object size:0x7C +SHIELD_REGEN_TIME = .rodata:0x804E07CC; // type:object size:0xC +sSwordRelatedX = .rodata:0x804E07D8; // type:object size:0x1C +sSwordRelatedUnk = .rodata:0x804E07F4; // type:object size:0x1C +sSwordRelatedZ = .rodata:0x804E0810; // type:object size:0x1C +sSwordRelatedY = .rodata:0x804E082C; // type:object size:0x1C lbl_804E0848 = .rodata:0x804E0848; // type:object size:0x24 align:4 data:float lbl_804E086C = .rodata:0x804E086C; // type:object size:0xAC align:4 data:float lbl_804E0918 = .rodata:0x804E0918; // type:object size:0x14 @@ -30811,12 +30815,12 @@ jumptable_8050D9AC = .data:0x8050D9AC; // type:object size:0x28 scope:local lbl_8050D9D4 = .data:0x8050D9D4; // type:object size:0x10 lbl_8050D9E4 = .data:0x8050D9E4; // type:object size:0xC lbl_8050D9F0 = .data:0x8050D9F0; // type:object size:0x10 -__vt__10daPlBase_c = .data:0x8050DA00; // type:object size:0x310 -__vt__19daPlBaseCallback2_c = .data:0x8050DD10; // type:object size:0x18 +__vt__19daPlayerModelBase_c = .data:0x8050DA00; // type:object size:0x310 +__vt__22daPlBaseHeadCallback_c = .data:0x8050DD10; // type:object size:0x18 __vt__27daPlBaseCalcWorldCallback_c = .data:0x8050DD28; // type:object size:0x18 __vt__16daPlBaseAnmChr_c = .data:0x8050DD40; // type:object size:0x18 -__vt__19daPlBaseCallback1_c = .data:0x8050DD58; // type:object size:0x18 -__vt__13daPlBaseMdl_c = .data:0x8050DD70; // type:object size:0x30 +__vt__22daPlBaseMainCallback_c = .data:0x8050DD58; // type:object size:0x18 +__vt__13daPlBaseMdl_c = .data:0x8050DD70; // type:object size:0x2C __vt__21daPlBaseMdlCallback_c = .data:0x8050DDA0; // type:object size:0x18 __vt__24daPlBaseScnObjCallback_c = .data:0x8050DDB8; // type:object size:0x20 @4669 = .data:0x8050DDD8; // type:object size:0xE scope:local data:string @@ -39116,7 +39120,7 @@ lbl_80571C58 = .sdata:0x80571C58; // type:object size:0x8 data:byte lbl_80571C60 = .sdata:0x80571C60; // type:object size:0x8 data:4byte lbl_80571C68 = .sdata:0x80571C68; // type:object size:0x8 OBTAINED_ITEM_ID = .sdata:0x80571C70; // type:object size:0x4 data:4byte -EQUIPPED_SWORD = .sdata:0x80571C74; // type:object size:0x1 data:byte +sCurrentSword__17daPlayerActBase_c = .sdata:0x80571C74; // type:object size:0x1 data:byte lbl_80571C78 = .sdata:0x80571C78; // type:object size:0x8 data:4byte lbl_80571C80 = .sdata:0x80571C80; // type:object size:0x4 data:4byte lbl_80571C84 = .sdata:0x80571C84; // type:object size:0x4 data:4byte diff --git a/include/d/a/d_a_player.h b/include/d/a/d_a_player.h index 2ad00f85..15cbd195 100644 --- a/include/d/a/d_a_player.h +++ b/include/d/a/d_a_player.h @@ -4,15 +4,18 @@ #include "common.h" #include "d/a/d_a_base.h" #include "d/a/d_a_itembase.h" +#include "d/a/e/d_a_en_base.h" #include "d/a/obj/d_a_obj_base.h" #include "d/col/cc/d_cc_d.h" -#include "d/a/e/d_a_en_base.h" #include "m/m3d/m_anmchr.h" #include "m/m3d/m_anmchrblend.h" #include "m/m3d/m_anmmatclr.h" #include "m/m3d/m_anmtexpat.h" #include "m/m3d/m_anmtexsrt.h" +#include "m/m3d/m_banm.h" +#include "m/m3d/m_bmdl.h" #include "m/m3d/m_mdl.h" +#include "m/m3d/m_scnleaf.h" #include "m/m3d/m_smdl.h" #include "m/m_allocator.h" #include "m/m_angle.h" @@ -22,6 +25,7 @@ #include "nw4r/g3d/g3d_calcworld.h" #include "nw4r/g3d/g3d_scnobj.h" #include "nw4r/g3d/res/g3d_resanmchr.h" +#include "nw4r/g3d/res/g3d_resanmtexsrt.h" #include "nw4r/g3d/res/g3d_resfile.h" #include "nw4r/g3d/res/g3d_resmdl.h" #include "toBeSorted/file_manager.h" @@ -30,6 +34,15 @@ // See Below for some info // https://github.com/lepelog/skywardsword-tools/wiki/Player-Actor +struct PlayerAnimation { + /* 0x00 */ const char *animName; + /* 0x04 */ u8 field_0x04; + /* 0x05 */ u8 field_0x05; + /* 0x06 */ u16 mFaceTexPatIdx; + /* 0x08 */ u16 mFaceTexSrtIdx; + /* 0x0A */ u16 mFaceAnmChrIdx; +}; + /* * The inheritance chain goes something like: * dAcObjBase_c straightfoward @@ -44,49 +57,111 @@ */ // Vtable at 80533128, no differences to dAcObjBase_c? + class daPlBase_c : public dAcObjBase_c { public: virtual ~daPlBase_c() {} }; -class daPlBaseCallback1_c : m3d::callback_c { - u8 _0x__[4]; -}; -class daPlBaseCallback2_c : m3d::callback_c { - u8 _0x__[4]; +class daPlayerModelBase_c; + +class daPlBaseScnObjCallback_c : public dScnCallback_c { +public: + daPlBaseScnObjCallback_c(dAcObjBase_c *b) : dScnCallback_c(b), field_0x0C(b) {} + + /* vt 0x10 */ virtual void + ExecCallback_CALC_MAT(nw4r::g3d::ScnObj::Timing, nw4r::g3d::ScnObj *, u32, void *) override; + + /* 0x18 */ virtual void ExecCallback_DRAW_OPA(nw4r::g3d::ScnObj::Timing, nw4r::g3d::ScnObj *, u32, void *) override; + +private: + /* 0x0C */ dAcObjBase_c *field_0x0C; }; -class daPlBaseMdlCallback_c : m3d::mdl_c::mdlCallback_c { - u8 _0x__[8]; +class daPlBaseMdlCallback_c : public m3d::mdl_c::mdlCallback_c { +public: + virtual void ExecCallbackA(nw4r::g3d::ChrAnmResult *, nw4r::g3d::ResMdl, nw4r::g3d::FuncObjCalcWorld *) override; + + void setNodeIds(u16 min, u16 max) { + mNodeIdMin = min; + mNodeIdMax = max; + } + +private: + /* 0x30 */ u16 mNodeIdMin; + /* 0x32 */ u16 mNodeIdMax; }; -class daPlBaseAnmChr_c : m3d::anmChr_c { +class daPlBaseMdl_c : public m3d::mdl_c { +public: + daPlBaseMdl_c() : field_0x5C(0) {} + + virtual bool setAnm(m3d::banm_c &anm) override; + virtual void remove() override; + + bool create( + daPlayerModelBase_c *player, nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u32 bufferOption, u32 nView, u32 *pSize + ); + void setBlendNodeRange(u16, u16, f32); + +private: + /* 0x24 */ daPlBaseMdlCallback_c mCallback; + /* 0x58 */ u8 field_0x58; + /* 0x5A */ u16 field_0x5A; + /* 0x5C */ u32 field_0x5C; +}; + +class daPlBaseMainCallback_c : public m3d::callback_c { +public: + virtual void timingA(u32, nw4r::g3d::ChrAnmResult *, nw4r::g3d::ResMdl) override; + virtual void timingB(u32, nw4r::g3d::WorldMtxManip *, nw4r::g3d::ResMdl) override; + virtual void timingC(nw4r::math::MTX34 *, nw4r::g3d::ResMdl) override; + + void setPlayer(daPlayerModelBase_c *p) { + mpPlayer = p; + } + +private: + daPlayerModelBase_c *mpPlayer; +}; + +class daPlBaseAnmChr_c : public m3d::anmChr_c { public: daPlBaseAnmChr_c() : field_0x35(0), field_0x36(0) {} + void play() override; + bool isFinished(); + private: /* 0x35 */ u8 field_0x35; /* 0x36 */ u8 field_0x36; }; -class daPlBaseMdl_c : m3d::mdl_c { -public: - daPlBaseMdl_c() : field_0x5C(0) {} - -private: - /* 0x24 */ daPlBaseMdlCallback_c mCallback; - /* 0x5C */ UNKWORD field_0x5C; -}; - class daPlBaseCalcWorldCallback_c : public nw4r::g3d::ICalcWorldCallback { public: virtual void ExecCallbackC( nw4r::math::MTX34 *pMtxArray, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *pFuncObj ) override; // at 0x14 + + void setPlayer(daPlayerModelBase_c *p) { + mpPlayer = p; + } + +private: + /* 0x04 */ daPlayerModelBase_c *mpPlayer; }; -class daPlBaseScnObjCallback_c : public nw4r::g3d::IScnObjCallback { - u8 _0x__[0x10]; + +class daPlBaseHeadCallback_c : public m3d::callback_c { +public: + virtual void timingB(u32, nw4r::g3d::WorldMtxManip *, nw4r::g3d::ResMdl) override; + + void setPlayer(daPlayerModelBase_c *p) { + mpPlayer = p; + } + +private: + daPlayerModelBase_c *mpPlayer; }; class UnkPlayerClass { @@ -119,6 +194,8 @@ public: return 0.0f; } /* vt 0x094 */ virtual void relatedToUsingItem0x11() { + // TODO obvious hack, not sure + delete (daPlBase_c *)0; } /* vt 0x098 */ virtual void setPosRot(const mVec3_c *pos, const mAng3_c *ang, bool force, UNKWORD, UNKWORD); /* vt 0x09C */ virtual bool isLiftingObject() { @@ -300,17 +377,19 @@ public: /* vt 0x18C */ virtual void getBodyMtx(mMtx_c *out_mtx, int boneIdx) { // unused; overridden by daPlayerModelBase_c } - /* vt 0x190 */ virtual void getSheathModelMatrix() { + /* vt 0x190 */ virtual void getSheathModelMatrix(mMtx_c *out_mtx) { // unused; overridden by daPlayerModelBase_c } - /* vt 0x194 */ virtual void getSwordModelMatrix() { + /* vt 0x194 */ virtual void getSwordModelMatrix(mMtx_c *out_mtx) { // unused; overridden by daPlayerModelBase_c } - /* vt 0x198 */ virtual void vt_0x198() { + /* vt 0x198 */ virtual mAng vt_0x198() { // unused; overridden by daPlayerModelBase_c + return 0; } - /* vt 0x19C */ virtual void vt_0x19C() { + /* vt 0x19C */ virtual mAng vt_0x19C() { // unused; overridden by daPlayerModelBase_c + return 0; } /* vt 0x1A0 */ virtual f32 vt_0x1A0() { return 0.0f; @@ -423,9 +502,7 @@ public: return 0; } /* vt 0x238 */ virtual void setVecIfInFreeFall() {} - /* vt 0x23C */ virtual void setActorRef10() { - - } + /* vt 0x23C */ virtual void setActorRef10() {} /* vt 0x240 */ virtual f32 vt_0x240() { return 0.0f; } @@ -551,66 +628,33 @@ public: ATTACK_FINAL_BLOW = 11, }; - static bool isInEvent(); - bool isAttackingLeft() const; - bool isAttackingRight() const; - bool isAttackingDown() const; - bool isAttackingUp() const; - bool isAttackingStab() const; - bool isAttackingSpinHorizontal() const; - bool isAttackingSpinVertical() const; - void setBonkRelatedAnimFlag(bool b); - void setPosYRot(const mVec3_c &pos, mAng rot, bool force, UNKWORD, UNKWORD); - void setTransform(const mMtx_c &mtx, bool force, UNKWORD, UNKWORD); - bool someTargetedActorCheck() const; - static mAng fn_8005BA90(); - static mAng fn_8005BAA0(); + enum ModelUpdateFlags_e { + UPDATE_MODEL_SWORD = 0x20, + UPDATE_MODEL_SHIELD = 0x40, + }; - static const mColor &getEarringsColor(); - - static mVec3_c sPos1; - static mVec3_c sPos2; - static mAng sRot1; - static mAng sRot2; - static const f32 sPushRelatedConstant; - -protected: - /* 0x330 */ u8 unk_0x330[0x334 - 0x330]; - /* 0x334 */ f32 field_0x334; - /* 0x338 */ u8 mAttackDirection; - /* 0x339 */ u8 mRidingActorType; - /* 0x33A */ u8 unk_0x33A[0x340 - 0x33A]; - /* 0x340 */ u32 someFlags_0x340; - /* 0x344 */ u8 unk_0x344[0x348 - 0x344]; - /* 0x348 */ u32 mSwordAndMoreStates; - /* 0x34C */ u8 unk_0x34C[0x350 - 0x34C]; - /* 0x350 */ u32 someFlags_0x350; - /* 0x354 */ u32 someFlags_0x354; - /* 0x358 */ u32 someFlags_0x358; - /* 0x35C */ u32 mForceOrPreventActionFlags; - /* 0x360 */ u32 field_0x360; - /* 0x364 */ u32 mActionFlags; - /* 0x368 */ u32 mActionFlagsCont; - /* 0x36C */ int mCurrentAction; // TODO (Document Enum) -}; - -// Vtable at 8050da00, dtor reveals two superclasses -// until dAcObjBase_c -class daPlayerModelBase_c : public daPlayerActBase_c { -public: - daPlayerModelBase_c() - : mSwordRes(nullptr), - mAlinkRes(nullptr), - mPlCommonAnimeRes(nullptr), - mPlCommonSoundRes(nullptr), - mCurrentRes(nullptr), - mAlink2Res(nullptr), - mScnCallback1(this), - mScnCallback2(this), - mScnCallback3(this), - mScnCallback4(this), - mScnCallback5(this) {} - virtual ~daPlayerModelBase_c() {} + enum SwordAndMoreStates_e { + NO_SHIETH = (1 << 0), + POUCH = (1 << 1), + SWORD_AWAY = (1 << 2), + FLASH_RED = (1 << 4), + DEPLETE_STAMINA = (1 << 5), + SPRINTING = (1 << 6), + B_WHEEL_OPEN = (1 << 7), + POUCH_OPEN = (1 << 8), + TRYING_TO_USE_STAMINA_NOT_ABLE = (1 << 9), + PUTTING_AWAY_SAILCLOTH = (1 << 10), + GRAB_LEDGE_FROM_UNDER = (1 << 13), + HOLDING_A_NO_STAMINA_DROP = (1 << 14), + FIRST_PERSON = (1 << 18), + SKYWARD_STRIKE_ACTIVE = (1 << 20), + LIGHTNING_STRIKE_ACTIVE = (1 << 22), + C_MENU_OPEN = (1 << 23), + SHIELD_OUT = (1 << 27), + HOLDING_TARGET = (1 << 28), + ITEM_NEAR_LINK = (1 << 29), + USING_ITEM = (1 << 31), + }; // These Flags are named under general guesses. Very likely may need some changes // Correspond to mActionFlags @@ -652,166 +696,14 @@ public: FLG0_HANGING_ITEM | FLG0_HANGING_LEDGE | FLG0_UNK_0x10 | FLG0_IN_AIR, }; - void fn_8005ED60(); - void fn_8005EAC0(); - void fn_8005F890(); - void fn_80061410(); - - /* vt 0x114 */ virtual void somethingWithCarriedActorFlags() override { - // TODO - } - /* vt 0x118 */ virtual dAcObjBase_c *getCurrentCarriedActor() override { - // TODO - return nullptr; - } - - /* vt 0x0E4 */ virtual const mVec3_c &getCenterTranslation() const override { - // TODO - return mVec3_c::Zero; - } - /* vt 0x0E8 */ virtual const mVec3_c &vt_0x0E8() const override { - return field_0x12F4; - } - /* vt 0x0EC */ virtual const mVec3_c &vt_0x0EC() const override { - // TODO - return mVec3_c::Zero; - } - /* vt 0x0F0 */ virtual const mVec3_c &vt_0x0F0() const override { - // TODO - return mVec3_c::Zero; - } - /* vt 0x0F4 */ virtual const mVec3_c &vt_0x0F4() const override { - // TODO - return mVec3_c::Zero; - } - - /* vt 0x2E0 */ virtual void vt_0x2E0() {} - /* vt 0x2E4 */ virtual void someDivingHrabbingStuff() {} - /* vt 0x2E8 */ virtual bool vt_0x2E8() { - return true; - } - /* vt 0x2EC */ virtual void isOnClawTargetMaybe(UNKWORD, mAng &a1, mAng &a2) { - a1.setR(0); - a2.setR(0); - } - /* vt 0x2F0 */ virtual bool isMPPose() { - return false; - } - /* vt 0x2F4 */ virtual bool isOnTightRope() { - return false; - } - /* vt 0x2F8 */ virtual bool isOnVines() { - return false; - } - /* vt 0x2FC */ virtual bool alwaysRet0() { - return 0; - } - /* vt 0x300 */ virtual bool canBlockAttack() { - return false; - } - /* vt 0x304 */ virtual const mVec3_c &vt_0x304() const { - return mVec3_c::Zero; - } - /* vt 0x308 */ virtual mAng vt_0x308() { - return 0; - } - /* vt 0x30C */ virtual void vt_0x30C(mVec3_c &res) { - res = mVec3_c::Ex; - } - -protected: - /* 0x370 */ mHeapAllocator_c mModelAllocator; - /* 0x38C */ mHeapAllocator_c mSwordAllocator; - /* 0x3A8 */ mHeapAllocator_c mShieldAllocator; - /* 0x3C4 */ u32 mModelUpdateFlags; - /* 0x3C8 */ nw4r::g3d::ResFile mSwordRes; - /* 0x3CC */ nw4r::g3d::ResFile mAlinkRes; - /* 0x3D0 */ nw4r::g3d::ResFile mPlCommonAnimeRes; - /* 0x3D4 */ nw4r::g3d::ResFile mPlCommonSoundRes; - /* 0x3D8 */ nw4r::g3d::ResFile mCurrentRes; - /* 0x3DC */ nw4r::g3d::ResFile mAlink2Res; - /* 0x3E0 */ daPlBaseMdl_c mMainMdl; - /* 0x440 */ daPlBaseCallback1_c mCallback1; - /* 0x448 */ m3d::mdl_c mHeadMdl; - /* 0x46C */ daPlBaseCallback2_c mCallback2; - /* 0x474 */ m3d::smdl_c mFaceMdl; - /* 0x490 */ m3d::anmChr_c mFaceAnmChr; - /* 0x4C8 */ u8 _0x4C8[4]; - /* 0x4CC */ m3d::anmTexPat_c mFaceTexPat; - /* 0x4F8 */ u8 _0x4F8[4]; - /* 0x4FC */ m3d::anmTexSrt_c mFaceTexSrt; - /* 0x528 */ u8 _0x528[4]; - /* 0x52C */ m3d::anmChr_c mHeadAnmChr; - /* 0x564 */ m3d::smdl_c mHandsMdl; - /* 0x580 */ daPlBaseCalcWorldCallback_c mCalcWorldCallback; - /* 0x588 */ daPlBaseScnObjCallback_c mScnObjCallback; - /* 0x598 */ m3d::smdl_c mSwordMdl; - /* 0x5B4 */ m3d::anmMatClr_c mAnmMatClr; - /* 0x5E0 */ m3d::smdl_c mShieldMdl; - /* 0x5FC */ m3d::anmTexPat_c mUnkAnmTextPat1; - /* 0x628 */ m3d::anmTexPat_c mUnkAnmTextPat2; - /* 0x654 */ m3d::smdl_c mSheathMdl; - /* 0x670 */ m3d::smdl_c mUnkMdl1; - /* 0x68C */ m3d::anmChr_c mAnmChr; - /* 0x6C4 */ m3d::anmChrBlend_c mAnmChrBlend; - /* 0x6EC */ dScnCallback_c mScnCallback1; - /* 0x6F8 */ dScnCallback_c mScnCallback2; - /* 0x704 */ dScnCallback_c mScnCallback3; - /* 0x610 */ dScnCallback_c mScnCallback4; - /* 0x61C */ dScnCallback_c mScnCallback5; - /* 0x728 */ daPlBaseAnmChr_c mAnmChrs[6]; - /* 0x878 */ dCcD_Cyl mCcCyls[3]; - /* 0xC68 */ dCcD_Cps mCcCpss[3]; - /* 0x10B8 */ dCcD_Cyl mCcCyl; - /* 0x1208 */ u8 _0x1208[0xA4]; - /* 0x12AC */ mVec3_c mTranslationHand[2]; - /* 0x12C4 */ mVec3_c mTranslationWeapon[2]; - /* 0x12DC */ mVec3_c mToeTranslation[2]; - /* 0x12F4 */ mVec3_c field_0x12F4; - /* 0x1300 */ UnkPlayerClass mUnk_0x1300[4]; - /* 0x1340 */ mQuat_c mQuat1; - /* 0x1350 */ mQuat_c mQuat2; - /* 0x1360 */ dAcRef_c mRef; // not sure about the class -}; - -// The split between daPlBase_c and dAcPy_c is somewhere after -// member offset 0x1368 and before 0x137C - -class dAcPy_c : public daPlayerModelBase_c { -public: - dAcPy_c(); - virtual ~dAcPy_c(); - - // argument is always false in existing code, true doesn't seem to make a difference - void bonk(bool unk = false); - bool fn_80202D90(bool); - - /* overrides omitted */ - /* vt 0x310 */ virtual void vt_0x310(); - /* vt 0x314 */ virtual void vt_0x314(); - /* vt 0x318 */ virtual void vt_0x318(); - -protected: - /* 0x136C */ u8 _0x136C[0x4564 - 0x136C]; - /* 0x4564 */ f32 field_0x4564; - -public: - f32 getField_0x4564() const { - return field_0x4564; - } - - f32 getAnmMatClrFrame() const { - return mAnmMatClr.getFrame(0); - } - - nw4r::g3d::ResFile getSwordResFile() const { - return mSwordRes; - } - inline bool checkFlags0x340(u32 mask) const { return (someFlags_0x340 & mask) != 0; } + inline void offFlags_0x340(u32 mask) { + someFlags_0x340 &= ~mask; + } + inline bool checkFlags0x350(u32 mask) const { return (someFlags_0x350 & mask) != 0; } @@ -840,10 +732,6 @@ public: return mCurrentAction == 0xAD || mCurrentAction == 0xAE; } - inline bool checkSwordAndMoreStates(u32 mask) const { - return (mSwordAndMoreStates & mask) != 0; - } - inline bool checkActionFlags(u32 mask) const { return (mActionFlags & mask) != 0; } @@ -855,6 +743,374 @@ public: return mRidingActorType; } + static bool isInEvent(); + bool isAttackingLeft() const; + bool isAttackingRight() const; + bool isAttackingDown() const; + bool isAttackingUp() const; + bool isAttackingStab() const; + bool isAttackingSpinHorizontal() const; + bool isAttackingSpinVertical() const; + void setBonkRelatedAnimFlag(bool b); + void setPosYRot(const mVec3_c &pos, mAng rot, bool force, UNKWORD, UNKWORD); + void setTransform(const mMtx_c &mtx, bool force, UNKWORD, UNKWORD); + bool someTargetedActorCheck() const; + static mAng fn_8005BA90(); + static mAng fn_8005BAA0(); + static void updateCurrentSword(); + + static s32 getCurrentSwordType(); + static const char *getSwordName(s32); + static s32 getCurrentlyEquippedShieldType(); + static s32 getCurrentlyEquippedShieldId(); + static u32 getCurrentShieldPouchSlot(); + + static const mColor &getEarringsColor(); + + static mVec3_c sPos1; + static mVec3_c sPos2; + static mAng sRot1; + static mAng sRot2; + static const f32 sPushRelatedConstant; + static u8 sCurrentSword; + +protected: + /* 0x330 */ u8 unk_0x330[0x334 - 0x330]; + /* 0x334 */ f32 field_0x334; + /* 0x338 */ u8 mAttackDirection; + /* 0x339 */ u8 mRidingActorType; + /* 0x33A */ u8 unk_0x33A[0x340 - 0x33A]; + /* 0x340 */ u32 someFlags_0x340; + /* 0x344 */ u8 unk_0x344[0x348 - 0x344]; + /* 0x348 */ u32 mSwordAndMoreStates; + /* 0x34C */ u32 mModelUpdateFlags; + /* 0x350 */ u32 someFlags_0x350; + /* 0x354 */ u32 someFlags_0x354; + /* 0x358 */ u32 someFlags_0x358; + /* 0x35C */ u32 mForceOrPreventActionFlags; + /* 0x360 */ u32 field_0x360; + /* 0x364 */ u32 mActionFlags; + /* 0x368 */ u32 mActionFlagsCont; + /* 0x36C */ int mCurrentAction; // TODO (Document Enum) +}; + +// Vtable at 8050da00, dtor reveals two superclasses +// until dAcObjBase_c +class daPlayerModelBase_c : public daPlayerActBase_c { +public: + daPlayerModelBase_c() + : mSwordRes(nullptr), + mAlinkRes(nullptr), + mPlCommonAnimeRes(nullptr), + mPlCommonSoundRes(nullptr), + mCurrentRes(nullptr), + mAlink2Res(nullptr), + mScnObjCallback(this), + mScnCallback1(this), + mScnCallback2(this), + mScnCallback3(this), + mScnCallback4(this), + mScnCallback5(this) {} + virtual ~daPlayerModelBase_c() {} + + enum TunicType_e { + TUNIC_0, + TUNIC_1, + TUNIC_SILENT, + }; + + // Alink.arc > g3d > model.brres > 3DModels(NW4R) > al > Bones > ... + enum PlayerMainModelNode_e { + PLAYER_MAIN_NODE_CENTER = 0, + PLAYER_MAIN_NODE_BACKBONE_1 = 1, + PLAYER_MAIN_NODE_BACKBONE_2 = 2, + PLAYER_MAIN_NODE_HEAD = 4, + PLAYER_MAIN_NODE_POD = 5, + PLAYER_MAIN_NODE_ARM_L1 = 7, + PLAYER_MAIN_NODE_ARM_L2 = 8, + PLAYER_MAIN_NODE_HAND_L = 9, + PLAYER_MAIN_NODE_ARM_R1 = 12, + PLAYER_MAIN_NODE_ARM_R2 = 13, + PLAYER_MAIN_NODE_HAND_R = 14, + PLAYER_MAIN_NODE_WAIST = 16, + + PLAYER_MAIN_NODE_FSKIRT_L1 = 27, + PLAYER_MAIN_NODE_FSKIRT_R1 = 29, + + PLAYER_MAIN_NODE_RSKIRT_L1 = 31, + PLAYER_MAIN_NODE_RSKIRT_L2 = 32, + PLAYER_MAIN_NODE_RSKIRT_R1 = 33, + PLAYER_MAIN_NODE_RSKIRT_R2 = 34, + }; + + void fn_8005F890(); + void fn_80061410(); + + static void freeFrmHeap(mHeapAllocator_c *allocator); + static void allocFrmHeap(mHeapAllocator_c *allocator, u32 size, const char *name); + void allocExternalDataBuffers(); + void initModelHeaps(); + void updateSwordShieldModelsIfNeeded(); + m3d::anmTexSrt_c *createAnmTexSrt(const char *resName, m3d::bmdl_c &mdl); + + static bool createGenericMdl(nw4r::g3d::ResMdl resMdl, m3d::mdl_c &mdl, mAllocator_c *alloc, u32 bufferOption); + static bool createGenericSmdl(nw4r::g3d::ResMdl resMdl, m3d::smdl_c &mdl, mAllocator_c *alloc, u32 bufferOption); + static void setTransformAndCalc(m3d::scnLeaf_c &lf, const mMtx_c *mtx); + + static nw4r::g3d::ResFile getItemResFile(const char *name, mAllocator_c &allocator); + nw4r::g3d::ResFile getExternalCompressedFile(const char *name, const char *extension, void *dest, u32 maxSize); + nw4r::g3d::ResAnmChr getExternalAnmChr(const char *name, void *dest, u32 maxSize); + nw4r::g3d::ResAnmTexPat getExternalAnmTexPat(const char *name, void *dest, u32 maxSize); + nw4r::g3d::ResAnmTexSrt getExternalAnmTexSrt(const char *name, void *dest, u32 maxSize); + + static bool isBodyAnmPart_0_2_4(s32 part); + + void updateEarringsColor(); + void loadBodyModels(); + void loadBody(); + void loadHandsModels(); + void setSwordAnm(const char *name); + void initSwordModel(); + void updateSwordModel(); + void initShieldModel(); + void updateShieldModel(); + + // Own virtual methods + + /* vt 0x2E0 */ virtual void transformBackbone1(nw4r::g3d::WorldMtxManip *) {} + /* vt 0x2E4 */ virtual void transformModelCenter(mMtx_c *) {} + /* vt 0x2E8 */ virtual bool vt_0x2E8() { + return true; + } + /* vt 0x2EC */ virtual void isOnClawTargetMaybe(UNKWORD, mAng &a1, mAng &a2) { + a1.setR(0); + a2.setR(0); + } + /* vt 0x2F0 */ virtual bool isMPPose() { + return false; + } + /* vt 0x2F4 */ virtual bool isOnTightRope() { + return false; + } + /* vt 0x2F8 */ virtual bool isOnVines() { + return false; + } + /* vt 0x2FC */ virtual bool alwaysRet0() { + return 0; + } + /* vt 0x300 */ virtual bool canBlockAttack() { + return false; + } + /* vt 0x304 */ virtual const mVec3_c &vt_0x304() const { + return mVec3_c::Zero; + } + // r = 1, l = 0, backbone = 2 + /* vt 0x308 */ virtual mAng getArmZRot(s32 which) { + return 0; + } + /* vt 0x30C */ virtual void vt_0x30C(mVec3_c &res) { + res = mVec3_c::Ex; + } + + // Overrides + + /* vt 0x0E4 */ virtual const mVec3_c &getCenterTranslation() const override { + return mCenterTranslation; + } + /* vt 0x0E8 */ virtual const mVec3_c &vt_0x0E8() const override { + return field_0x12F4; + } + /* vt 0x0EC */ virtual const mVec3_c &vt_0x0EC() const override { + return field_0x1294; + } + /* vt 0x0F0 */ virtual const mVec3_c &vt_0x0F0() const override { + return mTranslationHand[1]; + } + /* vt 0x0F4 */ virtual const mVec3_c &vt_0x0F4() const override { + return mTranslationHand[0]; + } + + /* vt 0x114 */ virtual void somethingWithCarriedActorFlags() override; + /* vt 0x118 */ virtual dAcObjBase_c *getCurrentCarriedActor() override { + return mRef.get(); + } + + /* vt 0x18C */ virtual void getBodyMtx(mMtx_c *out_mtx, int boneIdx) override { + mMainMdl.getNodeWorldMtx(boneIdx, *out_mtx); + } + /* vt 0x190 */ virtual void getSheathModelMatrix(mMtx_c *out_mtx) override { + mSheathMdl.getLocalMtx(); + } + /* vt 0x194 */ virtual void getSwordModelMatrix(mMtx_c *out_mtx) override { + mSwordMdl.getLocalMtx(); + } + /* vt 0x198 */ virtual mAng vt_0x198() override { + return field_0x1268; + } + /* vt 0x19C */ virtual mAng vt_0x19C() override { + return field_0x126A; + } + + u8 getHandMat(s32 idx) { + return field_0x1208[idx]; + } + + inline bool checkSwordAndMoreStates(u32 mask) const { + return (mSwordAndMoreStates & mask) != 0; + } + + inline void offSwordAndMoreStates(u32 mask) { + mSwordAndMoreStates &= ~mask; + } + + // Model callbacks - dropping the mdl argument, apparently + void mainModelTimingA(u32 nodeId, nw4r::g3d::ChrAnmResult *result); + void adjustMainModelChrAnm(PlayerMainModelNode_e nodeId, nw4r::g3d::ChrAnmResult *result); + + void mainModelTimingB(u32 nodeId, nw4r::g3d::WorldMtxManip *result); + void adjustMainModelWorldMtx(PlayerMainModelNode_e nodeId, nw4r::g3d::WorldMtxManip *result); + + void mainModelTimingC(nw4r::math::MTX34 *result); + + void fn_8005E900(mMtx_c *, mAng, mAng, mAng, mVec3_c *, bool); + void fn_8005EA20(nw4r::g3d::WorldMtxManip*, mAng, mAng, mAng, mVec3_c *, bool); + + static const PlayerAnimation sAnimations[443]; + static const u8 sShieldDurabilities[10]; + static const u8 sShieldRegenTimes[10]; + +protected: + /* 0x370 */ mHeapAllocator_c mModelAllocator; + /* 0x38C */ mHeapAllocator_c mSwordAllocator; + /* 0x3A8 */ mHeapAllocator_c mShieldAllocator; + /* 0x3C4 */ void *mpExternalAnmCharBuffer; + /* 0x3C8 */ nw4r::g3d::ResFile mSwordRes; + /* 0x3CC */ nw4r::g3d::ResFile mAlinkRes; + /* 0x3D0 */ nw4r::g3d::ResFile mPlCommonAnimeRes; + /* 0x3D4 */ nw4r::g3d::ResFile mPlCommonSoundRes; + /* 0x3D8 */ nw4r::g3d::ResFile mCurrentRes; + /* 0x3DC */ nw4r::g3d::ResFile mAlink2Res; + /* 0x3E0 */ daPlBaseMdl_c mMainMdl; + /* 0x440 */ daPlBaseMainCallback_c mMainBodyCallback; + /* 0x448 */ m3d::mdl_c mHeadMdl; + /* 0x46C */ daPlBaseHeadCallback_c mheadCallback; + /* 0x474 */ m3d::smdl_c mFaceMdl; + /* 0x490 */ m3d::anmChr_c mFaceAnmChr; + /* 0x4C8 */ void *mpAnmCharBuffer; + /* 0x4CC */ m3d::anmTexPat_c mFaceTexPat; + /* 0x4F8 */ void *mpTexPatBuffer; + /* 0x4FC */ m3d::anmTexSrt_c mFaceTexSrt; + /* 0x528 */ void *mpTexSrtBuffer; + /* 0x52C */ m3d::anmChr_c mHeadAnmChr; + /* 0x564 */ m3d::smdl_c mHandsMdl; + /* 0x580 */ daPlBaseCalcWorldCallback_c mCalcWorldCallback; + /* 0x588 */ daPlBaseScnObjCallback_c mScnObjCallback; + /* 0x598 */ m3d::smdl_c mSwordMdl; + /* 0x5B4 */ m3d::anmMatClr_c mSwordAnmMatClr; + /* 0x5E0 */ m3d::smdl_c mShieldMdl; + /* 0x5FC */ m3d::anmTexPat_c mShieldAnmTexPat1; + /* 0x628 */ m3d::anmTexPat_c mShieldAnmTexPat2; + /* 0x654 */ m3d::smdl_c mSheathMdl; + /* 0x670 */ m3d::smdl_c mUnkMdl1; + /* 0x68C */ m3d::anmChr_c mAnmChr; + /* 0x6C4 */ m3d::anmChrBlend_c mAnmChrBlend; + /* 0x6EC */ dScnCallback_c mScnCallback1; + /* 0x6F8 */ dScnCallback_c mScnCallback2; + /* 0x704 */ dScnCallback_c mScnCallback3; + /* 0x710 */ dScnCallback_c mScnCallback4; + /* 0x71C */ dScnCallback_c mScnCallback5; + /* 0x728 */ daPlBaseAnmChr_c mAnmChrs[6]; + /* 0x878 */ dCcD_Cyl mCcCyls[3]; + /* 0xC68 */ dCcD_Cps mCcCpss[3]; + /* 0x10B8 */ dCcD_Cyl mCcCyl; + /* 0x1208 */ u8 field_0x1208[2]; + /* 0x120A */ u8 field_0x120A; + /* 0x120B */ u8 mTunicType; + /* 0x120C */ u8 field_0x120C; + /* 0x120D */ u8 mShieldPouchSlot; + /* 0x120E */ s8 mPouchMatId; + /* 0x120F */ s8 mBeltMatId; + /* 0x1210 */ s8 mLowbodyMapId; + /* 0x1211 */ s8 mLowotherMapId; + /* 0x1212 */ s8 mPouch2MatId; + /* 0x1213 */ s8 mUpbodyMatId; + /* 0x1214 */ s8 mUpotherMatId; + /* 0x1215 */ s8 mBelt2MatId; + /* 0x1216 */ s8 mCapMatId; + /* 0x1217 */ s8 mSkinMatId; + /* 0x1218 */ u8 mSkywardStrikeChargeDuration; + /* 0x121A */ u16 mAnimations[6]; + /* 0x1226 */ u16 mFaceAnmChrIdx1; + /* 0x1228 */ u16 mFaceAnmChrIdx2; + /* 0x122A */ u16 mFaceAnmTexPatIdx1; + /* 0x122C */ u16 mFaceAnmTexPatIdx2; + /* 0x122E */ u16 mFaceAnmTexSrtIdx1; + /* 0x1230 */ u16 mFaceAnmTexSrtIdx2; + /* 0x1232 */ u16 mBreakingEffect; + /* 0x1234 */ mAng mWaistZRot; + /* 0x1236 */ mAng mWaistYRot; + /* 0x1238 */ u8 _0x1238[0x125C - 0x1238]; + /* 0x125C */ mAng mRSkirtR1Rot; + /* 0x125E */ mAng mRSkirtL1Rot; + /* 0x1260 */ mAng mRightHandRotation; + /* 0x1262 */ mAng mHeadZRot; + /* 0x1264 */ mAng mHeadYRot; + /* 0x1266 */ mAng mHeadXRot; + /* 0x1268 */ mAng field_0x1268; + /* 0x126A */ mAng field_0x126A; + /* 0x126C */ mAng field_0x126C; + /* 0x126E */ u8 _0x126C[0x1278 - 0x126E]; + /* 0x1278 */ f32 field_0x1278; + /* 0x127C */ mVec3_c field_0x127C; + /* 0x1288 */ mVec3_c mCenterTranslation; + /* 0x1294 */ mVec3_c field_0x1294; + /* 0x12A0 */ mVec3_c field_0x12A0; + /* 0x12AC */ mVec3_c mTranslationHand[2]; + /* 0x12C4 */ mVec3_c mTranslationWeapon[2]; + /* 0x12DC */ mVec3_c mToeTranslation[2]; + /* 0x12F4 */ mVec3_c field_0x12F4; + /* 0x1300 */ UnkPlayerClass mUnk_0x1300[4]; + /* 0x1340 */ mQuat_c mQuat1; + /* 0x1350 */ mQuat_c mQuat2; + /* 0x1360 */ dAcRef_c mRef; // not sure about the class + /* 0x136C */ mAng *field_0x136C; + /* 0x1370 */ mAng *field_0x1370; +}; + +// The split between daPlBase_c and dAcPy_c is somewhere after +// member offset 0x1368 and before 0x137C + +class dAcPy_c : public daPlayerModelBase_c { +public: + dAcPy_c(); + virtual ~dAcPy_c(); + + // argument is always false in existing code, true doesn't seem to make a difference + void bonk(bool unk = false); + bool fn_80202D90(bool); + + /* overrides omitted */ + /* vt 0x310 */ virtual void vt_0x310(); + /* vt 0x314 */ virtual void vt_0x314(); + /* vt 0x318 */ virtual void vt_0x318(); + +protected: + /* 0x1372 */ u8 _0x1374[0x4564 - 0x1374]; + /* 0x4564 */ f32 field_0x4564; + +public: + f32 getField_0x4564() const { + return field_0x4564; + } + + f32 getSwordAnmFrame() const { + return mSwordAnmMatClr.getFrame(0); + } + + nw4r::g3d::ResFile getSwordResFile() const { + return mSwordRes; + } + inline bool hasvt_0x1C0() const { return vt_0x1C0() != nullptr; } @@ -867,8 +1123,6 @@ public: return FileManager::GetInstance()->hasStaminaPotionPlus() && getRidingActorType() != RIDING_BOAT; } - static nw4r::g3d::ResFile getItemResFile(const char *name, mAllocator_c &allocator); - static const dAcPy_c *GetLink() { return LINK; } @@ -877,6 +1131,8 @@ public: return LINK2; } + void onShieldUpdate(); + static dAcPy_c *LINK; static dAcPy_c *LINK2; @@ -884,7 +1140,6 @@ public: static s32 getCurrentSlingshotType(); static s32 getCurrentBeetleType(); static s32 getCurrentBugNetType(); - static s32 getCurrentlyEquippedShieldType(); static bool isInBambooCuttingMinigame(); diff --git a/include/d/d_rawarchive.h b/include/d/d_rawarchive.h index 7c127147..3835ae10 100644 --- a/include/d/d_rawarchive.h +++ b/include/d/d_rawarchive.h @@ -3,6 +3,7 @@ #include "common.h" #include "m/m_dvd.h" +#include "nw4r/g3d/res/g3d_resfile.h" #include "sized_string.h" class ArcCallbackHandlerBase { @@ -23,6 +24,8 @@ public: static ArcCallbackHandler sInstance; }; +void BindSystemModelsAndLighting(nw4r::g3d::ResFile); + // TODO: loading status could be an enum (-2/-1/0/+1) // Ghidra: ArcManagerEntry diff --git a/include/d/d_sc_game.h b/include/d/d_sc_game.h index 25c42b57..6c86c0db 100644 --- a/include/d/d_sc_game.h +++ b/include/d/d_sc_game.h @@ -136,6 +136,7 @@ public: STATE_VIRTUAL_FUNC_DECLARE(dScGame_c, Stanby); // sic STATE_VIRTUAL_FUNC_DECLARE(dScGame_c, Action); + static bool isHeroMode(); static bool isCurrentStage(const char *stageName); static bool isStageSkyloftLayer20(); static bool isInCredits(); diff --git a/include/d/lyt/meter/d_lyt_meter.h b/include/d/lyt/meter/d_lyt_meter.h index c7618481..6f7b5b23 100644 --- a/include/d/lyt/meter/d_lyt_meter.h +++ b/include/d/lyt/meter/d_lyt_meter.h @@ -446,6 +446,18 @@ public: } } + static void setShieldMaxDurability(f32 durability) { + if (sInstance != nullptr) { + sInstance->mMain.mShield.setMaxDurability(durability); + } + } + + static void setShieldId(s32 type) { + if (sInstance != nullptr) { + sInstance->mMain.mShield.setShieldId(type); + } + } + static f32 getShieldMaxDurability() { if (sInstance != nullptr) { return sInstance->mMain.mShield.getMaxDurability(); diff --git a/include/d/lyt/meter/d_lyt_meter_shield_gauge.h b/include/d/lyt/meter/d_lyt_meter_shield_gauge.h index ec012a83..38cf0baf 100644 --- a/include/d/lyt/meter/d_lyt_meter_shield_gauge.h +++ b/include/d/lyt/meter/d_lyt_meter_shield_gauge.h @@ -47,6 +47,14 @@ public: return mMaxDurability; } + void setMaxDurability(f32 durability) { + mMaxDurability = durability; + } + + void setShieldId(s32 id) { + mShieldId = id; + } + private: s32 getLytFrameForShield(s32) const; void setLevel(f32 level); @@ -77,7 +85,7 @@ private: /* 0x30C */ u8 field_0x30C; /* 0x30D */ u8 field_0x30D; /* 0x30E */ u8 field_0x30E; - /* 0x310 */ s32 mShieldType; + /* 0x310 */ s32 mShieldId; /* 0x314 */ s32 mSavedShieldType; /* 0x318 */ s32 field_0x318; /* 0x31C */ u8 field_0x31C; diff --git a/include/egg/core/eggAllocator.h b/include/egg/core/eggAllocator.h index 4d9978c6..f260f1e1 100644 --- a/include/egg/core/eggAllocator.h +++ b/include/egg/core/eggAllocator.h @@ -21,6 +21,11 @@ public: inline MEMAllocator *getHandle() { return static_cast(this); } + + Heap *getHeap() { + return mHeap; + } + /* 0x14 */ Heap *mHeap; /* 0x18 */ s32 align; }; diff --git a/include/egg/core/eggHeap.h b/include/egg/core/eggHeap.h index 986248aa..c83a9956 100644 --- a/include/egg/core/eggHeap.h +++ b/include/egg/core/eggHeap.h @@ -5,13 +5,14 @@ #include "common.h" #include "egg/core/eggDisposer.h" -#include "egg/core/eggThread.h" +#include "egg/egg_types.h" #include "egg/prim/eggBitFlag.h" + #include "nw4r/ut.h" + #include "rvl/MEM.h" #include "rvl/OS.h" - namespace EGG { // class ExpHeap; @@ -79,6 +80,20 @@ public: return this; } + static inline EGG::FrmHeap *toFrmHeap(EGG::Heap *heap) { + if (heap != nullptr && heap->getHeapKind() == HEAP_KIND_FRAME) { + return (FrmHeap *)heap; + } + return nullptr; + } + + static inline EGG::ExpHeap *toExpHeap(EGG::Heap *heap) { + if (heap != nullptr && heap->getHeapKind() == HEAP_KIND_EXPANDED) { + return (ExpHeap *)heap; + } + return nullptr; + } + public: // members /* 0x10 */ MEMiHeapHead *mHeapHandle; diff --git a/include/m/m3d/m_anmchr.h b/include/m/m3d/m_anmchr.h index 49444ea6..2b564451 100644 --- a/include/m/m3d/m_anmchr.h +++ b/include/m/m3d/m_anmchr.h @@ -1,6 +1,7 @@ #ifndef M3D_M_ANMCHR_H #define M3D_M_ANMCHR_H +#include "common.h" #include "m/m3d/m_bmdl.h" #include "m/m3d/m_fanm.h" #include "nw4r/g3d/res/g3d_resanmchr.h" @@ -13,6 +14,9 @@ public: virtual int getType() const override; + bool create(nw4r::g3d::ResMdl mdl, nw4r::g3d::ResAnmChr anm, mAllocator_c *alloc) { + return create(mdl, anm, alloc, nullptr); + } bool create(nw4r::g3d::ResMdl, nw4r::g3d::ResAnmChr, mAllocator_c *, u32 *); void setAnm(bmdl_c &, nw4r::g3d::ResAnmChr, playMode_e); void setAnmAfter(bmdl_c &, nw4r::g3d::ResAnmChr, playMode_e); diff --git a/include/m/m3d/m_anmchrblend.h b/include/m/m3d/m_anmchrblend.h index 42e20bf2..4db8bda8 100644 --- a/include/m/m3d/m_anmchrblend.h +++ b/include/m/m3d/m_anmchrblend.h @@ -1,6 +1,7 @@ #ifndef M3D_M_ANMCHRBLEND_H #define M3D_M_ANMCHRBLEND_H +#include "common.h" #include "m/m3d/m_anmchr.h" #include "m/m3d/m_banm.h" #include "m/m3d/m_bmdl.h" @@ -14,6 +15,9 @@ public: virtual int getType() const override; + bool create(nw4r::g3d::ResMdl mdl, int nView, mAllocator_c *alloc) { + return create(mdl, nView, alloc, nullptr); + } bool create(nw4r::g3d::ResMdl, int, mAllocator_c *, u32 *); void attach(int, nw4r::g3d::AnmObjChrRes *, f32); void attach(int, anmChr_c *, f32); diff --git a/include/m/m3d/m_mdl.h b/include/m/m3d/m_mdl.h index c420330f..047b91af 100644 --- a/include/m/m3d/m_mdl.h +++ b/include/m/m3d/m_mdl.h @@ -43,7 +43,7 @@ public: mpBaseCallback = cb; } - private: + protected: /* 0x04 */ calcRatio_c mCalcRatio; /* 0x20 */ int mNumNode; /* 0x24 */ nw4r::g3d::ChrAnmResult *mpNodes; diff --git a/include/m/m_mtx.h b/include/m/m_mtx.h index 1251c980..6c9391af 100644 --- a/include/m/m_mtx.h +++ b/include/m/m_mtx.h @@ -32,6 +32,12 @@ public: operator nw4r::math::MTX34 &() { return *(nw4r::math::MTX34 *)(this); } + operator const nw4r::math::MTX34 *() const { + return (nw4r::math::MTX34 *)(this); + } + operator const nw4r::math::MTX34 &() const { + return *(nw4r::math::MTX34 *)(this); + } void XrotS(const mAng &angle); ///< Generates a rotation matrix for the X axis with the given angle. void XrotM(const mAng &angle); ///< Rotates the matrix on the X axis by the given angle. diff --git a/include/nw4r/g3d/g3d_calcworld.h b/include/nw4r/g3d/g3d_calcworld.h index 3a08e7b2..b31ed72a 100644 --- a/include/nw4r/g3d/g3d_calcworld.h +++ b/include/nw4r/g3d/g3d_calcworld.h @@ -76,6 +76,11 @@ public: } } + // Not sure + void SetMtxUnchecked(const nw4r::math::MTX34 *arg) { + PSMTXCopy(*arg, *mpM); + } + private: math::MTX34 *mpM; // at 0x0 math::VEC3 *mpS; // at 0x4 diff --git a/include/nw4r/g3d/res/g3d_resshp.h b/include/nw4r/g3d/res/g3d_resshp.h index 344f8757..e58e0a23 100644 --- a/include/nw4r/g3d/res/g3d_resshp.h +++ b/include/nw4r/g3d/res/g3d_resshp.h @@ -148,6 +148,15 @@ public: return !(ref().flag & ResShpData::FLAG_INVISIBLE); } + // Not sure, copied from ResNode + void SetVisibility(bool visible) { + if (visible) { + ptr()->flag &= ~ResShpData::FLAG_INVISIBLE; + } else { + ptr()->flag |= ResShpData::FLAG_INVISIBLE; + } + } + void DCStore(bool sync); }; diff --git a/include/toBeSorted/cx_util.h b/include/toBeSorted/cx_util.h new file mode 100644 index 00000000..44b5ee0b --- /dev/null +++ b/include/toBeSorted/cx_util.h @@ -0,0 +1,8 @@ +#ifndef CX_UTIL_H +#define CX_UTIL_H + +#include "common.h" + +bool lzSafeDecompress(const void *src, u32 maxSize, void *dest); + +#endif diff --git a/include/toBeSorted/stage_render_stuff.h b/include/toBeSorted/stage_render_stuff.h index 6a1ecbea..6aa0d00a 100644 --- a/include/toBeSorted/stage_render_stuff.h +++ b/include/toBeSorted/stage_render_stuff.h @@ -5,7 +5,6 @@ #include "m/m3d/m_scnleaf.h" #include "nw4r/g3d/g3d_scnobj.h" - class dScnCallback_c : public nw4r::g3d::IScnObjCallback { public: dScnCallback_c(dAcObjBase_c *arg) : mpActor(arg) {} diff --git a/src/REL/d/a/obj/d_a_obj_seat_sword.cpp b/src/REL/d/a/obj/d_a_obj_seat_sword.cpp index 6d297df9..625cc40c 100644 --- a/src/REL/d/a/obj/d_a_obj_seat_sword.cpp +++ b/src/REL/d/a/obj/d_a_obj_seat_sword.cpp @@ -42,16 +42,14 @@ const InteractionTargetDef dAcOSeatSword_c::sInteractionDef = { const Vec dAcOSeatSword_c::sEffectPos = {-20.f, 260.f, 30.f}; -extern "C" const char *getSwordName(int); -extern "C" u8 EQUIPPED_SWORD; bool dAcOSeatSword_c::createHeap() { if (mSubtype == 0) { - const char *goddess_sword = getSwordName(1); + const char *goddess_sword = daPlayerActBase_c::getSwordName(1); mRes = dAcPy_c::getItemResFile(goddess_sword, heap_allocator); TRY_CREATE(mSwordMdl.create(mRes.GetResMdl(goddess_sword), &heap_allocator, 0x120, 1, nullptr)); } else if (mSubtype == 1) { mRes = dAcPy_c::GetLink()->getSwordResFile(); - const char *sword_name = getSwordName(EQUIPPED_SWORD); + const char *sword_name = daPlayerActBase_c::getSwordName(daPlayerActBase_c::sCurrentSword); TRY_CREATE(mSwordMdl.create(mRes.GetResMdl(sword_name), &heap_allocator, 0x120, 1, nullptr)); } diff --git a/src/REL/d/t/d_t_reaction.cpp b/src/REL/d/t/d_t_reaction.cpp index 9c55a906..9c8f32d1 100644 --- a/src/REL/d/t/d_t_reaction.cpp +++ b/src/REL/d/t/d_t_reaction.cpp @@ -7,6 +7,7 @@ #include "d/col/c/c_cc_d.h" #include "d/col/cc/d_cc_s.h" #include "d/d_pouch.h" +#include "d/d_sc_game.h" #include "d/flag/sceneflag_manager.h" #include "m/m_angle.h" #include "toBeSorted/small_sound_mgr.h" @@ -30,8 +31,6 @@ bool dTgReaction_c::createHeap() { return true; } -extern "C" bool isHeroMode(); - int dTgReaction_c::create() { // Note the double _c here if (!initAllocatorWork1Heap(0x1000, "dTgReaction_c_c::m_allocator", 0x20)) { @@ -54,7 +53,7 @@ int dTgReaction_c::create() { return FAILED; } - if (isHeroMode()) { + if (dScGame_c::isHeroMode()) { if (getParam0x10() == 1) { field_0x4DE = 1; } diff --git a/src/d/a/obj/d_a_obj_tbox.cpp b/src/d/a/obj/d_a_obj_tbox.cpp index 6f63a834..eea6e056 100644 --- a/src/d/a/obj/d_a_obj_tbox.cpp +++ b/src/d/a/obj/d_a_obj_tbox.cpp @@ -96,6 +96,7 @@ const cCcD_SrcGObj dAcTbox_c::sColSrc = { }; // clang-format on +// TODO: pragma readonly_strings on? static const char sGetTriForce[] = "GetTriForce"; static const char sGetSwordA[] = "GetSwordA"; static const char sGetHarp[] = "GetHarp"; diff --git a/src/d/d_player_mdl.cpp b/src/d/d_player_mdl.cpp index a69d3fec..877afba6 100644 --- a/src/d/d_player_mdl.cpp +++ b/src/d/d_player_mdl.cpp @@ -1,29 +1,742 @@ +#include "common.h" +#include "d/a/d_a_base.h" #include "d/a/d_a_player.h" +#include "d/d_heap.h" +#include "d/d_pouch.h" +#include "d/d_rawarchive.h" +#include "d/d_sc_game.h" +#include "d/lyt/meter/d_lyt_meter.h" +#include "egg/core/eggHeap.h" +#include "m/m3d/m3d.h" +#include "m/m3d/m_fanm.h" +#include "m/m3d/m_mdl.h" +#include "m/m_allocator.h" +#include "m/m_mtx.h" #include "m/m_vec.h" +#include "nw4r/g3d/g3d_anmchr.h" +#include "nw4r/g3d/g3d_anmobj.h" +#include "nw4r/g3d/g3d_scnmdl.h" +#include "nw4r/g3d/g3d_scnmdlsmpl.h" +#include "nw4r/g3d/g3d_scnobj.h" +#include "nw4r/g3d/res/g3d_resanmchr.h" +#include "nw4r/g3d/res/g3d_resanmclr.h" +#include "nw4r/g3d/res/g3d_resanmtexsrt.h" +#include "nw4r/g3d/res/g3d_resfile.h" +#include "nw4r/g3d/res/g3d_resmdl.h" +#include "nw4r/g3d/res/g3d_resshp.h" +#include "nw4r/math/math_arithmetic.h" +#include "rvl/CX/cx.h" +#include "rvl/GX/GXTypes.h" +#include "sized_string.h" +#include "toBeSorted/cx_util.h" +#include "toBeSorted/file_manager.h" +#include "toBeSorted/stage_render_stuff.h" // TODO: This file contains the vtable and a bunch of weak functions // for daPlayerModelBase_c. How do we generate the vtable here though? // All virtual methods of daPlayerModelBase_c seem to be inline, so -// there's not much opportunity to get the vtable to be emitted here -// except for dtor hacks... +// there's not much opportunity to get the vtable to be emitted here. +// An explicit constructor seems unlikely given that we assume that the vtable +// of the base class is at 80533128, much later in the binary. -void daPlBaseCalcWorldCallback_c::ExecCallbackC( - nw4r::math::MTX34 *pMtxArray, nw4r::g3d::ResMdl mdl, - nw4r::g3d::FuncObjCalcWorld *pFuncObj - ) { +static u8 sSavedHandMats[2] = {}; +static u8 sHandMats[14] = {}; +#pragma push +#pragma readonly_strings on +const char *sFaceResNames[] = { + "F_Default", + "Fmaba01", + "F_M", + "F_Ha", + "F_Cut", + "F_CutAround", + "F_Damage", + "F_DamageLarge", + "F_Die", + "F_DieLargeDamage", + "F_DieMagma", + "F_Pain", + "F_Wa", + "F_DrinkSt", + "F_Drink", + "F_DrinkEd", + "F_Breath", + "F_Close", + "F_entrance", + "F_Binout", + "F_GetBigWait", + "F_getAwaitNice", + "F_WaitLookRound", + "F_Danger", + "F_BinShield", + "F_swimDieA", + "F_WaitServiceA", + "F_WaitServiceHotA", + "F_BoxOp", + "F_Notice", + "F_swimP", + "F_BedSleep", + "F_BedAwake", + "F_SwordPullSt", + "F_SwordPullWait", + "F_SwordPull", + "F_SwordSirenSt", + "F_SwordSirenRaise", + "F_SwordSirenStick", + "F_SwordSirenAfter", + "F_Bird_Reach", + "F_Bird_GetWait", + "F_DieTruck", + "F_Bird_FestivalStart", + "F_GetSurprise", + "F_AsuraCut", + "F_AsuraCutSt", + "F_AsuraCutEd", + "F_CannonWait", + "F_KrakenAppearance", + "F_GetFlower", + "F_Harp", + "F_SitWaitServiceA", + "F_Lightning", + "F_LastAttack", + "F_Bird_Call", + // this one will go in sbss2 if you explicitly define each string + // with const char[], so either a pragma or a file wide flag is used, + // and this whole array is part of the .data pool + "", +}; +#pragma pop + +const u8 daPlayerModelBase_c::sShieldDurabilities[10] = {16, 24, 32, 24, 36, 48, 12, 16, 20, 48}; +const u8 daPlayerModelBase_c::sShieldRegenTimes[10] = {0, 0, 0, 0, 0, 0, 90, 90, 90, 0}; + +/** + * Watch the player's hand material indices and change the ResMat + * so that the right hand mats are visible and all others are hidden. + */ +void daPlBaseScnObjCallback_c::ExecCallback_DRAW_OPA( + nw4r::g3d::ScnObj::Timing timing, nw4r::g3d::ScnObj *pObj, u32 param, void *pInfo +) { + if (timing != nw4r::g3d::ScnObj::CALLBACK_TIMING_C) { + nw4r::g3d::ScnMdl *pMdl = nw4r::g3d::ScnObj::DynamicCast(pObj); + nw4r::g3d::ResMdl mdl = pMdl->GetResMdl(); + nw4r::g3d::ResShp shp(nullptr); + for (int i = 0; i < 2; i++) { + u8 defaultMat = sSavedHandMats[i]; + // TODO: Is there a way to avoid this cast? + u8 playerHandMat = static_cast(field_0x0C)->getHandMat(i); + if (playerHandMat != defaultMat) { + if (defaultMat != 0xFE) { + shp = mdl.GetResShp(sHandMats[defaultMat]); + shp.SetVisibility(false); + shp.DCStore(false); + } + if (playerHandMat != 0xFE) { + shp = mdl.GetResShp(sHandMats[playerHandMat]); + shp.SetVisibility(true); + shp.DCStore(false); + } + sSavedHandMats[i] = playerHandMat; + } + } } - -void daPlayerModelBase_c::fn_8005EAC0() { - // Just getting weak functions to appear here - someDivingHrabbingStuff(); - vt_0x308(); } -void daPlayerModelBase_c::fn_8005ED60() { +void daPlBaseScnObjCallback_c::ExecCallback_CALC_MAT( + nw4r::g3d::ScnObj::Timing timing, nw4r::g3d::ScnObj *pObj, u32 param, void *pInfo +) { + if (timing != nw4r::g3d::ScnObj::CALLBACK_TIMING_C) { + return; + } + dScnCallback_c::ExecCallback_CALC_MAT(timing, pObj, param, pInfo); +} + +void daPlBaseMdlCallback_c::ExecCallbackA( + nw4r::g3d::ChrAnmResult *result, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *calcWorld +) { + u16 nodeId = calcWorld->GetCallbackNodeID(); + // Only run the full callback for certain specified nodes - TODO which ones? + if ((nodeId >= mNodeIdMin && nodeId < mNodeIdMax) || (mNodeIdMin == 16 && nodeId == 0)) { + m3d::mdl_c::mdlCallback_c::ExecCallbackA(result, mdl, calcWorld); + return; + } + // Otherwise only save the result + mpNodes[nodeId] = *result; + if (mpBaseCallback != nullptr) { + mpBaseCallback->timingA(nodeId, result, mdl); + } +} + +bool daPlBaseMdl_c::create( + daPlayerModelBase_c *player, nw4r::g3d::ResMdl mdl, mAllocator_c *alloc, u32 bufferOption, u32 nView, u32 *pSize +) { + if (!m3d::mdl_c::create(mdl, &mCallback, alloc, bufferOption, nView, pSize)) { + return false; + } + + setBlendNodeRange(0, 0xFFFF, 0.0f); + field_0x58 = 0; + field_0x5C = 0; + field_0x5A = 0xFFFF; + SoundSource *sound = player->getSoundSource(); + if (sound->isReadyMaybe()) { + sound->load(nullptr, ""); + } + return true; +} + +bool daPlBaseMdl_c::setAnm(m3d::banm_c &anm) { + return m3d::bmdl_c::setAnm(anm); +} + +void daPlBaseMdl_c::remove() { + mCallback.remove(); + m3d::mdl_c::remove(); +} + +void daPlBaseMdl_c::setBlendNodeRange(u16 nodeIdMin, u16 nodeIdMax, f32 blendFrame) { + mCallback.setBlendFrame(blendFrame + 1.0f); + mCallback.setNodeIds(nodeIdMin, nodeIdMax); + mCallback.calcBlend(); +} + +void daPlBaseMainCallback_c::timingA(u32 nodeId, nw4r::g3d::ChrAnmResult *result, nw4r::g3d::ResMdl mdl) { + mpPlayer->mainModelTimingA(nodeId, result); +} + +void daPlBaseMainCallback_c::timingB(u32 nodeId, nw4r::g3d::WorldMtxManip *result, nw4r::g3d::ResMdl mdl) { + mpPlayer->mainModelTimingB(nodeId, result); +} + +void daPlBaseMainCallback_c::timingC(nw4r::math::MTX34 *result, nw4r::g3d::ResMdl mdl) { + mpPlayer->mainModelTimingC(result); +} + +void daPlBaseAnmChr_c::play() { + m3d::fanm_c::play(); + field_0x36 = 0; +} + +bool daPlBaseAnmChr_c::isFinished() { + if (field_0x35 && !field_0x36) { + return true; + } + + if (isStop() || nw4r::math::FAbs(getRate()) < 0.001f) { + field_0x35 = 1; + field_0x36 = 1; + } + return false; +} + +void daPlBaseHeadCallback_c::timingB(u32, nw4r::g3d::WorldMtxManip *, nw4r::g3d::ResMdl) {} + +void daPlBaseCalcWorldCallback_c::ExecCallbackC( + nw4r::math::MTX34 *pMtxArray, nw4r::g3d::ResMdl mdl, nw4r::g3d::FuncObjCalcWorld *pFuncObj +) {} + +void daPlayerModelBase_c::freeFrmHeap(mHeapAllocator_c *allocator) { + EGG::Heap::toFrmHeap(allocator->getHeap())->free(0x1 | 0x2); +} + +void daPlayerModelBase_c::allocFrmHeap(mHeapAllocator_c *allocator, u32 size, const char *name) { + // TODO fix char constness + allocator->createNewTempFrmHeap(size, dHeap::work1Heap.heap, (char *)name, 0x20, 0); + new u8[size](); + allocator->adjustFrmHeapRestoreCurrent(); +} + +void daPlayerModelBase_c::allocExternalDataBuffers() { + mpExternalAnmCharBuffer = heap_allocator.alloc(0xD800); + mpAnmCharBuffer = heap_allocator.alloc(0x1000); + mpTexPatBuffer = heap_allocator.alloc(0x1000); + mpTexSrtBuffer = heap_allocator.alloc(0x1000); +} + +void daPlayerModelBase_c::initModelHeaps() { + allocFrmHeap(&mModelAllocator, 0x14000, "LinkClothes"); + allocFrmHeap(&mSwordAllocator, 0xE000, "LinkSword"); + allocFrmHeap(&mShieldAllocator, 0x1C100, "LinkShield"); +} + +void daPlayerModelBase_c::updateSwordShieldModelsIfNeeded() { + if (mModelUpdateFlags & UPDATE_MODEL_SWORD) { + updateSwordModel(); + } + FileManager *f = FileManager::GetInstance(); + if (mModelUpdateFlags & UPDATE_MODEL_SHIELD) { + f->setShieldPouchSlot(mShieldPouchSlot); + updateShieldModel(); + } +} + +m3d::anmTexSrt_c *daPlayerModelBase_c::createAnmTexSrt(const char *resName, m3d::bmdl_c &mdl) { + m3d::anmTexSrt_c *anm = new m3d::anmTexSrt_c(); + (void)mAlink2Res.GetResAnmTexSrt(resName); + anm->create(mdl.getResMdl(), mAlink2Res.GetResAnmTexSrt(resName), &heap_allocator, nullptr, 1); + mdl.setAnm(*anm); + return anm; +} + +void daPlayerModelBase_c::updateEarringsColor() { + if (mTunicType != TUNIC_SILENT) { + mColor color = getEarringsColor(); + mFaceMdl.setTevKColor(mFaceMdl.getMatID("al_face_m"), GX_KCOLOR1, color, false); + } +} + +static const char *sBodyMdls[] = {"al", "pl_body", "Sl"}; +static const char *sHeadMdls[] = {"al_head", "pl_head", "Sl_head"}; +static const char *sFaceMdls[] = {"al_face", "al_face", "Sl_face"}; +static const char *sHandMdls[] = {"al_hands", "pl_hands", "Sl_hands"}; + +void daPlayerModelBase_c::loadBodyModels() { + mQuat1.set(1.0f, 0.0, 0.0f, 0.0f); + mQuat2.set(1.0f, 0.0, 0.0f, 0.0f); + freeFrmHeap(&mModelAllocator); + + nw4r::g3d::ResMdl bodyMdl = mAlink2Res.GetResMdl(sBodyMdls[mTunicType]); + mMainMdl.create(this, bodyMdl, &mModelAllocator, 0x930, 1, nullptr); + mMainMdl.setPriorityDraw(0x82, 0x7F); + bodyMdl.ref().info.envelope_mtx_mode = nw4r::g3d::ResMdlInfoDataTypedef::EVPMATRIXMODE_APPROX; + + nw4r::g3d::ResMdl headMdl = mAlink2Res.GetResMdl(sHeadMdls[mTunicType]); + createGenericMdl(headMdl, mHeadMdl, &mModelAllocator, 0x800); + + nw4r::g3d::ResMdl faceMdl = mAlink2Res.GetResMdl(sFaceMdls[mTunicType]); + createGenericSmdl(faceMdl, mFaceMdl, &mModelAllocator, 0x807); + + mMainMdl.setCallback(&mMainBodyCallback); + mMainBodyCallback.setPlayer(this); + mHeadMdl.setCallback(&mheadCallback); + mheadCallback.setPlayer(this); + + mScnCallback1.attach(mMainMdl); + mScnCallback2.attach(mHeadMdl); + + nw4r::g3d::ResMdl handMdl = mAlink2Res.GetResMdl(sHandMdls[mTunicType]); + createGenericSmdl(handMdl, mHandsMdl, &mModelAllocator, 0x800); + nw4r::g3d::ScnMdlSimple *s = nw4r::g3d::ScnObj::DynamicCast(mHandsMdl.getG3dObject()); + s->SetScnMdlCallback(&mCalcWorldCallback); + s->EnableScnMdlCallbackTiming(nw4r::g3d::ScnObj::CALLBACK_TIMING_C); + mCalcWorldCallback.setPlayer(this); + mHandsMdl.setCallback(&mScnObjCallback); + // TODO args types + mHandsMdl.enableCallbackTiming( + nw4r::g3d::ScnObj::Timing(nw4r::g3d::ScnObj::CALLBACK_TIMING_A | nw4r::g3d::ScnObj::CALLBACK_TIMING_C) + ); + mHandsMdl.enableCallbackOp( + nw4r::g3d::ScnObj::ExecOp(nw4r::g3d::ScnObj::EXECOP_DRAW_OPA | nw4r::g3d::ScnObj::EXECOP_CALC_MAT) + ); + loadHandsModels(); + + mBeltMatId = mMainMdl.getMatID("al_belt_upper_m"); + mSkinMatId = mMainMdl.getMatID("al_skin_m"); + mPouchMatId = mMainMdl.getMatID("al_pouch_m"); + mUpbodyMatId = mMainMdl.getMatID("al_upbody_m"); + mUpotherMatId = mMainMdl.getMatID("al_upother_m"); + mBelt2MatId = mBeltMatId; + mLowbodyMapId = mMainMdl.getMatID("al_lowbody_m"); + mLowotherMapId = mMainMdl.getMatID("al_lowother_m"); + mPouch2MatId = mPouchMatId; + mCapMatId = mHeadMdl.getMatID("al_cap_m"); + + offSwordAndMoreStates(NO_SHIETH | POUCH | FIRST_PERSON); + + if (mPouchMatId >= 0) { + mMainMdl.setCullMode(mPouchMatId, GX_CULL_BACK, false); + } + mMainMdl.setCullMode(mBeltMatId, GX_CULL_BACK, false); + mMainMdl.setCullMode(mSkinMatId, GX_CULL_BACK, false); + updateEarringsColor(); +} + +void daPlayerModelBase_c::loadBody() { + loadBodyModels(); + nw4r::g3d::ResMdl bodyMdl = mMainMdl.getResMdl(); + mAnmChrBlend.create(bodyMdl, 6, &heap_allocator); + mAnmChrBlend.getAnimObj()->SetAnmFlag(nw4r::g3d::AnmObj::FLAG_USE_QUATERNION_ROTATION_BLEND, true); + + daPlBaseAnmChr_c *anms = mAnmChrs; + // "waitS" + nw4r::g3d::ResAnmChr resAnmChr26 = getExternalAnmChr(sAnimations[26].animName, mpExternalAnmCharBuffer, 0x2400); + nw4r::g3d::AnmObjChr *animObj; + for (s32 i = 0; i < 6; i++) { + // TODO: stack swap, need to mess with inlines more + anms->create(bodyMdl, resAnmChr26, &heap_allocator); + anms->setAnm(mMainMdl, resAnmChr26, m3d::PLAY_MODE_0); + f32 f; + switch (i) { + case 0: + case 1: f = 1.0f; break; + default: f = 0.0f; break; + } + animObj = static_cast(anms->getAnimObj()); + animObj->Release(); + if (isBodyAnmPart_0_2_4(i)) { + animObj->Bind(bodyMdl, 16, nw4r::g3d::AnmObjChr::BIND_PARTIAL); + animObj->Bind(bodyMdl, 0, nw4r::g3d::AnmObjChr::BIND_ONE); + } else { + animObj->Bind(bodyMdl, 1, nw4r::g3d::AnmObjChr::BIND_PARTIAL); + } + mAnmChrBlend.attach(i, anms, f); + anms++; + } + + mMainMdl.setAnm(mAnmChrBlend); + + // "F_default" + mFaceAnmChr.create( + mFaceMdl.getResMdl(), getExternalAnmChr(sFaceResNames[0], mpAnmCharBuffer, 0x1000), &heap_allocator, nullptr + ); + mFaceMdl.setAnm(mFaceAnmChr); + mFaceAnmChrIdx1 = 0; + mFaceAnmChrIdx2 = 57; // invalid? + + // "Fmaba01" + mFaceTexPat.create( + mFaceMdl.getResMdl(), getExternalAnmTexPat(sFaceResNames[1], mpTexPatBuffer, 0x1000), &heap_allocator, nullptr, + 1 + ); + mFaceMdl.setAnm(mFaceTexPat); + mFaceAnmTexPatIdx1 = 1; + mFaceAnmTexPatIdx2 = 57; // invalid + + bool isInTrial = dScGame_c::currentSpawnInfo.getTrial() == SpawnInfo::TRIAL; + mFaceTexSrt.create( + mFaceMdl.getResMdl(), getExternalAnmTexSrt(sFaceResNames[0], mpTexSrtBuffer, 0x1000), &heap_allocator, nullptr, + isInTrial ? 2 : 1 + ); + mFaceMdl.setAnm(mFaceTexSrt); + mFaceAnmTexSrtIdx1 = 0; + mFaceAnmTexSrtIdx2 = 57; // invalid + + // no allocator arg? + mHeadAnmChr.create(mHeadMdl.getResMdl(), mPlCommonAnimeRes.GetResAnmChr("H_Default"), nullptr, nullptr); + mHeadMdl.setAnm(mHeadAnmChr); +} + +void daPlayerModelBase_c::loadHandsModels() { + nw4r::g3d::ResMdl mdl = mHandsMdl.getResMdl(); + SizedString<16> handName("al_handRA_m"); + s32 ids[14]; + // Hand mats: al_handRA_m - al_handRG_m + // al_handLA_m - al_handLG_m + for (s32 i = 0; i < 14; i++) { + if (i < 7) { + handName.mChars[8] = i + 'A'; + } else { + if (i == 7) { + handName.mChars[7] = 'L'; + } + handName.mChars[8] = i + ('A' - 7); + } + ids[i] = m3d::getMatID(mdl, handName); + sHandMats[i] = 0xFF; + } + + nw4r::g3d::ResShp shp(nullptr); + + sSavedHandMats[0] = 7; + sSavedHandMats[1] = 0; + + nw4r::g3d::ResMdl::DrawEnumerator drawEnumerator(mdl.GetResByteCode("DrawOpa"), mdl.GetResByteCode("DrawXlu")); + while (drawEnumerator.IsValid()) { + for (int j = 0; j < 14; j++) { + if (ids[j] == drawEnumerator.GetMatID()) { + sHandMats[j] = drawEnumerator.GetShpID(); + break; + } + } + + drawEnumerator.MoveNext(); + } + + for (int i = 0; i < mdl.GetResShpNumEntries(); i++) { + shp = mdl.GetResShp(i); + bool visible = sHandMats[sSavedHandMats[0]] == i || sHandMats[sSavedHandMats[1]] == i; + if (visible) { + shp.SetVisibility(true); + } else { + shp.SetVisibility(false); + } + shp.DCStore(false); + } +} + +void daPlayerModelBase_c::setSwordAnm(const char *name) { + nw4r::g3d::ResAnmClr clr = mAlinkRes.GetResAnmClr(name); + mSwordAnmMatClr.setAnm(mSwordMdl, clr, 0, m3d::PLAY_MODE_4); + mSwordMdl.setAnm(mSwordAnmMatClr); +} +static const f32 sSwordRelatedX[] = {9.0f, 12.0, 12.0, 12.0, 12.0, 12.0, 9.0f}; +static const f32 sSwordRelatedUnk[] = {73.0f, 80.0f, 100.0f, 100.0f, 120.0f, 120.0f, 73.0f}; +static const f32 sSwordRelatedZ[] = {0.7f, 0.7f, 0.9f, 0.9f, 1.0f, 1.0f, 0.7f}; +static const f32 sSwordRelatedY[] = {0.7f, 0.8f, 0.9f, 0.9f, 1.0f, 1.0f, 0.7f}; + +static const char *sSwordPods[] = {"EquipPodA", "EquipPodB", "EquipPodC", "EquipPodD", + "EquipPodE", "EquipPodMaster", "EquipPodA"}; + +void daPlayerModelBase_c::initSwordModel() { + updateCurrentSword(); + freeFrmHeap(&mSwordAllocator); + const char *swordName = getSwordName(sCurrentSword); + mSwordRes = getItemResFile(swordName, mSwordAllocator); + field_0x1278 = sSwordRelatedUnk[sCurrentSword]; + field_0x127C.x = sSwordRelatedX[sCurrentSword]; + field_0x127C.y = sSwordRelatedY[sCurrentSword]; + field_0x127C.z = sSwordRelatedZ[sCurrentSword]; + // TODO instruction order + const char *pod = sSwordPods[sCurrentSword]; + + nw4r::g3d::ResMdl sheathMdl = mSwordRes.GetResMdl(pod); + createGenericSmdl(sheathMdl, mSheathMdl, &heap_allocator, 0x800); + mScnCallback4.attach(mSheathMdl); + + nw4r::g3d::ResMdl swordMdl = mSwordRes.GetResMdl(swordName); + createGenericSmdl(swordMdl, mSwordMdl, &heap_allocator, 0x810); + mSwordMdl.setPriorityDraw(0x84, 0x7F); + nw4r::g3d::ResAnmClr swordAnmClr = mAlinkRes.GetResAnmClr("appearance"); + nw4r::g3d::ResMdl swordResMdl = mSwordMdl.getResMdl(); + mSwordAnmMatClr.create(swordResMdl, swordAnmClr, &mSwordAllocator, nullptr, 1); + mSwordMdl.setAnm(mSwordAnmMatClr); + mScnCallback3.attach(mSwordMdl); + offFlags_0x340(1); + offSwordAndMoreStates(SWORD_AWAY); + + // TODO ids + if (sCurrentSword == 0) { + mSkywardStrikeChargeDuration = 82; + } else if (sCurrentSword == 5) { + if (dScGame_c::isHeroMode()) { + mSkywardStrikeChargeDuration = 10; + } else { + mSkywardStrikeChargeDuration = 40; + } + } else { + if (dScGame_c::isHeroMode()) { + field_0x127C.z = 1.0f; + mSkywardStrikeChargeDuration = 40; + } else { + mSkywardStrikeChargeDuration = 55; + } + } +} + +void daPlayerModelBase_c::updateSwordModel() { + mMtx_c sheathMtx; + mMtx_c swordMtx; + mSheathMdl.getLocalMtx(sheathMtx); + mSwordMdl.getLocalMtx(swordMtx); + + mSwordAnmMatClr.remove(); + mSheathMdl.remove(); + mSwordMdl.remove(); + + initSwordModel(); + + setTransformAndCalc(mSheathMdl, &sheathMtx); + setTransformAndCalc(mSwordMdl, &swordMtx); + mModelUpdateFlags &= ~UPDATE_MODEL_SWORD; +} + +static const char *sShieldModelsBase[] = { + "EquipShieldWood", "EquipShieldIron", "EquipShieldHoly", "EquipShieldHylia", "EquipShieldWood", +}; + +static const char *sShieldModelsBroken[] = { + "EquipShieldWoodBroken", "EquipShieldIronBroken", "EquipShieldHolyBroken", + "EquipShieldHyliaBroken", "EquipShieldWoodBroken", +}; + +extern "C" const u16 PARTICLE_RESOURCE_ID_MAPPING_529_; +extern "C" const u16 PARTICLE_RESOURCE_ID_MAPPING_535_; +extern "C" const u16 PARTICLE_RESOURCE_ID_MAPPING_537_; +void daPlayerModelBase_c::initShieldModel() { + static const u16 shieldEffects[] = { + PARTICLE_RESOURCE_ID_MAPPING_537_, PARTICLE_RESOURCE_ID_MAPPING_535_, PARTICLE_RESOURCE_ID_MAPPING_529_, + PARTICLE_RESOURCE_ID_MAPPING_529_, PARTICLE_RESOURCE_ID_MAPPING_529_, + }; + freeFrmHeap(&mShieldAllocator); + s32 shieldType = getCurrentlyEquippedShieldType(); + s32 shieldId = getCurrentlyEquippedShieldId(); + nw4r::g3d::ResFile shieldRes = getItemResFile(sShieldModelsBase[shieldType], mShieldAllocator); + createGenericSmdl(shieldRes.GetResMdl(sShieldModelsBase[shieldType]), mShieldMdl, &mShieldAllocator, 0x903); + mScnCallback5.attach(mShieldMdl); + if (shieldType != /* HYLIA */ 3) { + mShieldAnmTexPat1.create( + mShieldMdl.getResMdl(), shieldRes.GetResAnmTexPat(sShieldModelsBase[shieldType]), &mShieldAllocator, + nullptr, 1 + ); + mShieldMdl.setAnm(mShieldAnmTexPat1); + mShieldAnmTexPat1.setFrame(shieldId % 3, 0); + + createGenericSmdl(shieldRes.GetResMdl(sShieldModelsBroken[shieldType]), mUnkMdl1, &mShieldAllocator, 0x103); + mAnmChr.create( + mUnkMdl1.getResMdl(), shieldRes.GetResAnmChr(sShieldModelsBroken[shieldType]), &mShieldAllocator, nullptr + ); + mUnkMdl1.setAnm(mAnmChr); + mAnmChr.setFrameOnly(0.0f); + + mShieldAnmTexPat2.create( + mUnkMdl1.getResMdl(), shieldRes.GetResAnmTexPat(sShieldModelsBase[shieldType]), &mShieldAllocator, nullptr, + 1 + ); + mShieldAnmTexPat2.setFrame(mShieldAnmTexPat1.getFrame(0), 0); + mUnkMdl1.setAnm(mShieldAnmTexPat2); + } + mBreakingEffect = shieldEffects[shieldType]; + dLytMeter_c::setShieldId(shieldId); + dLytMeter_c::setShieldMaxDurability(sShieldDurabilities[shieldId]); + dAcPy_c::GetLink2()->onShieldUpdate(); +} + +void daPlayerModelBase_c::updateShieldModel() { + mModelUpdateFlags &= ~(UPDATE_MODEL_SHIELD | 8); // TODO ??? + if (getCurrentShieldPouchSlot() != POUCH_SLOT_NONE) { + mMtx_c mtx; + mShieldMdl.getLocalMtx(mtx); + mShieldAnmTexPat1.remove(); + mShieldAnmTexPat2.remove(); + mShieldMdl.remove(); + mAnmChr.remove(); + mUnkMdl1.remove(); + initShieldModel(); + setTransformAndCalc(mShieldMdl, &mtx); + } +} + +bool daPlayerModelBase_c::createGenericSmdl( + nw4r::g3d::ResMdl resMdl, m3d::smdl_c &mdl, mAllocator_c *alloc, u32 bufferOption +) { + bool ok = mdl.create(resMdl, alloc, bufferOption | 0x120, 1, nullptr); + mdl.setPriorityDraw(0x82, 0x7F); + return ok; +} + +bool daPlayerModelBase_c::createGenericMdl( + nw4r::g3d::ResMdl resMdl, m3d::mdl_c &mdl, mAllocator_c *alloc, u32 bufferOption +) { + bool ok = mdl.create(resMdl, alloc, bufferOption | 0x120, 1, nullptr); + mdl.setPriorityDraw(0x82, 0x7F); + return ok; +} + +void daPlayerModelBase_c::adjustMainModelChrAnm(PlayerMainModelNode_e nodeId, nw4r::g3d::ChrAnmResult *result) { + mMtx_c mtx; + result->GetMtx(mtx); + if (nodeId == PLAYER_MAIN_NODE_HEAD) { + mtx.YrotM(-mHeadYRot); + mtx.ZrotM(mHeadZRot); + mtx.XrotM(mHeadXRot); + } else if (nodeId == PLAYER_MAIN_NODE_WAIST) { + mtx.ZrotM(mWaistZRot); + mtx.YrotM(-mWaistYRot); + } else if (nodeId == PLAYER_MAIN_NODE_CENTER) { + transformModelCenter(&mtx); + } else if (nodeId == PLAYER_MAIN_NODE_ARM_R1 || nodeId == PLAYER_MAIN_NODE_ARM_R2) { + mtx.ZrotM(getArmZRot(1)); + } else if (nodeId == PLAYER_MAIN_NODE_ARM_L1 || nodeId == PLAYER_MAIN_NODE_ARM_L2) { + mtx.ZrotM(getArmZRot(0)); + } else if (nodeId == PLAYER_MAIN_NODE_RSKIRT_L1 || nodeId == PLAYER_MAIN_NODE_RSKIRT_L2) { + if (getRidingActorType() == RIDING_LOFTWING) { + if (nodeId == PLAYER_MAIN_NODE_RSKIRT_L1) { + mtx.ZrotM(mRSkirtL1Rot); + } else { + mtx.ZrotM(3000); + } + } + } else if (nodeId == PLAYER_MAIN_NODE_RSKIRT_R1 || nodeId == PLAYER_MAIN_NODE_RSKIRT_R2) { + if (getRidingActorType() == RIDING_LOFTWING) { + if (nodeId == PLAYER_MAIN_NODE_RSKIRT_R1) { + mtx.ZrotM(mRSkirtR1Rot); + } else { + mtx.ZrotM(3000); + } + } + } else if (mRightHandRotation != 0) { + if (nodeId == PLAYER_MAIN_NODE_HAND_R) { + static const mVec3_c v1(1.0f, 1.0f, 0.0f); + mMtx_c rotMtx; + rotMtx.setAxisRotation(v1, mRightHandRotation.radian2()); + mtx += rotMtx; + } + } + + result->SetMtx(mtx); +} + +void daPlayerModelBase_c::adjustMainModelWorldMtx(PlayerMainModelNode_e nodeId, nw4r::g3d::WorldMtxManip *result) { + if (checkCurrentAction(0xA9) && (nodeId == PLAYER_MAIN_NODE_ARM_R1 || nodeId == PLAYER_MAIN_NODE_ARM_R2)) { + mMtx_c mtx; + mtx.makeQ(mQuat1); + mtx.YrotM(-rotation.y); + mMtx_c mtx2; + mtx2.YrotS(rotation.y); + mtx += mtx2; + + mMtx_c orig; + result->GetMtx(orig); + mVec3_c origTrans(orig.m[0][3], orig.m[1][3], orig.m[2][3]); + orig += mtx; + orig.m[0][3] = origTrans.x; + orig.m[1][3] = origTrans.y; + orig.m[2][3] = origTrans.z; + if (nodeId == PLAYER_MAIN_NODE_ARM_R1) { + fn_8005E900(&orig, 1500, 0, 0, nullptr, false); + } + result->SetMtxUnchecked(orig); + } else if (mAnimations[3] == 0xE0 && nodeId == PLAYER_MAIN_NODE_ARM_R2) { + mMtx_c mtx; + mtx.makeQ(mQuat1); + mtx.YrotM(-rotation.y); + mMtx_c mtx2; + mtx2.YrotS(rotation.y); + mtx += mtx2; + + mMtx_c orig; + result->GetMtx(orig); + mVec3_c origTrans(orig.m[0][3], orig.m[1][3], orig.m[2][3]); + orig += mtx; + orig.m[0][3] = origTrans.x; + orig.m[1][3] = origTrans.y; + orig.m[2][3] = origTrans.z; + result->SetMtxUnchecked(orig); + } else if (nodeId == PLAYER_MAIN_NODE_BACKBONE_1) { + transformBackbone1(result); + fn_8005EA20(result, field_0x1268 >> 1, field_0x126A * 0.4f + getArmZRot(2), field_0x126C, nullptr, false); + } else if (nodeId == PLAYER_MAIN_NODE_BACKBONE_2) { + fn_8005EA20(result, field_0x1268 >> 1, field_0x126A * 0.6f + getArmZRot(2), 0, nullptr, false); + } else if (nodeId == PLAYER_MAIN_NODE_FSKIRT_L1 && *field_0x136C != 0) { + mVec3_c v; + vt_0x30C(v); + if (*field_0x136C < 0) { + v.z *= -1.0f; + + } + fn_8005EA20(result, v.x * *field_0x136C, 0, v.z * *field_0x136C, nullptr, true); + } else if (nodeId == PLAYER_MAIN_NODE_FSKIRT_R1 && field_0x1370) { + mVec3_c v; + vt_0x30C(v); + if (*field_0x1370 > 0) { + v.z *= -1.0f; + + } + fn_8005EA20(result, v.x * *field_0x1370, 0, v.z * *field_0x1370, nullptr, true); + } else if (nodeId == PLAYER_MAIN_NODE_POD) { + mAng a1 = 0; + mAng a2 = getArmZRot(2); + + fn_8005EA20(result, field_0x1268 / 2, field_0x126A * 0.6f + a1, a1, nullptr, false); + } else if ((nodeId == PLAYER_MAIN_NODE_ARM_R2 || nodeId == PLAYER_MAIN_NODE_HAND_R) && isMPPose()) { + mAng a1 = 0; + mAng a2 = getArmZRot(2); + + fn_8005EA20(result, field_0x1268 / 2, field_0x126A * 0.6f + a1, a1, nullptr, false); + } + // Just getting weak functions to appear here - vt_0x2E0(); - vt_0x308(); mVec3_c v; vt_0x30C(v); isMPPose(); @@ -39,11 +752,94 @@ void daPlayerModelBase_c::fn_8005F890() { isOnClawTargetMaybe(0, a1, a2); } +void daPlayerModelBase_c::mainModelTimingA(u32 nodeId, nw4r::g3d::ChrAnmResult *result) { + adjustMainModelChrAnm((PlayerMainModelNode_e)nodeId, result); +} + +void daPlayerModelBase_c::mainModelTimingB(u32 nodeId, nw4r::g3d::WorldMtxManip *result) {} + +void daPlayerModelBase_c::mainModelTimingC(nw4r::math::MTX34 *result) {} + +void daPlayerModelBase_c::setTransformAndCalc(m3d::scnLeaf_c &lf, const mMtx_c *mtx) { + if (mtx != nullptr) { + lf.setLocalMtx(*mtx); + } + lf.calc(false); +} + +nw4r::g3d::ResFile daPlayerModelBase_c::getItemResFile(const char *name, mAllocator_c &allocator) { + SizedString<64> buf; + buf.sprintf("dat/%s.brresC", name); + void *dat = getOarcFile("PLCompItem", buf); + u32 size = CXGetUncompressedSize(dat); + void *decompressedBuf = allocator.alloc(size); + lzSafeDecompress(dat, size, decompressedBuf); + nw4r::g3d::ResFile file(decompressedBuf); + file.Init(); + file.Bind(); + BindSystemModelsAndLighting(file); + return file; +} + +nw4r::g3d::ResFile +daPlayerModelBase_c::getExternalCompressedFile(const char *name, const char *extension, void *dest, u32 maxSize) { + if (maxSize != 0) { + SizedString<64> buf; + buf.sprintf("%s.%s", name, extension); + void *externalData = mPlCommonAnimeRes.GetExternalData(buf); + lzSafeDecompress(externalData, maxSize, dest); + } + nw4r::g3d::ResFile file(dest); + file.Init(); + return file; +} + +nw4r::g3d::ResAnmChr daPlayerModelBase_c::getExternalAnmChr(const char *name, void *dest, u32 maxSize) { + nw4r::g3d::ResAnmChr result; + if (mCurrentRes.IsValid()) { + result = mCurrentRes.GetResAnmChr(name); + if (result.IsValid()) { + return result; + } + } + nw4r::g3d::ResFile file = getExternalCompressedFile(name, "rchaC", dest, maxSize); + result = file.GetResAnmChr(name); + return result; +} + +nw4r::g3d::ResAnmTexPat daPlayerModelBase_c::getExternalAnmTexPat(const char *name, void *dest, u32 maxSize) { + nw4r::g3d::ResAnmTexPat result; + if (mCurrentRes.IsValid()) { + result = mCurrentRes.GetResAnmTexPat(name); + if (result.IsValid()) { + result.Bind(mAlink2Res); + return result; + } + } + nw4r::g3d::ResFile file = getExternalCompressedFile(name, "rtpaC", dest, maxSize); + result = file.GetResAnmTexPat(name); + result.Bind(mAlink2Res); + return result; +} + +nw4r::g3d::ResAnmTexSrt daPlayerModelBase_c::getExternalAnmTexSrt(const char *name, void *dest, u32 maxSize) { + nw4r::g3d::ResAnmTexSrt result; + if (mCurrentRes.IsValid()) { + result = mCurrentRes.GetResAnmTexSrt(name); + if (result.IsValid()) { + return result; + } + } + nw4r::g3d::ResFile file = getExternalCompressedFile(name, "rtsaC", dest, maxSize); + result = file.GetResAnmTexSrt(name); + return result; +} + void daPlayerModelBase_c::fn_80061410() { // Just getting weak functions to appear here alwaysRet0(); } -void dummy_triggerDtor(daPlayerModelBase_c *pl) { - delete pl; +/* vt 0x114 */ void daPlayerModelBase_c::somethingWithCarriedActorFlags() { + // TODO } diff --git a/src/d/lyt/meter/d_lyt_meter_cross_btn.cpp b/src/d/lyt/meter/d_lyt_meter_cross_btn.cpp index a16a09a7..c34e4d04 100644 --- a/src/d/lyt/meter/d_lyt_meter_cross_btn.cpp +++ b/src/d/lyt/meter/d_lyt_meter_cross_btn.cpp @@ -491,7 +491,8 @@ bool dLytMeterCrossBtn_c::execute() { if (field_0x637 != 0) { if (mIconDown == 0) { - f32 frame = dAcPy_c::GetLink2()->getAnmMatClrFrame(); + // Start UI animation together with sword animation on Link's back + f32 frame = dAcPy_c::GetLink2()->getSwordAnmFrame(); if (frame == 0.0f) { mAnm[CROSS_BTN_ANIM_CALL_0].setToEnd(); if (!mAnm[CROSS_BTN_ANIM_CALL_0].isEnabled()) { diff --git a/src/d/lyt/meter/d_lyt_meter_shield_gauge.cpp b/src/d/lyt/meter/d_lyt_meter_shield_gauge.cpp index 8c811edc..f89e6188 100644 --- a/src/d/lyt/meter/d_lyt_meter_shield_gauge.cpp +++ b/src/d/lyt/meter/d_lyt_meter_shield_gauge.cpp @@ -78,7 +78,7 @@ bool dLytMeterShieldGauge_c::build(d2d::ResAccIf_c *resAcc) { field_0x31F = 0; field_0x31E = 0; field_0x318 = 0; - mShieldType = 0; + mShieldId = 0; mSavedShieldType = -1; mAnm[SHIELD_ANIM_UPDOWN].setFrame(mCurrentDurability); @@ -134,11 +134,11 @@ bool dLytMeterShieldGauge_c::execute() { bool b3 = false; bool b4 = false; - if (mShieldType != mSavedShieldType || + if (mShieldId != mSavedShieldType || mCurrentShieldPouchSlot != convertFilePouchSlot(FileManager::GetInstance()->getShieldPouchSlot())) { mLyt.findPane("N_alpha_00")->SetVisible(true); - mSavedShieldType = mShieldType; - mAnm[SHIELD_ANIM_TYPE].setFrame(getLytFrameForShield(mShieldType)); + mSavedShieldType = mShieldId; + mAnm[SHIELD_ANIM_TYPE].setFrame(getLytFrameForShield(mShieldId)); mAnm[SHIELD_ANIM_TYPE].setAnimEnable(true); mAnm[SHIELD_ANIM_LOOP_0].setFrame(0.0f); field_0x31D = 1; diff --git a/src/egg/core/eggHeap.cpp b/src/egg/core/eggHeap.cpp index 37522dba..531585ef 100644 --- a/src/egg/core/eggHeap.cpp +++ b/src/egg/core/eggHeap.cpp @@ -1,9 +1,9 @@ #include "egg/core/eggHeap.h" #include "egg/core/eggAllocator.h" +#include "egg/core/eggThread.h" #include "nw4r/ut/ut_list.h" - namespace EGG { /* 80673ae8 */ nw4r::ut::List Heap::sHeapList; diff --git a/src/m/m_allocator.cpp b/src/m/m_allocator.cpp index 922c6889..1c6a56f0 100644 --- a/src/m/m_allocator.cpp +++ b/src/m/m_allocator.cpp @@ -63,19 +63,12 @@ void mHeapAllocator_c::destroyHeap() { } } -inline EGG::Heap *getHeapOfKind(EGG::Heap *heap, EGG::Heap::eHeapKind kind) { - if (heap != nullptr && heap->getHeapKind() == kind) { - return heap; - } - return nullptr; -} - s32 mHeapAllocator_c::adjustFrmHeap() { EGG::Heap *heap = mHeap; if (heap == mHeap::g_assertHeap) { return 0; } - return mHeap::adjustFrmHeap(static_cast(getHeapOfKind(heap, EGG::Heap::HEAP_KIND_FRAME))); + return mHeap::adjustFrmHeap(EGG::Heap::toFrmHeap(heap)); } s32 mHeapAllocator_c::adjustExpHeap() { @@ -83,7 +76,7 @@ s32 mHeapAllocator_c::adjustExpHeap() { if (heap == mHeap::g_assertHeap) { return 0; } - return mHeap::adjustExpHeap(static_cast(getHeapOfKind(heap, EGG::Heap::HEAP_KIND_EXPANDED))); + return mHeap::adjustExpHeap(EGG::Heap::toExpHeap(heap)); } bool mHeapAllocator_c::createNewTempFrmHeap(s32 size, EGG::Heap *newHeap, char *heapName, s32 align, u32 attrs) { @@ -98,7 +91,7 @@ bool mHeapAllocator_c::createNewTempFrmHeap(s32 size, EGG::Heap *newHeap, char * void mHeapAllocator_c::adjustFrmHeapRestoreCurrent() { mHeap::restoreCurrentHeap(); EGG::Heap *heap = mHeap; - mHeap::adjustFrmHeap(static_cast(getHeapOfKind(heap, EGG::Heap::HEAP_KIND_FRAME))); + mHeap::adjustFrmHeap(EGG::Heap::toFrmHeap(heap)); } void *operator new[](size_t size, mAllocator_c *allocator) { diff --git a/src/toBeSorted/special_item_drop_mgr.cpp b/src/toBeSorted/special_item_drop_mgr.cpp index c3ecf8d5..3ae89924 100644 --- a/src/toBeSorted/special_item_drop_mgr.cpp +++ b/src/toBeSorted/special_item_drop_mgr.cpp @@ -7,6 +7,7 @@ #include "d/a/d_a_itembase.h" #include "d/a/d_a_player.h" #include "d/d_pouch.h" +#include "d/d_sc_game.h" #include "m/m_angle.h" #include "m/m_vec.h" @@ -386,8 +387,6 @@ static const struct { }; static const u16 RAND_RUPEE_ARRAY[3] = {ITEM_GREEN_RUPEE, ITEM_BLUE_RUPEE, ITEM_RED_RUPEE}; -extern "C" bool isHeroMode(); - // 800c7bb0 int SpecialItemDropMgr::fn_800C7BB0(int specialItemId) { const DropList *list = &sDropTable.mList[specialItemId]; @@ -410,8 +409,8 @@ int SpecialItemDropMgr::fn_800C7BB0(int specialItemId) { // No seeds until you get the Slingshot weight = 0; } - } else if (specialItemId != 0x27 && (entryIdx == 1 || entryIdx == 2) && isHeroMode()) { - // Hearts generally don't drop on Hero Mode unless it's a special kind of heart (which?) + } else if (specialItemId != 0x27 && (entryIdx == 1 || entryIdx == 2) && dScGame_c::isHeroMode()) { + // Hearts generally don't drop on Hero Mode unless it's a special kind of heart (TODO which?) weight = 0; } else if ((entryIdx == 7 || entryIdx == 8) && !dAcItem_c::checkFlag(ITEM_BOMB_BAG)) { // Bombs won't drop until you get the Bomb Bag