mirror of https://github.com/AxioDL/metaforce.git
1516 lines
59 KiB
C++
1516 lines
59 KiB
C++
#include "Runtime/MP1/World/CIceSheegoth.hpp"
|
|
|
|
#include "Runtime/Factory/CSimplePool.hpp"
|
|
#include "Runtime/CStateManager.hpp"
|
|
#include "Runtime/Camera/CCameraManager.hpp"
|
|
#include "Runtime/Camera/CCameraShakeData.hpp"
|
|
#include "Runtime/Camera/CFirstPersonCamera.hpp"
|
|
#include "Runtime/Character/CPASAnimParmData.hpp"
|
|
#include "Runtime/Collision/CCollisionActor.hpp"
|
|
#include "Runtime/Collision/CCollisionActorManager.hpp"
|
|
#include "Runtime/GameGlobalObjects.hpp"
|
|
#include "Runtime/Graphics/CCubeRenderer.hpp"
|
|
#include "Runtime/Particle/CElementGen.hpp"
|
|
#include "Runtime/Particle/CParticleElectric.hpp"
|
|
#include "Runtime/Particle/CParticleSwoosh.hpp"
|
|
#include "Runtime/Weapon/CFlameInfo.hpp"
|
|
#include "Runtime/Weapon/CFlameThrower.hpp"
|
|
#include "Runtime/World/CGameArea.hpp"
|
|
#include "Runtime/World/CPatternedInfo.hpp"
|
|
#include "Runtime/World/CPlayer.hpp"
|
|
#include "Runtime/World/CWorld.hpp"
|
|
|
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
|
|
|
namespace metaforce::MP1 {
|
|
namespace {
|
|
constexpr std::array<SSphereJointInfo, 7> skSphereJointList = {{
|
|
{"Jaw_end_LCTR", 0.55f},
|
|
{"Pelvis", 1.1f},
|
|
{"LCTR_SHEMOUTH", 1.1f},
|
|
{"butt_LCTR", 0.7f},
|
|
{"Ice_Shards_LCTR", 1.2f},
|
|
{"GillL_LCTR", 0.6f},
|
|
{"GillR_LCTR", 0.6f},
|
|
}};
|
|
|
|
constexpr std::array<SJointInfo, 2> skLeftLegJointList = {{
|
|
{"L_hip", "L_knee", 0.4f, 0.75f},
|
|
{"L_ankle", "L_Toe_3", 0.4f, 0.75f},
|
|
}};
|
|
|
|
constexpr std::array<SJointInfo, 2> skRightLegJointList = {{
|
|
{"R_hip", "R_knee", 0.4f, 0.75f},
|
|
{"R_ankle", "R_Toe_3", 0.4f, 0.75f},
|
|
}};
|
|
} // namespace
|
|
|
|
CIceSheegothData::CIceSheegothData(CInputStream& in, [[maybe_unused]] s32 propertyCount)
|
|
: x0_(zeus::degToRad(in.ReadFloat()))
|
|
, x4_(zeus::degToRad(in.ReadFloat()))
|
|
, x8_(in.Get<zeus::CVector3f>())
|
|
, x14_(in.ReadFloat())
|
|
, x18_(in)
|
|
, x80_(in)
|
|
, xe8_(in)
|
|
, x150_(in)
|
|
, x154_(in)
|
|
, x170_(in.ReadFloat())
|
|
, x174_(in.ReadFloat())
|
|
, x178_(in)
|
|
, x17c_fireBreathResId(in)
|
|
, x180_fireBreathDamage(in)
|
|
, x19c_(in)
|
|
, x1a0_(in)
|
|
, x1a4_(in)
|
|
, x1a8_(in)
|
|
, x1ac_(in)
|
|
, x1b0_(in.ReadFloat())
|
|
, x1b4_(in.ReadFloat())
|
|
, x1b8_(in)
|
|
, x1d4_(CSfxManager::TranslateSFXID(in.ReadLong()))
|
|
, x1d8_(in.ReadFloat())
|
|
, x1dc_(in.ReadFloat())
|
|
, x1e0_maxInterestTime(in.ReadFloat())
|
|
, x1e4_(in)
|
|
, x1e8_(CSfxManager::TranslateSFXID(in.ReadLong()))
|
|
, x1ec_(in)
|
|
, x1f0_24_(in.ReadBool())
|
|
, x1f0_25_(in.ReadBool()) {}
|
|
|
|
CIceSheegoth::CIceSheegoth(TUniqueId uid, std::string_view name, const CEntityInfo& info, zeus::CTransform& xf,
|
|
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
|
|
const CIceSheegothData& sheegothData)
|
|
: CPatterned(ECharacter::IceSheeegoth, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
|
|
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large)
|
|
, x56c_sheegothData(sheegothData)
|
|
, x760_pathSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f)
|
|
, x844_approachSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f)
|
|
, x94c_(x3b4_speed)
|
|
, x974_(sheegothData.Get_x174())
|
|
, x98c_mouthVulnerability(pInfo.GetDamageVulnerability())
|
|
, x9f4_boneTracking(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f), zeus::degToRad(180.f),
|
|
EBoneTrackingFlags::None)
|
|
, xa30_(GetBoundingBox(), GetMaterialList())
|
|
, xa58_(sheegothData.Get_x150(), sheegothData.Get_x154())
|
|
, xa84_(sheegothData.Get_x178().IsValid() ? g_SimplePool->GetObj({SBIG('WPSC'), sheegothData.Get_x178()})
|
|
: g_SimplePool->GetObj("FlameThrower"sv))
|
|
, xa8c_(g_SimplePool->GetObj({SBIG('PART'), sheegothData.Get_x1a0()}))
|
|
, xa9c_(std::make_unique<CElementGen>(xa8c_, CElementGen::EModelOrientationType::Normal,
|
|
CElementGen::EOptionalSystemFlags::One))
|
|
, xaa0_(g_SimplePool->GetObj({SBIG('PART'), sheegothData.Get_x1a4()}))
|
|
, xab0_(std::make_unique<CElementGen>(xaa0_, CElementGen::EModelOrientationType::Normal,
|
|
CElementGen::EOptionalSystemFlags::One))
|
|
, xab4_(g_SimplePool->GetObj({SBIG('PART'), sheegothData.Get_x1a4()}))
|
|
, xac4_(std::make_unique<CElementGen>(xaa0_, CElementGen::EModelOrientationType::Normal,
|
|
CElementGen::EOptionalSystemFlags::One))
|
|
, xac8_(g_SimplePool->GetObj({SBIG('ELSC'), sheegothData.Get_x1ac()}))
|
|
, xad8_(std::make_unique<CParticleElectric>(xac8_))
|
|
, xadc_(g_SimplePool->GetObj({SBIG('PART'), sheegothData.Get_x19c()})) {
|
|
UpdateTouchBounds();
|
|
x460_knockBackController.SetEnableFreeze(false);
|
|
x460_knockBackController.SetX82_24(false);
|
|
x460_knockBackController.SetEnableLaggedBurnDeath(false);
|
|
x460_knockBackController.SetEnableExplodeDeath(false);
|
|
x950_ = GetAnimationDistance(
|
|
CPASAnimParmData(pas::EAnimationState::Step, CPASAnimParm::FromEnum(1), CPASAnimParm::FromEnum(0))) *
|
|
GetModelData()->GetScale().y();
|
|
xa9c_->SetGlobalScale(GetModelData()->GetScale());
|
|
xab0_->SetGlobalScale(GetModelData()->GetScale());
|
|
xac4_->SetGlobalScale(GetModelData()->GetScale());
|
|
xad8_->SetGlobalScale(GetModelData()->GetScale());
|
|
x450_bodyController->BodyStateInfo().SetLocoAnimChangeAtEndOfAnimOnly(true);
|
|
MakeThermalColdAndHot();
|
|
x328_31_energyAttractor = true;
|
|
}
|
|
|
|
void CIceSheegoth::Accept(IVisitor& visitor) { visitor.Visit(this); }
|
|
|
|
void CIceSheegoth::Think(float dt, CStateManager& mgr) {
|
|
if (!GetActive()) {
|
|
return;
|
|
}
|
|
|
|
CPatterned::Think(dt, mgr);
|
|
AttractProjectiles(mgr);
|
|
UpdateTimers(dt);
|
|
UpdateScanState(mgr);
|
|
if (!IsAlive()) {
|
|
x974_ = std::max(0.f, x974_ - (dt * x56c_sheegothData.Get_x170()));
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentState()->IsDying()) {
|
|
SetPassthroughVulnerability(mgr);
|
|
}
|
|
}
|
|
x96c_ -= dt;
|
|
if (x96c_ < 0.f) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCAdditiveReactionCmd(pas::EAdditiveReactionType::Four, 1.f, false));
|
|
x96c_ = 3.f * mgr.GetActiveRandom()->Float() + 2.f;
|
|
}
|
|
GetModelData()->GetAnimationData()->PreRender();
|
|
x9f4_boneTracking.Update(dt);
|
|
x9f4_boneTracking.PreRender(mgr, *GetModelData()->GetAnimationData(), GetTransform(), GetModelData()->GetScale(),
|
|
*GetBodyController());
|
|
xa2c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
|
|
PreventWorldCollisions(dt, mgr);
|
|
UpdateHealthInfo(mgr);
|
|
SetSteeringSpeed(dt, mgr);
|
|
UpdateParticleEffects(dt, mgr);
|
|
UpdateThermalFrozenState(x428_damageCooldownTimer > 0.f);
|
|
}
|
|
|
|
void CIceSheegoth::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
|
|
switch (msg) {
|
|
case EScriptObjectMessage::Activate: {
|
|
xa2c_collisionManager->SetActive(mgr, true);
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Deactivate: {
|
|
xa2c_collisionManager->SetActive(mgr, false);
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Start: {
|
|
xb28_24_shotAt = true;
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Touched: {
|
|
ApplyContactDamage(sender, mgr);
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(sender)) {
|
|
if (const TCastToConstPtr<CWeapon> wp = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
|
|
if (wp->GetOwnerId() == mgr.GetPlayer().GetUniqueId()) {
|
|
xb28_24_shotAt = true;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Registered: {
|
|
if (!HasPatrolPath(mgr, 0.f)) {
|
|
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
|
|
}
|
|
x450_bodyController->Activate(mgr);
|
|
SetupCollisionActorManager(mgr);
|
|
CreateFlameThrower(mgr);
|
|
if (x450_bodyController->GetBodyStateInfo().GetMaxSpeed() > 0.f) {
|
|
x944_ = x948_ = (0.9f * x450_bodyController->GetBodyStateInfo().GetLocomotionSpeed(pas::ELocomotionAnim::Walk)) /
|
|
x450_bodyController->GetBodyStateInfo().GetMaxSpeed();
|
|
}
|
|
GetBodyController()->GetCommandMgr().SetSteeringBlendMode(ESteeringBlendMode::FullSpeed);
|
|
xaf4_mouthLocator = GetModelData()->GetAnimationData()->GetLocatorSegId("LCTR_SHEMOUTH"sv);
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Deleted: {
|
|
xa2c_collisionManager->Destroy(mgr);
|
|
if (xa80_flameThrowerId != kInvalidUniqueId) {
|
|
mgr.FreeScriptObject(xa80_flameThrowerId);
|
|
xa80_flameThrowerId = kInvalidUniqueId;
|
|
}
|
|
if (xaf0_crackleSfx) {
|
|
CSfxManager::RemoveEmitter(xaf0_crackleSfx);
|
|
xaf0_crackleSfx.reset();
|
|
}
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::InitializedInArea: {
|
|
x760_pathSearch.SetArea(mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
|
|
x844_approachSearch.SetArea(mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::Damage: {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(sender)) {
|
|
if (const TCastToConstPtr<CWeapon> wp = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
|
|
if (sender == xaf6_iceShardsCollider && !xb28_27_) {
|
|
sub_8019ebf0(mgr, wp->GetDamageInfo().GetDamage());
|
|
if (!xaec_ || xaec_->IsSystemDeletable()) {
|
|
xaec_ = std::make_unique<CElementGen>(xadc_, CElementGen::EModelOrientationType::Normal,
|
|
CElementGen::EOptionalSystemFlags::One);
|
|
}
|
|
} else {
|
|
TakeDamage(zeus::skZero3f, 0.f);
|
|
if (IsGillCollider(colAct.GetPtr())) {
|
|
x97c_ = 0.2f;
|
|
x980_ = GetTransform().basis[1];
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
ApplyWeaponDamage(mgr, sender);
|
|
}
|
|
xb28_24_shotAt = true;
|
|
x968_interestTimer = 0.f;
|
|
mgr.InformListeners(GetTranslation(), EListenNoiseType::PlayerFire);
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::InvulnDamage: {
|
|
if (sender == xaf6_iceShardsCollider && !xb28_27_) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(sender)) {
|
|
if (const TCastToConstPtr<CWeapon> wp = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
|
|
sub_8019ebf0(mgr, wp->GetDamageInfo().GetDamage());
|
|
if (!xaec_ || xaec_->IsSystemDeletable()) {
|
|
xaec_ = std::make_unique<CElementGen>(xadc_, CElementGen::EModelOrientationType::Normal,
|
|
CElementGen::EOptionalSystemFlags::One);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mgr.InformListeners(GetTranslation(), EListenNoiseType::PlayerFire);
|
|
xb28_24_shotAt = true;
|
|
x968_interestTimer = 0.f;
|
|
break;
|
|
}
|
|
case EScriptObjectMessage::SuspendedMove: {
|
|
if (xa2c_collisionManager != nullptr) {
|
|
xa2c_collisionManager->SetMovable(mgr, false);
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
CPatterned::AcceptScriptMsg(msg, sender, mgr);
|
|
}
|
|
|
|
void CIceSheegoth::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
|
|
CPatterned::AddToRenderer(frustum, mgr);
|
|
|
|
if (mgr.GetThermalDrawFlag() == EThermalDrawFlag::Hot) {
|
|
if (x428_damageCooldownTimer == 0.f && xb29_25_ &&
|
|
(HasModelData() && (GetModelData()->HasAnimData() || GetModelData()->HasNormalModel()))) {
|
|
GetModelData()->RenderParticles(frustum);
|
|
}
|
|
} else {
|
|
std::optional<zeus::CAABox> bounds1;
|
|
if (xaec_) {
|
|
bounds1 = xaec_->GetBounds();
|
|
}
|
|
std::optional<zeus::CAABox> bounds2;
|
|
if (xa9c_) {
|
|
bounds2 = xa9c_->GetBounds();
|
|
}
|
|
|
|
std::optional<zeus::CAABox> bounds3;
|
|
if (xab0_) {
|
|
bounds3 = xab0_->GetBounds();
|
|
}
|
|
|
|
std::optional<zeus::CAABox> bounds4;
|
|
if (xac4_) {
|
|
bounds4 = xac4_->GetBounds();
|
|
}
|
|
|
|
std::optional<zeus::CAABox> bounds5;
|
|
if (xad8_) {
|
|
bounds5 = xad8_->GetBounds();
|
|
}
|
|
|
|
/* Lawl retro
|
|
std::optional<zeus::CAABox> bounds6;
|
|
if (xad8_) {
|
|
bounds6 = xad8_->GetBounds();
|
|
}
|
|
*/
|
|
|
|
zeus::CAABox accumulatedBounds = zeus::skInvertedBox;
|
|
if (bounds1) {
|
|
accumulatedBounds.accumulateBounds(*bounds1);
|
|
}
|
|
/* Lawl retro
|
|
if (bounds6) {
|
|
accumulatedBounds.accumulateBounds(*bounds6);
|
|
}
|
|
*/
|
|
if (bounds2) {
|
|
accumulatedBounds.accumulateBounds(*bounds2);
|
|
}
|
|
if (bounds3) {
|
|
accumulatedBounds.accumulateBounds(*bounds3);
|
|
}
|
|
if (bounds4) {
|
|
accumulatedBounds.accumulateBounds(*bounds4);
|
|
}
|
|
if (bounds5) {
|
|
accumulatedBounds.accumulateBounds(*bounds5);
|
|
}
|
|
|
|
if (frustum.aabbFrustumTest(accumulatedBounds)) {
|
|
if (xaec_) {
|
|
g_Renderer->AddParticleGen(*xaec_);
|
|
}
|
|
|
|
g_Renderer->AddParticleGen(*xa9c_);
|
|
g_Renderer->AddParticleGen(*xab0_);
|
|
g_Renderer->AddParticleGen(*xac4_);
|
|
g_Renderer->AddParticleGen(*xad8_);
|
|
}
|
|
}
|
|
}
|
|
|
|
zeus::CVector3f CIceSheegoth::GetAimPosition(const CStateManager& mgr, float dt) const {
|
|
if (GetBodyController()->GetLocomotionType() != pas::ELocomotionType::Crouch) {
|
|
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) {
|
|
zeus::CVector3f pos = zeus::skZero3f;
|
|
for (TUniqueId uid : xafc_gillColliders) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(uid)) {
|
|
pos += colAct->GetTranslation();
|
|
}
|
|
}
|
|
if (!pos.isZero()) {
|
|
return pos * (1.f / static_cast<float>(xafc_gillColliders.size()));
|
|
}
|
|
} else if (!xb29_29_scanned && mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::Scan) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) {
|
|
return colAct->GetTranslation();
|
|
}
|
|
} else if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(xaf8_mouthCollider)) {
|
|
return colAct->GetTranslation();
|
|
}
|
|
}
|
|
|
|
return CPatterned::GetAimPosition(mgr, dt);
|
|
}
|
|
|
|
EWeaponCollisionResponseTypes CIceSheegoth::GetCollisionResponseType(const zeus::CVector3f& v1,
|
|
const zeus::CVector3f& v2, const CWeaponMode& mode,
|
|
EProjectileAttrib attrib) const {
|
|
return mode.GetType() == EWeaponType::Ice ? EWeaponCollisionResponseTypes::None
|
|
: CPatterned::GetCollisionResponseType(v1, v2, mode, attrib);
|
|
}
|
|
|
|
zeus::CAABox CIceSheegoth::GetSortingBounds(const CStateManager& mgr) const {
|
|
const zeus::CAABox box = CActor::GetSortingBounds(mgr);
|
|
const zeus::CVector3f offset = 0.125f * (box.max - box.min);
|
|
const zeus::CVector3f center = box.center();
|
|
return {center - offset, center + offset};
|
|
}
|
|
|
|
void CIceSheegoth::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
|
|
switch (type) {
|
|
case EUserEventType::Projectile: {
|
|
zeus::CTransform gunPos = GetLctrTransform(node.GetLocatorName());
|
|
zeus::CVector3f interceptPos = GetProjectileInfo()->PredictInterceptPos(
|
|
gunPos.origin, mgr.GetPlayer().GetAimPosition(mgr, 0.f), mgr.GetPlayer(), true, dt);
|
|
zeus::CVector3f predictOffset = interceptPos - gunPos.origin;
|
|
zeus::CVector3f lookPos;
|
|
if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), predictOffset) > zeus::degToRad(60.f)) {
|
|
if (!predictOffset.canBeNormalized()) {
|
|
lookPos = gunPos.origin + predictOffset.magnitude() * gunPos.frontVector();
|
|
} else {
|
|
lookPos = gunPos.origin + (predictOffset.magnitude() *
|
|
zeus::CVector3f::slerp(GetTransform().frontVector(), predictOffset.normalized(),
|
|
zeus::CRelAngle::FromDegrees(60.f)));
|
|
}
|
|
}
|
|
|
|
LaunchProjectile(zeus::lookAt(gunPos.origin, lookPos), mgr, 4, EProjectileAttrib::None, false, std::nullopt, -1,
|
|
false, zeus::skOne3f);
|
|
x974_ = std::max(0.f, x974_ - 0.3333f * x56c_sheegothData.Get_x170());
|
|
if (xb28_27_ && !ShouldSpecialAttack(mgr, 0.f)) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd{EBodyStateCmd::ExitState});
|
|
}
|
|
return;
|
|
}
|
|
case EUserEventType::DamageOn:
|
|
if (!xb28_26_) {
|
|
break;
|
|
}
|
|
|
|
if (CFlameThrower* fl = static_cast<CFlameThrower*>(mgr.ObjectById(xa80_flameThrowerId))) {
|
|
fl->Fire(GetTransform(), mgr, false);
|
|
}
|
|
break;
|
|
case EUserEventType::DamageOff:
|
|
if (!xb28_26_) {
|
|
break;
|
|
}
|
|
|
|
if (CFlameThrower* fl = static_cast<CFlameThrower*>(mgr.ObjectById(xa80_flameThrowerId))) {
|
|
fl->Reset(mgr, false);
|
|
}
|
|
break;
|
|
case EUserEventType::ScreenShake:
|
|
ShakePlayer(mgr);
|
|
return;
|
|
case EUserEventType::BecomeShootThrough:
|
|
SetPassthroughVulnerability(mgr);
|
|
return;
|
|
default:
|
|
break;
|
|
}
|
|
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
|
}
|
|
|
|
void CIceSheegoth::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
xb28_24_shotAt = false;
|
|
xb29_28_ = false;
|
|
x968_interestTimer = 0.f;
|
|
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
|
x9f4_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
|
|
x9f4_boneTracking.SetActive(true);
|
|
UpdateAttackPosition(mgr, x2e0_destPos);
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
if (!x56c_sheegothData.Get_x1f0_24()) {
|
|
CPatterned::PathFind(mgr, msg, dt);
|
|
}
|
|
} else if (msg == EStateMsg::Update) {
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
if (x56c_sheegothData.Get_x1f0_24() && GetSearchPath() != nullptr && !PathShagged(mgr, 0.f) &&
|
|
x760_pathSearch.GetCurrentWaypoint() < x760_pathSearch.GetWaypoints().size() - 1) {
|
|
CPatterned::PathFind(mgr, EStateMsg::Update, dt);
|
|
x968_interestTimer = 0.f;
|
|
zeus::CVector3f moveVec = GetBodyController()->GetCommandMgr().GetMoveVector();
|
|
if (GetTransform().basis[1].dot(moveVec) < 0.f && moveVec.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, moveVec.normalized(), 1.f));
|
|
}
|
|
} else {
|
|
const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
if (sub_8019ecdc(mgr, zeus::degToRad(15.f)) && posDiff.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, posDiff.normalized(), 1.f));
|
|
}
|
|
}
|
|
|
|
x3b4_speed =
|
|
(GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn ? 2.f : 1.f) * x94c_;
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
x9f4_boneTracking.SetActive(false);
|
|
x3b4_speed = x94c_;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
|
|
|
if (HasPatrolPath(mgr, 0.f)) {
|
|
Patrol(mgr, msg, dt);
|
|
UpdateDest(mgr);
|
|
} else {
|
|
SetDestPos(x3a0_latestLeashPosition);
|
|
}
|
|
|
|
const zeus::CVector3f arrivalPos = x45c_steeringBehaviors.Arrival(*this, x92c_lastDest, 15.f);
|
|
x92c_lastDest = x2e0_destPos;
|
|
|
|
if (GetSearchPath() != nullptr) {
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
CPatterned::PathFind(mgr, msg, dt);
|
|
const zeus::CVector3f moveVec = GetBodyController()->GetCommandMgr().GetMoveVector();
|
|
if (moveVec.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCLocomotionCmd{arrivalPos.magnitude() * moveVec.normalized(), zeus::skZero3f, 1.f});
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{arrivalPos, zeus::skZero3f, 1.f});
|
|
}
|
|
}
|
|
} else if (msg == EStateMsg::Update) {
|
|
const zeus::CVector3f arrivalPos = x45c_steeringBehaviors.Arrival(*this, x92c_lastDest, 15.f);
|
|
|
|
if (GetSearchPath() && PathShagged(mgr, dt)) {
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
CPatterned::PathFind(mgr, EStateMsg::Update, dt);
|
|
const zeus::CVector3f moveVec = GetBodyController()->GetCommandMgr().GetMoveVector();
|
|
if (moveVec.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCLocomotionCmd{arrivalPos.magnitude() * moveVec.normalized(), zeus::skZero3f, 1.f});
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{arrivalPos, zeus::skZero3f, 1.f});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Generate(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
x938_ = GetTransform().basis[1];
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) {
|
|
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
|
x568_ = 3;
|
|
SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None);
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCGenerateCmd{x56c_sheegothData.Get_x1f0_25() ? pas::EGenerateType::Eight : pas::EGenerateType::Zero});
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
|
|
x568_ = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Deactivate(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 1;
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) {
|
|
x568_ = 3;
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCGenerateCmd{pas::EGenerateType::One});
|
|
}
|
|
} else if (x568_ == 1) {
|
|
if ((x3a0_latestLeashPosition - GetTranslation()).magSquared() > 1.f) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{
|
|
x45c_steeringBehaviors.Arrival(*this, x3a0_latestLeashPosition, 15.f), zeus::skZero3f, 1.f});
|
|
} else {
|
|
x568_ = 2;
|
|
}
|
|
} else if (x568_ == 2) {
|
|
const float angleDiff = zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), x938_);
|
|
if (angleDiff <= zeus::degToRad(5.f)) {
|
|
x568_ = 0;
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::skZero3f, x938_, 1.f});
|
|
}
|
|
} else if (x568_ == 3) {
|
|
x568_ = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Attack(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb28_29_ = true;
|
|
xb28_25_ = true;
|
|
x2e0_destPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
CPatterned::PathFind(mgr, msg, dt);
|
|
SetCollisionActorExtendedTouchBounds(mgr, zeus::CVector3f{2.f});
|
|
x95c_ = 0.f;
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
x95c_ += dt;
|
|
if (x95c_ >= x56c_sheegothData.Get_x1d8()) {
|
|
x568_ = 4;
|
|
} else if (!xb28_29_) {
|
|
x568_ = 3;
|
|
xb28_29_ = true;
|
|
const bool isPlayerMorphed =
|
|
mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed;
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCMeleeAttackCmd{isPlayerMorphed ? pas::ESeverity::Two : pas::ESeverity::One});
|
|
} else if (xb28_29_) {
|
|
const zeus::CTransform mouthXf = GetLctrTransform(xaf4_mouthLocator);
|
|
if (GetTransform().frontVector().dot(mgr.GetPlayer().GetTranslation() - mouthXf.origin) > 0.f) {
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
if (GetSearchPath() != nullptr && !PathShagged(mgr, 0.f)) {
|
|
CPatterned::PathFind(mgr, EStateMsg::Update, dt);
|
|
} else {
|
|
x568_ = 4;
|
|
}
|
|
} else {
|
|
x568_ = 4;
|
|
}
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) {
|
|
x568_ = 4;
|
|
}
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
if (!sub_801a1794(mgr)) {
|
|
x954_attackTimeLeft = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime;
|
|
}
|
|
|
|
SetCollisionActorExtendedTouchBounds(mgr, zeus::skZero3f);
|
|
xb28_29_ = false;
|
|
xb28_25_ = false;
|
|
x960_ = x56c_sheegothData.Get_x1dc();
|
|
x95c_ = 0.f;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::DoubleSnap(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb28_29_ = true;
|
|
xb28_28_ = true;
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
|
|
x568_ = 3;
|
|
} else if (IsOnGround()) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd{pas::ESeverity::Zero});
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack) {
|
|
x568_ = 4;
|
|
}
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
if (!sub_801a1794(mgr) || !TooClose(mgr, dt)) {
|
|
x958_ = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime;
|
|
}
|
|
xb28_29_ = false;
|
|
xb28_28_ = false;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::TurnAround(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x9f4_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
|
|
x9f4_boneTracking.SetActive(true);
|
|
UpdateAttackPosition(mgr, x2e0_destPos);
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
CPatterned::PathFind(mgr, EStateMsg::Activate, dt);
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (!sub_8019ecdc(mgr, zeus::degToRad(15.f))) {
|
|
const float speedScale = GetModelData()->GetAnimationData()->GetSpeedScale();
|
|
const zeus::CVector3f aimPos =
|
|
(mgr.GetPlayer().GetAimPosition(mgr, speedScale > 0.f ? 1.25f / speedScale : 0.f).toVec2f() -
|
|
GetTranslation().toVec2f());
|
|
if (aimPos.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::skZero3f, aimPos.normalized(), 1.f});
|
|
}
|
|
}
|
|
x3b4_speed =
|
|
(GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn ? 2.f : 1.f) * x94c_;
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
x9f4_boneTracking.SetActive(false);
|
|
x3b4_speed = x94c_;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Crouch(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
|
|
mgr.GetPlayer().SetOrbitRequestForTarget(GetUniqueId(), CPlayer::EPlayerOrbitRequest::ActivateOrbitSource, mgr);
|
|
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Crouch);
|
|
x968_interestTimer = x56c_sheegothData.GetMaxInterestTime();
|
|
x400_24_hitByPlayerProjectile = false;
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
AddMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Taunt(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb29_25_ = true;
|
|
SetMouthVulnerability(mgr, true);
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Taunt) {
|
|
x568_ = 3;
|
|
} else {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCTauntCmd{pas::ETauntType::Zero});
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) {
|
|
x568_ = 4;
|
|
}
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
SetMouthVulnerability(mgr, false);
|
|
xb29_25_ = false;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb28_26_ = true;
|
|
xb29_25_ = true;
|
|
xb29_27_ = false;
|
|
x968_interestTimer = 0.f;
|
|
SetGillVulnerability(mgr, true);
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(
|
|
CBCProjectileAttackCmd{pas::ESeverity::Two, mgr.GetPlayer().GetTranslation(), false});
|
|
} else {
|
|
x568_ = 3;
|
|
x3b4_speed = 2.f * x94c_;
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
|
|
x568_ = 4;
|
|
}
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
x3b4_speed = x94c_;
|
|
if (!sub_801a1794(mgr)) {
|
|
x954_attackTimeLeft = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime;
|
|
}
|
|
|
|
if (CFlameThrower* fl = static_cast<CFlameThrower*>(mgr.ObjectById(xa80_flameThrowerId))) {
|
|
fl->Reset(mgr, false);
|
|
}
|
|
SetGillVulnerability(mgr, false);
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd{EBodyStateCmd::NextState});
|
|
}
|
|
xb29_25_ = false;
|
|
xb28_26_ = false;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Flinch(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb29_25_ = true;
|
|
SetGillVulnerability(mgr, true);
|
|
SetMouthVulnerability(mgr, true);
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd{x980_, pas::ESeverity::One});
|
|
} else {
|
|
x568_ = 4;
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) {
|
|
x568_ = 4;
|
|
}
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
SetGillVulnerability(mgr, true);
|
|
SetMouthVulnerability(mgr, true);
|
|
xb29_25_ = false;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Approach(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
GetBodyController()->SetLocomotionType(pas::ELocomotionType::Relaxed);
|
|
x9f4_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
|
|
UpdateAttackPosition(mgr, x2e0_destPos);
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
if (!xb29_27_) {
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
}
|
|
xb29_24_ = !xb29_24_;
|
|
xb29_28_ = true;
|
|
x92c_lastDest = mgr.GetPlayer().GetTranslation();
|
|
} else if (msg == EStateMsg::Update) {
|
|
SetPathFindMode(EPathFindMode::Approach);
|
|
if (xb29_24_) {
|
|
x2e0_destPos = x92c_lastDest;
|
|
if (x844_approachSearch.FindClosestReachablePoint(GetTranslation(), x2e0_destPos) ==
|
|
CPathFindSearch::EResult::Success) {
|
|
if ((GetTranslation() - x2e0_destPos).magSquared() < 81.f) {
|
|
x2e0_destPos = GetTranslation();
|
|
}
|
|
x92c_lastDest = x2e0_destPos;
|
|
CPatterned::PathFind(mgr, EStateMsg::Activate, dt);
|
|
if (!xb29_27_) {
|
|
GetBodyController()->GetCommandMgr().ClearLocomotionCmds();
|
|
}
|
|
}
|
|
xb29_24_ = false;
|
|
}
|
|
|
|
if (x56c_sheegothData.Get_x1f0_24() && GetSearchPath() != nullptr && !PathShagged(mgr, 0.f) &&
|
|
x760_pathSearch.GetCurrentWaypoint() < x760_pathSearch.GetWaypoints().size() - 1) {
|
|
CPatterned::PathFind(mgr, EStateMsg::Update, dt);
|
|
} else {
|
|
const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
if (sub_8019ecdc(mgr, zeus::degToRad(15.f)) && posDiff.canBeNormalized()) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::skZero3f, posDiff.normalized(), 1.f});
|
|
}
|
|
}
|
|
|
|
xb29_27_ = true;
|
|
x3b4_speed =
|
|
(GetBodyController()->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Turn ? 2.f : 1.f) * x94c_;
|
|
} else if (msg == EStateMsg::Deactivate) {
|
|
x9f4_boneTracking.SetActive(false);
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
x3b4_speed = x94c_;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::Enraged(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
xb28_30_ = true;
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Three));
|
|
} else {
|
|
x568_ = 3;
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
|
|
x568_ = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) {
|
|
if (msg == EStateMsg::Activate) {
|
|
x568_ = 0;
|
|
x968_interestTimer = 0.f;
|
|
xb28_27_ = true;
|
|
xb29_27_ = false;
|
|
} else if (msg == EStateMsg::Update) {
|
|
if (x568_ == 0) {
|
|
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::LoopAttack) {
|
|
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLoopAttackCmd{pas::ELoopAttackType::Zero, true});
|
|
} else {
|
|
x568_ = 4;
|
|
x3b4_speed = 2.f * x94c_;
|
|
}
|
|
} else if (x568_ == 3 &&
|
|
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::LoopAttack) {
|
|
x568_ = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CIceSheegoth::Leash(CStateManager& mgr, float arg) {
|
|
const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
if ((x3a0_latestLeashPosition - posDiff).magSquared() <= x3c8_leashRadius * x3c8_leashRadius) {
|
|
return false;
|
|
}
|
|
|
|
return posDiff.magSquared() > x3cc_playerLeashRadius && x3d4_curPlayerLeashTime > x3d0_playerLeashTime;
|
|
}
|
|
|
|
bool CIceSheegoth::OffLine(CStateManager& mgr, float arg) {
|
|
SetPathFindMode(EPathFindMode::Normal);
|
|
return PathShagged(mgr, arg);
|
|
}
|
|
|
|
bool CIceSheegoth::TooClose(CStateManager& mgr, float arg) {
|
|
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) {
|
|
const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
if (posDiff.z() < 0.f && posDiff.magSquared() < x978_) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::InMaxRange(CStateManager& mgr, float arg) {
|
|
if (x56c_sheegothData.Get_x1f0_24()) {
|
|
return true;
|
|
}
|
|
|
|
return CPatterned::InMaxRange(mgr, arg);
|
|
}
|
|
|
|
bool CIceSheegoth::InDetectionRange(CStateManager& mgr, float arg) {
|
|
if (xb28_24_shotAt) {
|
|
return true;
|
|
}
|
|
|
|
zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
float range = std::min(1.f, arg) * x3bc_detectionRange;
|
|
if (posDiff.magSquared() < range * range) {
|
|
if (x3c0_detectionHeightRange <= 0.f) {
|
|
return true;
|
|
}
|
|
return (posDiff.z() * posDiff.z()) < x3c0_detectionHeightRange * x3c0_detectionHeightRange;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::SpotPlayer(CStateManager& mgr, float arg) {
|
|
return xb28_24_shotAt || CPatterned::SpotPlayer(mgr, arg);
|
|
}
|
|
|
|
bool CIceSheegoth::AnimOver(CStateManager& mgr, float arg) { return x568_ == 4; }
|
|
|
|
bool CIceSheegoth::ShouldAttack(CStateManager& mgr, float arg) {
|
|
if (GetAreaIdAlways() == mgr.GetPlayer().GetAreaId() && x954_attackTimeLeft <= 0.f &&
|
|
x974_ >= 0.3333f * x56c_sheegothData.Get_x170() && sub_8019ecbc()) {
|
|
const zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
|
const zeus::CTransform lctrXf = GetLctrTransform(xaf4_mouthLocator);
|
|
if ((aimPos - lctrXf.origin).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange &&
|
|
!ShouldTurn(mgr, zeus::degToRad(15.f))) {
|
|
return !IsPatternObstructed(mgr, lctrXf.origin, aimPos);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::ShouldDoubleSnap(CStateManager& mgr, float arg) {
|
|
if (GetAreaIdAlways() != mgr.GetPlayer().GetAreaIdAlways() || x958_ > 0.f) {
|
|
return false;
|
|
}
|
|
SetPathFindMode(EPathFindMode::Approach);
|
|
return (!PathShagged(mgr, 0.f) && x760_pathSearch.GetCurrentWaypoint() < x760_pathSearch.GetWaypoints().size() - 1) ||
|
|
(x92c_lastDest - GetTranslation()).magSquared() < 81.f;
|
|
}
|
|
|
|
bool CIceSheegoth::InPosition(CStateManager& mgr, float arg) {
|
|
return (x92c_lastDest - GetTranslation()).magSquared() < 81.f;
|
|
}
|
|
|
|
bool CIceSheegoth::ShouldTurn(CStateManager& mgr, float arg) {
|
|
if (arg == 0.f) {
|
|
arg = zeus::degToRad(45.f);
|
|
}
|
|
return zeus::CVector2f::getAngleDiff(GetTransform().frontVector().toVec2f(),
|
|
mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f()) > arg;
|
|
}
|
|
|
|
bool CIceSheegoth::AggressionCheck(CStateManager& mgr, float arg) {
|
|
return !(!IsAlive() || xb28_30_ || !sub_801a1794(mgr));
|
|
}
|
|
|
|
bool CIceSheegoth::ShouldFire(CStateManager& mgr, float arg) {
|
|
if (GetAreaIdAlways() != mgr.GetPlayer().GetAreaIdAlways()) {
|
|
return false;
|
|
}
|
|
zeus::CVector3f pos = mgr.GetPlayer().GetTranslation();
|
|
zeus::CTransform lctrXf = GetLctrTransform(xaf4_mouthLocator);
|
|
if ((pos - lctrXf.origin).magSquared() <= x300_maxAttackRange * x300_maxAttackRange &&
|
|
std::fabs(pos.z() - GetTranslation().z()) < (lctrXf.origin.z() - GetTranslation().z()) &&
|
|
!ShouldTurn(mgr, 0.2617994f)) {
|
|
return !IsPatternObstructed(mgr, lctrXf.origin, pos);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::ShouldFlinch(CStateManager& mgr, float arg) { return xb29_25_ && x97c_ > 0.f; }
|
|
|
|
bool CIceSheegoth::ShotAt(CStateManager& mgr, float arg) { return x400_24_hitByPlayerProjectile; }
|
|
|
|
bool CIceSheegoth::ShouldSpecialAttack(CStateManager& mgr, float arg) {
|
|
if (GetAreaIdAlways() == mgr.GetPlayer().GetAreaId() && x954_attackTimeLeft <= 0.f &&
|
|
x974_ >= 0.3333f * x56c_sheegothData.Get_x170() && sub_8019ecbc()) {
|
|
const zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
|
const zeus::CTransform lctrXf = GetLctrTransform(xaf4_mouthLocator);
|
|
if ((aimPos - lctrXf.origin).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange &&
|
|
!ShouldTurn(mgr, zeus::degToRad(15.f))) {
|
|
return !IsPatternObstructed(mgr, lctrXf.origin, aimPos);
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::LostInterest(CStateManager& mgr, float arg) {
|
|
return x968_interestTimer >= x56c_sheegothData.GetMaxInterestTime();
|
|
}
|
|
|
|
void CIceSheegoth::UpdateTouchBounds() {
|
|
x978_ = 1.75f * GetModelData()->GetScale().y();
|
|
zeus::CAABox box{-x978_, -x978_, 0.f, x978_, x978_, 2.f * x978_};
|
|
SetBoundingBox(box);
|
|
xa30_.SetBox(box);
|
|
x760_pathSearch.SetCharacterRadius(x978_);
|
|
x760_pathSearch.SetCharacterHeight(x978_);
|
|
x760_pathSearch.SetPadding(20.f);
|
|
x844_approachSearch.SetCharacterRadius(x978_);
|
|
x844_approachSearch.SetCharacterHeight(x978_);
|
|
x844_approachSearch.SetPadding(20.f);
|
|
}
|
|
|
|
void CIceSheegoth::ApplyContactDamage(TUniqueId sender, CStateManager& mgr) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(sender)) {
|
|
if (colAct->GetHealthInfo(mgr)->GetHP() <= 0.f) {
|
|
return;
|
|
}
|
|
bool bite = (xb28_29_ && !xb28_25_ && xb28_28_) ? true : IsMouthCollider(sender);
|
|
|
|
if (colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId()) {
|
|
if (!bite) {
|
|
if (x420_curDamageRemTime <= 0.f) {
|
|
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), GetContactDamage(),
|
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f);
|
|
}
|
|
} else {
|
|
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), x56c_sheegothData.Get_x1b8(),
|
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::AddSphereCollisionList(const SSphereJointInfo* info, size_t count,
|
|
std::vector<CJointCollisionDescription>& vecOut) {
|
|
for (size_t i = 0; i < count; ++i) {
|
|
const auto& joint = info[i];
|
|
CSegId id = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.name);
|
|
if (id.IsInvalid()) {
|
|
continue;
|
|
}
|
|
vecOut.push_back(CJointCollisionDescription::SphereCollision(id, joint.radius, joint.name, 1000.f));
|
|
xb1c_.push_back(id);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::AddCollisionList(const SJointInfo* info, size_t count,
|
|
std::vector<CJointCollisionDescription>& vecOut) {
|
|
for (size_t i = 0; i < count; ++i) {
|
|
const auto& joint = info[i];
|
|
CSegId fromId = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.from);
|
|
CSegId toId = GetModelData()->GetAnimationData()->GetLocatorSegId(joint.to);
|
|
if (fromId.IsInvalid() || toId.IsInvalid()) {
|
|
continue;
|
|
}
|
|
vecOut.push_back(CJointCollisionDescription::SphereSubdivideCollision(
|
|
fromId, toId, joint.radius, joint.separation, CJointCollisionDescription::EOrientationType::One, joint.from,
|
|
1000.f));
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SetupCollisionActorManager(CStateManager& mgr) {
|
|
std::vector<CJointCollisionDescription> joints;
|
|
joints.reserve(7);
|
|
AddSphereCollisionList(skSphereJointList.data(), skSphereJointList.size(), joints);
|
|
AddCollisionList(skLeftLegJointList.data(), skLeftLegJointList.size(), joints);
|
|
AddCollisionList(skRightLegJointList.data(), skRightLegJointList.size(), joints);
|
|
xa2c_collisionManager = std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), joints, true);
|
|
xa2c_collisionManager->SetActive(mgr, GetActive());
|
|
xa2c_collisionManager->AddMaterial(mgr, EMaterialTypes::CameraPassthrough);
|
|
xb04_.clear();
|
|
xafc_gillColliders.clear();
|
|
|
|
for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) {
|
|
const auto& desc = xa2c_collisionManager->GetCollisionDescFromIndex(i);
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(desc.GetCollisionActorId())) {
|
|
colAct->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerabilty());
|
|
if (desc.GetName() == "LCTR_SHEMOUTH"sv) {
|
|
xaf8_mouthCollider = desc.GetCollisionActorId();
|
|
colAct->SetDamageVulnerability(x98c_mouthVulnerability);
|
|
} else if (desc.GetName() == "Jaw_end_LCTR"sv) {
|
|
colAct->SetDamageVulnerability(CDamageVulnerability::PassThroughVulnerabilty());
|
|
} else if (desc.GetName() == "Ice_Shards_LCTR"sv) {
|
|
xaf6_iceShardsCollider = desc.GetCollisionActorId();
|
|
colAct->SetWeaponCollisionResponseType(EWeaponCollisionResponseTypes::None);
|
|
} else if (desc.GetName() == "GillL_LCTR"sv || desc.GetName() == "GillR_LCTR"sv) {
|
|
xafc_gillColliders.emplace_back(desc.GetCollisionActorId());
|
|
} else {
|
|
xb04_.emplace_back(desc.GetCollisionActorId());
|
|
colAct->SetDamageVulnerability(x56c_sheegothData.Get_x80());
|
|
}
|
|
}
|
|
}
|
|
|
|
SetupHealthInfo(mgr);
|
|
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
|
|
{EMaterialTypes::Solid},
|
|
{EMaterialTypes::Player, EMaterialTypes::CollisionActor, EMaterialTypes::AIPassthrough}));
|
|
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
|
|
xa2c_collisionManager->AddMaterial(mgr, {EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough});
|
|
}
|
|
|
|
void CIceSheegoth::SetupHealthInfo(CStateManager& mgr) {
|
|
CHealthInfo* thisHealth = HealthInfo(mgr);
|
|
x970_maxHp = thisHealth->GetHP();
|
|
for (auto& id : xafc_gillColliders) {
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(id)) {
|
|
*colAct->HealthInfo(mgr) = *thisHealth;
|
|
}
|
|
}
|
|
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(xaf8_mouthCollider)) {
|
|
*colAct->HealthInfo(mgr) = *thisHealth;
|
|
}
|
|
|
|
for (auto& id : xb04_) {
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(id)) {
|
|
*colAct->HealthInfo(mgr) = *thisHealth;
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::sub_8019ebf0(CStateManager& mgr, float damage) {
|
|
x974_ = zeus::clamp(0.f, x974_ + damage, x56c_sheegothData.Get_x170());
|
|
float fVar1 = (1.f / 3.f) * x56c_sheegothData.Get_x170();
|
|
if (fVar1 <= 0.f) {
|
|
xb29_26_ = true;
|
|
} else {
|
|
xb29_26_ = mgr.GetActiveRandom()->Float() <= (x974_ / (3.f * fVar1));
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::ApplyWeaponDamage(CStateManager& mgr, TUniqueId sender) {
|
|
if (const TCastToConstPtr<CWeapon> wp = mgr.GetObjectById(sender)) {
|
|
mgr.ApplyDamage(sender, xaf8_mouthCollider, wp->GetOwnerId(), wp->GetDamageInfo(),
|
|
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), zeus::skZero3f);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::CreateFlameThrower(CStateManager& mgr) {
|
|
if (xa80_flameThrowerId != kInvalidUniqueId) {
|
|
return;
|
|
}
|
|
|
|
xa80_flameThrowerId = mgr.AllocateUniqueId();
|
|
mgr.AddObject(new CFlameThrower(xa84_, "IceSheegoth_Flame"sv, EWeaponType::Plasma,
|
|
CFlameInfo{6, 4, x56c_sheegothData.GetFireBreathResId(), 15, 0.0625f, 20.f, 1.f}, {},
|
|
EMaterialTypes::CollisionActor, x56c_sheegothData.GetFireBreathDamage(),
|
|
xa80_flameThrowerId, GetAreaIdAlways(), GetUniqueId(), EProjectileAttrib::None,
|
|
x56c_sheegothData.Get_x1e4(), x56c_sheegothData.Get_x1e8(),
|
|
x56c_sheegothData.Get_x1ec()));
|
|
}
|
|
void CIceSheegoth::AttractProjectiles(CStateManager& mgr) {
|
|
if (!IsAlive())
|
|
return;
|
|
|
|
EntityList nearProjectiles;
|
|
zeus::CAABox attractionBounds =
|
|
zeus::CAABox{GetTranslation() - x56c_sheegothData.Get_x14(), GetTranslation() + x56c_sheegothData.Get_x14()};
|
|
mgr.BuildNearList(nearProjectiles, attractionBounds, CMaterialFilter::MakeInclude({EMaterialTypes::Projectile}),
|
|
nullptr);
|
|
|
|
if (nearProjectiles.empty())
|
|
return;
|
|
|
|
zeus::CVector3f attractionPos = GetEnergyAttractionPos(mgr);
|
|
EntityList nearCharacters;
|
|
mgr.BuildNearList(nearCharacters, attractionBounds, CMaterialFilter::MakeInclude({EMaterialTypes::Character}),
|
|
nullptr);
|
|
|
|
for (TUniqueId projectileId : nearProjectiles) {
|
|
if (TCastToPtr<CGameProjectile> proj = mgr.ObjectById(projectileId)) {
|
|
if (!ShouldAttractProjectile(*proj, mgr))
|
|
continue;
|
|
|
|
const zeus::CVector3f projPos = (attractionPos - proj->GetTranslation()) - proj->GetPreviousPos();
|
|
if (!projPos.canBeNormalized() || !IsClosestSheegoth(mgr, nearCharacters, projPos))
|
|
continue;
|
|
|
|
const float mag = (attractionPos - proj->GetTranslation()).magnitude();
|
|
const zeus::CVector3f b =
|
|
proj->GetTranslation() + (0.5f * mag) * (proj->GetTranslation() - proj->GetPreviousPos()).normalized();
|
|
const zeus::CVector3f c = attractionPos + zeus::CVector3f{0.f, 0.f, 0.4f * (0.4f * mag)};
|
|
const zeus::CVector3f point1 = zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos, 0.333f);
|
|
const zeus::CVector3f point2 = zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos, 0.666f);
|
|
const float t = (point2 - point1).magnitude() + (point1 - proj->GetTranslation()).magnitude() +
|
|
(attractionPos - point2).magnitude();
|
|
const zeus::CVector3f point3 =
|
|
zeus::getBezierPoint(proj->GetTranslation(), b, c, attractionPos,
|
|
t / (proj->GetTranslation() - proj->GetPreviousPos()).magnitude());
|
|
zeus::CVector3f lookPos = point3 - proj->GetTranslation();
|
|
if (!lookPos.canBeNormalized()) {
|
|
return;
|
|
}
|
|
|
|
zeus::CTransform xf = zeus::lookAt(zeus::skZero3f, lookPos);
|
|
xf.orthonormalize();
|
|
proj->ProjectileWeapon().SetWorldSpaceOrientation(xf);
|
|
zeus::CVector3f velocity = 0.8f * proj->GetProjectileWeapon().GetVelocity().normalized();
|
|
proj->ProjectileWeapon().SetVelocity(proj->ProjectileWeapon().GetVelocity() * (0.3999f + (velocity * 0.6f)));
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::UpdateTimers(float dt) {
|
|
if (x954_attackTimeLeft > 0.f) {
|
|
x954_attackTimeLeft -= (xb29_27_ ? 2.f : 1.f) * dt;
|
|
}
|
|
if (x960_ > 0.f) {
|
|
x960_ -= dt;
|
|
}
|
|
if (x97c_ > 0.f) {
|
|
x97c_ -= dt;
|
|
}
|
|
if (x958_ > 0.f) {
|
|
x958_ -= dt;
|
|
}
|
|
if (x968_interestTimer < x56c_sheegothData.GetMaxInterestTime()) {
|
|
x968_interestTimer += dt;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::UpdateScanState(CStateManager& mgr) {
|
|
if (!xb29_29_scanned && GetScannableObjectInfo() != nullptr &&
|
|
zeus::close_enough(1.f, mgr.GetPlayerState()->GetScanTime(GetScannableObjectInfo()->GetScannableObjectId()))) {
|
|
xb29_29_scanned = true;
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SetPassthroughVulnerability(CStateManager& mgr) {
|
|
for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) {
|
|
const auto& jInfo = xa2c_collisionManager->GetCollisionDescFromIndex(i);
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(jInfo.GetCollisionActorId())) {
|
|
colAct->AddMaterial(EMaterialTypes::ProjectilePassthrough);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::PreventWorldCollisions(float dt, CStateManager& mgr) {
|
|
if (GetBodyController()->GetLocomotionType() == pas::ELocomotionType::Crouch || !IsOnGround() ||
|
|
mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) {
|
|
return;
|
|
}
|
|
|
|
zeus::CAABox ourBox = GetModelData()->GetBounds(GetTransform());
|
|
zeus::CAABox plBox = mgr.GetPlayer().GetBoundingBox();
|
|
if (!ourBox.intersects(plBox)) {
|
|
return;
|
|
}
|
|
|
|
zeus::CVector3f maxDeviation = zeus::skZero3f;
|
|
float lastMag = 0.f;
|
|
zeus::CVector3f predictedTrans = PredictMotion(dt).x0_translation;
|
|
for (CSegId uid : xb1c_) {
|
|
auto deviation = xa2c_collisionManager->GetDeviation(mgr, uid);
|
|
if (!deviation) {
|
|
continue;
|
|
}
|
|
const zeus::CVector3f curDeviation = ((*deviation) + predictedTrans);
|
|
if (curDeviation.magnitude() > lastMag) {
|
|
maxDeviation = curDeviation;
|
|
lastMag = curDeviation.magnitude();
|
|
}
|
|
}
|
|
|
|
if (lastMag <= (0.6f * GetModelData()->GetScale().y())) {
|
|
return;
|
|
}
|
|
|
|
zeus::CVector3f posDiff = GetTranslation() - mgr.GetPlayer().GetTranslation();
|
|
const zeus::CVector3f direction = GetTransform().transposeRotate(
|
|
(posDiff.dot(posDiff * maxDeviation.normalized()) / posDiff.magSquared()) * posDiff);
|
|
ApplyImpulseOR(GetMoveToORImpulseWR(direction, dt), zeus::CAxisAngle{});
|
|
}
|
|
|
|
void CIceSheegoth::UpdateHealthInfo(CStateManager& mgr) {
|
|
if (!IsAlive()) {
|
|
return;
|
|
}
|
|
|
|
float hpDelta = 0.f;
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(xaf8_mouthCollider)) {
|
|
hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP());
|
|
}
|
|
|
|
for (const auto& uid : xafc_gillColliders) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
|
|
hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP());
|
|
}
|
|
}
|
|
|
|
for (const auto& uid : xb04_) {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
|
|
hpDelta = std::max(hpDelta, x970_maxHp - colAct->GetHealthInfo(mgr)->GetHP());
|
|
}
|
|
}
|
|
HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - hpDelta);
|
|
if (GetHealthInfo(mgr)->GetHP() > 0.f) {
|
|
if (const TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(xaf8_mouthCollider)) {
|
|
colAct->HealthInfo(mgr)->SetHP(x970_maxHp);
|
|
}
|
|
for (const auto& uid : xafc_gillColliders) {
|
|
if (const TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
|
|
colAct->HealthInfo(mgr)->SetHP(x970_maxHp);
|
|
}
|
|
}
|
|
|
|
for (const auto& uid : xb04_) {
|
|
if (const TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
|
|
colAct->HealthInfo(mgr)->SetHP(x970_maxHp);
|
|
}
|
|
}
|
|
} else {
|
|
Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SetSteeringSpeed(float dt, CStateManager& mgr) {
|
|
const float steeringSpeedRange = x95c_ > 0.f ? 1.f : x944_;
|
|
|
|
if (steeringSpeedRange > x948_) {
|
|
x948_ = std::max(steeringSpeedRange, x948_ - (2.f * dt));
|
|
} else if (steeringSpeedRange < x948_) {
|
|
x948_ = std::min(steeringSpeedRange, x948_ + (2.f * dt));
|
|
}
|
|
|
|
GetBodyController()->GetCommandMgr().SetSteeringSpeedRange(x948_, x948_);
|
|
}
|
|
|
|
void CIceSheegoth::UpdateParticleEffects(float dt, CStateManager& mgr) {
|
|
if (auto* fl = static_cast<CFlameThrower*>(mgr.ObjectById(xa80_flameThrowerId))) {
|
|
if (fl->GetActive()) {
|
|
fl->SetTransform(GetLctrTransform("LCTR_SHEMOUTH"sv), dt);
|
|
}
|
|
}
|
|
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) {
|
|
const float time = 0.333f * x56c_sheegothData.Get_x170();
|
|
if (x974_ >= 3.f * time) {
|
|
xa9c_->SetParticleEmission(false);
|
|
xab0_->SetParticleEmission(false);
|
|
xac4_->SetParticleEmission(true);
|
|
xad8_->SetParticleEmission(true);
|
|
} else if (x974_ >= 2.f * time) {
|
|
xa9c_->SetParticleEmission(false);
|
|
xab0_->SetParticleEmission(true);
|
|
xac4_->SetParticleEmission(false);
|
|
xad8_->SetParticleEmission(false);
|
|
} else {
|
|
xa9c_->SetParticleEmission(x974_ > 0.f);
|
|
xab0_->SetParticleEmission(false);
|
|
xac4_->SetParticleEmission(false);
|
|
xad8_->SetParticleEmission(false);
|
|
}
|
|
|
|
const zeus::CTransform rotation = GetTransform().getRotation();
|
|
const zeus::CVector3f pos = colAct->GetTranslation();
|
|
xa9c_->SetOrientation(rotation);
|
|
xa9c_->SetGlobalTranslation(pos);
|
|
xab0_->SetOrientation(rotation);
|
|
xab0_->SetGlobalTranslation(pos);
|
|
xac4_->SetOrientation(rotation);
|
|
xac4_->SetGlobalTranslation(pos);
|
|
xad8_->SetOrientation(rotation);
|
|
xad8_->SetGlobalTranslation(pos);
|
|
if (xaec_) {
|
|
xaec_->SetParticleEmission(true);
|
|
xaec_->SetOrientation(rotation);
|
|
xaec_->SetGlobalTranslation(pos);
|
|
xaec_->SetGlobalScale(GetModelData()->GetScale());
|
|
xaec_->Update(dt);
|
|
}
|
|
xa9c_->Update(dt);
|
|
xab0_->Update(dt);
|
|
xac4_->Update(dt);
|
|
xad8_->Update(dt);
|
|
if (x974_ < 2.f * time && xaf0_crackleSfx) {
|
|
CSfxManager::RemoveEmitter(xaf0_crackleSfx);
|
|
} else {
|
|
xaf0_crackleSfx = CSfxManager::AddEmitter(x56c_sheegothData.Get_x1d4(), GetTranslation(), zeus::skZero3f, false,
|
|
true, 127, kInvalidAreaId);
|
|
}
|
|
} else {
|
|
xa9c_->SetParticleEmission(false);
|
|
xab0_->SetParticleEmission(false);
|
|
xac4_->SetParticleEmission(false);
|
|
xad8_->SetParticleEmission(false);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::UpdateAttackPosition(CStateManager& mgr, zeus::CVector3f& attackPos) {
|
|
attackPos = GetTranslation();
|
|
if (x954_attackTimeLeft > 0.f) {
|
|
return;
|
|
}
|
|
|
|
attackPos = mgr.GetPlayer().GetTranslation();
|
|
zeus::CVector3f distVec = GetTranslation() - attackPos;
|
|
if (distVec.canBeNormalized()) {
|
|
attackPos += x2fc_minAttackRange * distVec.normalized();
|
|
}
|
|
}
|
|
|
|
bool CIceSheegoth::sub_8019ecdc(CStateManager& mgr, float minAngle) {
|
|
const zeus::CVector3f plAimPos =
|
|
mgr.GetPlayer().GetAimPosition(mgr, GetModelData()->GetAnimationData()->GetSpeedScale() > 0.f
|
|
? 1.25f / GetModelData()->GetAnimationData()->GetSpeedScale()
|
|
: 0.f);
|
|
return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(),
|
|
plAimPos.toVec2f() - GetTranslation().toVec2f()) > minAngle;
|
|
}
|
|
|
|
void CIceSheegoth::SetMouthVulnerability(CStateManager& mgr, bool isVulnerable) {
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(xaf8_mouthCollider)) {
|
|
colAct->SetDamageVulnerability(isVulnerable ? x56c_sheegothData.Get_xe8() : x98c_mouthVulnerability);
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SetGillVulnerability(CStateManager& mgr, bool isVulnerable) {
|
|
for (TUniqueId uid : xafc_gillColliders) {
|
|
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
|
|
colAct->SetDamageVulnerability(isVulnerable ? x56c_sheegothData.Get_x18()
|
|
: CDamageVulnerability::ImmuneVulnerabilty());
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::SetCollisionActorExtendedTouchBounds(CStateManager& mgr, const zeus::CVector3f& extents) {
|
|
for (size_t i = 0; i < xa2c_collisionManager->GetNumCollisionActors(); ++i) {
|
|
if (TCastToPtr<CCollisionActor> colAct =
|
|
mgr.ObjectById(xa2c_collisionManager->GetCollisionDescFromIndex(i).GetCollisionActorId())) {
|
|
colAct->SetExtendedTouchBounds(extents);
|
|
}
|
|
}
|
|
}
|
|
|
|
void CIceSheegoth::ShakePlayer(CStateManager& mgr) {
|
|
const zeus::CVector3f posDiff = mgr.GetPlayer().GetTranslation() - GetTranslation();
|
|
const float magnitude = (0.5f - (0.01f * posDiff.magnitude()));
|
|
if (magnitude > 0.f) {
|
|
if (mgr.GetPlayer().GetSurfaceRestraint() != CPlayer::ESurfaceRestraints::Air &&
|
|
!mgr.GetPlayer().IsInWaterMovement()) {
|
|
bool applyImpulseToPlayer = true;
|
|
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) {
|
|
if (mgr.GetCameraManager()->GetCurrentCameraId() ==
|
|
mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId()) {
|
|
mgr.GetCameraManager()->AddCameraShaker(
|
|
CCameraShakeData::BuildPatternedExplodeShakeData(GetTranslation(), 0.5f, magnitude, 50.f), true);
|
|
}
|
|
applyImpulseToPlayer = xb28_27_;
|
|
}
|
|
|
|
if (applyImpulseToPlayer) {
|
|
const zeus::CVector3f direction = magnitude * ((xb28_27_ ? 40.f : 25.f) * zeus::skUp);
|
|
zeus::CVector3f impulse = zeus::skZero3f;
|
|
if (x978_ < posDiff.magnitude() && xb28_27_ && posDiff.toVec2f().canBeNormalized()) {
|
|
impulse = magnitude * (12.5f * posDiff.toVec2f().normalized());
|
|
}
|
|
mgr.GetPlayer().ApplyImpulseWR(mgr.GetPlayer().GetMass() * (direction + impulse), zeus::CAxisAngle{});
|
|
mgr.GetPlayer().SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xb28_28_) {
|
|
sub_8019ebf0(mgr, 0.25f * x56c_sheegothData.Get_x170());
|
|
}
|
|
}
|
|
|
|
zeus::CVector3f CIceSheegoth::GetEnergyAttractionPos(CStateManager& mgr) const {
|
|
if (const TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(xaf6_iceShardsCollider)) {
|
|
return colAct->GetTranslation();
|
|
}
|
|
|
|
return GetTranslation();
|
|
}
|
|
|
|
bool CIceSheegoth::ShouldAttractProjectile(const CGameProjectile& proj, CStateManager& mgr) const {
|
|
if (proj.GetType() != EWeaponType::Missile && proj.GetType() != EWeaponType::Plasma &&
|
|
(!proj.GetDamageInfo().GetWeaponMode().IsComboed() || proj.GetType() != EWeaponType::Power)) {
|
|
const CActor* ent = static_cast<const CActor*>(mgr.GetObjectById(proj.GetOwnerId()));
|
|
if (ent != nullptr) {
|
|
if (CPatterned::CastTo<CIceSheegoth>(ent) == nullptr && ent->GetAreaIdAlways() == GetAreaIdAlways()) {
|
|
zeus::CVector3f r = GetTransform().rotate(x56c_sheegothData.Get_x8());
|
|
zeus::CVector3f posDiff = proj.GetTranslation() - ent->GetTranslation();
|
|
if (proj.GetType() == EWeaponType::Wave && !proj.GetDamageInfo().GetWeaponMode().IsCharged() &&
|
|
!proj.GetDamageInfo().GetWeaponMode().IsComboed() && posDiff.magSquared() < 100.f) {
|
|
return false;
|
|
}
|
|
|
|
zeus::CVector3f xyPos = posDiff.toVec2f() - GetTranslation().toVec2f() + r.toVec2f();
|
|
if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), xyPos) <= x56c_sheegothData.Get_x4()) {
|
|
if (zeus::CVector3f::getAngleDiff(GetTransform().frontVector(), -xyPos) >= x56c_sheegothData.Get_x0()) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CIceSheegoth::IsClosestSheegoth(CStateManager& mgr, const EntityList& nearList,
|
|
const zeus::CVector3f& projectileOffset) const {
|
|
zeus::CVector3f diff = projectileOffset - GetTranslation();
|
|
const float diffMag = diff.magSquared();
|
|
for (const auto& uid : nearList) {
|
|
const CIceSheegoth* goth = CPatterned::CastTo<CIceSheegoth>(mgr.GetObjectById(uid));
|
|
if (!goth || goth->GetUniqueId() == GetUniqueId())
|
|
continue;
|
|
|
|
diff = projectileOffset - goth->GetTranslation();
|
|
if (diff.magSquared() < diffMag) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
} // namespace metaforce::MP1
|