diff --git a/config/G2ME01/splits.txt b/config/G2ME01/splits.txt index 1a6633f..f5570bd 100644 --- a/config/G2ME01/splits.txt +++ b/config/G2ME01/splits.txt @@ -9,6 +9,11 @@ MetroidPrime/CEntity.cpp: MetroidPrime/Player/CPlayerState.cpp: .text start:0x80084864 end:0x80086410 +MetroidPrime/ScriptObjects/CScriptPickup.cpp: + .text start:0x800B389C end:0x800B5F14 + .ctors start:0x803A54E4 end:0x803A54E8 + .data start:0x803B3418 end:0x803B3494 + MetroidPrime/HUD/CHUDMemoParms.cpp: .text start:0x800BABD4 end:0x800BAC10 diff --git a/config/G2ME01/symbols.txt b/config/G2ME01/symbols.txt index 5ae0c9a..acf3cee 100644 --- a/config/G2ME01/symbols.txt +++ b/config/G2ME01/symbols.txt @@ -3383,23 +3383,23 @@ fn_800B34D0 = .text:0x800B34D0; // type:function size:0x120 fn_800B35F0 = .text:0x800B35F0; // type:function size:0x30 fn_800B3620 = .text:0x800B3620; // type:function size:0x1F4 align:0x4 fn_800B3814 = .text:0x800B3814; // type:function size:0x88 -fn_800B389C = .text:0x800B389C; // type:function size:0x818 align:0x4 -fn_800B40B4 = .text:0x800B40B4; // type:function size:0x148 -fn_800B41FC = .text:0x800B41FC; // type:function size:0x2A8 align:0x4 -fn_800B44A4 = .text:0x800B44A4; // type:function size:0x74 align:0x4 +ScriptLoader_LoadPickup = .text:0x800B389C; // type:function size:0x818 align:0x4 +LoadSLdrPickup = .text:0x800B40B4; // type:function size:0x148 +ShowAllKeysCollectedAlert_800b41fc = .text:0x800B41FC; // type:function size:0x2A8 align:0x4 +GetPosition_800B44A4 = .text:0x800B44A4; // type:function size:0x74 align:0x4 fn_800B4518 = .text:0x800B4518; // type:function size:0x58 align:0x4 -fn_800B4570 = .text:0x800B4570; // type:function size:0x8 align:0x4 -fn_800B4578 = .text:0x800B4578; // type:function size:0x4C align:0x4 -fn_800B45C4 = .text:0x800B45C4; // type:function size:0xF8 align:0x4 -fn_800B46BC = .text:0x800B46BC; // type:function size:0xC4 align:0x4 -fn_800B4780 = .text:0x800B4780; // type:function size:0x50C align:0x4 -fn_800B4C8C = .text:0x800B4C8C; // type:function size:0xCF8 align:0x4 -fn_800B5984 = .text:0x800B5984; // type:function size:0x38 -fn_800B59BC = .text:0x800B59BC; // type:function size:0x48 align:0x4 -fn_800B5A04 = .text:0x800B5A04; // type:function size:0x58 align:0x4 -fn_800B5A5C = .text:0x800B5A5C; // type:function size:0x88 align:0x4 -fn_800B5AE4 = .text:0x800B5AE4; // type:function size:0x424 -fn_800B5F08 = .text:0x800B5F08; // type:function size:0xC align:0x4 +GetItem__13CScriptPickupCFv = .text:0x800B4570; // type:function size:0x8 align:0x4 +AddToRenderer__13CScriptPickupCFRC14CFrustumPlanesRC13CStateManager = .text:0x800B4578; // type:function size:0x4C align:0x4 +AcceptScriptMsg__13CScriptPickupFR13CStateManagerR10CScriptMsg = .text:0x800B45C4; // type:function size:0xF8 align:0x4 +GetTouchBounds__13CScriptPickupCFv = .text:0x800B46BC; // type:function size:0xC4 align:0x4 +Touch__13CScriptPickupFR6CActorR13CStateManager = .text:0x800B4780; // type:function size:0x50C align:0x4 +Think__13CScriptPickupFfR13CStateManager = .text:0x800B4C8C; // type:function size:0xCF8 align:0x4 +IsVisible__13CScriptPickupCFv = .text:0x800B5984; // type:function size:0x38 +CScriptPickup_act_vtable_2 = .text:0x800B59BC; // type:function size:0x48 align:0x4 +CScriptPickup_act_vtable_6 = .text:0x800B5A04; // type:function size:0x58 align:0x4 +__dt__13CScriptPickupFv = .text:0x800B5A5C; // type:function size:0x88 align:0x4 +__ct__13CScriptPickupF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fRC10CModelDataRC16CActorParametersRC6CAABoxQ212CPlayerState9EItemTypeiiUiffffb = .text:0x800B5AE4; // type:function size:0x424 scope:global +__sinit_CScriptPickup_cpp = .text:0x800B5F08; // type:function size:0xC align:0x4 fn_800B5F14 = .text:0x800B5F14; // type:function size:0x78 align:0x4 fn_800B5F8C = .text:0x800B5F8C; // type:function size:0x64 align:0x4 fn_800B5FF0 = .text:0x800B5FF0; // type:function size:0x70 @@ -18011,7 +18011,7 @@ lbl_803B32E0 = .data:0x803B32E0; // type:object size:0x84 lbl_803B3364 = .data:0x803B3364; // type:object size:0x14 lbl_803B3378 = .data:0x803B3378; // type:object size:0x50 lbl_803B33C8 = .data:0x803B33C8; // type:object size:0x50 -lbl_803B3418 = .data:0x803B3418; // type:object size:0x80 +__vt__13CScriptPickup = .data:0x803B3418; // type:object size:0x80 lbl_803B3498 = .data:0x803B3498; // type:object size:0x98 lbl_803B3530 = .data:0x803B3530; // type:object size:0x7C lbl_803B35AC = .data:0x803B35AC; // type:object size:0xC diff --git a/configure.py b/configure.py index c202a1f..4c93b9c 100644 --- a/configure.py +++ b/configure.py @@ -24,6 +24,7 @@ LIBS = [ ["MetroidPrime/HUD/CHUDMemoParms.cpp", True], ["MetroidPrime/Player/CPlayerState.cpp", False], ["MetroidPrime/Player/CGameOptions.cpp", False], + ["MetroidPrime/ScriptObjects/CScriptPickup.cpp", False], ], }, { diff --git a/include/Collision/CCollidableAABox.hpp b/include/Collision/CCollidableAABox.hpp new file mode 100644 index 0000000..4f6bbb3 --- /dev/null +++ b/include/Collision/CCollidableAABox.hpp @@ -0,0 +1,40 @@ +#ifndef _CCOLLIDABLEAABOX +#define _CCOLLIDABLEAABOX + +#include "types.h" + +#include "Collision/CCollisionPrimitive.hpp" + +class CCollidableAABox : public CCollisionPrimitive { +public: + CCollidableAABox(); + CCollidableAABox(const CAABox& box, const CMaterialList& matList) + : CCollisionPrimitive(matList), x10_aabb(box) {} + + bool CollideMovingAABox(const CInternalCollisionStructure& collision, const CVector3f& dir, + double& dOut, CCollisionInfo& infoOut); + bool CollideMovingSphere(const CInternalCollisionStructure& collision, const CVector3f& dir, + double& dOut, CCollisionInfo& infoOut); + + uint GetTableIndex() const; + CAABox CalculateAABox(const CTransform4f&) const; + CAABox CalculateLocalAABox() const; + CAABox Transform(const CTransform4f& xf) const; + FourCC GetPrimType() const; + CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const; + + static void SetStaticTableIndex(uint idx); + static CCollisionPrimitive::Type GetType(); + +private: + static uint sTableIndex; + + CAABox x10_aabb; +}; +CHECK_SIZEOF(CCollidableAABox, 0x28) + +namespace Collide { +bool AABox_AABox_Bool(const CInternalCollisionStructure&); +bool AABox_AABox(const CInternalCollisionStructure& collision, CCollisionInfoList& list); +} // namespace Collide +#endif // _CCOLLIDABLEAABOX diff --git a/include/Collision/CCollisionPrimitive.hpp b/include/Collision/CCollisionPrimitive.hpp new file mode 100644 index 0000000..083bc26 --- /dev/null +++ b/include/Collision/CCollisionPrimitive.hpp @@ -0,0 +1,79 @@ +#ifndef _CCOLLISIONPRIMITIVE +#define _CCOLLISIONPRIMITIVE + +#include "types.h" + +#include "Collision/CMaterialList.hpp" + +#include "Kyoto/IObjectStore.hpp" +#include "Kyoto/Math/CAABox.hpp" +#include "Kyoto/Math/CTransform4f.hpp" +#include "rstl/single_ptr.hpp" +#include "rstl/vector.hpp" + +class CRayCastResult; +class CCollisionInfoList; +class CInternalCollisionStructure; +class CInternalRayCastStructure; +class CCollisionInfo; + +typedef void (*PrimitiveSetter)(uint); + +typedef bool (*ComparisonFunc)(const CInternalCollisionStructure&, CCollisionInfoList&); +typedef bool (*BooleanComparisonFunc)(const CInternalCollisionStructure&); +typedef bool (*MovingComparisonFunc)(const CInternalCollisionStructure&, const CVector3f&, double&, + CCollisionInfo&); + +class CCollisionPrimitive { +public: + class Type { + public: + Type(PrimitiveSetter setter, const char* info) : mSetter(setter), mInfo(info) {} + + PrimitiveSetter GetSetter() const { return mSetter; } + const char* GetInfo() const { return mInfo; } + + private: + PrimitiveSetter mSetter; + const char* mInfo; + }; + + CCollisionPrimitive(const CMaterialList& list); + + virtual uint GetTableIndex() const = 0; + virtual void SetMaterial(const CMaterialList&); + virtual const CMaterialList& GetMaterial() const; + virtual CAABox CalculateAABox(const CTransform4f&) const = 0; + virtual CAABox CalculateLocalAABox() const = 0; + virtual FourCC GetPrimType() const = 0; + virtual ~CCollisionPrimitive(); + virtual CRayCastResult CastRayInternal(const CInternalRayCastStructure&) const = 0; + + static void InitBeginTypes(); + static void InitAddType(const Type& type); + static void InitEndTypes(); + static void Uninitialize(); + +private: + static int sNumTypes; + static bool sInitComplete; + static bool sTypesAdded; + static bool sTypesAdding; + static bool sCollidersAdded; + static bool sCollidersAdding; + static rstl::single_ptr< rstl::vector< Type > > sCollisionTypeList; + static rstl::single_ptr< ComparisonFunc > sTableOfCollidables; + static rstl::single_ptr< BooleanComparisonFunc > sTableOfBooleanCollidables; + static rstl::single_ptr< MovingComparisonFunc > sTableOfMovingCollidables; + static ComparisonFunc sNullCollider; + static BooleanComparisonFunc sNullBooleanCollider; + static MovingComparisonFunc sNullMovingCollider; + + uint x4_; + CMaterialList x8_material; +}; +CHECK_SIZEOF(CCollisionPrimitive, 0x10) + +inline CCollisionPrimitive::~CCollisionPrimitive() {} + +#endif // _CCOLLISIONPRIMITIVE diff --git a/include/Collision/CMaterialFilter.hpp b/include/Collision/CMaterialFilter.hpp new file mode 100644 index 0000000..f819c30 --- /dev/null +++ b/include/Collision/CMaterialFilter.hpp @@ -0,0 +1,45 @@ +#ifndef _CMATERIALFILTER +#define _CMATERIALFILTER + +#include "types.h" + +#include "Collision/CMaterialList.hpp" + +class CMaterialFilter { + static const CMaterialFilter skPassEverything; + +public: + enum EFilterType { + kFT_Always, + kFT_Include, + kFT_Exclude, + kFT_IncludeExclude, + }; + + CMaterialFilter() : include(0x00000000FFFFFFFF), exclude(0), type(kFT_Always) {} + CMaterialFilter(const CMaterialList& include, const CMaterialList& exclude, EFilterType type) + : include(include), exclude(exclude), type(type) {} + + static CMaterialFilter MakeInclude(const CMaterialList& include) { + return CMaterialFilter(include, CMaterialList(), kFT_Include); + } + static CMaterialFilter MakeExclude(const CMaterialList& exclude) { + return CMaterialFilter(CMaterialList(), exclude, kFT_Exclude); + } + static CMaterialFilter MakeIncludeExclude(const CMaterialList& include, + const CMaterialList& exclude) { + return CMaterialFilter(include, exclude, kFT_IncludeExclude); + } + + static const CMaterialFilter& GetPassEverything() { return skPassEverything; } + + bool Passes(const CMaterialList& other) const; + +private: + CMaterialList include; + CMaterialList exclude; + EFilterType type; +}; +CHECK_SIZEOF(CMaterialFilter, 0x18) + +#endif // _CMATERIALFILTER diff --git a/include/Collision/CMaterialList.hpp b/include/Collision/CMaterialList.hpp new file mode 100644 index 0000000..7acf726 --- /dev/null +++ b/include/Collision/CMaterialList.hpp @@ -0,0 +1,132 @@ +#ifndef _CMATERIALLIST +#define _CMATERIALLIST + +#include "types.h" + +enum EMaterialTypes { + kMT_NoStepLogic = 0, + kMT_Stone = 1, + kMT_Metal = 2, + kMT_Grass = 3, + kMT_Ice = 4, + kMT_Pillar = 5, + kMT_MetalGrating = 6, + kMT_Phazon = 7, + kMT_Dirt = 8, + kMT_Lava = 9, + kMT_LavaStone = 10, + kMT_Snow = 11, + kMT_MudSlow = 12, + kMT_HalfPipe = 13, + kMT_Mud = 14, + kMT_Glass = 15, + kMT_Shield = 16, + kMT_Sand = 17, + kMT_ProjectilePassthrough = 18, + kMT_Solid = 19, + kMT_NoPlatformCollision = 20, + kMT_CameraPassthrough = 21, + kMT_Wood = 22, + kMT_Organic = 23, + kMT_NoEdgeCollision = 24, + kMT_RedundantEdgeOrFlippedTri = 25, + kMT_SeeThrough = 26, + kMT_ScanPassthrough = 27, + kMT_AIPassthrough = 28, + kMT_Ceiling = 29, + kMT_Wall = 30, + kMT_Floor = 31, + kMT_Player = 32, + kMT_Character = 33, + kMT_Trigger = 34, + kMT_Projectile = 35, + kMT_Bomb = 36, + kMT_GroundCollider = 37, + kMT_NoStaticCollision = 38, + kMT_Scannable = 39, + kMT_Target = 40, + kMT_Orbit = 41, + kMT_Occluder = 42, + kMT_Immovable = 43, + kMT_Debris = 44, + kMT_PowerBomb = 45, + kMT_Unknown46 = 46, + kMT_CollisionActor = 47, + kMT_AIBlock = 48, + kMT_Platform = 49, + kMT_NonSolidDamageable = 50, + kMT_RadarObject = 51, + kMT_PlatformSlave = 52, + kMT_AIJoint = 53, + kMT_Unknown54 = 54, + kMT_SolidCharacter = 55, + kMT_ExcludeFromLineOfSightTest = 56, + kMT_ExcludeFromRadar = 57, + kMT_NoPlayerCollision = 58, + kMT_SixtyThree = 63 +}; + +// TODO: how else would they end up in .data? +static EMaterialTypes SolidMaterial = kMT_Solid; + +class CMaterialList { +public: + CMaterialList() : value(0) {} + explicit CMaterialList(const EMaterialTypes& m1) : value(0) { Add(m1); } + CMaterialList(const EMaterialTypes& m1, const EMaterialTypes& m2) : value(0) { + Add(m1); + Add(m2); + } + CMaterialList(const EMaterialTypes& m1, const EMaterialTypes& m2, const EMaterialTypes& m3) + : value(0) { + Add(m1); + Add(m2); + Add(m3); + } + CMaterialList(const EMaterialTypes& m1, const EMaterialTypes& m2, const EMaterialTypes& m3, + const EMaterialTypes& m4) + : value(0) { + Add(m1); + Add(m2); + Add(m3); + Add(m4); + } + CMaterialList(const EMaterialTypes& m1, const EMaterialTypes& m2, const EMaterialTypes& m3, + const EMaterialTypes& m4, const EMaterialTypes& m5) + : value(0) { + Add(m1); + Add(m2); + Add(m3); + Add(m4); + Add(m5); + } + explicit CMaterialList(u64 value) : value(value) {} + + void Add(EMaterialTypes material) { value |= u64(1) << material; } + void Add(const CMaterialList& material) { value |= material.value; } + void Remove(EMaterialTypes material) { value &= ~(u64(1) << material); } + void Remove(const CMaterialList& material) { value &= ~material.value; } + const CMaterialList& Union(const CMaterialList& other) { + value |= other.value; + return *this; + } + bool HasMaterial(EMaterialTypes material) const { + return (value & (u64(1) << material)) ? true : false; + } + // HasMaterials__13CMaterialListCFv weak + // GetField__13CMaterialListCFUxUx weak + // Intersection__13CMaterialListCFRC13CMaterialList weak + static int BitPosition(u64 flags); + // GetMaterialString__13CMaterialListCFv weak + bool SharesMaterials(const CMaterialList& other) const { + return (other.value & value) ? true : false; + } + +private: + u64 value; + + // static CMaterialList kEverything; +}; +CHECK_SIZEOF(CMaterialList, 0x8) + +#endif // _CMATERIALLIST diff --git a/include/MetroidPrime/ActorCommon.hpp b/include/MetroidPrime/ActorCommon.hpp new file mode 100644 index 0000000..f7516dc --- /dev/null +++ b/include/MetroidPrime/ActorCommon.hpp @@ -0,0 +1,159 @@ +#ifndef _ACTORCOMMON +#define _ACTORCOMMON + +enum EWeaponCollisionResponseTypes { + kWCR_None, + kWCR_Default, + kWCR_Unknown2, + kWCR_Metal, + kWCR_Grass, + kWCR_Ice, + kWCR_Goo, + kWCR_Wood, + kWCR_Water, + kWCR_Mud, + kWCR_Lava, + kWCR_Sand, + kWCR_Projectile, + kWCR_OtherProjectile, + kWCR_Unknown14, + kWCR_Unknown15, + kWCR_EnemyNormal, + kWCR_EnemySpecial, + kWCR_EnemyShielded, + kWCR_Unknown19, + kWCR_Unknown20, + kWCR_Unknown21, + kWCR_Unknown22, + kWCR_Unknown23, + kWCR_Unknown24, + kWCR_Unknown25, + kWCR_Unknown26, + kWCR_Unknown27, + kWCR_Unknown28, + kWCR_Unknown29, + kWCR_Unknown30, + kWCR_Unknown31, + kWCR_Unknown32, + kWCR_Unknown33, + kWCR_Unknown34, + kWCR_Unknown35, + kWCR_Unknown36, + kWCR_Unknown37, + kWCR_ChozoGhost, + kWCR_Unknown39, + kWCR_Unknown40, + kWCR_Unknown41, + kWCR_AtomicBeta, + kWCR_AtomicAlpha, + kWCR_Unknown44, + kWCR_Unknown45, + kWCR_Unknown46, + kWCR_Unknown47, + kWCR_Unknown48, + kWCR_Unknown49, + kWCR_Unknown50, + kWCR_Unknown51, + kWCR_Unknown52, + kWCR_Unknown53, + kWCR_Unknown54, + kWCR_Unknown55, + kWCR_Unknown56, + kWCR_Unknown57, + kWCR_Unknown58, + kWCR_Unknown59, + kWCR_Unknown60, + kWCR_Unknown61, + kWCR_Unknown62, + kWCR_Unknown63, + kWCR_Unknown64, + kWCR_Unknown65, + kWCR_Unknown66, + kWCR_Unknown67, + kWCR_Unknown68, + kWCR_Unknown69, + kWCR_Unknown70, + kWCR_Unknown71, + kWCR_Unknown72, + kWCR_Unknown73, + kWCR_Unknown74, + kWCR_Unknown75, + kWCR_Unknown76, + kWCR_Unknown77, + kWCR_Unknown78, + kWCR_Unknown79, + kWCR_Unknown80, + kWCR_Unknown81, + kWCR_Unknown82, + kWCR_Unknown83, + kWCR_Unknown84, + kWCR_Unknown85, + kWCR_Unknown86, + kWCR_Unknown87, + kWCR_Unknown88, + kWCR_Unknown89, + kWCR_Unknown90, + kWCR_Unknown91, + kWCR_AtomicBetaReflect, + kWCR_AtomicAlphaReflect, +}; +enum EProjectileAttrib { + kPA_None = 0, + kPA_PartialCharge = (1 << 0), + kPA_PlasmaProjectile = (1 << 1), + kPA_Charged = (1 << 2), + kPA_Ice = (1 << 3), + kPA_Wave = (1 << 4), + kPA_Plasma = (1 << 5), + kPA_Phazon = (1 << 6), + kPA_ComboShot = (1 << 7), + kPA_Bombs = (1 << 8), + kPA_PowerBombs = (1 << 9), + kPA_BigProjectile = (1 << 10), + kPA_ArmCannon = (1 << 11), + kPA_BigStrike = (1 << 12), + kPA_DamageFalloff = (1 << 13), + kPA_StaticInterference = (1 << 14), + kPA_PlayerUnFreeze = (1 << 15), + kPA_ParticleOPTS = (1 << 16), + kPA_KeepInCinematic = (1 << 17), +}; +enum EUserEventType { + kUE_Projectile = 0, + kUE_EggLay = 1, + kUE_LoopedSoundStop = 2, + kUE_AlignTargetPos = 3, + kUE_AlignTargetRot = 4, + kUE_ChangeMaterial = 5, + kUE_Delete = 6, + kUE_GenerateEnd = 7, + kUE_DamageOn = 8, + kUE_DamageOff = 9, + kUE_AlignTargetPosStart = 10, + kUE_DeGenerate = 11, + kUE_Landing = 12, + kUE_TakeOff = 13, + kUE_FadeIn = 14, + kUE_FadeOut = 15, + kUE_ScreenShake = 16, + kUE_BeginAction = 17, + kUE_EndAction = 18, + kUE_BecomeRagDoll = 19, + kUE_IkLock = 20, + kUE_IkRelease = 21, + kUE_BreakLockOn = 22, + kUE_BecomeShootThrough = 23, + kUE_RemoveCollision = 24, + kUE_ObjectPickUp = 25, + kUE_ObjectDrop = 26, + kUE_EventStart = 27, + kUE_EventStop = 28, + kUE_Activate = 29, + kUE_Deactivate = 30, + kUE_SoundPlay = 31, + kUE_SoundStop = 32, + kUE_EffectOn = 33, + kUE_EffectOff = 34, +}; + +#endif // _ACTORCOMMON diff --git a/include/MetroidPrime/CActor.hpp b/include/MetroidPrime/CActor.hpp new file mode 100644 index 0000000..9c3c48a --- /dev/null +++ b/include/MetroidPrime/CActor.hpp @@ -0,0 +1,256 @@ +#ifndef _CACTOR +#define _CACTOR + +#include "types.h" + +#include "Collision/CMaterialFilter.hpp" +#include "Collision/CMaterialList.hpp" + +#include "MetroidPrime/CEntity.hpp" +#include "MetroidPrime/CModelData.hpp" +#include "MetroidPrime/ActorCommon.hpp" + +#include "Kyoto/Audio/CSfxHandle.hpp" +#include "Kyoto/Graphics/CColor.hpp" +#include "Kyoto/Graphics/CModelFlags.hpp" +#include "Kyoto/Math/CAABox.hpp" +#include "Kyoto/Math/CTransform4f.hpp" +#include "Kyoto/TToken.hpp" + +#include "rstl/optional_object.hpp" +#include "rstl/pair.hpp" +#include "rstl/reserved_vector.hpp" +#include "rstl/single_ptr.hpp" + +class CActorLights; +class CActorParameters; +class CScannableObjectInfo; +class CSimpleShadow; + +class CDamageInfo; +class CDamageVulnerability; +class CFrustumPlanes; +class CHealthInfo; +class CScriptWater; +class CWeaponMode; +class CInt32POINode; + +class CActor : public CEntity { +public: + enum EThermalFlags { + kTF_None = 0, + kTF_Cold = 1, + kTF_Hot = 2, + }; + enum EFluidState { + kFS_EnteredFluid, + kFS_InFluid, + kFS_LeftFluid, + }; + enum EScanState { + kSS_Start, + kSS_Processing, + kSS_Done, + }; + + CActor(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, void*, + const CTransform4f& xf, const CModelData& mData, const CMaterialList& list, + const CActorParameters& params, TUniqueId nextDrawNode); + ~CActor() override; + + void AcceptScriptMsg(CStateManager& mgr, CScriptMsg&) override; + void SetActive(const bool active) override; + + virtual void PreRender(CStateManager&, const CFrustumPlanes&); + virtual void AddToRenderer(const CFrustumPlanes&, const CStateManager&) const; + virtual void Render(const CStateManager&) const; + virtual bool CanRenderUnsorted(const CStateManager&) const; + virtual void CalculateRenderBounds(); + const CHealthInfo* GetHealthInfo(const CStateManager& mgr) const { + return const_cast< CActor* >(this)->HealthInfo(const_cast< CStateManager& >(mgr)); + } + virtual CHealthInfo* HealthInfo(CStateManager&); + virtual const CDamageVulnerability* GetDamageVulnerability() const; + virtual const CDamageVulnerability* GetDamageVulnerability(const CVector3f&, const CVector3f&, + const CDamageInfo&) const; + virtual rstl::optional_object< CAABox > GetTouchBounds() const; + virtual void Touch(CActor&, CStateManager&); + virtual CVector3f GetOrbitPosition(const CStateManager&) const; + virtual CVector3f GetAimPosition(const CStateManager&, float) const; + virtual CVector3f GetHomingPosition(const CStateManager&, float) const; + virtual CVector3f GetScanObjectIndicatorPosition(const CStateManager&) const; + virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const CVector3f&, const CVector3f&, + const CWeaponMode&, + int /*EProjectileAttrib?*/) const; + virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&); + virtual void OnScanStateChange(EScanState, CStateManager&); + virtual CAABox GetSortingBounds(const CStateManager&) const; + virtual void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, + float dt); + + CAdvancementDeltas UpdateAnimation(float dt, CStateManager& mgr, bool advTree); + + void ProcessSoundEvent(int sfxId, float weight, int flags, float fallOff, float maxDist, + uchar minVol, uchar maxVol, const CVector3f& toListener, + const CVector3f& position, int aid, CStateManager& mgr, bool translateId); + + void UpdateSfxEmitters(); + void RemoveEmitter(); + void SetModelData(const CModelData& modelData); + float GetAverageAnimVelocity(int anim); + void EnsureRendered(const CStateManager& mgr) const; + void EnsureRendered(const CStateManager& mgr, const CVector3f& pos, const CAABox& bounds) const; + void DrawTouchBounds() const; + bool IsModelOpaque(const CStateManager& mgr) const; + void RenderInternal(const CStateManager& mgr) const; + void CreateShadow(bool); + + const CTransform4f& GetTransform() const { return transform; } + void SetTransform(const CTransform4f& xf) { + transform = xf; + SetTransformDirty(true); + SetTransformDirtySpare(true); + SetPreRenderHasMoved(true); + } + void SetRotation(const CQuaternion& rot) { SetTransform(rot.BuildTransform4f(GetTranslation())); } + CQuaternion GetRotation() const { return CQuaternion::FromMatrix(GetTransform()); } + CVector3f GetTranslation() const { return transform.GetTranslation(); } + void SetTranslation(const CVector3f& vec); + CTransform4f GetLocatorTransform(const rstl::string& segName) const; + CTransform4f GetScaledLocatorTransform(const rstl::string& segName) const; + float GetYaw() const; + + /// ???? + bool NullModel() const { return !GetAnimationData() && !GetModelData()->HasNormalModel(); } + + bool HasModelData() const { + return GetModelData() && (GetModelData()->HasAnimation() || GetModelData()->HasNormalModel()); + } + CModelData* ModelData() { return modelData.get(); } + const CModelData* GetModelData() const { return modelData.get(); } + + bool HasAnimation() const { return GetModelData() && GetModelData()->HasAnimation(); } + CAnimData* AnimationData() { return ModelData()->AnimationData(); } + const CAnimData* GetAnimationData() const { return GetModelData()->GetAnimationData(); } + + bool HasShadow() const { return GetShadow() != nullptr; } + CSimpleShadow* Shadow() { return x94_simpleShadow.get(); } + const CSimpleShadow* GetShadow() const { return x94_simpleShadow.get(); } + + bool HasActorLights() const { return !x90_actorLights.null(); } + CActorLights* ActorLights() { return x90_actorLights.get(); } + const CActorLights* GetActorLights() const { return x90_actorLights.get(); } + + const CModelFlags& GetModelFlags() const { return xb4_drawFlags; } + void SetModelFlags(const CModelFlags& flags) { xb4_drawFlags = flags; } + + const CMaterialList& GetMaterialList() const { return material; } + CMaterialList& MaterialList() { return material; } + + const CMaterialFilter& GetMaterialFilter() const; + void SetMaterialFilter(const CMaterialFilter& filter); + + bool GetTransformDirty() const { return xe4_27_notInSortedLists; } + bool GetTransformDirtySpare() const { return xe4_28_transformDirty; } + bool GetPreRenderHasMoved() const { return xe4_29_actorLightsDirty; } + bool GetPreRenderClipped() const { return xe4_30_outOfFrustum; } + bool GetCalculateLighting() const { return xe4_31_calculateLighting && HasActorLights(); } + bool GetDrawShadow() const { return xe5_24_shadowEnabled; } + bool GetShadowDirty() const { return xe5_25_shadowDirty; } + bool GetMuted() const { return xe5_26_muted; } + EThermalFlags GetThermalFlags() const { + return static_cast< EThermalFlags >(xe6_27_thermalVisorFlags); + } + bool GetRenderParticleDatabaseInside() const { return xe6_29_renderParticleDBInside; } + bool GetTargetable() const { return xe7_31_targetable; } + + void SetTransformDirty(bool b) { xe4_27_notInSortedLists = b; } + void SetTransformDirtySpare(bool b) { xe4_28_transformDirty = b; } + void SetPreRenderHasMoved(bool b) { xe4_29_actorLightsDirty = b; } + void SetPreRenderClipped(bool b) { xe4_30_outOfFrustum = b; } + void SetCalculateLighting(bool b) { xe4_31_calculateLighting = b; } + void SetDrawShadow(bool b) { xe5_24_shadowEnabled = b; } + void SetShadowDirty(bool b) { xe5_25_shadowDirty = b; } + void SetMuted(bool b) { xe5_26_muted = b; } + void SetThermalFlags(EThermalFlags flags) { xe6_27_thermalVisorFlags = flags; } + void SetRenderParticleDatabaseInside(bool b) { xe6_29_renderParticleDBInside = b; } + void SetTargetable(bool b) { xe7_31_targetable = b; } + + void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, + CStateManager&); + void RemoveMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void RemoveMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); + void RemoveMaterial(EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, + CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, EMaterialTypes, CStateManager&); + void AddMaterial(EMaterialTypes, CStateManager&); + void AddMaterial(const CMaterialList& l) { material.Add(l); } + + const CAABox& GetRenderBoundsCached() const { return renderBounds; } + void SetRenderBounds(const CAABox& bounds) { renderBounds = bounds; } + + // 000c0ec8 00001c 801711a8 4 GetUseInSortedLists__6CActorCFv CActor.o + void SetUseInSortedLists(bool use); + // 000c0ef8 00001c 801711d8 4 GetCallTouch__6CActorCFv CActor.o + void SetCallTouch(bool); + // GetOrbitDistanceCheck__6CActorCFv + // GetCalculateLighting__6CActorCFv + // GetDrawShadow__6CActorCFv + // GetRenderBoundsCached__6CActorCFv + // GetRenderParticleDatabaseInside__6CActorCFv + // HasModelParticles__6CActorCFv + void SetVolume(uchar volume); + +private: + CTransform4f transform; // x24 + CVector3f position; // x54 + rstl::single_ptr< CModelData > modelData; // x60 + CMaterialList material; // x68 + CMaterialFilter x70_materialFilter; + TSfxId x88_sfxId; + CSfxHandle x8c_loopingSfxHandle; + rstl::single_ptr< CActorLights > x90_actorLights; + rstl::single_ptr< CSimpleShadow > x94_simpleShadow; + rstl::single_ptr< TCachedToken< CScannableObjectInfo > > x98_scanObjectInfo; + CAABox renderBounds; + CModelFlags xb4_drawFlags; + float xbc_time; + uint xc0_pitchBend; + TUniqueId xc4_fluidId; + TUniqueId xc6_nextDrawNode; + int xc8_drawnToken; + int xcc_addedToken; + float xd0_damageMag; + uchar xd4_maxVol; + rstl::reserved_vector< CSfxHandle, 2 > xd8_nonLoopingSfxHandles; + uint xe4_24_nextNonLoopingSfxHandle : 3; + uint xe4_27_notInSortedLists : 1; + uint xe4_28_transformDirty : 1; + uint xe4_29_actorLightsDirty : 1; + uint xe4_30_outOfFrustum : 1; + uint xe4_31_calculateLighting : 1; + uint xe5_24_shadowEnabled : 1; + uint xe5_25_shadowDirty : 1; + uint xe5_26_muted : 1; + uint xe5_27_useInSortedLists : 1; + uint xe5_28_callTouch : 1; + uint xe5_29_globalTimeProvider : 1; + uint xe5_30_renderUnsorted : 1; + uint xe5_31_pointGeneratorParticles : 1; + uint xe6_24_fluidCounter : 3; + uint xe6_27_thermalVisorFlags : 2; + uint xe6_29_renderParticleDBInside : 1; + uint xe6_30_enablePitchBend : 1; + uint xe6_31_targetableVisorFlags : 4; + uint xe7_27_enableRender : 1; + uint xe7_28_worldLightingDirty : 1; + uint xe7_29_drawEnabled : 1; + uint xe7_30_doTargetDistanceTest : 1; + uint xe7_31_targetable : 1; +}; +// CHECK_SIZEOF(CActor, 0xe8) 0x158 + +#endif // _CACTOR diff --git a/include/MetroidPrime/CAxisAngle.hpp b/include/MetroidPrime/CAxisAngle.hpp new file mode 100644 index 0000000..e8078ce --- /dev/null +++ b/include/MetroidPrime/CAxisAngle.hpp @@ -0,0 +1,41 @@ +#ifndef _CAXISANGLE +#define _CAXISANGLE + +#include "types.h" + +#include "Kyoto/Math/CUnitVector3f.hpp" +#include "Kyoto/Math/CVector3f.hpp" + +#include + +class CAxisAngle { + static const CAxisAngle sIdentity; + friend CAxisAngle operator+(const CAxisAngle&, const CAxisAngle&); + friend CAxisAngle operator*(const CAxisAngle&, const float&); + friend CAxisAngle operator*(const float&, const CAxisAngle&); + +public: + CAxisAngle() : mVector(CVector3f::Zero()) {} + explicit CAxisAngle(const CVector3f& vec); + explicit CAxisAngle(const CUnitVector3f& vec, float); + CAxisAngle(float x, float y, float z) : mVector(x, y, z) {} + void FromVector(const CVector3f& angle); + + static const CAxisAngle& Identity(); + float GetAngle() const; + const CVector3f& GetVector() const; + + const CAxisAngle& operator*=(const float& rhs); + const CAxisAngle& operator+=(const CAxisAngle& rhs); + +private: + CVector3f mVector; +}; + +CAxisAngle operator+(const CAxisAngle& lhs, const CAxisAngle& rhs); +CAxisAngle operator*(const CAxisAngle& lhs, const float& rhs); +CAxisAngle operator*(const float& rhs, const CAxisAngle& lhs); + +CHECK_SIZEOF(CAxisAngle, 0xc) + +#endif // _CAXISANGLE diff --git a/include/MetroidPrime/CEntity.hpp b/include/MetroidPrime/CEntity.hpp index 76a2961..3a2ac7f 100644 --- a/include/MetroidPrime/CEntity.hpp +++ b/include/MetroidPrime/CEntity.hpp @@ -50,5 +50,6 @@ private: bool inGraveyard : 1; bool scriptingBlocked : 1; }; +CHECK_SIZEOF(CEntity, 0x24) #endif // _CENTITY diff --git a/include/MetroidPrime/CModelData.hpp b/include/MetroidPrime/CModelData.hpp new file mode 100644 index 0000000..da7dbe0 --- /dev/null +++ b/include/MetroidPrime/CModelData.hpp @@ -0,0 +1,126 @@ +#ifndef _CMODELDATA +#define _CMODELDATA + +#include "types.h" + +#include "MetroidPrime/TGameTypes.hpp" + +#include "Kyoto/Animation/IAnimReader.hpp" +#include "Kyoto/Graphics/CColor.hpp" +#include "Kyoto/Math/CTransform4f.hpp" +#include "Kyoto/Math/CVector3f.hpp" +#include "Kyoto/TToken.hpp" + +#include "rstl/auto_ptr.hpp" +#include "rstl/optional_object.hpp" +#include "rstl/pair.hpp" +#include "rstl/string.hpp" + +class CAABox; +class CActorLights; +class CAnimData; +class CAnimRes; +class CFrustumPlanes; +class CModel; +class CModelFlags; +class CStateManager; +class CSkinnedModel; +class CRandom16; + +// TODO move +#include "Kyoto/Math/CQuaternion.hpp" +struct CAdvancementDeltas { +public: + CAdvancementDeltas(const CVector3f& posDelta, const CQuaternion& rotDelta) + : x0_posDelta(posDelta), xc_rotDelta(rotDelta) {} + + const CVector3f& GetOffsetDelta() const { return x0_posDelta; } + const CQuaternion& GetOrientationDelta() const { return xc_rotDelta; } + +private: + CVector3f x0_posDelta; + CQuaternion xc_rotDelta; +}; +CHECK_SIZEOF(CAdvancementDeltas, 0x1c) + +class CStaticRes { + CAssetId x0_cmdlId; + CVector3f x4_scale; + +public: + CStaticRes(CAssetId id, const CVector3f& scale) : x0_cmdlId(id), x4_scale(scale) {} +}; + +class CModelData { +public: + enum EWhichModel { + kWM_Normal, + kWM_XRay, + kWM_Thermal, + kWM_ThermalHot, + }; + + // TODO these probably aren't real + bool HasNormalModel() const { return x1c_normalModel; } + + CModelData(); + CModelData(const CAnimRes&); + CModelData(const CStaticRes&); + CModelData(const CModelData& other); + ~CModelData(); + + CAdvancementDeltas AdvanceAnimation(float dt, CStateManager& mgr, TAreaId aid, bool advTree); + void AdvanceParticles(const CTransform4f& xf, float dt, CStateManager& mgr); + void RenderParticles(const CFrustumPlanes& planes) const; + void RenderUnsortedParts(EWhichModel which, const CTransform4f& xf, const CActorLights* lights, + const CModelFlags& flags) const; + void RenderThermal(const CTransform4f& xf, const CColor& mulColor, const CColor& addColor, + const CModelFlags& flags) const; + void Render(const CStateManager&, const CTransform4f&, const CActorLights*, + const CModelFlags&) const; + void Render(EWhichModel, const CTransform4f&, const CActorLights*, const CModelFlags&) const; + void FlatDraw(EWhichModel which, const CTransform4f& xf, bool unsortedOnly, + const CModelFlags& flags) const; + CSkinnedModel& PickAnimatedModel(EWhichModel which) const; + void Touch(const CStateManager& mgr, int) const; + SAdvancementDeltas AdvanceAnimationIgnoreParticles(float dt, CRandom16& rand, bool advTree); + + const CAnimData* GetAnimationData() const { return xc_animData.get(); } + CAnimData* AnimationData() { return xc_animData.get(); } + CAABox GetBounds(const CTransform4f& xf) const; + CAABox GetBounds() const; + bool IsLoaded(int shaderIdx) const; + + CTransform4f GetScaledLocatorTransform(const rstl::string& name) const; + + bool HasAnimation() const { return !xc_animData.null(); } + bool IsNull() const { return xc_animData.null() && !x1c_normalModel; } + + void SetXRayModel(const rstl::pair< CAssetId, CAssetId >& assets); + void SetInfraModel(const rstl::pair< CAssetId, CAssetId >& assets); + + void SetAmbientColor(const CColor& color) { x18_ambientColor = color; } + bool GetSortThermal() const { return x14_25_sortThermal; } + void SetSortThermal(bool b) { x14_25_sortThermal = b; } + + CVector3f GetScale() const { return x0_scale; } + void SetScale(const CVector3f& scale) { x0_scale = scale; } + + bool GetIsLoop() const; + void EnableLooping(bool enable); + static CModelData CModelDataNull(); + static EWhichModel GetRenderingModel(const CStateManager& mgr); + +private: + CVector3f x0_scale; + rstl::auto_ptr< CAnimData > xc_animData; + bool x14_24_renderSorted : 1; + bool x14_25_sortThermal : 1; + CColor x18_ambientColor; + rstl::optional_object< TCachedToken< CModel > > x1c_normalModel; + rstl::optional_object< TCachedToken< CModel > > x2c_xrayModel; + rstl::optional_object< TCachedToken< CModel > > x3c_infraModel; +}; +CHECK_SIZEOF(CModelData, 0x4c) + +#endif // _CMODELDATA diff --git a/include/MetroidPrime/CPhysicsActor.hpp b/include/MetroidPrime/CPhysicsActor.hpp new file mode 100644 index 0000000..ddfc502 --- /dev/null +++ b/include/MetroidPrime/CPhysicsActor.hpp @@ -0,0 +1,205 @@ +#ifndef _CPHYSICSACTOR +#define _CPHYSICSACTOR + +#include "types.h" + +#include "MetroidPrime/CActor.hpp" +#include "MetroidPrime/CAxisAngle.hpp" +#include "MetroidPrime/CPhysicsState.hpp" + +#include "Kyoto/Math/CAABox.hpp" +#include "Kyoto/Math/CMatrix3f.hpp" +#include "Kyoto/Math/CNUQuaternion.hpp" +#include "Kyoto/Math/CVector3f.hpp" + +#include "Collision/CCollidableAABox.hpp" + +#include "rstl/optional_object.hpp" + +struct SMoverData { + CVector3f x0_velocity; + CAxisAngle xc_angularVelocity; + CVector3f x18_momentum; + CAxisAngle x24_; + float x30_mass; + + SMoverData(float mass, const CVector3f& velocity = CVector3f::Zero(), + const CAxisAngle& angularVelocity = CAxisAngle::Identity(), + const CVector3f& momentum = CVector3f::Zero(), + const CAxisAngle& unk = CAxisAngle::Identity()) + : x0_velocity(velocity) + , xc_angularVelocity(angularVelocity) + , x18_momentum(momentum) + , x24_(unk) + , x30_mass(mass) {} +}; + +class CMotionState { +public: + CMotionState(const CVector3f& translation, const CNUQuaternion& orientation, + const CVector3f& velocity, const CAxisAngle& angularMomentum) + : x0_translation(translation) + , xc_orientation(orientation) + , x1c_velocity(velocity) + , x28_angularMomentum(angularMomentum) {} + + const CVector3f& GetTranslation() const { return x0_translation; } + const CNUQuaternion& GetOrientation() const { return xc_orientation; } + const CVector3f& GetVelocity() const { return x1c_velocity; } + const CAxisAngle& GetAngularMomentum() const { return x28_angularMomentum; } + +private: + CVector3f x0_translation; + CNUQuaternion xc_orientation; + CVector3f x1c_velocity; + CAxisAngle x28_angularMomentum; +}; +CHECK_SIZEOF(CMotionState, 0x34) + +class CCollisionInfoList; + +class CPhysicsActor : public CActor { + static const float kGravityAccel; + +public: + CPhysicsActor(TUniqueId uid, bool active, const rstl::string& name, const CEntityInfo& info, + const CTransform4f& xf, const CModelData& mData, const CMaterialList& matList, + const CAABox& aabb, const SMoverData& moverData, const CActorParameters& actParams, + float stepUp, float stepDown); + + // CActor + ~CPhysicsActor() override; + void Render(const CStateManager&) const override; + CVector3f GetOrbitPosition(const CStateManager& mgr) const override; + CVector3f GetAimPosition(const CStateManager& mgr, float val) const override; + + // CPhysicsActor + virtual const CCollisionPrimitive* GetCollisionPrimitive() const; + virtual CTransform4f GetPrimitiveTransform() const; + virtual void CollidedWith(const TUniqueId& id, const CCollisionInfoList& list, + CStateManager& mgr); + virtual float GetStepDownHeight() const; + virtual float GetStepUpHeight() const; + virtual float GetWeight() const; + float GetMass() const { return xe8_mass; } + void SetMass(float mass); + void SetInertiaTensorScalar(float tensor); + + const CAABox& GetBaseBoundingBox() const; + CAABox GetBoundingBox() const; + void SetBoundingBox(const CAABox& box); + CAABox GetMotionVolume(float dt) const; + + void ApplyImpulseWR(const CVector3f& impulse, const CAxisAngle& angularImpulse); + void ApplyTorqueWR(const CVector3f& torque); + void ApplyForceWR(const CVector3f& force, const CAxisAngle& torque); + + void ApplyImpulseOR(const CVector3f& impulse, const CAxisAngle& angularImpulse); + void ApplyForceOR(const CVector3f& impulse, const CAxisAngle& torque); + + void MoveCollisionPrimitive(const CVector3f&); + void SetVelocityWR(const CVector3f&); + void SetAngularVelocityWR(const CAxisAngle& angVel); + void SetVelocityOR(const CVector3f& vel); + CAxisAngle GetAngularVelocityOR() const; + void SetAngularVelocityOR(const CAxisAngle& angleVel); + void ClearForcesAndTorques(); + void ClearImpulses(); + void ComputeDerivedQuantities(); + void UseCollisionImpulses(); + bool WillMove(const CStateManager& mgr); + void Stop(); + + CVector3f GetPrimitiveOffset() const; + const CVector3f& GetConstantForceWR() const { return xfc_constantForce; } + void SetConstantForceWR(const CVector3f& force) { xfc_constantForce = force; } + const CAxisAngle& GetAngularMomentumWR() const { return x108_angularMomentum; } + void SetAngularMomentumWR(const CAxisAngle& angularMomentum) { + x108_angularMomentum = angularMomentum; + } + const CVector3f& GetMomentumWR() const { return x150_momentum; } + void SetMomentumWR(const CVector3f& momentum) { x150_momentum = momentum; } + const CVector3f& GetForceWR() const { return x15c_force; } + void SetForceWR(const CVector3f& force) { x15c_force = force; } + const CVector3f& GetImpulseWR() const { return x168_impulse; } + void SetImpulseWR(const CVector3f& impulse) { x168_impulse = impulse; } + const CAxisAngle& GetTorqueWR() const { return x174_torque; } + void SetTorqueWR(const CAxisAngle& torque) { x174_torque = torque; } + const CAxisAngle& GetAngularImpulseWR() const { return x180_angularImpulse; } + void SetAngularImpulseWR(const CAxisAngle& angularImpulse) { + x180_angularImpulse = angularImpulse; + } + + float GetCoefficientOfRestitutionModifier() const; + void SetCoefficientOfRestitutionModifier(float modifier); + float GetCollisionAccuracyModifier() const; + void SetCollisionAccuracyModifier(float modifier); + float GetMaximumCollisionVelocity() const; + void SetMaximumCollisionVelocity(float velocity); + + CPhysicsState GetPhysicsState() const; + void SetPhysicsState(const CPhysicsState& state); + CMotionState GetMotionState() const; + void SetMotionState(const CMotionState& state); + CVector3f CalculateNewVelocityWR_UsingImpulses() const; + CMotionState PredictMotion(float dt) const; + CMotionState PredictAngularMotion(float dt) const; + CMotionState PredictLinearMotion(float dt) const; + CMotionState PredictMotion_Internal(float dt) const; + void AddMotionState(const CMotionState& state); + bool GetMovable() const { return xf8_24_movable; } + void SetMovable(bool v) { xf8_24_movable = v; } + + void MoveToWR(const CVector3f&, float); + void MoveToInOneFrameWR(const CVector3f&, float); + CVector3f GetMoveToORImpulseWR(const CVector3f& impulse, float d) const; + CVector3f GetRotateToORAngularMomentumWR(const CQuaternion& q, float d) const; + void RotateToWR(const CQuaternion&, float); + + void MoveInOneFrameOR(const CVector3f& trans, float d); + void RotateInOneFrameOR(const CQuaternion&, float); + + void MoveToOR(const CVector3f&, float); + void RotateToOR(const CQuaternion&, float); + + CVector3f GetTotalForceWR() const; + + static float GravityConstant() { return kGravityAccel; } + +private: + float xe8_mass; + float xec_massRecip; + float xf0_inertiaTensor; + float xf4_inertiaTensorRecip; + bool xf8_24_movable : 1; + bool xf8_25_angularEnabled : 1; + bool xf9_standardCollider; + CVector3f xfc_constantForce; + CAxisAngle x108_angularMomentum; + CMatrix3f x114_; + CVector3f x138_velocity; + CAxisAngle x144_angularVelocity; + CVector3f x150_momentum; + CVector3f x15c_force; + CVector3f x168_impulse; + CAxisAngle x174_torque; + CAxisAngle x180_angularImpulse; + CVector3f x18c_moveImpulse; + CAxisAngle x198_moveAngularImpulse; + CAABox x1a4_baseBoundingBox; + CCollidableAABox x1c0_collisionPrimitive; + CVector3f x1e8_primitiveOffset; + CMotionState x1f4_lastNonCollidingState; + rstl::optional_object< CVector3f > x228_lastFloorPlaneNormal; + float x238_maximumCollisionVelocity; + float x23c_stepUpHeight; + float x240_stepDownHeight; + float x244_restitutionCoefModifier; + float x248_collisionAccuracyModifier; + uint x24c_numTicksStuck; + uint x250_numTicksPartialUpdate; + uint x254_; +}; +// CHECK_SIZEOF(CPhysicsActor, 0x258) 0x2d0 + +#endif // _CPHYSICSACTOR diff --git a/include/MetroidPrime/CPhysicsState.hpp b/include/MetroidPrime/CPhysicsState.hpp new file mode 100644 index 0000000..3f584b5 --- /dev/null +++ b/include/MetroidPrime/CPhysicsState.hpp @@ -0,0 +1,38 @@ +#ifndef _CPHYSICSSTATE +#define _CPHYSICSSTATE + +#include "MetroidPrime/CAxisAngle.hpp" + +#include "Kyoto/Math/CQuaternion.hpp" +#include "Kyoto/Math/CVector3f.hpp" + +class CPhysicsState { +public: + CPhysicsState(const CVector3f& trasnlation, const CQuaternion& orientation, + const CVector3f& constantForce, const CAxisAngle& angularMomentum, + const CVector3f& momentum, const CVector3f& force, const CVector3f& impulse, + const CAxisAngle& torque, const CAxisAngle& angularImpulse); + + CVector3f GetTranslation() const { return x0_translation; } + CQuaternion GetOrientationWR() const { return xc_orientation; } + CVector3f GetConstantForceWR() const { return x1c_constantForce; } + CAxisAngle GetAngularMomentumWR() const { return x28_angularMomentum; } + CVector3f GetMomentumWR() const { return x34_momentum; } + CVector3f GetForceWR() const { return x40_force; } + CVector3f GetImpulseWR() const { return x4c_impulse; } + CAxisAngle GetTorque() const { return x58_torque; } + CAxisAngle GetAngularImpulseWR() const { return x64_angularImpulse; } + +private: + CVector3f x0_translation; + CQuaternion xc_orientation; + CVector3f x1c_constantForce; + CAxisAngle x28_angularMomentum; + CVector3f x34_momentum; + CVector3f x40_force; + CVector3f x4c_impulse; + CAxisAngle x58_torque; + CAxisAngle x64_angularImpulse; +}; + +#endif // _CPHYSICSSTATE diff --git a/include/MetroidPrime/ScriptObjects/CScriptPickup.hpp b/include/MetroidPrime/ScriptObjects/CScriptPickup.hpp new file mode 100644 index 0000000..a879e8f --- /dev/null +++ b/include/MetroidPrime/ScriptObjects/CScriptPickup.hpp @@ -0,0 +1,50 @@ +#ifndef _CSCRIPTPICKUP +#define _CSCRIPTPICKUP + +#include "types.h" + +#include "MetroidPrime/CActor.hpp" +#include "MetroidPrime/Player/CPlayerState.hpp" + +class CGenDescription; + +class CScriptPickup : public CActor { + CPlayerState::EItemType itemType; // x158 + int amount; + int capacity; + float possibility; + float fadeInTime; + float lifeTime; + float curTime; + float tractorTime; + float delayTimer; + rstl::optional_object< TCachedToken< CGenDescription > > pickupParticleDesc; + bool generated : 1; + bool inTractor : 1; + bool enableTractorTest : 1; + +public: + CScriptPickup(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, + const CTransform4f& xf, const CModelData& mData, const CActorParameters& aParams, + const CAABox& aabb, CPlayerState::EItemType itemType, int amount, int capacity, + CAssetId pickupEffect, float possibility, float lifeTime, float fadeInTime, + float startDelay, bool active); + ~CScriptPickup(); + + CEntity* TypesMatch(EEntityType) override; + + void Think(float, CStateManager&) override; + void Touch(CActor&, CStateManager&) override; + rstl::optional_object< CAABox > GetTouchBounds() const override; + void AcceptScriptMsg(CStateManager& mgr, CScriptMsg&) override; + + void Render(const CStateManager&) const override; + void AddToRenderer(const CFrustumPlanes&, const CStateManager&) const override; + + float GetPossibility() const; + CPlayerState::EItemType GetItem() const; + void SetSpawned(); + bool IsVisible() const; +}; + +#endif // _CSCRIPTPICKUP diff --git a/src/MetroidPrime/ScriptObjects/CScriptPickup.cpp b/src/MetroidPrime/ScriptObjects/CScriptPickup.cpp new file mode 100644 index 0000000..70b425e --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CScriptPickup.cpp @@ -0,0 +1,218 @@ +#include "MetroidPrime/ScriptObjects/CScriptPickup.hpp" + +// #include "MetroidPrime/CAnimData.hpp" +// #include "MetroidPrime/CAnimPlaybackParms.hpp" +// #include "MetroidPrime/CArtifactDoll.hpp" +// #include "MetroidPrime/CExplosion.hpp" +#include "MetroidPrime/CModelData.hpp" +// #include "MetroidPrime/CStateManager.hpp" +// #include "MetroidPrime/Cameras/CCameraManager.hpp" +// #include "MetroidPrime/Cameras/CFirstPersonCamera.hpp" +#include "MetroidPrime/Player/CGameState.hpp" +// #include "MetroidPrime/Player/CPlayer.hpp" +// #include "MetroidPrime/Player/CPlayerGun.hpp" +#include "MetroidPrime/Player/CPlayerState.hpp" +#include "MetroidPrime/Tweaks/CTweakGame.hpp" + +#include "MetroidPrime/HUD/CHUDMemoParms.hpp" +// #include "MetroidPrime/HUD/CSamusHud.hpp" + +#include "Kyoto/CResFactory.hpp" +#include "Kyoto/Math/CAbsAngle.hpp" +#include "Kyoto/Math/CMath.hpp" +#include "Kyoto/Text/CStringTable.hpp" + +#include "rstl/math.hpp" + +static float skDrawInDistance = 30.f; + +CScriptPickup::CScriptPickup(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, + const CTransform4f& xf, const CModelData& mData, + const CActorParameters& aParams, const CAABox& aabb, + CPlayerState::EItemType itemType, int amount, int capacity, + CAssetId pickupEffect, float possibility, float lifeTime, + float fadeInTime, float startDelay, bool active) + +: CActor(uid, name, info, nullptr, xf, mData, CMaterialList(), aParams, kInvalidUniqueId) +, itemType(itemType) +, amount(amount) +, capacity(capacity) +, possibility(possibility) +, fadeInTime(fadeInTime) +, lifeTime(lifeTime) +, curTime(0.f) +, delayTimer(startDelay) +, generated(false) +, inTractor(false) +, enableTractorTest(false) { + if (pickupEffect != kInvalidAssetId) { + pickupParticleDesc = gpSimplePool->GetObj(SObjectTag('PART', pickupEffect)); + pickupParticleDesc->Lock(); + } + + if (HasAnimation()) { + // AnimationData()->SetAnimation(CAnimPlaybackParms(0, -1, 1.f, true), false); + } + + if (fadeInTime) { + SetModelFlags(CModelFlags::AlphaBlended(0.f).DepthCompareUpdate(true, false)); + } +} + +CScriptPickup::~CScriptPickup() {} + +bool CScriptPickup::IsVisible() const { return false; } + +void CScriptPickup::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + return; + } + + // if (delayTimer >= 0.f) { + // CActor::Stop(); + // x278_delayTimer -= dt; + // return; + // } + + // x270_curTime += dt; + // if (x28c_25_inTractor && (x26c_lifeTime - x270_curTime) < 2.f) { + // x270_curTime = rstl::max_val(x26c_lifeTime - 2.f - FLT_EPSILON, x270_curTime - 2.f * dt); + // } + + // CModelFlags drawFlags = CModelFlags::Normal(); + + // if (x268_fadeInTime) { + // if (x270_curTime < x268_fadeInTime) { + // drawFlags = + // CModelFlags::AlphaBlended(x270_curTime / x268_fadeInTime).DepthCompareUpdate(true, + // false); + // } else { + // x268_fadeInTime = 0.f; + // } + // } else if (x26c_lifeTime) { + // float alpha = 1.f; + // if (x26c_lifeTime < 2.f) { + // alpha = 1.f - (x26c_lifeTime / x270_curTime); + // } else if ((x26c_lifeTime - x270_curTime) < 2.f) { + // alpha = (x26c_lifeTime - x270_curTime) / 2.f; + // } + + // drawFlags = CModelFlags::AlphaBlended(alpha).DepthCompareUpdate(true, false); + // } + + // SetModelFlags(drawFlags); + + // if (HasAnimation()) { + // CAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); + // MoveToOR(deltas.GetOffsetDelta(), dt); + // RotateToOR(deltas.GetOrientationDelta(), dt); + // } + + // if (x28c_25_inTractor) { + // CVector3f velocity = + // mgr.GetPlayer()->GetTranslation() + (CVector3f::Up() * 2.f) - GetTranslation(); + // x274_tractorTime += dt; + // float halfTractorTime = rstl::min_val(x274_tractorTime, 2.f) * 0.5f; + // velocity = velocity.AsNormalized() * (halfTractorTime * 20.f); + // if (x28c_26_enableTractorTest && mgr.GetPlayer()->GetPlayerGun()->GetChargeBeamFactor() < + // CPlayerGun::GetTractorBeamFactor()) { + // x28c_26_enableTractorTest = false; + // x28c_25_inTractor = false; + // velocity = CVector3f::Zero(); + // } + // SetVelocityWR(velocity); + // } else if (x28c_24_generated) { + // if (mgr.GetPlayer()->GetPlayerGun()->GetChargeBeamFactor() > + // CPlayerGun::GetTractorBeamFactor()) { + // const CFirstPersonCamera* camera = mgr.CameraManager()->FirstPersonCamera(); + // CVector3f posDelta = GetTranslation() - camera->GetTranslation(); + // CVector3f cameraFront = camera->GetTransform().GetColumn(kDY); + // float dot = CVector3f::Dot(cameraFront, posDelta.AsNormalized()); + // float fovCos = cosine(CAbsAngle::FromDegrees(gpTweakGame->GetFirstPersonFOV())); + // if (dot > fovCos && posDelta.MagSquared() < skDrawInDistance * skDrawInDistance) { + // x28c_25_inTractor = true; + // x28c_26_enableTractorTest = true; + // x274_tractorTime = 0.f; + // } + // } + // } + + // if (x26c_lifeTime && x270_curTime > x26c_lifeTime) { + // mgr.FreeScriptObject(GetUniqueId()); + // } +} + +void CScriptPickup::Touch(CActor& act, CStateManager& mgr) { + // if (GetActive() && !(x278_delayTimer >= 0) && TCastToPtr< CPlayer >(act)) { + // CPlayerState::EItemType itemType = x258_itemType; + // if (itemType >= CPlayerState::kIT_Truth && itemType <= CPlayerState::kIT_Newborn) { + // CAssetId id = CArtifactDoll::GetArtifactHeadScanFromItemType(itemType); + // if (id != kInvalidAssetId) { + // mgr.PlayerState()->SetScanTime(id, 0.5f); + // } + // } + + // if (x27c_pickupParticleDesc) { + // if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::kPV_Thermal) { + // mgr.AddObject(new CExplosion( + // TLockedToken< CGenDescription >(*x27c_pickupParticleDesc), mgr.AllocateUniqueId(), + // true, CEntityInfo(GetCurrentAreaId(), CEntity::NullConnectionList, kInvalidEditorId), + // rstl::string_l("Explosion - Pickup Effect"), GetTransform(), 0, + // CVector3f(1.f, 1.f, 1.f), CColor::White())); + + // } + // } + + // mgr.PlayerState()->InitializePowerUp(itemType, x260_capacity); + // mgr.PlayerState()->IncrPickUp(itemType, x25c_amount); + // mgr.FreeScriptObject(GetUniqueId()); + // SendScriptMsgs(kSS_Arrived, mgr, kSM_None); + + // if (x260_capacity > 0) { + // const CPlayerState* playerState = mgr.GetPlayerState(); + // int total = playerState->GetTotalPickupCount(); + // int colRate = playerState->CalculateItemCollectionRate(); + // if (colRate == total) { + // CSystemOptions& opts = gpGameState->SystemOptions(); + // CAssetId id = + // gpResourceFactory + // ->GetResourceIdByName(opts.GetAllItemsCollected() ? "STRG_AllPickupsFound_2" + // : "STRG_AllPickupsFound_1") + // ->id; + // mgr.QueueMessage(mgr.GetHUDMessageFrameCount() + 1, id, 0.f); + // opts.SetAllItemsCollected(true); + // } + // } + + // if (itemType == CPlayerState::kIT_PowerBombs) { + // CSystemOptions& opts = gpGameState->SystemOptions(); + // if (opts.GetShowPowerBombAmmoMessage()) { + // opts.IncrementPowerBombAmmoCount(); + // CSamusHud::DisplayHudMemo(rstl::wstring_l(gpStringTable->GetString(109)), + // CHUDMemoParms(5.f, true, false, false)); + // } + // } + // } +} + +rstl::optional_object< CAABox > CScriptPickup::GetTouchBounds() const { + // return CActor::GetBoundingBox(); +} + +void CScriptPickup::AcceptScriptMsg(CStateManager& mgr, CScriptMsg& msg) { + CActor::AcceptScriptMsg(mgr, msg); +} + +void CScriptPickup::Render(const CStateManager& mgr) const { CActor::Render(mgr); } + +void CScriptPickup::AddToRenderer(const CFrustumPlanes& a, const CStateManager& mgr) const { + if (IsVisible()) { + CActor::AddToRenderer(a, mgr); + } +} + +CPlayerState::EItemType CScriptPickup::GetItem() const { return itemType; } + +float CScriptPickup::GetPossibility() const { return possibility; } + +void CScriptPickup::SetSpawned() { generated = true; }