2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-08-04 15:35:35 +00:00
metaforce/Runtime/World/CScriptPlayerActor.cpp
Lioncash cabbfcc320 CActor: Make AddToRenderer() non-const
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.
2020-04-06 00:52:10 -04:00

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