2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-08-11 10:59:06 +00:00
metaforce/Runtime/MP1/World/CMetroidBeta.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

302 lines
13 KiB
C++

#include "Runtime/MP1/World/CMetroidBeta.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/Collision/CCollisionActorManager.hpp"
#include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/Particle/CParticleSwoosh.hpp"
#include "Runtime/Weapon/CGameProjectile.hpp"
#include "Runtime/World/CGameArea.hpp"
#include "Runtime/World/CPatternedInfo.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CTeamAiMgr.hpp"
#include "Runtime/World/CWorld.hpp"
#include "Runtime/World/ScriptLoader.hpp"
namespace urde::MP1 {
CMetroidBetaData::CMetroidBetaData(CInputStream& in)
: x0_(in)
, x68_(in)
, xd0_(in.readFloatBig())
, xd4_(in.readFloatBig())
, xd8_(in.readFloatBig())
, xdc_(in.readFloatBig())
, xe0_(in.readFloatBig())
, xe4_(in.readFloatBig())
, xe8_(in.readFloatBig())
, xec_(in.readFloatBig())
, xf0_(in.readFloatBig())
, xf4_(in)
, xf8_(in)
, xfc_(in)
, x100_(in)
, x104_(in)
, x108_24_(in.readBool()) {}
CMetroidBeta::CMetroidBeta(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& aParms,
const CMetroidBetaData& metroidData)
: CPatterned(ECharacter::MetroidBeta, uid, name, EFlavorType::One, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, aParms, EKnockBackVariant::Large)
, x56c_metroidBetaData(metroidData)
, x67c_pathFind(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f)
, x768_colPrim(GetBoundingBox(), GetMaterialList())
, x7b4_(GetModelData()->GetScale())
, x7c0_(GetModelData()->GetScale())
, x7cc_(GetModelData()->GetScale())
, x7e4_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.xf4_}))
, x7f0_(g_SimplePool->GetObj({FOURCC('SWHC'), metroidData.xf8_}))
, x7fc_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.xfc_}))
, x808_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.x100_}))
, x814_(g_SimplePool->GetObj({FOURCC('PART'), metroidData.x104_}))
, x820_(std::make_unique<CElementGen>(x7e4_))
, x824_(std::make_unique<CParticleSwoosh>(x7f0_, 0))
, x828_(std::make_unique<CElementGen>(x7fc_))
, x82c_(std::make_unique<CElementGen>(x808_))
, x830_(std::make_unique<CElementGen>(x814_)) {
x820_->SetParticleEmission(false);
x828_->SetParticleEmission(false);
x82c_->SetParticleEmission(false);
x824_->DoElectricWarmup();
const float scale = 0.75f * GetModelData()->GetScale().y();
const zeus::CVector3f scaleVec(scale, scale, 2.f * scale);
zeus::CAABox box = {-scaleVec, scaleVec};
SetBoundingBox(box);
x768_colPrim.SetBox(box);
}
void CMetroidBeta::Think(float dt, CStateManager& mgr) {
if (CTeamAiMgr::GetTeamAiRole(mgr, x678_teamMgr, GetUniqueId())) {
AddToTeam(mgr);
}
CPatterned::Think(dt, mgr);
x764_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
// sub801c1928(mgr);
// sub801c0da4(dt, mgr);
// sub801c21b4(dt, mgr);
}
void CMetroidBeta::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
switch (msg) {
case EScriptObjectMessage::Registered: {
x450_bodyController->Activate(mgr);
CreateCollisionActorManager(mgr);
//sub801c13d4();
x760_ = GetModelData()->GetAnimationData()->GetLocatorSegId("L_Claw_1"sv);
x761_ = GetModelData()->GetAnimationData()->GetLocatorSegId("R_Claw_1"sv);
break;
}
case EScriptObjectMessage::Activate: {
x764_collisionManager->SetActive(mgr, true);
break;
}
case EScriptObjectMessage::Deactivate: {
x764_collisionManager->SetActive(mgr, false);
break;
}
case EScriptObjectMessage::Deleted: {
x764_collisionManager->Destroy(mgr);
RemoveFromTeam(mgr);
break;
}
case EScriptObjectMessage::Damage:
case EScriptObjectMessage::InvulnDamage: {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
if (TCastToConstPtr<CGameProjectile> proj = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
if (proj->GetOwnerId() != mgr.GetPlayer().GetUniqueId())
break;
// sub801c14b4(proj->GetDamageInfo().GetDamage(), mgr);
const CDamageInfo& dInfo = proj->GetDamageInfo();
if (colAct->GetDamageVulnerability()->WeaponHits(dInfo.GetWeaponMode(), false)) {
if (dInfo.GetWeaponMode().IsCharged() || dInfo.GetWeaponMode().IsComboed() ||
dInfo.GetWeaponMode().GetType() == EWeaponType::Missile) {
x840_31_ = true;
x83c_ += 1.f;
}
KnockBack(proj->GetTranslation() - proj->GetPreviousPos(), mgr, dInfo, EKnockBackType::Radius, false,
dInfo.GetKnockBackPower());
}
if (x840_25_)
x83c_ += 0.1f;
x840_26_ = true;
}
} else if (TCastToConstPtr<CWeapon> weap = mgr.GetObjectById(uid)) {
CDamageInfo info = weap->GetDamageInfo();
info.SetRadius(0.f);
mgr.ApplyDamage(uid, x790_, weap->GetOwnerId(), info,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
}
break;
}
case EScriptObjectMessage::Alert: {
x840_26_ = true;
break;
}
case EScriptObjectMessage::Touched: {
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(uid)) {
if (HealthInfo(mgr)->GetHP() > 0.f && colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId() &&
x420_curDamageRemTime <= 0.f) {
CDamageInfo dInfo = GetContactDamage();
dInfo.SetDamage(0.5f * dInfo.GetDamage());
if (x840_29_ && x840_30_)
dInfo = GetContactDamage();
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), dInfo,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
x420_curDamageRemTime = x424_damageWaitTime;
x840_30_ = false;
}
}
break;
}
case EScriptObjectMessage::InitializedInArea: {
if (x678_teamMgr == kInvalidUniqueId)
x678_teamMgr = CTeamAiMgr::GetTeamAiMgr(*this, mgr);
x67c_pathFind.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaId())->GetPostConstructed()->x10bc_pathArea);
break;
}
case EScriptObjectMessage::SuspendedMove: {
if (x764_collisionManager)
x764_collisionManager->SetMovable(mgr, false);
break;
}
default:
break;
}
}
void CMetroidBeta::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
CPatterned::AddToRenderer(frustum, mgr);
}
void CMetroidBeta::Render(const CStateManager& mgr) const { CPatterned::Render(mgr); }
const CDamageVulnerability* CMetroidBeta::GetDamageVulnerability() const { return CAi::GetDamageVulnerability(); }
const CDamageVulnerability* CMetroidBeta::GetDamageVulnerability(const zeus::CVector3f& vec1,
const zeus::CVector3f& vec2,
const CDamageInfo& dInfo) const {
return CActor::GetDamageVulnerability(vec1, vec2, dInfo);
}
void CMetroidBeta::Touch(CActor& act, CStateManager& mgr) { CPatterned::Touch(act, mgr); }
zeus::CVector3f CMetroidBeta::GetAimPosition(const CStateManager& mgr, float dt) const {
return CPatterned::GetAimPosition(mgr, dt);
}
void CMetroidBeta::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType eType, float dt) {
CPatterned::DoUserAnimEvent(mgr, node, eType, dt);
}
const CCollisionPrimitive* CMetroidBeta::GetCollisionPrimitive() const {
return CPhysicsActor::GetCollisionPrimitive();
}
void CMetroidBeta::CollidedWith(TUniqueId collidee, const CCollisionInfoList& info, CStateManager& mgr) {
CPatterned::CollidedWith(collidee, info, mgr);
}
zeus::CVector3f CMetroidBeta::GetOrigin(const CStateManager& mgr, const CTeamAiRole& role,
const zeus::CVector3f& aimPos) const {
return CAi::GetOrigin(mgr, role, aimPos);
}
void CMetroidBeta::Patrol(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::Patrol(mgr, msg, arg); }
void CMetroidBeta::PathFind(CStateManager& mgr, EStateMsg msg, float arg) { CPatterned::PathFind(mgr, msg, arg); }
void CMetroidBeta::SelectTarget(CStateManager& mgr, EStateMsg msg, float arg) { CAi::SelectTarget(mgr, msg, arg); }
void CMetroidBeta::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::TargetPatrol(mgr, msg, arg);
}
void CMetroidBeta::Generate(CStateManager& mgr, EStateMsg msg, float arg) {
CAi::Generate(mgr, msg, arg);
}
void CMetroidBeta::Attack(CStateManager& mgr, EStateMsg msg, float arg) { CAi::Attack(mgr, msg, arg); }
void CMetroidBeta::TurnAround(CStateManager& mgr, EStateMsg msg, float arg) { CAi::TurnAround(mgr, msg, arg); }
void CMetroidBeta::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) {
CAi::TelegraphAttack(mgr, msg, arg);
}
void CMetroidBeta::WallHang(CStateManager& mgr, EStateMsg msg, float arg) { CAi::WallHang(mgr, msg, arg); }
void CMetroidBeta::SpecialAttack(CStateManager& mgr, EStateMsg msg, float arg) { CAi::SpecialAttack(mgr, msg, arg); }
bool CMetroidBeta::InAttackPosition(CStateManager& mgr, float arg) { return CAi::InAttackPosition(mgr, arg); }
bool CMetroidBeta::Attacked(CStateManager& mgr, float arg) { return CPatterned::Attacked(mgr, arg); }
bool CMetroidBeta::PathShagged(CStateManager& mgr, float arg) { return CPatterned::PathShagged(mgr, arg); }
bool CMetroidBeta::InDetectionRange(CStateManager& mgr, float arg) { return CPatterned::InDetectionRange(mgr, arg); }
bool CMetroidBeta::AnimOver(CStateManager& mgr, float arg) { return CPatterned::AnimOver(mgr, arg); }
bool CMetroidBeta::ShouldAttack(CStateManager& mgr, float arg) { return CAi::ShouldAttack(mgr, arg); }
bool CMetroidBeta::InPosition(CStateManager& mgr, float arg) { return CPatterned::InPosition(mgr, arg); }
bool CMetroidBeta::ShouldTurn(CStateManager& mgr, float arg) { return CAi::ShouldTurn(mgr, arg); }
bool CMetroidBeta::AttackOver(CStateManager& mgr, float arg) { return CAi::AttackOver(mgr, arg); }
bool CMetroidBeta::ShotAt(CStateManager& mgr, float arg) { return CAi::ShotAt(mgr, arg); }
bool CMetroidBeta::ShouldWallHang(CStateManager& mgr, float arg) { return CAi::ShouldWallHang(mgr, arg); }
bool CMetroidBeta::StartAttack(CStateManager& mgr, float arg) { return CAi::StartAttack(mgr, arg); }
bool CMetroidBeta::BreakAttack(CStateManager& mgr, float arg) { return CAi::BreakAttack(mgr, arg); }
bool CMetroidBeta::ShouldSpecialAttack(CStateManager& mgr, float arg) { return CAi::ShouldSpecialAttack(mgr, arg); }
void CMetroidBeta::RenderHitGunEffect() const {}
void CMetroidBeta::RenderHitBallEffect() const {}
static SSphereJointInfo skPelvisInfo[1] {
{"Pelvis", 1.5f},
};
void CMetroidBeta::CreateCollisionActorManager(CStateManager& mgr) {
std::vector<CJointCollisionDescription> joints;
AddSphereJoints(skPelvisInfo, 1, joints);
x764_collisionManager =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), joints, false);
x764_collisionManager->SetActive(mgr, GetActive());
for (u32 i = 0; i < x764_collisionManager->GetNumCollisionActors(); ++i) {
const CJointCollisionDescription& desc = x764_collisionManager->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor>(mgr.ObjectById(desc.GetCollisionActorId()))) {
if (desc.GetName() == "Pelvis"sv)
x790_ = desc.GetCollisionActorId();
}
}
SetCollisionActorHealthAndVulnerability(mgr);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid, EMaterialTypes::Wall, EMaterialTypes::Floor, EMaterialTypes::Ceiling},
{EMaterialTypes::CollisionActor, EMaterialTypes::Player, EMaterialTypes::Character}));
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
x764_collisionManager->AddMaterial(mgr, CMaterialList(EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough));
}
void CMetroidBeta::AddSphereJoints(SSphereJointInfo* sphereJoints, s32 count,
std::vector<CJointCollisionDescription>& joints) {
for (s32 i = 0; i < count; ++i) {
const auto& sphereJoint = sphereJoints[i];
const CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(sphereJoint.name);
if (id.IsInvalid()) {
continue;
}
joints.push_back(CJointCollisionDescription::SphereCollision(id, sphereJoint.radius, sphereJoint.name, 1000.0f));
}
}
void CMetroidBeta::SetCollisionActorHealthAndVulnerability(CStateManager& mgr) {
CHealthInfo* hInfo = HealthInfo(mgr);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x790_)) {
*colAct->HealthInfo(mgr) = *hInfo;
colAct->SetDamageVulnerability(*GetDamageVulnerability());
}
}
void CMetroidBeta::RemoveFromTeam(CStateManager& mgr) {
if (x678_teamMgr == kInvalidUniqueId)
return;
if (TCastToPtr<CTeamAiMgr> teamMgr = mgr.ObjectById(x678_teamMgr)) {
if (teamMgr->IsPartOfTeam(GetUniqueId()))
teamMgr->RemoveTeamAiRole(GetUniqueId());
}
}
void CMetroidBeta::AddToTeam(CStateManager& mgr) {
if (x678_teamMgr == kInvalidUniqueId)
return;
if (TCastToPtr<CTeamAiMgr> teamMgr = mgr.ObjectById(x678_teamMgr)) {
if (!teamMgr->IsPartOfTeam(GetUniqueId()))
teamMgr->AssignTeamAiRole(*this, CTeamAiRole::ETeamAiRole::Ranged, CTeamAiRole::ETeamAiRole::Invalid,
CTeamAiRole::ETeamAiRole::Invalid);
}
}
} // namespace urde::MP1