prime/src/MetroidPrime/ScriptLoader.cpp
Henrique Gemignani Passos Lima 7117050a17 Start ScriptLoader
Former-commit-id: f782c0c72d3bdb85ea076b0878e2b78d56e71f7f
2022-11-14 15:37:44 +02:00

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);
}