diff --git a/include/Kyoto/CResFactory.hpp b/include/Kyoto/CResFactory.hpp index dcfdcd39..208f3b23 100644 --- a/include/Kyoto/CResFactory.hpp +++ b/include/Kyoto/CResFactory.hpp @@ -35,6 +35,7 @@ public: void AsyncIdle(uint time); CResLoader& GetResLoader() { return x4_resLoader; } + FourCC GetResourceTypeById(CAssetId id) { return GetResLoader().GetResourceTypeById(id); } private: CResLoader x4_resLoader; diff --git a/include/MetroidPrime/CModelData.hpp b/include/MetroidPrime/CModelData.hpp index 51242fd9..dae5e8bf 100644 --- a/include/MetroidPrime/CModelData.hpp +++ b/include/MetroidPrime/CModelData.hpp @@ -61,7 +61,7 @@ public: CModelData(); CModelData(const CAnimRes&); - // __ct__10CModelDataFRC10CStaticRes + CModelData(const CStaticRes&); CModelData(const CModelData& other); ~CModelData(); diff --git a/include/MetroidPrime/ScriptLoader.hpp b/include/MetroidPrime/ScriptLoader.hpp index 652469af..34c4ec7d 100644 --- a/include/MetroidPrime/ScriptLoader.hpp +++ b/include/MetroidPrime/ScriptLoader.hpp @@ -14,6 +14,8 @@ public: static CEntity* LoadCameraHintTrigger(CStateManager&, CInputStream&, int, const CEntityInfo&); static CEntity* LoadDamageableTrigger(CStateManager&, CInputStream&, int, const CEntityInfo&); static CEntity* LoadSpawnPoint(CStateManager&, CInputStream&, int, const CEntityInfo&); + static CEntity* LoadDock(CStateManager&, CInputStream&, int, const CEntityInfo&); + static CEntity* LoadActor(CStateManager&, CInputStream&, int, const CEntityInfo&); }; #endif // _SCRIPTLOADER diff --git a/include/MetroidPrime/ScriptObjects/CScriptDock.hpp b/include/MetroidPrime/ScriptObjects/CScriptDock.hpp index 4caa3e73..95849aa7 100644 --- a/include/MetroidPrime/ScriptObjects/CScriptDock.hpp +++ b/include/MetroidPrime/ScriptObjects/CScriptDock.hpp @@ -5,7 +5,40 @@ class CScriptDock : public CPhysicsActor { public: + CScriptDock(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, + const CVector3f& position, const CVector3f& extent, int dock, TAreaId area, + bool active, int dockReferenceCount, bool loadConnected); + void SetDockReference(CStateManager& mgr, int); + + void Accept(IVisitor& visitor) override; + void Think(float, CStateManager&) override; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override; + rstl::optional_object< CAABox > GetTouchBounds() const override; + void Touch(CActor&, CStateManager&) override; + void CleanUp() {} + CPlane GetPlane(const CStateManager&) const; + TAreaId GetAreaId() const { return x260_area; } + int GetDockId() const { return x25c_dock; } + int GetDockReference(const CStateManager& mgr) const; + TAreaId GetCurrentConnectedAreaId(const CStateManager&) const; + void UpdateAreaActivateFlags(CStateManager&); + bool HasPointCrossedDock(const CStateManager&, const CVector3f&) const; + void AreaLoaded(CStateManager&); + void AreaUnloaded(CStateManager&); + void SetLoadConnected(CStateManager&, bool); + +private: + enum EDockState { kDS_InSourceRoom, kDS_PlayerTouched, kDS_EnterNextArea, kDS_InNextRoom }; + + friend class CScriptDoor; + int x258_dockReferenceCount; + int x25c_dock; + TAreaId x260_area; + EDockState x264_dockState; + bool x268_24_dockReferenced : 1; + bool x268_25_loadConnected : 1; + bool x268_26_areaPostConstructed : 1; }; #endif // _CSCRIPTDOCK diff --git a/src/MetroidPrime/ScriptLoader.cpp b/src/MetroidPrime/ScriptLoader.cpp index 0f3ac2ef..82a96e35 100644 --- a/src/MetroidPrime/ScriptLoader.cpp +++ b/src/MetroidPrime/ScriptLoader.cpp @@ -1,20 +1,26 @@ #include "MetroidPrime/ScriptLoader.hpp" #include "MetroidPrime/CActorParameters.hpp" +#include "MetroidPrime/CAnimRes.hpp" #include "MetroidPrime/CAnimationParameters.hpp" #include "MetroidPrime/CDamageVulnerability.hpp" #include "MetroidPrime/CGrappleParameters.hpp" #include "MetroidPrime/CHealthInfo.hpp" +#include "MetroidPrime/CModelData.hpp" #include "MetroidPrime/CStateManager.hpp" #include "MetroidPrime/CWorld.hpp" #include "MetroidPrime/Player/CPlayerState.hpp" +#include "MetroidPrime/ScriptObjects/CScriptActor.hpp" #include "MetroidPrime/ScriptObjects/CScriptCameraHintTrigger.hpp" #include "MetroidPrime/ScriptObjects/CScriptDamageableTrigger.hpp" +#include "MetroidPrime/ScriptObjects/CScriptDock.hpp" #include "MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp" #include "MetroidPrime/ScriptObjects/CScriptTrigger.hpp" + #include "Kyoto/Alloc/CMemory.hpp" +#include "Kyoto/CResFactory.hpp" #include "Kyoto/Math/CQuaternion.hpp" #include "Kyoto/Math/CRelAngle.hpp" #include "Kyoto/Streams/CInputStream.hpp" @@ -305,3 +311,95 @@ CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int rstl::reserved_vector< int, int(CPlayerState::kIT_Max) >(itemCounts), defaultSpawn, active, morphed); } + +CEntity* ScriptLoader::LoadDock(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (propCount != 7) + return nullptr; + + rstl::string name = mgr.HashInstanceName(in); + bool active = in.Get< bool >(); + CVector3f position(in); + CVector3f scale(in); + int dock = in.Get< int >(); + TAreaId area = in.Get< int >(); + bool loadConnected = in.Get< bool >(); + return new CScriptDock(mgr.AllocateUniqueId(), name, info, position, scale, dock, area, active, 0, + loadConnected); +} + +static CAABox GetCollisionBox(CStateManager& stateMgr, TAreaId id, const CVector3f& extent, + const CVector3f& offset) { + CAABox box(-extent * 0.5f + offset, extent * 0.5f + offset); + const CTransform4f& rot = stateMgr.GetWorld()->GetAreaAlways(id).GetTM().GetRotation(); + return box.GetTransformedAABox(rot); +} + +CEntity* ScriptLoader::LoadActor(CStateManager& mgr, CInputStream& in, int propCount, + const CEntityInfo& info) { + if (propCount != 24) + return nullptr; + + SScaledActorHead head(in, mgr); + CVector3f collisionExtent(in); + CVector3f centroid(in); + + float mass = in.ReadFloat(); + float zMomentum = in.ReadFloat(); + + CHealthInfo hInfo(in); + + CDamageVulnerability dVuln(in); + + CAssetId staticId = in.Get< CAssetId >(); + CAnimationParameters aParms = LoadAnimationParameters(in); + + CActorParameters actParms = LoadActorParameters(in); + + bool looping = in.Get< bool >(); + bool immovable = in.Get< bool >(); + bool solid = in.Get< bool >(); + bool cameraPassthrough = in.Get< bool >(); + bool active = in.Get< bool >(); + int shaderIdx = in.Get< int >(); + float xrayAlpha = in.Get< float >(); + bool noThermalHotZ = in.Get< bool >(); + bool castsShadow = in.Get< bool >(); + bool scaleAdvancementDelta = in.Get< bool >(); + bool materialFlag54 = in.Get< bool >(); + + FourCC animType = gpResourceFactory->GetResourceTypeById(aParms.GetACSFile()); + if (gpResourceFactory->GetResourceTypeById(staticId) == 0 && animType == 0) + return nullptr; + + CAABox aabb = GetCollisionBox(mgr, info.GetAreaId(), collisionExtent, centroid); + + CMaterialList list; + if (immovable) // Bool 2 + list.Add(kMT_Immovable); + + if (solid) // Bool 3 + list.Add(kMT_Solid); + + if (cameraPassthrough) // Bool 4 + list.Add(kMT_CameraPassthrough); + + bool negativeCollisionExtent = + collisionExtent.GetX() < 0.f || collisionExtent.GetY() < 0.f || collisionExtent.GetZ() < 0.f; + + CModelData data(CModelData::CModelDataNull()); + if (animType == 'ANCS') { + data = CModelData(CAnimRes(aParms.GetACSFile(), aParms.GetCharacter(), head.x40_scale, + aParms.GetInitialAnimation(), false)); + } else { + data = CModelData(CStaticRes(staticId, head.x40_scale)); + } + + if (collisionExtent == CVector3f::Zero() || negativeCollisionExtent) + aabb = data.GetBounds(head.x0_actorHead.x10_transform.GetRotation()); + + return new CScriptActor(mgr.AllocateUniqueId(), head.x0_actorHead.x0_name, info, + head.x0_actorHead.x10_transform, data, aabb, list, mass, zMomentum, hInfo, + dVuln, actParms, looping, active, shaderIdx, xrayAlpha, noThermalHotZ, + castsShadow, scaleAdvancementDelta, materialFlag54); +}