mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-08-04 14:55:36 +00:00
This member function alters instance state in a few implementations, so it shouldn't be made const. The state manager parameter also shouldn't be const. Retrieved data from the post constructed instance is further modified in some implementations. This removes the constness on this parameter in order to fix more const_cast usages in a follow-up change.
441 lines
15 KiB
C++
441 lines
15 KiB
C++
#include "Runtime/World/CScriptPlayerActor.hpp"
|
|
|
|
#include "Runtime/CStateManager.hpp"
|
|
#include "Runtime/GameGlobalObjects.hpp"
|
|
#include "Runtime/Camera/CGameCamera.hpp"
|
|
#include "Runtime/Character/CAssetFactory.hpp"
|
|
#include "Runtime/Character/CCharacterFactory.hpp"
|
|
#include "Runtime/Graphics/CBooRenderer.hpp"
|
|
#include "Runtime/MP1/MP1.hpp"
|
|
#include "Runtime/World/CActorParameters.hpp"
|
|
#include "Runtime/World/CLightParameters.hpp"
|
|
#include "Runtime/World/CPlayer.hpp"
|
|
#include "Runtime/World/CWorld.hpp"
|
|
|
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
|
|
|
namespace urde {
|
|
CScriptPlayerActor::CScriptPlayerActor(TUniqueId uid, std::string_view name, const CEntityInfo& info,
|
|
const zeus::CTransform& xf, const CAnimRes& animRes, CModelData&& mData,
|
|
const zeus::CAABox& aabox, bool setBoundingBox, const CMaterialList& list,
|
|
float mass, float zMomentum, const CHealthInfo& hInfo,
|
|
const CDamageVulnerability& dVuln, const CActorParameters& aParams, bool loop,
|
|
bool active, u32 flags, CPlayerState::EBeamId beam)
|
|
: CScriptActor(uid, name, info, xf, std::move(mData), aabox, mass, zMomentum, list, hInfo, dVuln, aParams, loop, active,
|
|
0, 1.f, false, false, false, false)
|
|
, x2e8_suitRes(animRes)
|
|
, x304_beam(beam)
|
|
, x350_flags(flags) {
|
|
x354_24_setBoundingBox = setBoundingBox;
|
|
x354_29_loading = true;
|
|
x354_30_enableLoading = true;
|
|
CMaterialList exclude = GetMaterialFilter().GetExcludeList();
|
|
CMaterialList include = GetMaterialFilter().GetIncludeList();
|
|
include.Add(EMaterialTypes::Player);
|
|
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
|
|
|
|
SetActorLights(aParams.GetLightParameters().MakeActorLights());
|
|
xe7_29_drawEnabled = true;
|
|
x2e3_24_isPlayerActor = true;
|
|
|
|
_CreateReflectionCube();
|
|
}
|
|
|
|
u32 CScriptPlayerActor::GetSuitCharIdx(const CStateManager& mgr, CPlayerState::EPlayerSuit suit) const {
|
|
if (mgr.GetPlayerState()->IsFusionEnabled()) {
|
|
switch (suit) {
|
|
case CPlayerState::EPlayerSuit::Power:
|
|
return 4;
|
|
case CPlayerState::EPlayerSuit::Varia:
|
|
return 7;
|
|
case CPlayerState::EPlayerSuit::Gravity:
|
|
return 6;
|
|
case CPlayerState::EPlayerSuit::Phazon:
|
|
return 8;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
return u32(suit);
|
|
}
|
|
|
|
u32 CScriptPlayerActor::GetNextSuitCharIdx(const CStateManager& mgr) const {
|
|
CPlayerState::EPlayerSuit nextSuit = CPlayerState::EPlayerSuit::Phazon;
|
|
|
|
if (x350_flags & 0x2) {
|
|
switch (x308_suit) {
|
|
case CPlayerState::EPlayerSuit::Gravity:
|
|
nextSuit = CPlayerState::EPlayerSuit::Varia;
|
|
break;
|
|
case CPlayerState::EPlayerSuit::Phazon:
|
|
nextSuit = CPlayerState::EPlayerSuit::Gravity;
|
|
break;
|
|
case CPlayerState::EPlayerSuit::Varia:
|
|
default:
|
|
nextSuit = CPlayerState::EPlayerSuit::Power;
|
|
break;
|
|
}
|
|
} else {
|
|
switch (x308_suit) {
|
|
case CPlayerState::EPlayerSuit::Power:
|
|
nextSuit = CPlayerState::EPlayerSuit::Varia;
|
|
break;
|
|
case CPlayerState::EPlayerSuit::Varia:
|
|
nextSuit = CPlayerState::EPlayerSuit::Gravity;
|
|
break;
|
|
case CPlayerState::EPlayerSuit::Gravity:
|
|
nextSuit = CPlayerState::EPlayerSuit::Phazon;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return GetSuitCharIdx(mgr, nextSuit);
|
|
}
|
|
|
|
void CScriptPlayerActor::LoadSuit(u32 charIdx) {
|
|
if (charIdx != x310_loadedCharIdx) {
|
|
TToken<CCharacterFactory> fac = g_CharFactoryBuilder->GetFactory(x2e8_suitRes);
|
|
const CCharacterInfo& chInfo = fac->GetCharInfo(charIdx);
|
|
x320_suitModel = g_SimplePool->GetObj({FOURCC('CMDL'), chInfo.GetModelId()});
|
|
x324_suitSkin = g_SimplePool->GetObj({FOURCC('CSKR'), chInfo.GetSkinRulesId()});
|
|
x354_28_suitModelLoading = true;
|
|
x310_loadedCharIdx = charIdx;
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::LoadBeam(CPlayerState::EBeamId beam) {
|
|
if (beam != x30c_setBeamId) {
|
|
x31c_beamModel = g_SimplePool->GetObj({FOURCC('CMDL'), g_tweakPlayerRes->GetBeamCineModel(beam)});
|
|
x354_27_beamModelLoading = true;
|
|
x30c_setBeamId = beam;
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::PumpBeamModel(CStateManager& mgr) {
|
|
if (!x31c_beamModel || !x31c_beamModel.IsLoaded())
|
|
return;
|
|
BuildBeamModelData();
|
|
x314_beamModelData->Touch(mgr, 0);
|
|
mgr.GetWorld()->CycleLoadPauseState();
|
|
x31c_beamModel = TLockedToken<CModel>();
|
|
x354_27_beamModelLoading = false;
|
|
}
|
|
|
|
void CScriptPlayerActor::BuildBeamModelData() {
|
|
x314_beamModelData = std::make_unique<CModelData>(
|
|
CStaticRes(g_tweakPlayerRes->GetBeamCineModel(x30c_setBeamId), x2e8_suitRes.GetScale()));
|
|
}
|
|
|
|
void CScriptPlayerActor::PumpSuitModel(CStateManager& mgr) {
|
|
if (!x320_suitModel || !x320_suitModel.IsLoaded() || !x324_suitSkin || !x324_suitSkin.IsLoaded())
|
|
return;
|
|
|
|
x320_suitModel->Touch(0);
|
|
mgr.GetWorld()->CycleLoadPauseState();
|
|
|
|
bool didSetup = false;
|
|
if (x354_26_deferOfflineModelData) {
|
|
didSetup = true;
|
|
x354_26_deferOfflineModelData = false;
|
|
SetupOfflineModelData();
|
|
} else if (x354_25_deferOnlineModelData) {
|
|
didSetup = true;
|
|
x354_25_deferOnlineModelData = false;
|
|
SetupOnlineModelData();
|
|
}
|
|
|
|
if (didSetup) {
|
|
x354_28_suitModelLoading = false;
|
|
x320_suitModel = TLockedToken<CModel>();
|
|
x324_suitSkin = TLockedToken<CSkinRules>();
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::SetupOfflineModelData() {
|
|
x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx);
|
|
x318_suitModelData = std::make_unique<CModelData>(x2e8_suitRes);
|
|
if (!static_cast<MP1::CMain&>(*g_Main).GetScreenFading()) {
|
|
x328_backupModelData = x64_modelData->GetAnimationData()->GetModelData();
|
|
x348_deallocateBackupCountdown = 2;
|
|
}
|
|
x64_modelData->GetAnimationData()->SubstituteModelData(x318_suitModelData->GetAnimationData()->GetModelData());
|
|
}
|
|
|
|
void CScriptPlayerActor::SetupOnlineModelData() {
|
|
if (x310_loadedCharIdx != x2e8_suitRes.GetCharacterNodeId() || !x64_modelData || !x64_modelData->HasAnimData()) {
|
|
x2e8_suitRes.SetCharacterNodeId(x310_loadedCharIdx);
|
|
SetModelData(std::make_unique<CModelData>(x2e8_suitRes));
|
|
CAnimPlaybackParms parms(x2e8_suitRes.GetDefaultAnim(), -1, 1.f, true);
|
|
x64_modelData->GetAnimationData()->SetAnimation(parms, false);
|
|
if (x354_24_setBoundingBox)
|
|
SetBoundingBox(x64_modelData->GetBounds(GetTransform().getRotation()));
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::Think(float dt, CStateManager& mgr) {
|
|
auto& pState = *mgr.GetPlayerState();
|
|
|
|
if (x354_31_deferOnlineLoad) {
|
|
x354_25_deferOnlineModelData = true;
|
|
x354_31_deferOnlineLoad = false;
|
|
x308_suit = pState.GetCurrentSuitRaw();
|
|
LoadSuit(GetSuitCharIdx(mgr, x308_suit));
|
|
}
|
|
|
|
if (x354_30_enableLoading) {
|
|
if (!(x350_flags & 0x1)) {
|
|
u32 tmpIdx = GetSuitCharIdx(mgr, pState.GetCurrentSuitRaw());
|
|
if (tmpIdx != x310_loadedCharIdx) {
|
|
SetModelData(std::make_unique<CModelData>(CModelData::CModelDataNull()));
|
|
LoadSuit(tmpIdx);
|
|
x354_25_deferOnlineModelData = true;
|
|
}
|
|
}
|
|
|
|
LoadBeam(x304_beam != CPlayerState::EBeamId::Invalid ? x304_beam : pState.GetCurrentBeam());
|
|
|
|
if (x354_27_beamModelLoading)
|
|
PumpBeamModel(mgr);
|
|
|
|
if (x354_28_suitModelLoading)
|
|
PumpSuitModel(mgr);
|
|
|
|
if (!x354_29_loading) {
|
|
if (x354_28_suitModelLoading || x354_27_beamModelLoading || !x64_modelData || x64_modelData->IsNull() ||
|
|
!x64_modelData->IsLoaded(0))
|
|
x354_29_loading = true;
|
|
}
|
|
|
|
if (x354_29_loading && !x354_28_suitModelLoading && !x354_27_beamModelLoading && x64_modelData &&
|
|
!x64_modelData->IsNull() && x64_modelData->IsLoaded(0)) {
|
|
if (x355_24_areaTrackingLoad) {
|
|
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId);
|
|
--const_cast<CGameArea::CPostConstructed*>(area->GetPostConstructed())->x113c_playerActorsLoading;
|
|
x355_24_areaTrackingLoad = false;
|
|
}
|
|
x354_29_loading = false;
|
|
SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None);
|
|
}
|
|
}
|
|
|
|
if (x2e8_suitRes.GetCharacterNodeId() == 3) {
|
|
if (!x338_phazonIndirectTexture)
|
|
x338_phazonIndirectTexture = g_SimplePool->GetObj("PhazonIndirectTexture");
|
|
} else {
|
|
if (x338_phazonIndirectTexture)
|
|
x338_phazonIndirectTexture = TLockedToken<CTexture>();
|
|
}
|
|
|
|
if (x338_phazonIndirectTexture) {
|
|
x34c_phazonOffsetAngle += 0.03f;
|
|
x34c_phazonOffsetAngle = zeus::CRelAngle(x34c_phazonOffsetAngle).asRel();
|
|
}
|
|
|
|
CScriptActor::Think(dt, mgr);
|
|
}
|
|
|
|
void CScriptPlayerActor::SetupEnvFx(CStateManager& mgr, bool set) {
|
|
if (set) {
|
|
if (mgr.GetWorld()->GetNeededEnvFx() == EEnvFxType::Rain)
|
|
if (x64_modelData && !x64_modelData->IsNull())
|
|
if (mgr.GetEnvFxManager()->GetRainMagnitude() != 0.f)
|
|
mgr.GetActorModelParticles()->AddRainSplashGenerator(*this, mgr, 250, 10, 1.2f);
|
|
} else {
|
|
mgr.GetActorModelParticles()->RemoveRainSplashGenerator(*this);
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::SetIntoStateManager(CStateManager& mgr, bool set) {
|
|
if (!set && mgr.GetPlayerActorHead() == x8_uid) {
|
|
mgr.SetPlayerActorHead(x356_nextPlayerActor);
|
|
x356_nextPlayerActor = kInvalidUniqueId;
|
|
} else {
|
|
TUniqueId paId = mgr.GetPlayerActorHead();
|
|
CScriptPlayerActor* other = nullptr;
|
|
while (paId != kInvalidUniqueId) {
|
|
if (paId == x8_uid) {
|
|
if (!set && other) {
|
|
other->x356_nextPlayerActor = x356_nextPlayerActor;
|
|
x356_nextPlayerActor = kInvalidUniqueId;
|
|
}
|
|
return;
|
|
}
|
|
|
|
TCastToPtr<CScriptActor> act = mgr.ObjectById(paId);
|
|
if (act && act->IsPlayerActor()) {
|
|
other = static_cast<CScriptPlayerActor*>(act.GetPtr());
|
|
paId = other->x356_nextPlayerActor;
|
|
} else {
|
|
paId = kInvalidUniqueId;
|
|
x356_nextPlayerActor = kInvalidUniqueId;
|
|
}
|
|
}
|
|
|
|
if (set) {
|
|
x356_nextPlayerActor = mgr.GetPlayerActorHead();
|
|
mgr.SetPlayerActorHead(x8_uid);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
|
|
switch (msg) {
|
|
case EScriptObjectMessage::InitializedInArea:
|
|
x354_31_deferOnlineLoad = true;
|
|
if (x350_flags & 0x8) {
|
|
const CGameArea* area = mgr.GetWorld()->GetAreaAlways(x4_areaId);
|
|
++const_cast<CGameArea::CPostConstructed*>(area->GetPostConstructed())->x113c_playerActorsLoading;
|
|
x355_24_areaTrackingLoad = true;
|
|
}
|
|
if (GetActive()) {
|
|
SetupEnvFx(mgr, true);
|
|
SetIntoStateManager(mgr, true);
|
|
}
|
|
break;
|
|
case EScriptObjectMessage::Activate:
|
|
if (!GetActive()) {
|
|
if (x350_flags & 0x1)
|
|
LoadSuit(GetNextSuitCharIdx(mgr));
|
|
SetIntoStateManager(mgr, true);
|
|
SetupEnvFx(mgr, true);
|
|
x354_30_enableLoading = true;
|
|
}
|
|
break;
|
|
case EScriptObjectMessage::Increment:
|
|
if (x350_flags & 0x1) {
|
|
x354_25_deferOnlineModelData = false;
|
|
x354_26_deferOfflineModelData = true;
|
|
mgr.GetPlayer().AsyncLoadSuit(mgr);
|
|
}
|
|
break;
|
|
case EScriptObjectMessage::Deactivate:
|
|
if (GetActive()) {
|
|
if (!(x350_flags & 0x10))
|
|
SetIntoStateManager(mgr, false);
|
|
SetupEnvFx(mgr, false);
|
|
}
|
|
if (!(x350_flags & 0x4))
|
|
break;
|
|
[[fallthrough]];
|
|
case EScriptObjectMessage::Reset:
|
|
if (GetActive() || msg == EScriptObjectMessage::Reset) {
|
|
x30c_setBeamId = CPlayerState::EBeamId::Invalid;
|
|
x310_loadedCharIdx = -1;
|
|
x314_beamModelData.reset();
|
|
x318_suitModelData.reset();
|
|
x31c_beamModel = TLockedToken<CModel>();
|
|
x320_suitModel = TLockedToken<CModel>();
|
|
x324_suitSkin = TLockedToken<CSkinRules>();
|
|
x328_backupModelData = TLockedToken<CSkinnedModel>();
|
|
x338_phazonIndirectTexture = TLockedToken<CTexture>();
|
|
x348_deallocateBackupCountdown = 0;
|
|
x350_flags &= ~0x1;
|
|
x354_25_deferOnlineModelData = false;
|
|
x354_26_deferOfflineModelData = false;
|
|
x354_27_beamModelLoading = false;
|
|
x354_28_suitModelLoading = false;
|
|
x354_30_enableLoading = false;
|
|
SetModelData(std::make_unique<CModelData>(CModelData::CModelDataNull()));
|
|
}
|
|
break;
|
|
case EScriptObjectMessage::Deleted:
|
|
SetIntoStateManager(mgr, false);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
CScriptActor::AcceptScriptMsg(msg, uid, mgr);
|
|
}
|
|
|
|
void CScriptPlayerActor::SetActive(bool active) {
|
|
CActor::SetActive(active);
|
|
xe7_29_drawEnabled = true;
|
|
}
|
|
|
|
void CScriptPlayerActor::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
|
|
if (x328_backupModelData) {
|
|
if (x348_deallocateBackupCountdown == 0)
|
|
x328_backupModelData = TLockedToken<CSkinnedModel>();
|
|
else
|
|
--x348_deallocateBackupCountdown;
|
|
}
|
|
if (x2e8_suitRes.GetCharacterNodeId() == 3)
|
|
g_Renderer->AllocatePhazonSuitMaskTexture();
|
|
xb4_drawFlags.m_extendedShader = EExtendedShader::LightingCubeReflection;
|
|
CScriptActor::PreRender(mgr, frustum);
|
|
}
|
|
|
|
void CScriptPlayerActor::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
|
|
TouchModels_Internal(mgr);
|
|
if (GetActive()) {
|
|
CActor::AddToRenderer(frustum, mgr);
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::Render(const CStateManager& mgr) const {
|
|
CBooModel::SetReflectionCube(m_reflectionCube);
|
|
|
|
bool phazonSuit = x2e8_suitRes.GetCharacterNodeId() == 3;
|
|
if (phazonSuit) {
|
|
// Draw into alpha buffer
|
|
CModelFlags flags = xb4_drawFlags;
|
|
flags.x4_color = zeus::skWhite;
|
|
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
|
|
CModelData::EWhichModel which = CModelData::GetRenderingModel(mgr);
|
|
x64_modelData->Render(which, x34_transform, x90_actorLights.get(), flags);
|
|
}
|
|
|
|
CPhysicsActor::Render(mgr);
|
|
|
|
if (x314_beamModelData && !x314_beamModelData->IsNull() && x64_modelData && !x64_modelData->IsNull()) {
|
|
zeus::CTransform modelXf = GetTransform() * x64_modelData->GetScaledLocatorTransform("GUN_LCTR");
|
|
CModelFlags flags(5, 0, 3, zeus::skWhite);
|
|
flags.m_extendedShader = EExtendedShader::SolidColorBackfaceCullLEqualAlphaOnly;
|
|
x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags);
|
|
flags.m_extendedShader = EExtendedShader::LightingCubeReflection;
|
|
flags.x4_color = zeus::CColor{1.f, xb4_drawFlags.x4_color.a()};
|
|
x314_beamModelData->Render(mgr, modelXf, x90_actorLights.get(), flags);
|
|
}
|
|
|
|
if (phazonSuit) {
|
|
zeus::CVector3f vecFromCam =
|
|
GetBoundingBox().center() - mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation();
|
|
float radius = zeus::clamp(0.25f, (6.f - vecFromCam.magnitude()) / 6.f, 2.f);
|
|
float offsetX = std::sin(x34c_phazonOffsetAngle);
|
|
float offsetY = std::sin(x34c_phazonOffsetAngle) * 0.5f;
|
|
g_Renderer->DrawPhazonSuitIndirectEffect(zeus::CColor(0.1f, 1.f), x338_phazonIndirectTexture, zeus::skWhite,
|
|
radius, 0.05f, offsetX, offsetY);
|
|
}
|
|
}
|
|
|
|
void CScriptPlayerActor::TouchModels_Internal(const CStateManager& mgr) const {
|
|
if (x64_modelData && !x64_modelData->IsNull())
|
|
x64_modelData->Touch(mgr, 0);
|
|
|
|
if (x318_suitModelData && !x318_suitModelData->IsNull())
|
|
x318_suitModelData->Touch(mgr, 0);
|
|
|
|
if (!x354_27_beamModelLoading)
|
|
if (x314_beamModelData && !x314_beamModelData->IsNull())
|
|
x314_beamModelData->Touch(mgr, 0);
|
|
}
|
|
|
|
void CScriptPlayerActor::TouchModels(const CStateManager& mgr) const {
|
|
TouchModels_Internal(mgr);
|
|
TUniqueId paId = x356_nextPlayerActor;
|
|
while (paId != kInvalidUniqueId) {
|
|
TCastToConstPtr<CScriptActor> act = mgr.GetObjectById(paId);
|
|
if (act && act->IsPlayerActor()) {
|
|
const auto* pa = static_cast<const CScriptPlayerActor*>(act.GetPtr());
|
|
pa->TouchModels_Internal(mgr);
|
|
paId = pa->x356_nextPlayerActor;
|
|
} else {
|
|
paId = kInvalidUniqueId;
|
|
}
|
|
}
|
|
}
|
|
} // namespace urde
|