metaforce/Runtime/Weapon/CGrappleArm.cpp

616 lines
22 KiB
C++

#include "Runtime/Weapon/CGrappleArm.hpp"
#include <array>
#include "Runtime/CDependencyGroup.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Camera/CGameCamera.hpp"
#include "Runtime/Graphics/CSkinnedModel.hpp"
#include "Runtime/Graphics/CVertexMorphEffect.hpp"
#include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
namespace metaforce {
float CGrappleArm::g_GrappleBeamAnglePhaseDelta = 0.875f;
float CGrappleArm::g_GrappleBeamXWaveAmplitude = 0.25f;
float CGrappleArm::g_GrappleBeamZWaveAmplitude = 0.125f;
float CGrappleArm::g_GrappleBeamSpeed = 5.f;
CGrappleArm::CGrappleArm(const zeus::CVector3f& scale)
: x0_grappleArmModel(CAnimRes(g_tweakGunRes->x8_grappleArm, 0, scale, 41, false))
, xa0_grappleGearModel(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrappleGear"), scale))
, xec_grapNoz1Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz1"), scale))
, x138_grapNoz2Model(CStaticRes(NWeaponTypes::get_asset_id_from_name("GrapNoz2"), scale))
, x184_grappleArm(g_SimplePool->GetObj(SObjectTag{FOURCC('ANCS'), g_tweakGunRes->x8_grappleArm}))
, x31c_scale(scale)
, x354_grappleSegmentDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb4_grappleSegment}))
, x360_grappleClawDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xb8_grappleClaw}))
, x36c_grappleHitDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xbc_grappleHit}))
, x378_grappleMuzzleDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('PART'), g_tweakGunRes->xc0_grappleMuzzle}))
, x384_grappleSwooshDesc(g_SimplePool->GetObj(SObjectTag{FOURCC('SWHC'), g_tweakGunRes->xc4_grappleSwoosh}))
, x390_grappleSegmentGen(std::make_unique<CElementGen>(x354_grappleSegmentDesc))
, x394_grappleClawGen(std::make_unique<CElementGen>(x360_grappleClawDesc))
, x398_grappleHitGen(std::make_unique<CElementGen>(x36c_grappleHitDesc))
, x39c_grappleMuzzleGen(std::make_unique<CElementGen>(x378_grappleMuzzleDesc))
, x3a0_grappleSwooshGen(std::make_unique<CParticleSwoosh>(x384_grappleSwooshDesc, 0))
, x3a4_rainSplashGenerator(std::make_unique<CRainSplashGenerator>(scale, 20, 2, 0.f, 0.125f)) {
x0_grappleArmModel->SetSortThermal(true);
xa0_grappleGearModel.SetSortThermal(true);
xec_grapNoz1Model.SetSortThermal(true);
x138_grapNoz2Model.SetSortThermal(true);
g_GrappleBeamAnglePhaseDelta = g_tweakPlayer->GetGrappleBeamAnglePhaseDelta();
g_GrappleBeamXWaveAmplitude = g_tweakPlayer->GetGrappleBeamXWaveAmplitude();
g_GrappleBeamZWaveAmplitude = g_tweakPlayer->GetGrappleBeamZWaveAmplitude();
g_GrappleBeamSpeed = g_tweakPlayer->GetGrappleBeamSpeed();
x39c_grappleMuzzleGen->SetParticleEmission(false);
x390_grappleSegmentGen->SetParticleEmission(false);
x3a0_grappleSwooshGen->DoGrappleWarmup();
BuildSuitDependencyList();
LoadAnimations();
}
void CGrappleArm::FillTokenVector(const std::vector<SObjectTag>& tags, std::vector<CToken>& objects) {
objects.reserve(tags.size());
for (const SObjectTag& tag : tags)
objects.push_back(g_SimplePool->GetObj(tag));
}
void CGrappleArm::BuildSuitDependencyList() {
static constexpr std::array dependencyNames{
"PowerSuit_DGRP"sv, "GravitySuit_DGRP"sv, "VariaSuit_DGRP"sv, "PhazonSuit_DGRP"sv,
"FusionSuit_DGRP"sv, "FusionSuitG_DGRP"sv, "FusionSuitV_DGRP"sv, "FusionSuitP_DGRP"sv,
};
x184_grappleArm.Lock();
for (const auto& name : dependencyNames) {
TLockedToken<CDependencyGroup> dgrp = g_SimplePool->GetObj(name);
std::vector<CToken>& depsOut = x19c_suitDeps.emplace_back();
FillTokenVector(dgrp->GetObjectTagVector(), depsOut);
}
}
void CGrappleArm::LoadAnimations() {
NWeaponTypes::get_token_vector(*x0_grappleArmModel->GetAnimationData(), 0, 42, x18c_anims, true);
x0_grappleArmModel = std::nullopt;
}
void CGrappleArm::AsyncLoadSuit(CStateManager& mgr) {
CPlayerState::EPlayerSuit suit = NWeaponTypes::get_current_suit(mgr);
if (suit == x3a8_loadedSuit)
return;
x0_grappleArmModel = std::nullopt;
x3b2_29_suitLoading = true;
if (x3a8_loadedSuit != CPlayerState::EPlayerSuit::Invalid) {
NWeaponTypes::unlock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]);
x19c_suitDeps[int(x3a8_loadedSuit)].clear();
}
if (suit < CPlayerState::EPlayerSuit::Power || suit > CPlayerState::EPlayerSuit::FusionPhazon)
x3a8_loadedSuit = CPlayerState::EPlayerSuit::Power;
else
x3a8_loadedSuit = suit;
NWeaponTypes::lock_tokens(x19c_suitDeps[int(x3a8_loadedSuit)]);
}
void CGrappleArm::ResetAuxParams(bool resetGunController) {
x3b2_24_active = false;
x3b2_27_armMoving = false;
x2e0_auxXf = zeus::CTransform();
if (resetGunController)
x328_gunController->Reset();
}
void CGrappleArm::DisconnectGrappleBeam() {
x394_grappleClawGen->SetParticleEmission(false);
x3b2_25_beamActive = false;
GrappleBeamDisconnected();
}
void CGrappleArm::SetAnimState(EArmState state) {
if (x334_animState == state)
return;
x0_grappleArmModel->GetAnimationData()->EnableLooping(false);
x3b2_28_isGrappling = true;
switch (state) {
case EArmState::IntoGrapple: {
ResetAuxParams(true);
constexpr CAnimPlaybackParms parms(0, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
x3b2_25_beamActive = false;
x3b2_24_active = true;
break;
}
case EArmState::IntoGrappleIdle: {
constexpr CAnimPlaybackParms parms(1, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->EnableLooping(true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::FireGrapple: {
constexpr CAnimPlaybackParms parms(2, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::ConnectGrapple: {
constexpr CAnimPlaybackParms parms(3, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::Connected: {
constexpr CAnimPlaybackParms parms(3, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::OutOfGrapple: {
constexpr CAnimPlaybackParms parms(4, -1, 1.f, true);
x0_grappleArmModel->GetAnimationData()->SetAnimation(parms, false);
DisconnectGrappleBeam();
break;
}
case EArmState::Done:
x3b2_28_isGrappling = false;
break;
default:
break;
}
x334_animState = state;
}
void CGrappleArm::Activate(bool intoGrapple) {
SetAnimState(intoGrapple ? EArmState::IntoGrapple : EArmState::OutOfGrapple);
}
void CGrappleArm::GrappleBeamDisconnected() {
if (x32c_grappleLoopSfx) {
CSfxManager::SfxStop(x32c_grappleLoopSfx);
x32c_grappleLoopSfx.reset();
}
}
void CGrappleArm::GrappleBeamConnected() {
if (!x32c_grappleLoopSfx)
x32c_grappleLoopSfx = NWeaponTypes::play_sfx(SFXsam_grapple_lp, false, true, -0.15f);
}
void CGrappleArm::RenderGrappleBeam(const CStateManager& mgr, const zeus::CVector3f& pos) {
if (!x3b2_24_active || x3b2_29_suitLoading) {
return;
}
const zeus::CTransform tmpXf = zeus::CTransform::Translate(pos) * x220_xf;
if (!x3b2_25_beamActive) {
return;
}
if (x3b2_26_grappleHit) {
x398_grappleHitGen->Render();
}
x394_grappleClawGen->Render();
x3a0_grappleSwooshGen->Render();
x390_grappleSegmentGen->Render();
const zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix;
CGraphics::SetViewPointMatrix(tmpXf.inverse() * backupViewMtx);
CGraphics::SetModelMatrix(zeus::CTransform());
x39c_grappleMuzzleGen->Render();
CGraphics::SetViewPointMatrix(backupViewMtx);
}
void CGrappleArm::TouchModel(const CStateManager& mgr) {
if (!x3b2_24_active || x3b2_29_suitLoading) {
return;
}
x0_grappleArmModel->Touch(mgr, 0);
if (x50_grappleArmSkeletonModel) {
x50_grappleArmSkeletonModel->Touch(mgr, 0);
}
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) {
xa0_grappleGearModel.Touch(mgr, 0);
xec_grapNoz1Model.Touch(mgr, 0);
x138_grapNoz2Model.Touch(mgr, 0);
}
}
void CGrappleArm::LoadSuitPoll() {
if (!NWeaponTypes::are_tokens_ready(x19c_suitDeps[size_t(x3a8_loadedSuit)])) {
return;
}
x0_grappleArmModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, int(x3a8_loadedSuit), x31c_scale, 41, false));
x0_grappleArmModel->SetSortThermal(true);
x328_gunController = std::make_unique<CGunController>(*x0_grappleArmModel);
x3b2_29_suitLoading = false;
}
void CGrappleArm::BuildXRayModel() {
x50_grappleArmSkeletonModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, 8, x31c_scale,
!x328_gunController ? 41 : x328_gunController->GetCurAnimId(), false));
x50_grappleArmSkeletonModel->SetSortThermal(true);
}
void CGrappleArm::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type) {
switch (type) {
case EUserEventType::Projectile:
if (x3b2_27_armMoving)
return;
x3b2_25_beamActive = true;
x398_grappleHitGen = std::make_unique<CElementGen>(x36c_grappleHitDesc);
x39c_grappleMuzzleGen = std::make_unique<CElementGen>(x378_grappleMuzzleDesc);
x338_beamT = 0.f;
x33c_beamDist = 0.f;
x340_anglePhase = 0.f;
x344_xAmplitude = g_GrappleBeamXWaveAmplitude;
x348_zAmplitude = g_GrappleBeamZWaveAmplitude;
x398_grappleHitGen->SetParticleEmission(false);
x394_grappleClawGen->SetParticleEmission(true);
NWeaponTypes::play_sfx(SFXsam_grapple_fire, false, false, -0.15f);
mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleFire, 1.f, ERumblePriority::Three);
break;
default:
break;
}
}
void CGrappleArm::DoUserAnimEvents(CStateManager& mgr) {
zeus::CVector3f armToCam = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTranslation() - x220_xf.origin;
const CAnimData& animData = *x0_grappleArmModel->GetAnimationData();
for (size_t i = 0; i < animData.GetPassedSoundPOICount(); ++i) {
const CSoundPOINode& node = CAnimData::g_SoundPOINodes[i];
if (node.GetPoiType() != EPOIType::Sound ||
(node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex()))
continue;
NWeaponTypes::do_sound_event(x34c_animSfx, x3ac_pitchBend, false, node.GetSfxId(), node.GetWeight(),
node.GetFlags(), node.GetFalloff(), node.GetMaxDist(), 0.16f, 1.f, armToCam,
x220_xf.origin, mgr.GetPlayer().GetAreaIdAlways(), mgr);
}
for (size_t i = 0; i < animData.GetPassedIntPOICount(); ++i) {
const CInt32POINode& node = CAnimData::g_Int32POINodes[i];
switch (node.GetPoiType()) {
case EPOIType::UserEvent:
DoUserAnimEvent(mgr, node, EUserEventType(node.GetValue()));
break;
case EPOIType::SoundInt32:
if (node.GetCharacterIndex() != -1 && animData.x204_charIdx != node.GetCharacterIndex())
break;
NWeaponTypes::do_sound_event(x34c_animSfx, x3ac_pitchBend, false, u32(node.GetValue()), node.GetWeight(),
node.GetFlags(), 0.1f, 150.f, 0.16f, 1.f, armToCam, x220_xf.origin,
mgr.GetPlayer().GetAreaIdAlways(), mgr);
break;
default:
break;
}
}
}
void CGrappleArm::UpdateArmMovement(float dt, CStateManager& mgr) {
DoUserAnimEvents(mgr);
if (x328_gunController->Update(dt, mgr))
ResetAuxParams(false);
}
void CGrappleArm::UpdateGrappleBeamFx(const zeus::CVector3f& beamGunPos, const zeus::CVector3f& beamAirPos,
CStateManager& mgr) {
x394_grappleClawGen->SetTranslation(beamAirPos);
x390_grappleSegmentGen->SetParticleEmission(true);
zeus::CVector3f segmentDelta = beamAirPos - beamGunPos;
zeus::CVector3f swooshSegmentDelta = segmentDelta * 0.02f;
int numSegments = int(2.f * segmentDelta.magnitude() + 1.f);
segmentDelta = (1.f / float(numSegments)) * segmentDelta;
zeus::CVector3f segmentPos = beamGunPos;
zeus::CTransform rotation = x220_xf.getRotation();
for (int i = 0; i < numSegments; ++i) {
zeus::CVector3f vec;
if (i > 0)
vec = rotation *
zeus::CVector3f(std::cos(i + x340_anglePhase) * x344_xAmplitude, 0.f, std::sin(float(i)) * x348_zAmplitude);
x390_grappleSegmentGen->SetTranslation(vec * segmentPos);
x390_grappleSegmentGen->ForceParticleCreation(1);
segmentPos += segmentDelta;
}
x390_grappleSegmentGen->SetParticleEmission(false);
x3a0_grappleSwooshGen->DoGrappleUpdate(beamGunPos, rotation, x340_anglePhase, x344_xAmplitude, x348_zAmplitude,
swooshSegmentDelta);
}
bool CGrappleArm::UpdateGrappleBeam(float dt, const zeus::CTransform& beamLoc, CStateManager& mgr) {
bool beamConnected = false;
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(mgr.GetPlayer().GetOrbitTargetId()))
x310_grapplePointPos = act->GetTranslation();
else
x310_grapplePointPos = x220_xf.origin;
zeus::CVector3f beamGunPos = (x220_xf * beamLoc).origin;
zeus::CVector3f beamAirPos = beamGunPos * (1.f - x338_beamT) + x310_grapplePointPos * x338_beamT;
switch (x334_animState) {
case EArmState::FireGrapple:
case EArmState::Three: {
float gunToPointMag = (x310_grapplePointPos - beamGunPos).magnitude();
if (gunToPointMag > 0.f)
x338_beamT = x33c_beamDist / gunToPointMag;
else
x338_beamT = 1.f;
float speedMult = mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround ? 2.f : 1.f;
x33c_beamDist += speedMult * (dt * g_GrappleBeamSpeed);
if (x338_beamT >= 1.f) {
x338_beamT = 1.f;
beamConnected = true;
}
break;
}
case EArmState::ConnectGrapple: {
float delta = 4.f * dt;
x344_xAmplitude -= delta;
x348_zAmplitude -= delta;
if (x344_xAmplitude < 0.f)
x344_xAmplitude = 0.f;
if (x348_zAmplitude < 0.f)
x348_zAmplitude = 0.f;
break;
}
default:
break;
}
if (x3b2_25_beamActive) {
x340_anglePhase += g_GrappleBeamAnglePhaseDelta;
UpdateGrappleBeamFx(beamGunPos, beamAirPos, mgr);
x394_grappleClawGen->Update(dt);
x390_grappleSegmentGen->Update(dt);
}
return beamConnected;
}
void CGrappleArm::UpdateSwingAction(float grappleSwingT, float dt, CStateManager& mgr) {
if (x3b2_29_suitLoading)
return;
if (x334_animState == EArmState::FireGrapple)
DoUserAnimEvents(mgr);
zeus::CTransform beamLocXf = x0_grappleArmModel->GetScaledLocatorTransform("LGBeam");
bool grappleConnected = UpdateGrappleBeam(dt, beamLocXf, mgr);
if ((grappleSwingT > 0.175f && grappleSwingT < 0.3f) || (grappleSwingT > 0.7f && grappleSwingT < 0.9f)) {
if (!CSfxManager::IsPlaying(x330_swooshSfx)) {
x330_swooshSfx = NWeaponTypes::play_sfx(SFXsam_grapple_swoosh, false, false, -0.15f);
if (x3b0_rumbleHandle != -1)
mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle);
x3b0_rumbleHandle =
mgr.GetRumbleManager().Rumble(mgr, ERumbleFxId::PlayerGrappleSwoosh, 1.f, ERumblePriority::Three);
}
}
if (!x0_grappleArmModel->GetAnimationData()->IsAnimTimeRemaining(dt, "Whole Body")) {
switch (x334_animState) {
case EArmState::IntoGrapple:
case EArmState::Seven:
SetAnimState(EArmState::IntoGrappleIdle);
break;
case EArmState::FireGrapple:
if (grappleConnected) {
SetAnimState(EArmState::ConnectGrapple);
x3b2_26_grappleHit = true;
x398_grappleHitGen->SetParticleEmission(true);
GrappleBeamConnected();
if (x3b0_rumbleHandle != -1)
mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle);
}
break;
case EArmState::ConnectGrapple:
if (x344_xAmplitude == 0.f)
SetAnimState(EArmState::Connected);
break;
case EArmState::OutOfGrapple:
if (x3b0_rumbleHandle != -1)
mgr.GetRumbleManager().StopRumble(x3b0_rumbleHandle);
SetAnimState(EArmState::Done);
x3b2_24_active = false;
break;
default:
break;
}
}
if (x3b2_25_beamActive) {
x39c_grappleMuzzleGen->SetTranslation(beamLocXf.origin);
x39c_grappleMuzzleGen->Update(dt);
if (x3b2_26_grappleHit) {
x3b2_26_grappleHit = !x398_grappleHitGen->IsSystemDeletable();
x398_grappleHitGen->SetTranslation(x310_grapplePointPos);
x398_grappleHitGen->Update(dt);
}
}
}
void CGrappleArm::Update(float grappleSwingT, float dt, CStateManager& mgr) {
if (!(x3b2_24_active && !x3b2_29_suitLoading)) {
if (x3b2_29_suitLoading)
LoadSuitPoll();
return;
}
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) {
if (!x50_grappleArmSkeletonModel)
BuildXRayModel();
} else {
if (x50_grappleArmSkeletonModel)
x50_grappleArmSkeletonModel = std::nullopt;
}
float speed = 1.f;
if (!x3b2_27_armMoving)
speed = (mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround &&
x334_animState != EArmState::OutOfGrapple)
? 4.f
: 1.f;
x0_grappleArmModel->AdvanceAnimation(speed * dt, mgr, kInvalidAreaId, true);
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) {
x250_grapLocatorXf = x0_grappleArmModel->GetScaledLocatorTransformDynamic("grapLocator_SDK", nullptr);
x280_grapNozLoc1Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK");
x2b0_grapNozLoc2Xf = x0_grappleArmModel->GetScaledLocatorTransform("gNozLoc1_SDK");
}
if (x3b2_27_armMoving)
UpdateArmMovement(dt, mgr);
else
UpdateSwingAction(grappleSwingT, dt, mgr);
if (x3a4_rainSplashGenerator)
x3a4_rainSplashGenerator->Update(dt, mgr);
}
void CGrappleArm::PreRender(const CStateManager& mgr, const zeus::CFrustum& frustum, const zeus::CVector3f& camPos) {
if (!x3b2_24_active || x3b2_29_suitLoading) {
return;
}
x0_grappleArmModel->GetAnimationData()->PreRender();
if (x50_grappleArmSkeletonModel) {
x50_grappleArmSkeletonModel->GetAnimationData()->PreRender();
}
}
void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf, const CModelFlags& flags) {
CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(x0_grappleArmModel->GetScale()));
// TODO
// CGraphics::DisableAllLights();
// g_Renderer->SetAmbientColor(zeus::skWhite);
CSkinnedModel& model = *x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData();
// model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::skWhite)});
x0_grappleArmModel->GetAnimationData()->Render(model, flags, nullptr, nullptr);
// g_Renderer->SetAmbientColor(zeus::skWhite);
// CGraphics::DisableAllLights();
}
void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos, const CModelFlags& flags,
const CActorLights* lights) {
if (!x3b2_24_active || x3b2_29_suitLoading) {
return;
}
SCOPED_GRAPHICS_DEBUG_GROUP("CGrappleArm::Render", zeus::skOrange);
const zeus::CTransform modelXf = zeus::CTransform::Translate(pos) * x220_xf * x2e0_auxXf;
if (x50_grappleArmSkeletonModel) {
RenderXRayModel(mgr, modelXf, flags);
}
CModelFlags useFlags;
const CActorLights* useLights;
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::XRay) {
useFlags = CModelFlags(5, 0, 3, zeus::CColor(1.f, 0.25f));
useLights = nullptr;
} else {
useFlags = flags;
useLights = lights;
}
if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) {
CSkinnedModel::SetPointGeneratorFunc(
[&](const auto& workspace) { x3a4_rainSplashGenerator->GeneratePoints(workspace); });
}
x0_grappleArmModel->Render(mgr, modelXf, useLights, useFlags);
if (x3a4_rainSplashGenerator && x3a4_rainSplashGenerator->IsRaining()) {
CSkinnedModel::ClearPointGeneratorFunc();
x3a4_rainSplashGenerator->Draw(modelXf);
}
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::GrappleBeam)) {
xa0_grappleGearModel.Render(mgr, modelXf * x250_grapLocatorXf, useLights, useFlags);
xec_grapNoz1Model.Render(mgr, modelXf * x280_grapNozLoc1Xf, useLights, useFlags);
x138_grapNoz2Model.Render(mgr, modelXf * x2b0_grapNozLoc2Xf, useLights, useFlags);
}
}
void CGrappleArm::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
if (msg == EScriptObjectMessage::Registered)
AsyncLoadSuit(mgr);
}
void CGrappleArm::EnterStruck(CStateManager& mgr, float angle, bool bigStrike, bool notInFreeLook) {
if (x3b2_29_suitLoading)
return;
if (x3b2_28_isGrappling) {
DisconnectGrappleBeam();
x3b2_28_isGrappling = false;
}
if (!x3b2_27_armMoving) {
x3b2_24_active = true;
x3b2_27_armMoving = true;
x334_animState = EArmState::GunControllerAnimation;
}
x328_gunController->EnterStruck(mgr, angle, bigStrike, notInFreeLook);
}
void CGrappleArm::EnterIdle(CStateManager& mgr) {
if (x3b2_29_suitLoading)
return;
x328_gunController->EnterIdle(mgr);
}
void CGrappleArm::EnterFidget(CStateManager& mgr, SamusGun::EFidgetType type, s32 gunId, s32 animSet) {
if (x3b2_29_suitLoading)
return;
x3b2_24_active = true;
x3b2_27_armMoving = true;
x334_animState = EArmState::GunControllerAnimation;
x328_gunController->EnterFidget(mgr, s32(type), gunId, animSet);
}
void CGrappleArm::EnterFreeLook(s32 gunId, s32 setId, CStateManager& mgr) {
if (x3b2_29_suitLoading)
return;
x3b2_24_active = true;
x3b2_27_armMoving = true;
x334_animState = EArmState::GunControllerAnimation;
x328_gunController->EnterFreeLook(mgr, gunId, setId);
}
void CGrappleArm::EnterComboFire(s32 gunId, CStateManager& mgr) {
if (x3b2_29_suitLoading)
return;
x3b2_24_active = true;
x3b2_27_armMoving = true;
x334_animState = EArmState::GunControllerAnimation;
x328_gunController->EnterComboFire(mgr, gunId);
}
void CGrappleArm::ReturnToDefault(CStateManager& mgr, float dt, bool setState) {
if (x3b2_29_suitLoading)
return;
x328_gunController->ReturnToDefault(mgr, dt, setState);
}
} // namespace metaforce