mirror of
https://github.com/PrimeDecomp/prime.git
synced 2025-07-16 02:25:51 +00:00
308 lines
10 KiB
C++
308 lines
10 KiB
C++
#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);
|
|
}
|