mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-12-16 01:37:00 +00:00
Start ScriptLoader
This commit is contained in:
307
src/MetroidPrime/ScriptLoader.cpp
Normal file
307
src/MetroidPrime/ScriptLoader.cpp
Normal file
@@ -0,0 +1,307 @@
|
||||
#include "MetroidPrime/ScriptLoader.hpp"
|
||||
|
||||
#include "MetroidPrime/CActorParameters.hpp"
|
||||
#include "MetroidPrime/CAnimationParameters.hpp"
|
||||
#include "MetroidPrime/CDamageVulnerability.hpp"
|
||||
#include "MetroidPrime/CGrappleParameters.hpp"
|
||||
#include "MetroidPrime/CHealthInfo.hpp"
|
||||
#include "MetroidPrime/CStateManager.hpp"
|
||||
#include "MetroidPrime/CWorld.hpp"
|
||||
#include "MetroidPrime/Player/CPlayerState.hpp"
|
||||
|
||||
#include "MetroidPrime/ScriptObjects/CScriptCameraHintTrigger.hpp"
|
||||
#include "MetroidPrime/ScriptObjects/CScriptDamageableTrigger.hpp"
|
||||
#include "MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp"
|
||||
#include "MetroidPrime/ScriptObjects/CScriptTrigger.hpp"
|
||||
|
||||
#include "Kyoto/Alloc/CMemory.hpp"
|
||||
#include "Kyoto/Math/CQuaternion.hpp"
|
||||
#include "Kyoto/Math/CRelAngle.hpp"
|
||||
#include "Kyoto/Streams/CInputStream.hpp"
|
||||
|
||||
static CTransform4f ConvertEditorEulerToTransform4f(const CVector3f& orientation,
|
||||
const CVector3f& position) {
|
||||
CQuaternion quat = CQuaternion::ZRotation(CRelAngle::FromDegrees(orientation.GetZ())) *
|
||||
CQuaternion::YRotation(CRelAngle::FromDegrees(orientation.GetY())) *
|
||||
CQuaternion::XRotation(CRelAngle::FromDegrees(orientation.GetX()));
|
||||
|
||||
CMatrix3f mat = quat.BuildTransform();
|
||||
// return CTransform4f(mat, position);
|
||||
return CTransform4f(mat.GetRow(kDX), mat.GetRow(kDY), mat.GetRow(kDZ), position);
|
||||
}
|
||||
|
||||
static CTransform4f LoadEditorTransform(CInputStream& in) {
|
||||
CVector3f position(in);
|
||||
CVector3f orientation(in);
|
||||
return ConvertEditorEulerToTransform4f(orientation, position);
|
||||
}
|
||||
|
||||
static CTransform4f LoadEditorTransformPivotOnly(CInputStream& in) {
|
||||
CVector3f position(in);
|
||||
CVector3f orientation(in);
|
||||
orientation.SetY(0.0f);
|
||||
orientation.SetX(0.0f);
|
||||
return ConvertEditorEulerToTransform4f(orientation, position);
|
||||
}
|
||||
|
||||
struct SActorHead {
|
||||
rstl::string x0_name;
|
||||
CTransform4f x10_transform;
|
||||
|
||||
SActorHead(CInputStream& in, CStateManager& stateMgr);
|
||||
};
|
||||
|
||||
SActorHead::SActorHead(CInputStream& in, CStateManager& stateMgr)
|
||||
: x0_name(stateMgr.HashInstanceName(in)), x10_transform(LoadEditorTransform(in)) {}
|
||||
|
||||
struct SScaledActorHead {
|
||||
SActorHead x0_actorHead;
|
||||
CVector3f x40_scale;
|
||||
|
||||
SScaledActorHead(CInputStream& in, CStateManager& stateMgr);
|
||||
};
|
||||
|
||||
SScaledActorHead::SScaledActorHead(CInputStream& in, CStateManager& stateMgr)
|
||||
: x0_actorHead(in, stateMgr), x40_scale(in) {}
|
||||
|
||||
static CAnimationParameters LoadAnimationParameters(CInputStream& in) {
|
||||
CAssetId ancs = in.Get< CAssetId >();
|
||||
int charIdx = in.ReadLong();
|
||||
uint defaultAnim = in.ReadLong();
|
||||
return CAnimationParameters(ancs, charIdx, defaultAnim);
|
||||
}
|
||||
|
||||
static CLightParameters LoadLightParameters(CInputStream& in) {
|
||||
int propCount = in.ReadLong();
|
||||
if (propCount != 14) {
|
||||
return CLightParameters::None();
|
||||
}
|
||||
|
||||
bool a = in.Get< bool >();
|
||||
float b = in.Get< float >();
|
||||
CLightParameters::EShadowTessellation shadowTess =
|
||||
CLightParameters::EShadowTessellation(in.Get< int >());
|
||||
float d = in.Get< float >();
|
||||
float e = in.Get< float >();
|
||||
|
||||
CColor noLightsAmbient(in);
|
||||
|
||||
bool makeLights = in.ReadBool();
|
||||
CLightParameters::EWorldLightingOptions lightOpts =
|
||||
CLightParameters::EWorldLightingOptions(in.ReadLong());
|
||||
CLightParameters::ELightRecalculationOptions recalcOpts =
|
||||
CLightParameters::ELightRecalculationOptions(in.ReadLong());
|
||||
|
||||
CVector3f actorPosBias(in);
|
||||
|
||||
int maxDynamicLights = -1;
|
||||
int maxAreaLights = -1;
|
||||
if (propCount >= 12) {
|
||||
maxDynamicLights = in.ReadLong();
|
||||
maxAreaLights = in.ReadLong();
|
||||
}
|
||||
|
||||
bool ambientChannelOverflow = false;
|
||||
if (propCount >= 13)
|
||||
ambientChannelOverflow = in.ReadBool();
|
||||
|
||||
int layerIdx = 0;
|
||||
if (propCount >= 14)
|
||||
layerIdx = in.ReadLong();
|
||||
|
||||
return CLightParameters(a, b, shadowTess, d, e, noLightsAmbient, makeLights, lightOpts,
|
||||
recalcOpts, actorPosBias, maxDynamicLights, maxAreaLights,
|
||||
ambientChannelOverflow, layerIdx);
|
||||
}
|
||||
|
||||
static CScannableParameters LoadScannableParameters(CInputStream& in) {
|
||||
int propCount = in.ReadLong();
|
||||
if (propCount != 1) {
|
||||
return CScannableParameters(kInvalidAssetId);
|
||||
} else {
|
||||
return CScannableParameters(in.Get< CAssetId >());
|
||||
}
|
||||
}
|
||||
|
||||
static CVisorParameters LoadVisorParameters(CInputStream& in) {
|
||||
u32 propCount = in.ReadLong();
|
||||
if (propCount >= 1 && propCount <= 3) {
|
||||
bool b1 = in.ReadBool();
|
||||
bool scanPassthrough = false;
|
||||
u8 mask = 0xf;
|
||||
if (propCount > 2)
|
||||
scanPassthrough = in.ReadBool();
|
||||
if (propCount >= 2)
|
||||
mask = u8(in.ReadLong());
|
||||
return CVisorParameters(mask, b1, scanPassthrough);
|
||||
}
|
||||
return CVisorParameters(0xf, false, false);
|
||||
}
|
||||
|
||||
static CActorParameters LoadActorParameters(CInputStream&) {}
|
||||
|
||||
static CGrappleParameters LoadGrappleParameters(CInputStream& in) {
|
||||
in.ReadLong();
|
||||
float a = in.ReadFloat();
|
||||
float b = in.ReadFloat();
|
||||
float c = in.ReadFloat();
|
||||
float d = in.ReadFloat();
|
||||
float e = in.ReadFloat();
|
||||
float f = in.ReadFloat();
|
||||
float g = in.ReadFloat();
|
||||
float h = in.ReadFloat();
|
||||
float i = in.ReadFloat();
|
||||
float j = in.ReadFloat();
|
||||
float k = in.ReadFloat();
|
||||
bool l = in.ReadBool();
|
||||
return CGrappleParameters(a, b, c, d, e, f, g, h, i, j, k, l);
|
||||
}
|
||||
|
||||
static int LoadParameterFlags(CInputStream& in) {
|
||||
int count = in.ReadLong();
|
||||
int ret = 0;
|
||||
for (int i = 0; i < count; ++i)
|
||||
if (in.ReadBool())
|
||||
ret |= 1 << i;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CEntity* ScriptLoader::LoadTrigger(CStateManager& mgr, CInputStream& in, int propCount,
|
||||
const CEntityInfo& info) {
|
||||
if (propCount != 9)
|
||||
return nullptr;
|
||||
|
||||
rstl::string name(mgr.HashInstanceName(in));
|
||||
CVector3f position(in);
|
||||
CVector3f extent(in);
|
||||
CDamageInfo dInfo(in);
|
||||
CVector3f forceVec(in);
|
||||
ETriggerFlags flags = ETriggerFlags(in.ReadLong());
|
||||
bool active = in.Get< bool >();
|
||||
bool b2 = in.Get< bool >();
|
||||
bool b3 = in.Get< bool >();
|
||||
|
||||
CAABox box(CVector3f(-(extent.GetX()), -(extent.GetY() * 0.5f), -(extent.GetZ() * 0.5f)),
|
||||
CVector3f((extent.GetX() * 0.5f), (extent.GetY() * 0.5f), (extent.GetZ() * 0.5f)));
|
||||
|
||||
CVector3f orientedForce =
|
||||
mgr.GetWorld()->GetAreaAlways(info.GetAreaId()).GetTM().Rotate(forceVec);
|
||||
|
||||
return new CScriptTrigger(mgr.AllocateUniqueId(), name, info, position, box, dInfo, orientedForce,
|
||||
flags, active, b2, b3);
|
||||
}
|
||||
|
||||
CEntity* ScriptLoader::LoadCameraHintTrigger(CStateManager& mgr, CInputStream& in, int propCount,
|
||||
const CEntityInfo& info) {
|
||||
if (propCount != 7)
|
||||
return nullptr;
|
||||
|
||||
SActorHead aHead(in, mgr);
|
||||
CVector3f scale = CVector3f(in) * 0.5f;
|
||||
bool active = in.ReadBool();
|
||||
bool deactivateOnEnter = in.ReadBool();
|
||||
bool deactivateOnExit = in.ReadBool();
|
||||
|
||||
if (aHead.x10_transform.GetRotation() == CTransform4f::Identity()) {
|
||||
CAABox box(CVector3f(-(scale.GetX()), -(scale.GetY()), -(scale.GetZ())),
|
||||
CVector3f((scale.GetX()), (scale.GetY()), (scale.GetZ())));
|
||||
return new CScriptTrigger(mgr.AllocateUniqueId(), aHead.x0_name, info,
|
||||
aHead.x10_transform.GetTranslation(), box, CDamageInfo(),
|
||||
CVector3f::Zero(), kTFL_DetectPlayer, active, deactivateOnEnter,
|
||||
deactivateOnExit);
|
||||
} else {
|
||||
return new CScriptCameraHintTrigger(mgr.AllocateUniqueId(), active, aHead.x0_name, info, scale,
|
||||
aHead.x10_transform, deactivateOnEnter, deactivateOnExit);
|
||||
}
|
||||
}
|
||||
|
||||
static int ClassifyVector(const CVector3f& dir) {
|
||||
CVector3f absDir(fabsf(dir.GetX()), fabsf(dir.GetY()), fabsf(dir.GetZ()));
|
||||
int max = (absDir.GetX() > absDir.GetY() ? 0 : 1);
|
||||
max = (absDir[max] > absDir.GetZ() ? max : 2);
|
||||
|
||||
bool positive = (absDir[max] == dir[max]);
|
||||
if (max == 0)
|
||||
return (positive ? 0x08 : 0x04);
|
||||
else if (max == 1)
|
||||
return (positive ? 0x01 : 0x02);
|
||||
else if (max == 2)
|
||||
return (positive ? 0x10 : 0x20);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int TransformDamageableTriggerFlags(CStateManager& mgr, TAreaId aId, uint flags) {
|
||||
const CGameArea& area = mgr.GetWorld()->GetAreaAlways(aId);
|
||||
CTransform4f rotation = area.GetTM().GetRotation();
|
||||
|
||||
u32 ret = 0;
|
||||
if (flags & 0x01)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Forward());
|
||||
if (flags & 0x02)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Back());
|
||||
if (flags & 0x04)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Left());
|
||||
if (flags & 0x08)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Right());
|
||||
if (flags & 0x10)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Up());
|
||||
if (flags & 0x20)
|
||||
ret |= ClassifyVector(rotation * CVector3f::Down());
|
||||
return ret;
|
||||
}
|
||||
|
||||
CEntity* ScriptLoader::LoadDamageableTrigger(CStateManager& mgr, CInputStream& in, int propCount,
|
||||
const CEntityInfo& info) {
|
||||
if (propCount != 12)
|
||||
return nullptr;
|
||||
|
||||
rstl::string name = mgr.HashInstanceName(in);
|
||||
CVector3f position(in);
|
||||
CVector3f volume(in);
|
||||
|
||||
CHealthInfo hInfo(in);
|
||||
CDamageVulnerability dVuln(in);
|
||||
int triggerFlags = TransformDamageableTriggerFlags(mgr, info.GetAreaId(), in.Get< int >());
|
||||
CAssetId patternTex1 = in.Get< CAssetId >();
|
||||
CAssetId patternTex2 = in.Get< CAssetId >();
|
||||
CAssetId colorTex = in.Get< CAssetId >();
|
||||
CScriptDamageableTrigger::ECanOrbit canOrbit =
|
||||
CScriptDamageableTrigger::ECanOrbit(in.Get< bool >());
|
||||
bool active = in.Get< bool >();
|
||||
CVisorParameters vParms = LoadVisorParameters(in);
|
||||
return new CScriptDamageableTrigger(mgr.AllocateUniqueId(), name, info, position, volume, hInfo,
|
||||
dVuln, triggerFlags, patternTex1, patternTex2, colorTex,
|
||||
canOrbit, active, vParms);
|
||||
}
|
||||
|
||||
// static CFluidUVMotion LoadFluidUVMotion(CInputStream&) {}
|
||||
|
||||
CEntity* ScriptLoader::LoadSpawnPoint(CStateManager& mgr, CInputStream& in, int propCount,
|
||||
const CEntityInfo& info) {
|
||||
if (propCount < 35)
|
||||
return nullptr;
|
||||
|
||||
rstl::string name = mgr.HashInstanceName(in);
|
||||
CVector3f position(in);
|
||||
CVector3f rotation(in);
|
||||
|
||||
rstl::reserved_vector< int, int(CPlayerState::kIT_Max) > itemCounts;
|
||||
for (int i = 0; i < propCount - 6; ++i)
|
||||
itemCounts.push_back(in.ReadLong());
|
||||
|
||||
for (int i = itemCounts.size(); i < itemCounts.capacity(); ++i) {
|
||||
itemCounts.push_back(0);
|
||||
}
|
||||
|
||||
bool defaultSpawn = in.Get< bool >();
|
||||
bool active = in.Get< bool >();
|
||||
bool morphed = false;
|
||||
if (propCount >= 35)
|
||||
morphed = in.Get< bool >();
|
||||
|
||||
return new CScriptSpawnPoint(mgr.AllocateUniqueId(), name, info,
|
||||
ConvertEditorEulerToTransform4f(rotation, position),
|
||||
rstl::reserved_vector< int, int(CPlayerState::kIT_Max) >(itemCounts),
|
||||
defaultSpawn, active, morphed);
|
||||
}
|
||||
Reference in New Issue
Block a user