metaforce/Runtime/MP1/World/CThardus.cpp

1599 lines
57 KiB
C++
Raw Normal View History

#include "Runtime/MP1/World/CThardus.hpp"
#include <array>
2020-09-12 04:37:45 +00:00
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
2020-01-06 04:24:54 +00:00
#include "Runtime/Camera/CCameraManager.hpp"
#include "Runtime/Camera/CFirstPersonCamera.hpp"
#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/Collision/CCollisionActorManager.hpp"
#include "Runtime/MP1/CSamusHud.hpp"
#include "Runtime/MP1/World/CIceAttackProjectile.hpp"
2019-12-14 23:50:29 +00:00
#include "Runtime/MP1/World/CThardusRockProjectile.hpp"
2020-07-26 04:53:49 +00:00
#include "Runtime/Weapon/CGameProjectile.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "Runtime/World/CDestroyableRock.hpp"
2019-12-14 23:50:29 +00:00
#include "Runtime/World/CGameLight.hpp"
#include "Runtime/World/CPatternedInfo.hpp"
#include "Runtime/World/CPlayer.hpp"
2020-09-12 04:37:45 +00:00
#include "Runtime/World/CRepulsor.hpp"
#include "Runtime/World/CScriptDistanceFog.hpp"
2019-12-14 23:50:29 +00:00
#include "Runtime/World/CScriptWaypoint.hpp"
#include "Runtime/World/CWorld.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
#include <DataSpec/DNAMP1/SFX/IceWorld.h>
2020-07-26 04:53:49 +00:00
#include <DataSpec/DNAMP1/SFX/Thardus.h>
2021-04-10 08:42:06 +00:00
namespace metaforce::MP1 {
2019-12-14 23:50:29 +00:00
namespace {
constexpr std::array<SSphereJointInfo, 7> skDamageableSphereJointInfoList1{{
{"R_knee", 1.f},
2019-12-14 23:50:29 +00:00
{"R_Elbow_Collision_LCTR", 1.5f},
{"L_Elbow_Collision_LCTR", 1.5f},
{"L_Knee_Collision_LCTR", 1.f},
{"R_Back_Rock_Collision_LCTR", 2.5f},
{"L_Back_Rock_Collision_LCTR", 1.5f},
{"Head_Collision_LCTR", 1.5f},
}};
2019-12-14 23:50:29 +00:00
constexpr std::array<SSphereJointInfo, 5> skDamageableSphereJointInfoList2{{
{"R_Shoulder_Collision_LCTR", 0.75f},
{"L_Shoulder_Collision_LCTR", 0.75f},
{"Spine_Collision_LCTR", 0.75f},
{"R_Hand_Collision_LCTR", 2.25f},
{"L_Hand_Collision_LCTR", 2.f},
}};
2019-12-14 23:50:29 +00:00
constexpr std::array<SAABoxJointInfo, 2> skFootCollision{{
2019-12-14 23:50:29 +00:00
{"R_Foot_Collision_LCTR", zeus::CVector3f(3.f, 3.f, 1.f)},
{"L_Foot_Collision_LCTR", zeus::CVector3f(3.f, 2.f, 3.f)},
}};
2019-12-14 23:50:29 +00:00
constexpr std::array skSearchJointNames{
"R_knee"sv,
2019-12-14 23:50:29 +00:00
"R_Elbow_Collision_LCTR"sv,
"L_Elbow_Collision_LCTR"sv,
"L_Knee_Collision_LCTR"sv,
"R_Back_Rock_Collision_LCTR"sv,
"L_Back_Rock_Collision_LCTR"sv,
"Head_Collision_LCTR"sv,
};
2020-01-06 04:24:54 +00:00
constexpr std::array skRockJoints{
2020-01-06 04:24:54 +00:00
"R_knee"sv, "R_forearm"sv, "L_elbow"sv, "L_hip"sv, "R_collar_BigRock_SDK"sv, "collar_rock4_SDK"sv, "Neck_1"sv,
};
} // Anonymous namespace
CThardus::CThardus(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo,
std::vector<CStaticRes> mData1, std::vector<CStaticRes> mData2, CAssetId particle1,
CAssetId particle2, CAssetId particle3, float f1, float f2, float f3, float f4, float f5, float f6,
CAssetId stateMachine, CAssetId particle4, CAssetId particle5, CAssetId particle6,
CAssetId particle7, CAssetId particle8, CAssetId particle9, CAssetId texture, u32 sfxId1,
CAssetId particle10, u32 sfxId2, u32 sfxId3, u32 sfxId4)
: CPatterned(ECharacter::Thardus, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large)
, x5cc_(std::move(mData1))
, x5dc_(std::move(mData2))
, x600_(particle1)
, x604_(particle2)
, x608_(particle3)
, x630_(stateMachine)
, x694_(f1)
, x698_(f2)
, x6a0_(f3)
, x6a4_(f4)
, x6a8_(f5)
, x6ac_(f6)
, x6d0_(particle4)
, x6d4_(particle5)
, x6d8_(particle6)
, x6dc_(particle7)
, x6e0_(particle8)
, x6e4_(particle9)
, x6e8_(texture)
, x6ec_(CSfxManager::TranslateSFXID(sfxId1))
, x6f0_(particle10)
, x758_(sfxId2)
, x75c_(sfxId3)
, x760_(sfxId4)
2020-01-06 04:24:54 +00:00
, x7f0_pathFindSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f) {
CMaterialList exclude = GetMaterialFilter().GetExcludeList();
CMaterialList include = GetMaterialFilter().GetIncludeList();
exclude.Add(EMaterialTypes::Player);
exclude.Add(EMaterialTypes::Character);
exclude.Add(EMaterialTypes::CollisionActor);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
std::vector<CAssetId> gens;
gens.reserve(6);
gens.push_back(particle4);
gens.push_back(particle5);
gens.push_back(particle6);
gens.push_back(particle7);
gens.push_back(particle8);
gens.push_back(particle9);
GetModelData()->GetAnimationData()->GetParticleDB().CacheParticleDesc(
CCharacterInfo::CParticleResData(std::move(gens), {}, {}, {}));
x798_.reserve(6);
2020-01-06 04:24:54 +00:00
x7a8_timers.reserve(16);
UpdateThermalFrozenState(true);
xd0_damageMag = 0.f;
x50c_baseDamageMag = 0.f;
2020-01-06 04:24:54 +00:00
x8f4_waypoints.reserve(16);
x91c_flareTexture = g_SimplePool->GetObj("Thermal_Spot_2"sv);
x91c_flareTexture.Lock();
x403_26_stateControlledMassiveDeath = false;
x460_knockBackController.SetAutoResetImpulse(false);
SetMass(100000.f);
}
2021-05-06 17:53:19 +00:00
void CThardus::UpdateRockThermalState(float dt, CStateManager& mgr) {
if (x7c4_ == 0) {
x93a_ = false;
return;
}
bool bVar9 = false;
float dVar15 = 0.f;
float dVar13 = 1.f;
if (x928_currentRockId != kInvalidUniqueId) {
if (TCastToPtr<CActor> rock = mgr.ObjectById(x928_currentRockId)) {
x92c_currentRockPos = rock->GetTranslation();
} else {
x928_currentRockId = kInvalidUniqueId;
}
}
if (!x939_) {
CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
zeus::CVector3f posDiff = x92c_currentRockPos - cam->GetTranslation();
zeus::CVector3f camFront = cam->GetTransform().frontVector();
zeus::CVector3f direction = posDiff.normalized();
dVar13 = 0.f;
float dVar11 = direction.dot(camFront);
if (dVar13 <= dVar11) {
dVar13 = dVar11 * dVar11;
}
}
if (x7c4_ == 2) {
dVar15 = -(x7b8_ <= 2.f ? x7b8_ : 2.f) * 0.5f - 1.f; // std::min doesn't quite cut the mustard here
if (x7b8_ > 2.f) {
x7c4_ = 0;
x7b8_ = 0.f;
x7c0_ = 0.f;
}
x7b8_ += dt;
} else if (x7c4_ == 1) {
dVar15 = (x7b8_ <= 0.25f ? x7b8_ : 0.25f) / 0.25f;
if (x7b8_ > 0.25f) {
x7c4_ = 3;
x7b8_ = 0.f;
}
x7b8_ += dt;
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) {
x688_ = true;
}
} else if (x7c4_ == 3) {
dVar15 = 1.f;
if (x7bc_ < x7b8_ && !x938_) {
x7c4_ = 2;
x7b8_ = 0.f;
}
x7b8_ += dt;
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) {
bVar9 = false;
x688_ = true;
if (x938_ && dVar13 > 0.75f) {
bVar9 = true;
}
}
}
x7c0_ = dVar15 * dVar13;
const float mag = 0.8f * (dVar15 * dVar13);
mgr.SetThermalColdScale2(mgr.GetThermalColdScale2() + mag);
x50c_baseDamageMag = mag;
if (x93a_ != bVar9) {
if (bVar9) {
CSamusHud::DisplayHudMemo(g_MainStringTable->GetString(18), CHUDMemoParms(5.f, true, false, false));
}
x93a_ = bVar9;
}
}
void CThardus::sub801de9f8(CStateManager& mgr) {
float dVar5 = mgr.GetActiveRandom()->Float();
if (!sub801dc2c8() || dVar5 >= 0.3f) {
2020-09-12 04:37:45 +00:00
const float local_28 = std::max(0.f, dVar5 - 0.19999999f);
if (local_28 > 0.8f) {
x5c4_ = 2;
} else if (local_28 >= 0.4f) {
x5c4_ = 1;
} else {
x5c4_ = 0;
}
++x574_;
x944_ = 0.3f;
} else {
x93b_ = true;
}
}
2020-01-06 04:24:54 +00:00
void CThardus::sub801dd608(CStateManager& mgr) {
zeus::CVector3f scale = GetModelData()->GetScale();
CAnimData* animData = GetModelData()->GetAnimationData();
for (size_t i = 0; i < x610_destroyableRocks.size(); ++i) {
zeus::CTransform xf =
GetTransform() * (zeus::CTransform::Scale(scale) * animData->GetLocatorTransform(skRockJoints[i], nullptr));
2020-09-12 04:37:45 +00:00
if (TCastToPtr<CActor> act = mgr.ObjectById(x610_destroyableRocks[i])) {
2020-01-06 04:24:54 +00:00
act->SetTransform(xf);
2020-09-12 04:37:45 +00:00
}
if (TCastToPtr<CGameLight> gl = mgr.ObjectById(x6c0_rockLights[i])) {
2020-01-06 04:24:54 +00:00
gl->SetTransform(xf);
2020-09-12 04:37:45 +00:00
}
2020-01-06 04:24:54 +00:00
}
}
void CThardus::sub801dcfa4(CStateManager& mgr) {
for (size_t j = 0; j < x5f0_rockColliders->GetNumCollisionActors(); ++j) {
const auto& jInfo = x5f0_rockColliders->GetCollisionDescFromIndex(j);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(jInfo.GetCollisionActorId())) {
if (!colAct->GetActive()) {
continue;
}
TUniqueId rockId = x610_destroyableRocks[j];
2020-09-13 19:03:49 +00:00
if (auto* rock = static_cast<CDestroyableRock*>(mgr.ObjectById(rockId))) {
if (x909_) {
*rock->HealthInfo(mgr) = CHealthInfo(x90c_rockHealths[j], 0.f);
}
if (j == x648_currentRock && !x93d_) {
colAct->SetDamageVulnerability(*rock->GetDamageVulnerability());
rock->SetThermalMag(0.8f);
} else {
colAct->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerabilty());
rock->SetThermalMag(0.f);
}
CHealthInfo* hInfo = colAct->HealthInfo(mgr);
2020-09-13 19:03:49 +00:00
if (hInfo != nullptr) {
if (hInfo->GetHP() > 0.f) {
*rock->HealthInfo(mgr) = *hInfo;
if (!x909_) {
x90c_rockHealths[j] = hInfo->GetHP();
}
} else if (!rock->IsUsingPhazonModel()) {
2021-05-06 17:53:19 +00:00
BreakRock(mgr, j);
DoFaint(mgr);
} else {
rock->SetActive(false);
colAct->SetActive(false);
mgr.ObjectById(x6c0_rockLights[j])->SetActive(false);
++x648_currentRock;
DoFlinch(mgr);
const bool isThermalActive = mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal;
if (isThermalActive || (!isThermalActive && x7c4_ != 3)) {
2021-05-06 17:53:19 +00:00
SetRockParticle(mgr, GetTranslation(), x6d8_);
}
ProcessSoundEvent(x758_, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, GetTranslation(),
mgr.GetNextAreaId(), mgr, true);
if (sub801dc2c8() && !x8f0_) {
DoDoubleSnap(mgr);
}
sub801dbc40();
}
}
}
}
}
}
2020-01-06 04:24:54 +00:00
2019-12-14 23:50:29 +00:00
void CThardus::Think(float dt, CStateManager& mgr) {
2020-09-13 19:03:49 +00:00
if (!GetActive() || !x450_bodyController->GetActive()) {
return;
}
if (!x91c_flareTexture) {
x91c_flareTexture.Lock();
2020-01-06 04:24:54 +00:00
}
if (x7c8_) {
float fVar2 = 10.f * GetModelData()->GetScale().x();
2020-09-13 19:03:49 +00:00
zeus::CVector3f diff = mgr.GetPlayer().GetTranslation() - x7cc_;
2020-01-06 04:24:54 +00:00
if (diff.magSquared() < fVar2 * fVar2) {
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(),
CDamageInfo(CWeaponMode(EWeaponType::AI), 0.f, 0.f, 10.f), CMaterialFilter::skPassEverything,
diff.normalized());
x688_ = true;
x7c8_ = false;
x7cc_.zeroOut();
}
}
2021-05-06 17:53:19 +00:00
UpdateRockThermalState(dt, mgr);
2020-01-06 04:24:54 +00:00
2019-12-14 23:50:29 +00:00
if (!sub801dc2c8()) {
2020-09-13 19:03:49 +00:00
// NOTE: (phil), yes this is what's actually happening
#if 0
if (x648_currentRock < x610_destroyableRocks.size() - 2) {
2019-12-14 23:50:29 +00:00
x690_ = 1.f;
} else {
2019-12-14 23:50:29 +00:00
x690_ = 1.f;
}
2020-09-13 19:03:49 +00:00
#endif
x690_ = 1.f;
2019-12-14 23:50:29 +00:00
} else {
x690_ = 1.f;
SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None);
}
2020-01-06 04:24:54 +00:00
2019-12-14 23:50:29 +00:00
if (!x93c_) {
x3b4_speed = x690_;
x402_28_isMakingBigStrike = false;
x504_damageDur = 0.f;
} else {
x3b4_speed = x690_;
x402_28_isMakingBigStrike = true;
x504_damageDur = 1.f;
2020-01-06 04:24:54 +00:00
}
2019-12-14 23:50:29 +00:00
CPatterned::Think(dt, mgr);
2020-01-06 04:24:54 +00:00
if (x648_currentRock > 2 && !x689_) {
_DoSuckState(mgr);
2019-12-14 23:50:29 +00:00
}
2020-01-06 04:24:54 +00:00
x5f0_rockColliders->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
2019-12-14 23:50:29 +00:00
x5f4_->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
x5f8_->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
2020-01-06 04:24:54 +00:00
sub801dd608(mgr);
sub801dcfa4(mgr);
if (x610_destroyableRocks.size() <= x648_currentRock) {
2020-01-06 04:24:54 +00:00
Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle);
}
2020-01-06 04:24:54 +00:00
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) {
x402_29_drawParticles = false;
2020-09-13 19:03:49 +00:00
UpdateNonDestroyableCollisionActorMaterials(EUpdateMaterialMode::Remove, EMaterialTypes::ProjectilePassthrough,
mgr);
2020-01-06 04:24:54 +00:00
for (size_t i = 0; i < x610_destroyableRocks.size(); ++i) {
if (auto* act = static_cast<CActor*>(mgr.ObjectById(x610_destroyableRocks[i]))) {
2020-01-06 04:24:54 +00:00
if (x648_currentRock == i && !x688_ && !x93c_ && !x909_ && !x93d_) {
act->AddMaterial(EMaterialTypes::Orbit, mgr);
act->AddMaterial(EMaterialTypes::Target, mgr);
} else {
2020-08-03 01:34:49 +00:00
act->RemoveMaterial(EMaterialTypes::Orbit, mgr);
act->RemoveMaterial(EMaterialTypes::Target, mgr);
2020-01-06 04:24:54 +00:00
}
}
}
if (x688_) {
2020-01-06 04:24:54 +00:00
x688_ = false;
}
2020-01-06 04:24:54 +00:00
} else {
x402_29_drawParticles = true;
2020-09-13 19:03:49 +00:00
UpdateNonDestroyableCollisionActorMaterials(EUpdateMaterialMode::Add, EMaterialTypes::ProjectilePassthrough, mgr);
2020-01-06 04:24:54 +00:00
for (size_t i = 0; i < x610_destroyableRocks.size(); ++i) {
if (auto* act = static_cast<CActor*>(mgr.ObjectById(x610_destroyableRocks[i]))) {
2020-01-06 04:24:54 +00:00
if (!x688_ && !x93c_ && !x909_ && !x93d_) {
bool found = act->GetName().find("Neck_1"sv) != std::string::npos;
2021-05-06 17:53:19 +00:00
if (!found || !x6b0_destroyedRocks[x648_currentRock] ||
x648_currentRock == x610_destroyableRocks.size() - 1) {
if (!x6b0_destroyedRocks[i]) {
if (!found || x6b0_destroyedRocks[i]) {
2020-01-06 04:24:54 +00:00
act->RemoveMaterial(EMaterialTypes::Orbit, mgr);
act->RemoveMaterial(EMaterialTypes::Target, mgr);
}
} else {
act->AddMaterial(EMaterialTypes::Orbit, mgr);
act->AddMaterial(EMaterialTypes::Target, mgr);
}
} else {
act->RemoveMaterial(EMaterialTypes::Orbit, mgr);
act->RemoveMaterial(EMaterialTypes::Target, mgr);
}
} else {
x688_ = false;
act->RemoveMaterial(EMaterialTypes::Orbit, mgr);
act->RemoveMaterial(EMaterialTypes::Target, mgr);
}
}
}
}
2020-01-06 04:24:54 +00:00
if (x644_ == 1) {
UpdateExcludeList(x5f0_rockColliders, EUpdateMaterialMode::Add, EMaterialTypes::Player, mgr);
UpdateExcludeList(x5f4_, EUpdateMaterialMode::Add, EMaterialTypes::Player, mgr);
UpdateExcludeList(x5f8_, EUpdateMaterialMode::Add, EMaterialTypes::Player, mgr);
CCameraManager* cameraManager = mgr.GetCameraManager();
if (x93c_) {
if (x6f8_ < 0.3f) {
x6f8_ += dt;
} else {
if (cameraManager->GetFirstPersonCamera()->GetUniqueId() == cameraManager->GetCurrentCameraId()) {
cameraManager->AddCameraShaker(
CCameraShakeData::BuildMissileCameraShake(0.25f, 0.75f, 125.f, GetTranslation()), true);
}
x6f8_ = 0.f;
}
2019-12-14 23:50:29 +00:00
2020-01-06 04:24:54 +00:00
if (cameraManager->GetCurrentCameraId() != cameraManager->GetFirstPersonCamera()->GetUniqueId() && x95d_ == 0) {
CSamusHud::DisplayHudMemo(g_MainStringTable->GetString(104), CHUDMemoParms(5.f, true, false, false));
}
}
} else {
UpdateExcludeList(x5f0_rockColliders, EUpdateMaterialMode::Remove, EMaterialTypes::Player, mgr);
UpdateExcludeList(x5f4_, EUpdateMaterialMode::Remove, EMaterialTypes::Player, mgr);
UpdateExcludeList(x5f8_, EUpdateMaterialMode::Remove, EMaterialTypes::Player, mgr);
}
2020-08-03 01:34:49 +00:00
UpdateHealthInfo(mgr);
2019-12-14 23:50:29 +00:00
}
2020-08-03 01:34:49 +00:00
void CThardus::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
switch (msg) {
case EScriptObjectMessage::Reset: {
2019-12-14 23:50:29 +00:00
x95c_doCodeTrigger = true;
x450_bodyController->SetFallState(pas::EFallState::Zero);
x450_bodyController->SetState(pas::EAnimationState::Locomotion);
x93d_ = false;
break;
}
case EScriptObjectMessage::SetToMax: {
2020-01-06 04:24:54 +00:00
for (size_t i = x648_currentRock; i < x610_destroyableRocks.size() - 1; ++i) {
2019-12-14 23:50:29 +00:00
if (CEntity* ent = mgr.ObjectById(x610_destroyableRocks[i])) {
ent->SetActive(false);
2019-11-19 23:15:45 +00:00
}
2020-01-06 04:24:54 +00:00
++x648_currentRock;
}
break;
}
case EScriptObjectMessage::Stop: {
Death(mgr, {}, EScriptObjectState::DeathRattle);
break;
}
case EScriptObjectMessage::Action: {
2020-09-13 19:03:49 +00:00
if (!x5c8_heardPlayer) {
2019-12-14 23:50:29 +00:00
x5c8_heardPlayer = true;
2020-09-13 19:03:49 +00:00
}
break;
}
case EScriptObjectMessage::Touched: {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
if (TCastToPtr<CPlayer> pl = mgr.ObjectById(colAct->GetLastTouchedObject())) {
2020-09-13 19:03:49 +00:00
if (x420_curDamageRemTime > 0.f) {
break;
2020-09-13 19:03:49 +00:00
}
2020-08-03 01:34:49 +00:00
u32 rand = static_cast<u32>(mgr.GetActiveRandom()->Next());
float damageMult = 1.f;
zeus::CVector3f knockBack = zeus::skForward;
if (x644_ == 1) {
damageMult = 2.f;
2020-09-13 19:03:49 +00:00
knockBack = (rand % 2) != 0u ? zeus::skRight : zeus::skLeft;
}
2020-09-13 19:03:49 +00:00
if (mgr.GetPlayer().GetFrozenState()) {
mgr.GetPlayer().UnFreeze(mgr);
2020-09-13 19:03:49 +00:00
}
knockBack = GetTransform().buildMatrix3f() * knockBack;
CDamageInfo dInfo = GetContactDamage();
dInfo.SetDamage(damageMult * dInfo.GetDamage());
mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), dInfo,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}),
x644_ == 1 ? knockBack : zeus::skZero3f);
x420_curDamageRemTime = x424_damageWaitTime;
} else if (TCastToConstPtr<CBomb>(mgr.GetObjectById(colAct->GetLastTouchedObject()))) {
2020-09-13 19:03:49 +00:00
if (x644_ == 1 && x93c_) {
2021-05-06 17:53:19 +00:00
BreakRock(mgr, x648_currentRock);
2020-09-13 19:03:49 +00:00
}
}
}
break;
}
case EScriptObjectMessage::Registered: {
2019-12-14 23:50:29 +00:00
x610_destroyableRocks.reserve(x5cc_.size());
x6b0_destroyedRocks.reserve(x5cc_.size());
2019-12-14 23:50:29 +00:00
x6c0_rockLights.reserve(x5cc_.size());
x90c_rockHealths.reserve(x5cc_.size());
for (size_t i = 0; i < x5cc_.size(); ++i) {
2019-12-14 23:50:29 +00:00
float health = (i == x5cc_.size() - 1) ? 2.f * x6a8_ : x6a8_;
TUniqueId rockId = mgr.AllocateUniqueId();
CModelData mData1(x5cc_[i]);
mgr.AddObject(new CDestroyableRock(
rockId, true, "", CEntityInfo(GetAreaIdAlways(), NullConnectionList), {}, std::move(mData1), 0.f,
2019-12-14 23:50:29 +00:00
CHealthInfo(health, 0.f),
CDamageVulnerability(
EVulnerability::Normal, EVulnerability::Deflect, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::One),
GetMaterialList(), x630_,
CActorParameters(CLightParameters(false, 0.f, CLightParameters::EShadowTesselation::Invalid, 0.f, 0.f,
2020-01-06 04:24:54 +00:00
zeus::skWhite, true, CLightParameters::EWorldLightingOptions::NoShadowCast,
CLightParameters::ELightRecalculationOptions::LargeFrameCount,
zeus::skZero3f, -1, -1, false, 0),
{}, {}, {}, {}, true, true, false, false, 0.f, 0.f, 1.f),
2020-01-06 04:24:54 +00:00
x5dc_[i], 0));
2019-12-14 23:50:29 +00:00
x610_destroyableRocks.push_back(rockId);
x6b0_destroyedRocks.push_back(false);
2019-12-14 23:50:29 +00:00
TUniqueId lightId = mgr.AllocateUniqueId();
2020-09-13 19:03:49 +00:00
auto* gl = new CGameLight(lightId, GetAreaIdAlways(), false, ""sv, {}, GetUniqueId(),
CLight::BuildPoint({}, zeus::skBlue), 0, 0, 0.f);
2020-01-06 04:24:54 +00:00
gl->SetActive(false);
mgr.AddObject(gl);
2019-12-14 23:50:29 +00:00
x6c0_rockLights.push_back(lightId);
x90c_rockHealths.push_back(health);
}
AddMaterial(EMaterialTypes::ScanPassthrough, mgr);
AddMaterial(EMaterialTypes::CameraPassthrough, mgr);
RemoveMaterial(EMaterialTypes::Orbit, mgr);
RemoveMaterial(EMaterialTypes::Target, mgr);
2019-12-14 23:50:29 +00:00
_SetupCollisionManagers(mgr);
x450_bodyController->SetFallState(pas::EFallState::Two);
x450_bodyController->Activate(mgr);
x450_bodyController->BodyStateInfo().SetLocoAnimChangeAtEndOfAnimOnly(true);
2019-12-14 23:50:29 +00:00
SetState(0, mgr);
sub801dec80();
AddMaterial(EMaterialTypes::RadarObject, mgr);
break;
}
2019-12-14 23:50:29 +00:00
case EScriptObjectMessage::Deleted: {
2020-01-06 04:24:54 +00:00
x5f0_rockColliders->Destroy(mgr);
2019-12-14 23:50:29 +00:00
x5f4_->Destroy(mgr);
x5f8_->Destroy(mgr);
2020-01-06 04:24:54 +00:00
mgr.FreeScriptObject(x64c_fog);
2019-12-14 23:50:29 +00:00
for (const auto& id : x610_destroyableRocks) {
mgr.FreeScriptObject(id);
}
for (const auto& id : x6c0_rockLights) {
mgr.FreeScriptObject(id);
}
break;
}
case EScriptObjectMessage::InitializedInArea: {
2020-09-13 19:03:49 +00:00
if (x94c_initialized) {
2019-12-14 23:50:29 +00:00
break;
2020-09-13 19:03:49 +00:00
}
2020-01-06 04:24:54 +00:00
x94c_initialized = true;
x764_startTransform = GetTransform();
2019-12-14 23:50:29 +00:00
for (const SConnection& conn : GetConnectionList()) {
TUniqueId connId = mgr.GetIdForScript(conn.x8_objId);
if (connId == kInvalidUniqueId) {
2019-12-14 23:50:29 +00:00
continue;
}
2019-12-14 23:50:29 +00:00
if (conn.x0_state == EScriptObjectState::Patrol) {
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(connId)) {
rstl::reserved_vector<TUniqueId, 16> wpIds;
GatherWaypoints(wp, mgr, wpIds);
x578_waypoints.push_back(wpIds);
2019-12-14 23:50:29 +00:00
} else if (CPatterned* p = CPatterned::CastTo<CThardusRockProjectile>(mgr.ObjectById(connId))) {
2020-01-06 04:24:54 +00:00
x5fc_projectileId = connId;
x60c_projectileEditorId = conn.x8_objId;
2019-12-14 23:50:29 +00:00
p->SetActive(false);
} else if (TCastToConstPtr<CRepulsor>(mgr.GetObjectById(connId))) {
x664_repulsors.push_back(connId);
2019-12-14 23:50:29 +00:00
} else if (TCastToConstPtr<CScriptDistanceFog>(mgr.GetObjectById(connId))) {
2020-01-06 04:24:54 +00:00
x64c_fog = connId;
2019-12-14 23:50:29 +00:00
}
} else if (conn.x0_state == EScriptObjectState::Zero) {
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(connId)) {
2020-01-06 04:24:54 +00:00
x8f4_waypoints.push_back(connId);
2019-12-14 23:50:29 +00:00
wp->SetActive(false);
}
} else if (conn.x0_state == EScriptObjectState::Dead) {
2020-09-13 19:03:49 +00:00
if (TCastToConstPtr<CScriptTimer>(mgr.GetObjectById(connId))) {
2020-01-06 04:24:54 +00:00
x7a8_timers.push_back(connId);
2020-09-13 19:03:49 +00:00
}
2019-12-14 23:50:29 +00:00
}
}
2020-01-06 04:24:54 +00:00
x7f0_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
2019-12-14 23:50:29 +00:00
break;
}
case EScriptObjectMessage::Damage: {
2020-07-28 11:07:11 +00:00
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(uid)) {
2020-07-26 04:53:49 +00:00
TUniqueId lastTouchedObj = colAct->GetLastTouchedObject();
TUniqueId targetRock = kInvalidUniqueId;
for (size_t i = 0; i < x5f0_rockColliders->GetNumCollisionActors(); ++i) {
const CJointCollisionDescription& desc = x5f0_rockColliders->GetCollisionDescFromIndex(i);
if (desc.GetCollisionActorId() == uid) {
targetRock = x610_destroyableRocks[i];
2020-07-28 11:07:11 +00:00
break;
2020-07-26 04:53:49 +00:00
}
}
if (targetRock == kInvalidUniqueId) {
break;
}
2020-09-13 19:03:49 +00:00
if (auto* rock = static_cast<CDestroyableRock*>(mgr.ObjectById(targetRock))) {
2020-07-26 04:53:49 +00:00
if (TCastToConstPtr<CGameProjectile> proj = mgr.GetObjectById(lastTouchedObj)) {
if (GetBodyController()->GetBodyStateInfo().GetCurrentAdditiveStateId() !=
pas::EAnimationState::AdditiveReaction &&
rock->Get_x324() <= 0.f) {
2020-07-26 04:53:49 +00:00
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCAdditiveReactionCmd(pas::EAdditiveReactionType::Five, 1.f, false));
}
rock->TakeDamage(zeus::skZero3f, 0.f);
const bool thermalInactive = mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal;
2020-07-28 11:07:11 +00:00
if (thermalInactive || x7c4_ != 3) {
2021-05-06 17:53:19 +00:00
SetRockParticle(mgr, proj->GetTranslation(), x6d0_);
2020-07-26 04:53:49 +00:00
}
if (!rock->IsUsingPhazonModel()) {
ProcessSoundEvent(x75c_, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, rock->GetTranslation(),
mgr.GetNextAreaId(), mgr, true);
} else {
ProcessSoundEvent(SFXsfx0AC0, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, rock->GetTranslation(),
mgr.GetNextAreaId(), mgr, false);
}
}
}
}
2019-12-14 23:50:29 +00:00
break;
}
default:
break;
}
}
2019-12-14 23:50:29 +00:00
2020-01-06 04:24:54 +00:00
void CThardus::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
CPatterned::PreRender(mgr, frustum);
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) {
xb4_drawFlags = CModelFlags(0, 0, 1, zeus::skWhite);
} else {
xb4_drawFlags = CModelFlags(0, 0, 3, zeus::skWhite);
}
}
void CThardus::Render(CStateManager& mgr) {
2019-12-14 23:50:29 +00:00
CPatterned::Render(mgr);
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal && x7c4_ != 0) {
RenderFlare(mgr, x7c0_);
2019-12-14 23:50:29 +00:00
}
}
void CThardus::Touch(CActor& act, CStateManager& mgr) {
// Intentionally empty
}
2019-12-14 23:50:29 +00:00
zeus::CVector3f CThardus::GetOrbitPosition(const CStateManager& mgr) const { return GetAimPosition(mgr, 0.f); }
2019-12-14 23:50:29 +00:00
zeus::CVector3f CThardus::GetAimPosition(const CStateManager& mgr, float dt) const {
return GetLctrTransform(x93c_ ? "center_LCTR"sv : "Neck_1"sv).origin;
}
zeus::CAABox CThardus::GetSortingBounds(const CStateManager& mgr) const {
zeus::CVector3f extents = 0.15f * (x9c_renderBounds.max - x9c_renderBounds.min);
return zeus::CAABox(x9c_renderBounds.min - extents, x9c_renderBounds.max + extents);
}
void CThardus::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
switch (type) {
case EUserEventType::Projectile: {
2020-09-12 04:37:45 +00:00
zeus::CTransform wristXf = GetLctrTransform("L_wrist"sv);
CRayCastResult res = mgr.RayStaticIntersection(wristXf.origin, zeus::skDown, 100.f,
CMaterialFilter::MakeInclude(EMaterialTypes::Solid));
zeus::CTransform xf = zeus::lookAt(res.GetPoint() + zeus::CVector3f{0.f, 0.f, 1.f}, GetTranslation());
xf.rotateLocalZ(zeus::degToRad(mgr.GetActiveRandom()->Range(-5.f, 5.f)));
mgr.AddObject(new CIceAttackProjectile(
g_SimplePool->GetObj({SBIG('PART'), x600_}), g_SimplePool->GetObj({SBIG('PART'), x604_}),
g_SimplePool->GetObj({SBIG('PART'), x608_}), mgr.AllocateUniqueId(), GetAreaIdAlways(),
mgr.GetPlayer().GetUniqueId(), true, xf, CDamageInfo(CWeaponMode::Ice(), 6.f, 0.f, 0.f), zeus::CAABox(0.f, 1.f),
x6ac_, zeus::degToRad(42.f), x6e8_, x6ec_, SFXsfx0AAD, x6f0_));
break;
}
case EUserEventType::LoopedSoundStop:
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
break;
case EUserEventType::AlignTargetPos: {
SetState(2, mgr);
break;
}
case EUserEventType::Delete:
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
break;
case EUserEventType::DamageOn: {
2020-09-13 19:03:49 +00:00
x7c8_ = true;
x7cc_ = (zeus::CTransform::Scale(GetModelData()->GetScale()) *
GetModelData()->GetAnimationData()->GetLocatorTransform("R_ankle"sv, nullptr))
.origin;
break;
}
case EUserEventType::DamageOff: {
x7c8_ = false;
x7cc_ = zeus::skZero3f;
break;
}
case EUserEventType::Landing: {
x93c_ = false;
break;
}
case EUserEventType::TakeOff: {
2020-09-13 19:03:49 +00:00
s32 rnd = mgr.GetActiveRandom()->Next();
std::vector<u32> inRangeWaypoints;
inRangeWaypoints.reserve(x8f4_waypoints.size());
zeus::CVector3f plPos = mgr.GetPlayer().GetTranslation();
for (size_t i = 0; i < x8f4_waypoints.size(); ++i) {
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x8f4_waypoints[i])) {
if ((wp->GetTranslation() - plPos).magSquared() > 10.f) {
inRangeWaypoints.push_back(i);
}
}
}
for (size_t i = 0; i < (rnd & 1) + 2; ++i) {
if (TCastToPtr<CScriptWaypoint> wp =
mgr.ObjectById(x8f4_waypoints[mgr.GetActiveRandom()->Next() % inRangeWaypoints.size()])) {
wp->SetActive(true);
SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None);
wp->SetActive(false);
}
}
break;
}
case EUserEventType::FadeIn: {
break;
}
case EUserEventType::FadeOut: {
if (x644_ == 1) {
x93c_ = true;
x688_ = true;
}
break;
}
case EUserEventType::ScreenShake:
ApplyCameraShake(1.25f, 125.f, 1.f, mgr, GetTranslation());
[[fallthrough]];
default:
break;
}
2019-12-14 23:50:29 +00:00
}
2020-01-06 04:24:54 +00:00
void CThardus::Patrol(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x658_ = -1;
2020-09-13 19:03:49 +00:00
x950_ = mgr.GetPlayer().GetTranslation();
2020-01-06 04:24:54 +00:00
} else if (msg == EStateMsg::Update) {
2020-09-13 19:03:49 +00:00
if (!ShouldTurn(mgr, 0.f)) {
2020-01-06 04:24:54 +00:00
return;
2020-09-13 19:03:49 +00:00
}
2020-01-06 04:24:54 +00:00
zeus::CVector3f plPos = mgr.GetPlayer().GetTranslation();
zeus::CQuaternion q = zeus::CQuaternion::lookAt(x950_, plPos.normalized(), zeus::degToRad(360.f));
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCLocomotionCmd(zeus::skZero3f, q.toTransform() * (plPos - GetTranslation()).normalized(), 1.f));
x950_ = plPos;
} else if (msg == EStateMsg::Deactivate) {
sub80deadc(mgr);
x94d_ = false;
}
}
2020-01-06 04:24:54 +00:00
void CThardus::Dead(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
SetTransform(x764_startTransform);
}
CPatterned::Dead(mgr, msg, arg);
}
void CThardus::PathFind(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::PathFind(mgr, msg, arg);
if (msg == EStateMsg::Activate) {
x2e0_destPos = sub801de550(mgr);
x7e4_ = x7d8_ = x2e0_destPos;
CPatterned::PathFind(mgr, EStateMsg::Activate, arg);
} else if (msg == EStateMsg::Update) {
if ((GetTranslation().toVec2f() - x7e4_.toVec2f()).magnitude() < 10.f) {
x2e0_destPos = sub801de434(mgr);
x7d8_ = x2e0_destPos;
x7e4_ = x7d8_;
CPatterned::PathFind(mgr, EStateMsg::Activate, arg);
++x660_;
}
2021-05-06 17:53:19 +00:00
x650_ = GetTargetVector(arg, mgr);
} else if (msg == EStateMsg::Deactivate) {
x8d4_ = false;
}
}
2019-12-14 23:50:29 +00:00
void CThardus::TargetPatrol(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
2020-09-13 19:03:49 +00:00
if (x95e_) {
2019-12-14 23:50:29 +00:00
return;
2020-09-13 19:03:49 +00:00
}
2019-12-14 23:50:29 +00:00
mgr.SetBossParams(GetUniqueId(), GetHealthInfo(mgr)->GetHP(), 88);
x95e_ = true;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
2020-09-13 19:03:49 +00:00
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Taunt) {
2019-12-14 23:50:29 +00:00
x5ec_ = 2;
2020-09-13 19:03:49 +00:00
} else {
2019-12-14 23:50:29 +00:00
x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::One));
2020-09-13 19:03:49 +00:00
}
2019-12-14 23:50:29 +00:00
} else if (x5ec_ == 2 &&
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) {
x5ec_ = 3;
}
}
}
void CThardus::Generate(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Getup) {
x5ec_ = 2;
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero));
}
} else if (x5ec_ == 2 && x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Getup) {
x5ec_ = 3;
}
} else if (msg == EStateMsg::Deactivate) {
x93d_ = false;
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Attack(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
++x570_;
x5ec_ = 0;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetCurrentStateId() != pas::EAnimationState::MeleeAttack) {
if (mgr.GetActiveRandom()->Float() <= 0.5f) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One));
} else {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Zero));
}
++x570_;
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::MeleeAttack) {
x5ec_ = 3;
}
}
}
2020-07-28 11:07:11 +00:00
void CThardus::LoopedAttack(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x658_ = 0;
x660_ = 0;
2020-07-28 11:07:11 +00:00
x570_ = 0;
x574_ = 0;
2020-07-28 11:07:11 +00:00
sub801dec80();
x93b_ = false;
x5c4_ = -1;
} else if (msg == EStateMsg::Update) {
const zeus::CVector3f thisPos = GetTranslation();
if (x658_ == 1) {
2020-08-03 01:34:49 +00:00
const zeus::CVector3f offset = thisPos + zeus::CVector3f{0.f, 0.f, 10.f};
2020-07-28 11:07:11 +00:00
CRayCastResult result = mgr.RayStaticIntersection(
offset, zeus::CQuaternion(GetTransform().buildMatrix3f()).toTransform() * zeus::CVector3f{0.f, 1.f, 0.f},
100.f, CMaterialFilter::MakeInclude({EMaterialTypes::Wall, EMaterialTypes::Floor, EMaterialTypes::Ceiling}));
2020-09-13 19:03:49 +00:00
if (result.IsInvalid()) {
2021-05-06 17:53:19 +00:00
zeus::CVector2f vec = GetSteeringVector(mgr);
2020-07-28 11:07:11 +00:00
if (vec != zeus::skZero2f) {
x650_ = vec;
2020-09-13 19:03:49 +00:00
}
} else {
x8d8_ = result.GetPoint();
x8e4_ = offset;
if ((result.GetPoint() - offset).magnitude() < 20.f) {
x658_ = 2;
x8d4_ = true;
2020-07-28 11:07:11 +00:00
}
}
2020-08-03 01:34:49 +00:00
} else if (x658_ == 0) {
zeus::CVector3f dir = (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized();
2021-05-06 17:53:19 +00:00
zeus::CVector2f vec = GetSteeringVector(mgr);
2020-09-13 20:00:13 +00:00
if (vec != zeus::skZero2f) {
2020-08-03 01:34:49 +00:00
x650_ = vec;
} else {
x650_ = dir.toVec2f().normalized();
}
if (dir.magnitude() < x698_) {
x658_ = 1;
}
2020-07-28 11:07:11 +00:00
}
2020-08-03 01:34:49 +00:00
GetBodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd{EBodyStateCmd::MaintainVelocity});
GetBodyController()->GetCommandMgr().DeliverCmd(CBCLocomotionCmd{zeus::CVector3f(x650_), zeus::skZero3f, 1.f});
2020-07-28 11:07:11 +00:00
}
}
void CThardus::DoubleSnap(CStateManager& mgr, EStateMsg msg, float arg) {
// Intentionally empty
}
2020-07-28 11:07:11 +00:00
void CThardus::Shuffle(CStateManager& mgr, EStateMsg msg, float arg) {
// Intentionally empty
}
2020-07-28 11:07:11 +00:00
void CThardus::GetUp(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg != EStateMsg::Activate) {
return;
}
RemoveMaterial(EMaterialTypes::RadarObject, mgr);
}
2019-12-14 23:50:29 +00:00
void CThardus::Taunt(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
2020-09-13 19:03:49 +00:00
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Taunt) {
2019-12-14 23:50:29 +00:00
x5ec_ = 2;
2020-09-13 19:03:49 +00:00
} else {
2019-12-14 23:50:29 +00:00
x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::One));
2020-09-13 19:03:49 +00:00
}
2019-12-14 23:50:29 +00:00
} else if (x5ec_ == 2 && x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Taunt) {
x5ec_ = 3;
}
}
}
void CThardus::Suck(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x909_ = true;
x93d_ = true;
SendScriptMsgs(EScriptObjectState::MaxReached, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Deactivate) {
x689_ = true;
}
}
2020-07-28 11:07:11 +00:00
void CThardus::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
} else if (msg == EStateMsg::Update) {
2020-09-13 19:03:49 +00:00
if (x5ec_ == 1) {
return;
2020-09-13 19:03:49 +00:00
}
if (x5ec_ == 0) {
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity::Zero, {}, false));
x5ec_ = 0;
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 &&
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
x5ec_ = 3;
}
}
}
2020-07-26 04:53:49 +00:00
void CThardus::Flinch(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
for (TUniqueId uid : x798_) {
2020-09-13 19:03:49 +00:00
if (auto* rock = CPatterned::CastTo<CThardusRockProjectile>(mgr.ObjectById(uid))) {
rock->sub80203d58();
2020-09-13 19:03:49 +00:00
}
}
x93b_ = true;
x93d_ = true;
x909_ = true;
x93c_ = false;
SetState(-1, mgr);
x94d_ = true;
} else if (msg == EStateMsg::Update) {
pas::ESeverity severity = pas::ESeverity::Invalid;
switch (x648_currentRock) {
case 1:
severity = pas::ESeverity::Zero;
break;
case 2:
severity = pas::ESeverity::One;
break;
case 3:
severity = pas::ESeverity::Two;
break;
case 4:
severity = pas::ESeverity::Three;
break;
case 5:
severity = pas::ESeverity::Four;
break;
case 6:
severity = pas::ESeverity::Five;
break;
2020-08-03 01:34:49 +00:00
default:
break;
}
if (x5ec_ == 0) {
2020-09-13 19:03:49 +00:00
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd({}, severity));
2020-09-13 19:03:49 +00:00
} else {
x5ec_ = 2;
2020-09-13 19:03:49 +00:00
}
} else if (x5ec_ == 2 &&
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::KnockBack) {
x5ec_ = 3;
}
}
}
2020-07-28 11:07:11 +00:00
void CThardus::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity::One, {}, false));
x5ec_ = 0;
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 &&
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
x5ec_ = 3;
}
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Explode(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
CSfxManager::SfxStop(x904_);
x909_ = true;
x93d_ = true;
x909_ = true;
SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) {
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::Dodge));
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 &&
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Step) {
x5ec_ = 3;
}
} else if (msg == EStateMsg::Deactivate) {
x8f0_ = true;
x909_ = false;
x93d_ = false;
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Cover(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
SetState(1, mgr);
x93d_ = false;
x909_ = false;
2020-09-13 19:03:49 +00:00
if (x610_destroyableRocks.size() - 2 <= x648_currentRock) {
x690_ = 1.1f;
2020-09-13 19:03:49 +00:00
}
AddMaterial(EMaterialTypes::RadarObject, mgr);
} else if (msg == EStateMsg::Deactivate) {
x690_ = 1.f;
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Enraged(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
x688_ = true;
x908_ = true;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::Zero));
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 &&
GetBodyController()->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt) {
x5ec_ = 3;
}
} else if (msg == EStateMsg::Deactivate) {
x908_ = false;
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Growth(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
x904_ = CSfxManager::SfxStart(SFXsfx07AD, 1.f, 0.f, false, 0x7f, true, GetAreaIdAlways());
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) {
GetBodyController()->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Forward, pas::EStepType::BreakDodge));
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::Step) {
x5ec_ = 3;
}
} else if (msg == EStateMsg::Deactivate) {
if (TCastToPtr<CScriptDistanceFog> fog = mgr.ObjectById(x64c_fog)) {
mgr.SendScriptMsg(GetUniqueId(), mgr.GetEditorIdForUniqueId(fog->GetUniqueId()), EScriptObjectMessage::Activate,
EScriptObjectState::Any);
SendScriptMsgs(EScriptObjectState::Play, mgr, EScriptObjectMessage::None);
}
}
}
2020-07-28 11:07:11 +00:00
void CThardus::Faint(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x5ec_ = 0;
x93c_ = false;
SetState(-1, mgr);
for (TUniqueId uid : x798_) {
2020-09-13 19:03:49 +00:00
if (auto* rock = CPatterned::CastTo<CThardusRockProjectile>(mgr.ObjectById(uid))) {
rock->sub80203d58();
2020-09-13 19:03:49 +00:00
}
}
x94d_ = true;
} else if (msg == EStateMsg::Update) {
if (x5ec_ == 0) {
if (GetBodyController()->GetCurrentStateId() != pas::EAnimationState::KnockBack) {
GetBodyController()->GetCommandMgr().DeliverCmd(CBCKnockBackCmd({}, pas::ESeverity::Six));
} else {
x5ec_ = 2;
}
} else if (x5ec_ == 2 && GetBodyController()->GetCurrentStateId() != pas::EAnimationState::KnockBack) {
x5ec_ = 3;
}
}
}
2020-01-06 04:24:54 +00:00
bool CThardus::PathFound(CStateManager& mgr, float arg) { return x8d4_; }
bool CThardus::InRange(CStateManager& mgr, float arg) {
return (mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f()).magnitude() <
10.f * GetModelData()->GetScale().x();
}
2020-07-26 04:53:49 +00:00
bool CThardus::PatternOver(CStateManager& mgr, float arg) { return x570_ != 0 || x93b_; }
2020-01-06 04:24:54 +00:00
bool CThardus::AnimOver(CStateManager& mgr, float arg) { return x5ec_ == 3; }
bool CThardus::InPosition(CStateManager& mgr, float arg) { return x660_ > 3; }
2020-07-26 04:53:49 +00:00
bool CThardus::ShouldTurn(CStateManager& mgr, float arg) {
return std::fabs(zeus::CVector2f::getAngleDiff(GetTransform().frontVector().toVec2f(),
mgr.GetPlayer().GetTranslation().toVec2f() -
GetTranslation().toVec2f())) > zeus::degToRad(30.f);
}
bool CThardus::HitSomething(CStateManager& mgr, float arg) { return mgr.GetPlayer().GetFrozenState(); }
2019-12-14 23:50:29 +00:00
2021-04-10 08:42:06 +00:00
void CThardus::GatherWaypoints(metaforce::CScriptWaypoint* wp, metaforce::CStateManager& mgr,
2019-12-14 23:50:29 +00:00
rstl::reserved_vector<TUniqueId, 16>& uids) {
if (uids.size() < uids.capacity() && wp->GetActive()) {
uids.push_back(wp->GetUniqueId());
wp->SetActive(false);
for (const SConnection& conn : wp->GetConnectionList()) {
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
2020-09-13 19:03:49 +00:00
if (TCastToPtr<CScriptWaypoint> wp2 = mgr.ObjectById(uid)) {
2019-12-14 23:50:29 +00:00
GatherWaypoints(wp2, mgr, uids);
2020-09-13 19:03:49 +00:00
}
2019-12-14 23:50:29 +00:00
}
wp->SetActive(true);
}
}
void CThardus::_BuildSphereJointList(const SSphereJointInfo* arr, size_t count,
2019-12-14 23:50:29 +00:00
std::vector<CJointCollisionDescription>& list) {
for (size_t i = 0; i < count; ++i) {
const auto& jInfo = arr[i];
list.push_back(CJointCollisionDescription::SphereCollision(
GetModelData()->GetAnimationData()->GetLocatorSegId(jInfo.name), jInfo.radius, jInfo.name, 0.001f));
}
}
void CThardus::_BuildAABoxJointList(const SAABoxJointInfo* arr, size_t count,
2019-12-14 23:50:29 +00:00
std::vector<CJointCollisionDescription>& list) {
for (size_t i = 0; i < count; ++i) {
const auto& jInfo = arr[i];
list.push_back(CJointCollisionDescription::AABoxCollision(
GetModelData()->GetAnimationData()->GetLocatorSegId(jInfo.name), jInfo.extents, jInfo.name, 0.001f));
}
}
void CThardus::_SetupCollisionActorMaterials(const std::unique_ptr<CCollisionActorManager>& colMgr,
CStateManager& mgr) {
for (size_t i = 0; i < colMgr->GetNumCollisionActors(); ++i) {
const auto& colDesc = colMgr->GetCollisionDescFromIndex(i);
2020-09-13 19:03:49 +00:00
if (auto* act = static_cast<CActor*>(mgr.ObjectById(colDesc.GetCollisionActorId()))) {
2019-12-14 23:50:29 +00:00
act->AddMaterial(EMaterialTypes::ScanPassthrough, mgr);
act->AddMaterial(EMaterialTypes::CameraPassthrough, mgr);
act->AddMaterial(EMaterialTypes::Immovable, mgr);
act->AddMaterial(EMaterialTypes::NoPlayerCollision, mgr);
CMaterialList include = GetMaterialFilter().GetIncludeList();
include.Add(act->GetMaterialFilter().GetIncludeList());
CMaterialList exclude = GetMaterialFilter().GetExcludeList();
exclude.Add(act->GetMaterialFilter().GetExcludeList());
act->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
}
}
}
void CThardus::_SetupCollisionManagers(CStateManager& mgr) {
std::vector<CJointCollisionDescription> list;
_BuildSphereJointList(skDamageableSphereJointInfoList1.data(), skDamageableSphereJointInfoList1.size(), list);
x5f0_rockColliders = std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), list, true);
2020-01-06 04:24:54 +00:00
_SetupCollisionActorMaterials(x5f0_rockColliders, mgr);
2019-12-14 23:50:29 +00:00
list.clear();
_BuildSphereJointList(skDamageableSphereJointInfoList2.data(), skDamageableSphereJointInfoList2.size(), list);
x5f4_ = std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), list, true);
2019-12-14 23:50:29 +00:00
_SetupCollisionActorMaterials(x5f4_, mgr);
list.clear();
_BuildAABoxJointList(skFootCollision.data(), skFootCollision.size(), list);
x5f8_ = std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), list, true);
2019-12-14 23:50:29 +00:00
_SetupCollisionActorMaterials(x5f8_, mgr);
list.clear();
2020-01-06 04:24:54 +00:00
x634_nonDestroyableActors.reserve(x5f4_->GetNumCollisionActors() + x5f0_rockColliders->GetNumCollisionActors() +
x5f8_->GetNumCollisionActors());
2020-09-12 04:37:45 +00:00
FindNonDestroyableActors(x5f4_);
FindNonDestroyableActors(x5f8_);
2020-01-06 04:24:54 +00:00
for (size_t i = 0; i < x5f0_rockColliders->GetNumCollisionActors(); ++i) {
const auto& colDesc = x5f0_rockColliders->GetCollisionDescFromIndex(i);
2019-12-14 23:50:29 +00:00
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(colDesc.GetCollisionActorId())) {
2020-09-13 19:03:49 +00:00
if (auto* rock = static_cast<CDestroyableRock*>(mgr.ObjectById(x610_destroyableRocks[i]))) {
2019-12-14 23:50:29 +00:00
if (i == 0) {
colAct->SetDamageVulnerability(*rock->GetDamageVulnerability());
rock->SetThermalMag(0.8f);
2019-12-14 23:50:29 +00:00
} else {
colAct->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerabilty());
rock->SetThermalMag(0.f);
2019-12-14 23:50:29 +00:00
}
*colAct->HealthInfo(mgr) = *rock->HealthInfo(mgr);
}
}
}
}
2020-09-12 04:37:45 +00:00
void CThardus::FindNonDestroyableActors(const std::unique_ptr<CCollisionActorManager>& colMgr) {
2019-12-14 23:50:29 +00:00
for (size_t i = 0; i < colMgr->GetNumCollisionActors(); ++i) {
const auto& colDesc = colMgr->GetCollisionDescFromIndex(i);
TUniqueId uid = colDesc.GetCollisionActorId();
bool foundBone = false;
for (const auto& name : skSearchJointNames) {
if (colDesc.GetName().find(name) != std::string::npos) {
foundBone = true;
break;
}
}
2020-09-12 04:37:45 +00:00
if (!foundBone) {
2020-01-06 04:24:54 +00:00
x634_nonDestroyableActors.push_back(uid);
2020-09-12 04:37:45 +00:00
}
2019-12-14 23:50:29 +00:00
}
}
2021-05-06 17:53:19 +00:00
void CThardus::BreakRock(CStateManager& mgr, u32 rockIndex) {
2020-01-06 04:24:54 +00:00
TCastToPtr<CCollisionActor> rockCol =
mgr.ObjectById(x5f0_rockColliders->GetCollisionDescFromIndex(rockIndex).GetCollisionActorId());
if (TCastToPtr<CDestroyableRock> rock = mgr.ObjectById(x610_destroyableRocks[rockIndex])) {
if (!rock->IsUsingPhazonModel()) {
rock->UsePhazonModel();
float hp = rockIndex == x5f0_rockColliders->GetNumCollisionActors() - 1 ? 2.f * x6a4_ : x6a4_;
CHealthInfo* hInfo = rock->HealthInfo(mgr);
hInfo->SetHP(hp);
hInfo->SetKnockbackResistance(2.f);
hInfo = rockCol->HealthInfo(mgr);
hInfo->SetHP(hp);
hInfo->SetKnockbackResistance(2.f);
x6b0_destroyedRocks[rockIndex] = true;
rock->SetThermalMag(1.5f);
auto* light = static_cast<CGameLight*>(mgr.ObjectById(x6c0_rockLights[rockIndex]));
2020-01-06 04:24:54 +00:00
light->SetActive(true);
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal ||
(mgr.GetPlayerState()->GetCurrentVisor() != CPlayerState::EPlayerVisor::Thermal && x7c4_ != 3)) {
2021-05-06 17:53:19 +00:00
SetRockParticle(mgr, GetTranslation(), x6d4_);
2020-01-06 04:24:54 +00:00
}
x90c_rockHealths[rockIndex] = hp;
2020-01-06 04:24:54 +00:00
sub801dbc5c(mgr, rock);
ProcessSoundEvent(x760_, 1.f, 0, 0.1f, 1000.f, 0.16f, 1.f, zeus::skZero3f, GetTranslation(), mgr.GetNextAreaId(),
mgr, true);
}
}
}
2021-05-06 17:53:19 +00:00
void CThardus::SetRockParticle(CStateManager& mgr, const zeus::CVector3f& pos, CAssetId particle) {
2020-01-06 04:24:54 +00:00
u32 w = x6f4_;
++x6f4_;
2020-04-11 22:51:39 +00:00
std::string particleName = fmt::format(FMT_STRING("ROCK_EFFECT{}-{}"), particle.Value(), w);
2020-01-06 04:24:54 +00:00
GetModelData()->GetAnimationData()->GetParticleDB().AddAuxiliaryParticleEffect(
particleName, 0x40, CAuxiliaryParticleData(0, {FOURCC('PART'), particle}, pos, 1.f),
2.f * GetModelData()->GetScale(), mgr, GetAreaIdAlways(), 0);
}
void CThardus::sub801dbc5c(CStateManager& mgr, CDestroyableRock* rock) {
2020-09-12 04:37:45 +00:00
if (x938_) {
return;
2020-01-06 04:24:54 +00:00
}
2020-09-12 04:37:45 +00:00
x938_ = true;
x939_ = false;
sub801dbbdc(mgr, rock);
2020-01-06 04:24:54 +00:00
}
void CThardus::sub801dbbdc(CStateManager& mgr, CDestroyableRock* rock) {
2020-09-12 04:37:45 +00:00
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Thermal) {
2020-01-06 04:24:54 +00:00
x688_ = true;
2020-09-12 04:37:45 +00:00
}
2020-01-06 04:24:54 +00:00
if (x7c4_ == 0 || x7c4_ == 2) {
x7c4_ = 1;
x7b8_ = 0.f;
}
x928_currentRockId = rock->GetUniqueId();
x92c_currentRockPos = rock->GetTranslation();
}
void CThardus::UpdateNonDestroyableCollisionActorMaterials(EUpdateMaterialMode mode, EMaterialTypes mat,
2021-04-10 08:42:06 +00:00
metaforce::CStateManager& mgr) {
2020-01-06 04:24:54 +00:00
for (const auto& uid : x634_nonDestroyableActors) {
if (TCastToPtr<CCollisionActor> col = mgr.ObjectById(uid)) {
if (mode == EUpdateMaterialMode::Remove) {
2020-01-06 04:24:54 +00:00
col->RemoveMaterial(mat, mgr);
} else if (mode == EUpdateMaterialMode::Add) {
2020-01-06 04:24:54 +00:00
col->AddMaterial(mat, mgr);
}
2020-01-06 04:24:54 +00:00
2020-08-03 01:34:49 +00:00
*col->HealthInfo(mgr) = CHealthInfo(1000000.0f, 10.f);
2020-01-06 04:24:54 +00:00
}
}
}
void CThardus::UpdateExcludeList(const std::unique_ptr<CCollisionActorManager>& colMgr, EUpdateMaterialMode mode,
EMaterialTypes w2, CStateManager& mgr) {
2020-01-06 04:24:54 +00:00
for (size_t i = 0; i < colMgr->GetNumCollisionActors(); ++i) {
if (TCastToPtr<CActor> colAct = mgr.ObjectById(colMgr->GetCollisionDescFromIndex(i).GetCollisionActorId())) {
CMaterialList exclude = colAct->GetMaterialFilter().GetExcludeList();
if (mode == EUpdateMaterialMode::Remove) {
2020-01-06 04:24:54 +00:00
exclude.Remove(w2);
} else if (mode == EUpdateMaterialMode::Add) {
2020-01-06 04:24:54 +00:00
exclude.Add(w2);
}
2020-01-06 04:24:54 +00:00
colAct->SetMaterialFilter(
CMaterialFilter::MakeIncludeExclude(colAct->GetMaterialFilter().GetIncludeList(), exclude));
}
}
}
void CThardus::RenderFlare(const CStateManager& mgr, float t) {
if (!x91c_flareTexture) {
return;
}
if (!m_flareFilter) {
m_flareFilter.emplace(EFilterType::Add, x91c_flareTexture);
}
const float scale = 30.f * t;
zeus::CVector3f offset = scale * CGraphics::g_ViewMatrix.basis[2];
zeus::CVector3f max = x92c_currentRockPos + (scale * CGraphics::g_ViewMatrix.basis[0]);
zeus::CVector3f min = x92c_currentRockPos - (scale * CGraphics::g_ViewMatrix.basis[0]);
CGraphics::SetModelMatrix(zeus::CTransform());
const std::array<CTexturedQuadFilter::Vert, 4> verts{{
{{max.x() + offset.x(), max.y() + offset.y(), max.z() + offset.z()}, {0.f, 1.f}},
{{min.x() + offset.x(), min.y() + offset.y(), min.z() + offset.z()}, {0.f, 0.f}},
{{max.x() - offset.x(), max.y() - offset.y(), max.z() - offset.z()}, {1.f, 1.f}},
{{min.x() - offset.x(), min.y() - offset.y(), min.z() - offset.z()}, {1.f, 0.f}},
}};
2020-04-19 06:47:25 +00:00
m_flareFilter->drawVerts({t, t}, verts);
}
#if 0
CGraphics::SetModelMatrix(zeus::CTransform());
CGraphics::SetBlendMode(ERglBlendMode::Blend, ERglBlendFactor::One, ERglBlendFactor::One, ERglLogicOp::Clear);
CGraphics::SetTevOp(0, CGraphics::sTevPass805a5ebc);
CGraphics::SetTevOp(1, CGraphics::sTevPass805a564c);
CGraphics::SetDepthWriteMode(false, ERglEnum::Always, false);
CGraphics::StreamColor(zeus::CColor(f1, f1));
CGraphics::StreamBegin(0xa0);
CGraphics::StreamTexCoord(0.f, 0.f);
CGraphics::StreamVertex(min + offset);
CGraphics::StreamTexCoord(1.f, 0.f);
CGraphics::StreamVertex(min - offset);
CGraphics::StreamTexCoord(1.f, 1.f);
CGraphics::StreamVertex(max - offset);
CGraphics::StreamTexCoord(0.f, 1.f);
CGraphics::StreamVertex(max + offset);
CGraphics::StreamEnd();
#endif
zeus::CVector3f CThardus::sub801de550(CStateManager& mgr) {
s8 wpIdx = -1;
s8 pathIdx = -1;
if (!x578_waypoints.empty()) {
zeus::CVector2f thisPos = GetTranslation().toVec2f();
std::vector<u32> unkVec;
unkVec.reserve(x578_waypoints.size());
for (const auto& path : x578_waypoints) {
float maxDist = 1000000.f;
u32 lastIdx = 0;
for (size_t i = 0; i < path.size(); ++i) {
TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(path[i]);
const float curDist = (wp->GetTranslation().toVec2f() - thisPos).magnitude();
if (curDist < maxDist) {
lastIdx = i;
maxDist = curDist;
}
}
unkVec.push_back(lastIdx);
}
2021-05-06 17:53:19 +00:00
// zeus::CVector2f plVec = mgr.GetPlayer().GetTranslation().toVec2f();
float maxDist = 0.f;
float curDist = 0.f;
for (size_t i = 0; i < x578_waypoints.size(); ++i) {
TCastToConstPtr<CScriptWaypoint> wp1 = mgr.GetObjectById(x578_waypoints[i][unkVec[i]]);
TCastToConstPtr<CScriptWaypoint> wp2 = mgr.GetObjectById(wp1->NextWaypoint(mgr));
const float wp1Dist = (wp1->GetTranslation().toVec2f() - mgr.GetPlayer().GetTranslation().toVec2f()).magnitude();
const float wp2Dist = (wp2->GetTranslation().toVec2f() - mgr.GetPlayer().GetTranslation().toVec2f()).magnitude();
if (curDist < wp1Dist && wp1Dist <= wp2Dist) {
curDist = wp1Dist;
pathIdx = i;
}
if (maxDist < wp1Dist) {
maxDist = wp1Dist;
wpIdx = i;
}
}
if (pathIdx == -1) {
pathIdx = wpIdx;
}
}
if (pathIdx == -1 || wpIdx == -1) {
return {};
}
x8f1_curPatrolPath = pathIdx;
x8f2_curPatrolPathWaypoint = wpIdx;
return TCastToConstPtr<CScriptWaypoint>(mgr.GetObjectById(x578_waypoints[pathIdx][wpIdx]))->GetTranslation();
}
zeus::CVector3f CThardus::sub801de434(CStateManager& mgr) {
if (x8f1_curPatrolPath == -1 || x8f2_curPatrolPathWaypoint == -1) {
return {};
}
s8 tmpWpIdx = x8f2_curPatrolPathWaypoint;
x8f2_curPatrolPathWaypoint = (x8f2_curPatrolPathWaypoint + 1) % x578_waypoints[x8f1_curPatrolPath].size();
return TCastToConstPtr<CScriptWaypoint>(
mgr.GetObjectById(x578_waypoints[x8f1_curPatrolPath][x8f2_curPatrolPathWaypoint]))
->GetTranslation();
}
2021-05-06 17:53:19 +00:00
zeus::CVector2f CThardus::GetSteeringVector(CStateManager& mgr) const {
zeus::CVector2f ret;
zeus::CVector3f pos = GetTranslation();
for (const auto& repulsor : x664_repulsors) {
TCastToConstPtr<CRepulsor> rep = mgr.GetObjectById(repulsor);
const zeus::CVector2f repPos = rep->GetTranslation().toVec2f();
const float dist = (pos - repPos).magSquared();
if (dist < (rep->GetAffectRadius() * rep->GetAffectRadius())) {
// std::sqrt(dist);
x45c_steeringBehaviors.Flee2D(*this, repPos);
break;
}
}
if (ret != zeus::skZero2f) {
2021-05-06 17:53:19 +00:00
ret = x45c_steeringBehaviors.Arrival2D(*this, x764_startTransform.origin.toVec2f()) * zeus::CVector2f(1.f) +
ret * zeus::CVector2f(0.f);
}
return ret;
}
bool CThardus::sub801db5b4(CStateManager& mgr) const {
2020-09-12 04:37:45 +00:00
return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal ? !x93a_ || x7c4_ == 0 : true;
}
void CThardus::ApplyCameraShake(float magnitude, float sfxDistance, float duration, CStateManager& mgr,
const zeus::CVector3f& v1) {
float bounceIntensity =
std::max(0.f, -((v1 - mgr.GetPlayer().GetTranslation()).magnitude() * (magnitude / sfxDistance) - magnitude));
if (mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId() == mgr.GetCameraManager()->GetCurrentCameraId()) {
mgr.GetCameraManager()->AddCameraShaker(
CCameraShakeData::BuildMissileCameraShake(duration, magnitude, sfxDistance, GetTranslation()), true);
}
if (x908_) {
BouncePlayer(bounceIntensity, mgr);
}
}
void CThardus::UpdateHealthInfo(CStateManager& mgr) {
2020-09-13 19:03:49 +00:00
// TODO(phil): This isn't quite right, need to figure out why
float hp = 0.f;
for (size_t i = x648_currentRock; i < x610_destroyableRocks.size(); ++i) {
float fVar1 = x648_currentRock == (x610_destroyableRocks.size() - 1) ? 2.f * x6a4_ : x6a4_;
2020-09-13 19:03:49 +00:00
if (auto* rock = static_cast<CDestroyableRock*>(mgr.ObjectById(x610_destroyableRocks[i]))) {
if (!rock->IsUsingPhazonModel()) {
hp += fVar1;
}
hp += rock->GetHealthInfo(mgr)->GetHP();
}
}
HealthInfo(mgr)->SetHP(hp);
}
void CThardus::BouncePlayer(float intensity, CStateManager& mgr) {
if (intensity <= 0.f) {
return;
}
zeus::CVector3f posDiff = GetTranslation() - mgr.GetPlayer().GetTranslation();
CPlayer::ESurfaceRestraints restraints = mgr.GetPlayer().GetSurfaceRestraint();
if (restraints != CPlayer::ESurfaceRestraints::Air && !mgr.GetPlayer().IsInWaterMovement()) {
zeus::CVector3f baseImpulse = intensity * (40.f * zeus::skUp);
zeus::CVector3f additionalImpulse;
if (posDiff.magnitude() > 10.f) {
zeus::CVector3f tmpVec = posDiff.toVec2f();
if (tmpVec.canBeNormalized()) {
additionalImpulse = intensity * (12.5f * tmpVec.normalized());
}
}
mgr.GetPlayer().ApplyImpulseWR(mgr.GetPlayer().GetMass() * (baseImpulse + additionalImpulse), zeus::CAxisAngle());
mgr.GetPlayer().SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr);
}
}
void CThardus::sub801dbc40() {
x7b8_ = FLT_EPSILON + x7bc_;
x938_ = false;
}
2020-09-12 04:37:45 +00:00
2021-05-06 17:53:19 +00:00
zeus::CVector2f CThardus::GetTargetVector(float arg, CStateManager& mgr) {
zeus::CVector2f ret;
2020-09-12 04:37:45 +00:00
if (GetSearchPath() != nullptr) {
if (GetSearchPath()->GetResult() == CPathFindSearch::EResult::Success) {
CPatterned::PathFind(mgr, EStateMsg::Update, arg);
ret = GetBodyController()->GetCommandMgr().GetMoveVector().toVec2f();
} else {
ret = x45c_steeringBehaviors.Arrival(*this, x7d8_, 0.f).toVec2f();
}
}
if (x8d4_ || (!x8d4_ && x7f0_pathFindSearch.OnPath(GetTranslation()) != CPathFindSearch::EResult::Success)) {
2021-05-06 17:53:19 +00:00
zeus::CVector2f vec = GetSteeringVector(mgr);
if (vec != zeus::skZero2f) {
return vec;
}
}
2020-09-13 20:00:13 +00:00
if (ret == zeus::skZero2f) {
return x45c_steeringBehaviors.Arrival(*this, x7d8_, 0.f).toVec2f();
}
return ret;
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce::MP1