metaforce/Runtime/Weapon/CGrappleArm.cpp

684 lines
23 KiB
C++

#include "Particle/CElementGen.hpp"
#include "CDependencyGroup.hpp"
#include "CGrappleArm.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "World/CPlayer.hpp"
#include "TCastTo.hpp"
#include "Camera/CGameCamera.hpp"
#include "Graphics/CSkinnedModel.hpp"
#include "Graphics/CVertexMorphEffect.hpp"
namespace urde
{
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();
}
static const char* skDependencyNames[] =
{
"PowerSuit_DGRP",
"GravitySuit_DGRP",
"VariaSuit_DGRP",
"PhazonSuit_DGRP",
"FusionSuit_DGRP",
"FusionSuitG_DGRP",
"FusionSuitV_DGRP",
"FusionSuitP_DGRP",
};
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()
{
x184_grappleArm.Lock();
for (const char* name : skDependencyNames)
{
TLockedToken<CDependencyGroup> dgrp = g_SimplePool->GetObj(name);
x19c_suitDeps.emplace_back();
std::vector<CToken>& depsOut = x19c_suitDeps.back();
FillTokenVector(dgrp->GetObjectTagVector(), depsOut);
}
}
void CGrappleArm::LoadAnimations()
{
NWeaponTypes::get_token_vector(*x0_grappleArmModel->GetAnimationData(), 0, 42, x18c_anims, true);
x0_grappleArmModel = std::experimental::nullopt;
}
void CGrappleArm::AsyncLoadSuit(CStateManager& mgr)
{
CPlayerState::EPlayerSuit suit = NWeaponTypes::get_current_suit(mgr);
if (suit == x3a8_loadedSuit)
return;
x0_grappleArmModel = std::experimental::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::Identity();
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->AnimationData()->EnableLooping(false);
x3b2_28_isGrappling = true;
switch (state)
{
case EArmState::IntoGrapple:
{
ResetAuxParams(true);
CAnimPlaybackParms parms(0, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->SetAnimation(parms, false);
x3b2_25_beamActive = false;
x3b2_24_active = true;
break;
}
case EArmState::IntoGrappleIdle:
{
CAnimPlaybackParms parms(1, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->EnableLooping(true);
x0_grappleArmModel->AnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::FireGrapple:
{
CAnimPlaybackParms parms(2, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::ConnectGrapple:
{
CAnimPlaybackParms parms(3, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::Connected:
{
CAnimPlaybackParms parms(3, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->SetAnimation(parms, false);
break;
}
case EArmState::OutOfGrapple:
{
CAnimPlaybackParms parms(4, -1, 1.f, true);
x0_grappleArmModel->AnimationData()->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)
{
zeus::CTransform tmpXf = zeus::CTransform::Translate(pos) * x220_xf;
if (x3b2_25_beamActive)
{
if (x3b2_26_grappleHit)
x398_grappleHitGen->Render();
x394_grappleClawGen->Render();
x3a0_grappleSwooshGen->Render();
x390_grappleSegmentGen->Render();
zeus::CTransform backupViewMtx = CGraphics::g_ViewMatrix;
CGraphics::SetViewPointMatrix(tmpXf.inverse() * backupViewMtx);
CGraphics::SetModelMatrix(zeus::CTransform::Identity());
x39c_grappleMuzzleGen->Render();
CGraphics::SetViewPointMatrix(backupViewMtx);
}
}
}
void CGrappleArm::TouchModel(const CStateManager& mgr) const
{
if (x3b2_24_active && !x3b2_29_suitLoading)
{
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[int(x3a8_loadedSuit)]))
{
x0_grappleArmModel.emplace(CAnimRes(g_tweakGunRes->x8_grappleArm, 0, 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 (int 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 (int 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::experimental::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)
{
x0_grappleArmModel->AnimationData()->PreRender();
if (x50_grappleArmSkeletonModel)
x50_grappleArmSkeletonModel->AnimationData()->PreRender();
}
}
void CGrappleArm::RenderXRayModel(const CStateManager& mgr, const zeus::CTransform& modelXf,
const CModelFlags& flags) const
{
CGraphics::SetModelMatrix(modelXf * zeus::CTransform::Scale(x0_grappleArmModel->GetScale()));
//CGraphics::DisableAllLights();
//g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
CSkinnedModel& model =
const_cast<CSkinnedModel&>(*x50_grappleArmSkeletonModel->GetAnimationData()->GetModelData());
model.GetModelInst()->ActivateLights({CLight::BuildLocalAmbient({}, zeus::CColor::skWhite)});
const_cast<CGrappleArm*>(this)->x0_grappleArmModel->AnimationData()->Render(model, flags, {}, nullptr);
//g_Renderer->SetAmbientColor(zeus::CColor::skWhite);
//CGraphics::DisableAllLights();
}
void CGrappleArm::PointGenerator(void* ctx, const std::vector<std::pair<zeus::CVector3f, zeus::CVector3f>>& vn)
{
reinterpret_cast<CRainSplashGenerator*>(ctx)->GeneratePoints(vn);
}
void CGrappleArm::Render(const CStateManager& mgr, const zeus::CVector3f& pos,
const CModelFlags& flags, const CActorLights* lights) const
{
if (x3b2_24_active && !x3b2_29_suitLoading)
{
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(x3a4_rainSplashGenerator.get(), PointGenerator);
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);
}
}