metaforce/Runtime/MP1/World/CFlaahgra.cpp

1383 lines
50 KiB
C++
Raw Normal View History

#include "Runtime/MP1/World/CFlaahgra.hpp"
#include "Runtime/CDependencyGroup.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Camera/CCameraManager.hpp"
#include "Runtime/Camera/CFirstPersonCamera.hpp"
#include "Runtime/Character/CBoneTracking.hpp"
#include "Runtime/Collision/CCollisionActor.hpp"
#include "Runtime/Collision/CCollisionActorManager.hpp"
#include "Runtime/Graphics/CBooRenderer.hpp"
#include "Runtime/MP1/World/CFlaahgraProjectile.hpp"
#include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "Runtime/World/CGameArea.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Runtime/World/CScriptWaypoint.hpp"
#include "Runtime/World/CWorld.hpp"
#include "Runtime/World/ScriptLoader.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
2019-06-10 08:28:33 +00:00
namespace urde::MP1 {
constexpr zeus::CColor skFlaahgraDamageColor{0.5f, 0.5f, 0.f, 1.f};
constexpr zeus::CColor skUnkColor{0.5f, 0.f, 0.f, 1.f};
constexpr zeus::CVector3f skUnkVec1{0.5f, 7.f, 0.f};
constexpr zeus::CVector3f skUnkVec2{12.f, 12.f, 12.f};
constexpr std::array<SJointInfo, 3> skLeftArmJointList{{
{"L_elbow", "L_blade", 0.6f, 1.f},
{"L_blade", "L_CLAW_LCTR", 0.6f, 1.f},
{"L_CLAW_LCTR", "L_CLAW_END_LCTR", 0.6f, 1.f},
}};
constexpr std::array<SJointInfo, 3> skRightArmJointList{{
{"R_elbow", "R_blade", 0.6f, 1.f},
{"R_blade", "R_CLAW_LCTR", 0.6f, 1.f},
{"R_CLAW_LCTR", "R_CLAW_END_LCTR", 0.6f, 1.f},
}};
constexpr std::array<SSphereJointInfo, 5> skSphereJointList{{
{"Head_1", 1.5f},
{"Spine_2", 1.5f},
{"Spine_4", 1.5f},
{"Spine_6", 1.5f},
{"Collar", 1.5f},
}};
2019-06-10 08:28:33 +00:00
CFlaahgraData::CFlaahgraData(CInputStream& in)
: x0_(in.readFloatBig())
, x4_(in.readFloatBig())
, x8_(in.readFloatBig())
, xc_(in.readFloatBig())
, x10_(in)
, x78_(in)
, x7c_(in)
, x98_(in)
, x9c_(in)
, xb8_(in)
, xbc_(in)
, xd8_(ScriptLoader::LoadActorParameters(in))
, x140_(in.readFloatBig())
, x144_(in.readFloatBig())
, x148_(in.readFloatBig())
, x14c_animationParameters(ScriptLoader::LoadAnimationParameters(in))
, x158_(in) {}
CFlaahgraRenderer::CFlaahgraRenderer(TUniqueId uid, TUniqueId owner, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf)
: CActor(uid, true, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::Character),
CActorParameters::None(), kInvalidUniqueId)
, xe8_owner(owner) {}
void CFlaahgraRenderer::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
2019-06-10 08:28:33 +00:00
if (const CActor* act = static_cast<const CActor*>(mgr.GetObjectById(xe8_owner))) {
if (act->HasModelData() && (act->GetModelData()->HasAnimData() || act->GetModelData()->HasNormalModel())) {
2019-06-10 08:28:33 +00:00
act->GetModelData()->RenderParticles(frustum);
}
2019-06-10 08:28:33 +00:00
}
}
2019-06-10 08:28:33 +00:00
void CFlaahgraRenderer::Accept(IVisitor& visitor) { visitor.Visit(this); }
CFlaahgra::CFlaahgra(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
const CAnimRes& animRes, const CPatternedInfo& pInfo, const CActorParameters& actParms,
const CFlaahgraData& flaahgraData)
: CPatterned(ECharacter::Flaahgra, uid, name, EFlavorType::Zero, info, xf, CModelData::CModelDataNull(), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::Restricted, actParms, EKnockBackVariant::Large)
, x56c_(flaahgraData)
, x6d4_(g_SimplePool->GetObj({SBIG('PART'), x56c_.xb8_}))
, x6dc_(x56c_.x78_, x56c_.x7c_)
, x704_(x56c_.x98_, x56c_.x9c_)
, x7dc_(x404_contactDamage)
2019-06-10 08:28:33 +00:00
, x820_(xf.origin)
, x8a0_(xf.frontVector())
, x8ac_(animRes) {
xe7_30_doTargetDistanceTest = false;
2019-06-10 08:28:33 +00:00
x6dc_.Token().Lock();
x704_.Token().Lock();
x7dc_.SetDamage(0.5f * x7dc_.GetDamage());
SetActorLights(actParms.GetLightParameters().MakeActorLights());
x90_actorLights->SetCastShadows(false);
x90_actorLights->SetMaxAreaLights(2);
x90_actorLights->SetHasAreaLights(x90_actorLights->GetMaxAreaLights() > 0);
x90_actorLights->SetMaxDynamicLights(1);
x460_knockBackController.SetAutoResetImpulse(false);
x460_knockBackController.SetEnableLaggedBurnDeath(false);
x430_damageColor = skFlaahgraDamageColor;
2019-06-10 08:28:33 +00:00
LoadDependencies(x56c_.x158_);
2019-06-27 01:06:03 +00:00
float curAngle = zeus::degToRad(17.5f);
while (curAngle < zeus::degToRad(360.f)) {
x82c_.push_back(GetTransform().rotate(zeus::CVector3f(std::cos(curAngle), std::sin(curAngle), 0.f)));
x860_.push_back(GetTransform().rotate(
zeus::CVector3f(std::cos(curAngle + zeus::degToRad(45.f)), std::sin(curAngle + zeus::degToRad(45.f)), 0.f)));
curAngle += zeus::degToRad(90.f);
}
2019-06-10 08:28:33 +00:00
}
void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
switch (msg) {
case EScriptObjectMessage::InitializedInArea: {
if (!x8e4_25_loading && !x8e4_24_loaded) {
mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x113c_playerActorsLoading++;
2019-06-10 08:28:33 +00:00
x8e4_25_loading = true;
}
GetMirrorWaypoints(mgr);
break;
}
case EScriptObjectMessage::Activate: {
GatherAssets(mgr);
if (x8e5_27_)
2019-06-10 08:28:33 +00:00
break;
SetupCollisionManagers(mgr);
x6d0_rendererId = mgr.AllocateUniqueId();
mgr.AddObject(new CFlaahgraRenderer(x6d0_rendererId, GetUniqueId(), "Flaahgra Renderer"sv,
CEntityInfo(GetAreaIdAlways(), NullConnectionList), GetTransform()));
2019-06-18 01:39:56 +00:00
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
2019-06-10 08:28:33 +00:00
x450_bodyController->Activate(mgr);
x8e5_27_ = true;
break;
}
case EScriptObjectMessage::Deleted: {
if (!x8e5_27_)
break;
x79c_leftArmCollision->Destroy(mgr);
x7a0_rightArmCollision->Destroy(mgr);
x7a4_sphereCollision->Destroy(mgr);
mgr.FreeScriptObject(x6d0_rendererId);
x6d0_rendererId = kInvalidUniqueId;
x8e5_27_ = false;
break;
}
case EScriptObjectMessage::Touched: {
2019-06-18 01:39:56 +00:00
if (HealthInfo(mgr)->GetHP() <= 0.f)
break;
if (TCastToConstPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
if (colAct->GetLastTouchedObject() == mgr.GetPlayer().GetUniqueId() && x420_curDamageRemTime <= 0.f) {
CDamageInfo contactDamage = GetContactDamage();
if (x7a8_ == 4)
contactDamage = x7dc_;
2019-08-04 00:02:53 +00:00
else if (!sub801ae670())
2019-06-18 01:39:56 +00:00
contactDamage.SetDamage(0.5f * contactDamage.GetDamage());
if (x788_ >= 2)
2019-06-18 01:39:56 +00:00
contactDamage.SetDamage(1.33f * contactDamage.GetDamage());
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), contactDamage,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
x420_curDamageRemTime = x424_damageWaitTime;
}
}
2019-06-10 08:28:33 +00:00
break;
}
case EScriptObjectMessage::Damage: {
2019-06-18 01:39:56 +00:00
if (HealthInfo(mgr)->GetHP() <= 0.f)
break;
2019-06-20 21:22:06 +00:00
if (!IsSphereCollider(uid))
2019-06-18 01:39:56 +00:00
break;
if (TCastToConstPtr<CCollisionActor> colAct = mgr.GetObjectById(uid)) {
if (TCastToConstPtr<CGameProjectile> proj = mgr.GetObjectById(colAct->GetLastTouchedObject())) {
if (x780_ != 3)
break;
2019-08-04 00:02:53 +00:00
if (!IsDizzy(mgr, 0.f) && x450_bodyController->HasBodyState(pas::EAnimationState::LoopReaction)) {
2019-06-18 01:39:56 +00:00
TakeDamage({}, 0.f);
if ((x56c_.x140_ - proj->GetDamageInfo().GetDamage()) >= x810_) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLoopHitReactionCmd(pas::EReactionType::One));
} else if (uid == x80c_headActor &&
(proj->GetDamageInfo().GetWeaponMode().IsCharged() ||
proj->GetDamageInfo().GetWeaponMode().IsComboed() ||
proj->GetDamageInfo().GetWeaponMode().GetType() == EWeaponType::Missile)) {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCKnockBackCmd(-GetTransform().frontVector(), pas::ESeverity::One));
2019-06-18 01:39:56 +00:00
}
} else {
if (x8e5_30_)
TakeDamage({}, 0.f);
if (uid == x80c_headActor &&
(proj->GetDamageInfo().GetWeaponMode().IsCharged() ||
proj->GetDamageInfo().GetWeaponMode().IsComboed() ||
proj->GetDamageInfo().GetWeaponMode().GetType() == EWeaponType::Missile)) {
2019-06-18 01:39:56 +00:00
x450_bodyController->GetCommandMgr().DeliverCmd(CBCAdditiveFlinchCmd(1.f));
}
}
}
}
2019-06-10 08:28:33 +00:00
break;
}
case EScriptObjectMessage::Decrement: {
x780_ = 0;
break;
}
case EScriptObjectMessage::Close: {
sub801ae980(mgr);
break;
}
case EScriptObjectMessage::Start: {
x8e4_31_ = false;
break;
}
case EScriptObjectMessage::Stop: {
x8e4_31_ = true;
break;
}
case EScriptObjectMessage::Play: {
x7d0_ = 3.f;
x8e5_24_ = true;
break;
}
case EScriptObjectMessage::Action: {
if (TCastToConstPtr<CGameProjectile>(mgr.GetObjectById(uid)))
x7f8_ = x788_;
break;
}
case EScriptObjectMessage::SetToMax: {
x7d4_ = 0.f;
break;
}
case EScriptObjectMessage::Reset: {
x8e5_28_ = true;
break;
}
default:
break;
}
CPatterned::AcceptScriptMsg(msg, uid, mgr);
}
2019-06-19 21:11:13 +00:00
void CFlaahgra::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
if ((!GetModelData()->HasAnimData() && !GetModelData()->HasNormalModel()) || xe4_30_outOfFrustum) {
2019-06-20 21:22:06 +00:00
return;
}
2019-06-20 21:22:06 +00:00
if (CanRenderUnsorted(mgr)) {
2019-06-20 21:22:06 +00:00
Render(mgr);
} else {
2019-06-20 21:22:06 +00:00
EnsureRendered(mgr);
}
2019-06-20 21:22:06 +00:00
}
2019-06-19 21:11:13 +00:00
void CFlaahgra::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptObjectState state) {
if (!x400_25_alive)
return;
x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Dead"sv);
if (x450_bodyController->GetPercentageFrozen() > 0.f)
x450_bodyController->UnFreeze();
x400_25_alive = false;
}
void CFlaahgra::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
2019-06-20 21:22:06 +00:00
switch (type) {
2019-06-19 21:11:13 +00:00
case EUserEventType::Projectile: {
const auto lctrXf = GetLctrTransform(node.GetLocatorName());
const auto attackTargetPos = GetAttackTargetPos(mgr);
if (x7b4_ == 0 || x7b4_ == 1) {
if (x72c_ == 0) {
x730_.clear();
auto& player = mgr.GetPlayer();
const auto interceptPos =
GetProjectileInfo()->PredictInterceptPos(lctrXf.origin, attackTargetPos, player, false, dt);
x730_.push_back(interceptPos);
const auto& xf = GetTransform();
auto basis = xf.basis;
const auto rot = zeus::CMatrix3f::RotateZ(zeus::degToRad(x7b4_ == 1 ? -4.f : 4.f));
for (int i = 1; i < x730_.capacity(); ++i) {
basis = basis * rot;
const auto vec = basis * xf.transposeRotate(interceptPos - xf.origin);
x730_.push_back(zeus::CVector3f{xf.origin.x() + vec.x(), xf.origin.y() + vec.y(), interceptPos.z()});
}
if (x72c_ > -1 && x730_.size() > x72c_) {
CreateProjectile(zeus::lookAt(lctrXf.origin, x730_[x72c_]), mgr);
x72c_++;
}
}
} else {
CPlayer& player = mgr.GetPlayer();
const auto interceptPos =
GetProjectileInfo()->PredictInterceptPos(lctrXf.origin, attackTargetPos, player, false, dt);
auto target = interceptPos;
auto dir = interceptPos - lctrXf.origin;
dir.z() = 0.f;
const auto frontVec = GetTransform().frontVector();
if (zeus::CVector3f::getAngleDiff(frontVec, dir) > zeus::degToRad(45.f)) {
if (dir.canBeNormalized()) {
target = lctrXf.origin +
(dir.magnitude() * zeus::CVector3f::slerp(frontVec, dir.normalized(), zeus::degToRad(45.f)));
} else {
target = lctrXf.origin + dir.magnitude() * lctrXf.frontVector();
}
}
CreateProjectile(zeus::lookAt(lctrXf.origin, target), mgr);
}
2019-06-20 21:22:06 +00:00
return;
2019-06-19 21:11:13 +00:00
}
case EUserEventType::BeginAction: {
x8e4_26_ = true;
x7c4_ = GetEndActionTime();
break;
}
case EUserEventType::ScreenShake: {
2019-06-20 21:22:06 +00:00
RattlePlayer(mgr, GetLctrTransform(node.GetLocatorName()).origin);
return;
2019-06-19 21:11:13 +00:00
}
case EUserEventType::AlignTargetRot: {
if (x77c_ == kInvalidUniqueId)
break;
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x77c_)) {
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
if (x7f8_ > 0)
--x7f8_;
}
break;
}
case EUserEventType::GenerateEnd: {
2019-06-20 21:22:06 +00:00
zeus::CVector3f boneOrigin = GetLctrTransform(node.GetLocatorName()).origin;
zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
boneOrigin.z() = zeus::max<float>(aimPos.z(), boneOrigin.z());
zeus::CTransform xf = GetTransform();
xf.origin = boneOrigin;
CRayCastResult res = mgr.RayStaticIntersection(xf.origin, zeus::skDown, 100.f,
CMaterialFilter::MakeInclude({EMaterialTypes::Floor}));
if (res.IsValid()) {
2020-08-15 07:34:24 +00:00
xf.origin = res.GetPoint();
2019-06-20 21:22:06 +00:00
CFlaahgraPlants* plants = new CFlaahgraPlants(x6d4_, x56c_.xd8_, mgr.AllocateUniqueId(), GetAreaIdAlways(),
GetUniqueId(), xf, x56c_.xbc_, {5.f, 10.f, 5.f});
mgr.AddObject(plants);
mgr.SetActorAreaId(*plants, GetAreaIdAlways());
x7cc_ = 8.f;
}
x8e4_27_ = true;
2019-06-19 21:11:13 +00:00
break;
}
case EUserEventType::ObjectDrop: {
SendScriptMsgs(EScriptObjectState::Modify, mgr, EScriptObjectMessage::None);
break;
}
2019-06-20 21:22:06 +00:00
default:
break;
2019-06-19 21:11:13 +00:00
}
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::LoadDependencies(CAssetId dgrpId) {
if (!dgrpId.IsValid()) {
ResetModelDataAndBodyController();
x8e4_24_loaded = true;
return;
}
x8c8_depGroup = {g_SimplePool->GetObj({SBIG('DGRP'), dgrpId})};
x8c8_depGroup->Lock();
}
void CFlaahgra::ResetModelDataAndBodyController() {
SetModelData(std::make_unique<CModelData>(x8ac_));
_CreateShadow();
CreateShadow(true);
x94_simpleShadow->SetAlwaysCalculateRadius(false);
BuildBodyController(EBodyType::Restricted);
x6cc_boneTracking =
std::make_unique<CBoneTracking>(*GetModelData()->GetAnimationData(), "Head_1"sv, zeus::degToRad(80.f),
zeus::degToRad(180.f), EBoneTrackingFlags::None);
2019-06-10 08:28:33 +00:00
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::GatherAssets(CStateManager& mgr) {
if (x8e4_24_loaded)
return;
x8c8_depGroup->GetObj();
LoadTokens(mgr);
if (x8e4_24_loaded)
return;
for (const CToken& tok : x8d4_tokens)
tok.GetObj();
FinalizeLoad(mgr);
}
void CFlaahgra::LoadTokens(CStateManager& mgr) {
if (!x8d4_tokens.empty()) {
for (const CToken& tok : x8d4_tokens) {
if (!tok.IsLoaded())
return;
}
FinalizeLoad(mgr);
}
if (!x8c8_depGroup)
return;
TToken<CDependencyGroup> depGroup = *x8c8_depGroup;
if (depGroup->GetObjectTagVector().empty()) {
FinalizeLoad(mgr);
return;
}
if (x8d4_tokens.empty()) {
x8d4_tokens.reserve(depGroup->GetObjectTagVector().size());
for (const auto& tag : depGroup->GetObjectTagVector()) {
CToken token = g_SimplePool->GetObj({tag.type, tag.id});
token.Lock();
x8d4_tokens.push_back(token);
}
}
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::FinalizeLoad(CStateManager& mgr) {
x8e4_24_loaded = true;
if (x8e4_25_loading) {
mgr.GetWorld()->GetArea(GetAreaIdAlways())->GetPostConstructed()->x113c_playerActorsLoading--;
2019-06-10 08:28:33 +00:00
x8e4_25_loading = false;
}
ResetModelDataAndBodyController();
}
void CFlaahgra::Think(float dt, CStateManager& mgr) {
if (!GetActive())
return;
CPatterned::Think(dt, mgr);
x6cc_boneTracking->Update(dt);
UpdateCollisionManagers(dt, mgr);
x6cc_boneTracking->PreRender(mgr, *GetModelData()->GetAnimationData(), GetTransform(), GetModelData()->GetScale(),
2019-06-10 08:28:33 +00:00
*x450_bodyController);
UpdateSmallScaleReGrowth(dt);
UpdateHealthInfo(mgr);
UpdateAimPosition(mgr, dt);
x15c_force = {};
x168_impulse = {};
}
void CFlaahgra::PreThink(float dt, CStateManager& mgr) {
if (!x8e4_24_loaded)
LoadTokens(mgr);
CPatterned::PreThink(dt, mgr);
}
void CFlaahgra::GetMirrorWaypoints(CStateManager& mgr) {
x770_mirrorWaypoints.clear();
for (const SConnection& conn : x20_conns) {
if (conn.x0_state != EScriptObjectState::Modify || conn.x4_msg != EScriptObjectMessage::Follow)
continue;
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(uid))
x770_mirrorWaypoints.push_back(uid);
}
}
void CFlaahgra::AddCollisionList(const SJointInfo* joints, size_t count,
2019-06-10 08:28:33 +00:00
std::vector<CJointCollisionDescription>& outJoints) {
const CAnimData* animData = GetModelData()->GetAnimationData();
for (size_t i = 0; i < count; ++i) {
const auto& joint = joints[i];
const CSegId from = animData->GetLocatorSegId(joint.from);
const CSegId to = animData->GetLocatorSegId(joint.to);
if (to.IsInvalid() || from.IsInvalid()) {
continue;
2019-06-10 08:28:33 +00:00
}
outJoints.push_back(CJointCollisionDescription::SphereSubdivideCollision(
to, from, joint.radius, joint.separation, CJointCollisionDescription::EOrientationType::One, joint.from, 10.f));
2019-06-10 08:28:33 +00:00
}
}
void CFlaahgra::AddSphereCollisionList(const SSphereJointInfo* joints, size_t count,
2019-06-10 08:28:33 +00:00
std::vector<CJointCollisionDescription>& outJoints) {
const CAnimData* animData = GetModelData()->GetAnimationData();
for (size_t i = 0; i < count; ++i) {
const auto& joint = joints[i];
const CSegId seg = animData->GetLocatorSegId(joint.name);
if (seg.IsInvalid()) {
continue;
2019-06-10 08:28:33 +00:00
}
outJoints.push_back(CJointCollisionDescription::SphereCollision(seg, joint.radius, joint.name, 10.f));
2019-06-10 08:28:33 +00:00
}
}
2019-06-19 01:55:38 +00:00
void CFlaahgra::SetupHealthInfo(CStateManager& mgr) {
x7fc_sphereColliders.clear();
for (u32 i = 0; i < x7a4_sphereCollision->GetNumCollisionActors(); ++i) {
const auto& desc = x7a4_sphereCollision->GetCollisionDescFromIndex(i);
TUniqueId uid = desc.GetCollisionActorId();
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
*colAct->HealthInfo(mgr) = *HealthInfo(mgr);
if (desc.GetName() == "Head_1"sv)
x80c_headActor = uid;
x7fc_sphereColliders.push_back(uid);
}
}
2019-06-20 21:22:06 +00:00
x818_curHp = HealthInfo(mgr)->GetHP();
2019-06-19 01:55:38 +00:00
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::SetupCollisionManagers(CStateManager& mgr) {
2019-06-19 01:55:38 +00:00
zeus::CVector3f oldScale = GetModelData()->GetScale();
GetModelData()->SetScale(zeus::CVector3f{x56c_.x4_ * 1.f});
std::vector<CJointCollisionDescription> leftArmJointList;
leftArmJointList.reserve(skLeftArmJointList.size());
AddCollisionList(skLeftArmJointList.data(), skLeftArmJointList.size(), leftArmJointList);
x79c_leftArmCollision =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), leftArmJointList, true);
2019-06-10 08:28:33 +00:00
SetMaterialProperties(x79c_leftArmCollision, mgr);
2019-06-10 08:28:33 +00:00
std::vector<CJointCollisionDescription> rightArmJointList;
rightArmJointList.reserve(skRightArmJointList.size());
AddCollisionList(skRightArmJointList.data(), skRightArmJointList.size(), rightArmJointList);
x7a0_rightArmCollision =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), rightArmJointList, true);
2019-06-10 08:28:33 +00:00
SetMaterialProperties(x7a0_rightArmCollision, mgr);
2019-06-10 08:28:33 +00:00
std::vector<CJointCollisionDescription> sphereJointList;
sphereJointList.reserve(skSphereJointList.size());
AddSphereCollisionList(skSphereJointList.data(), skSphereJointList.size(), sphereJointList);
x7a4_sphereCollision =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(), sphereJointList, true);
2019-06-10 08:28:33 +00:00
SetMaterialProperties(x7a4_sphereCollision, mgr);
2019-06-19 01:55:38 +00:00
SetupHealthInfo(mgr);
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid},
{EMaterialTypes::CollisionActor, EMaterialTypes::AIPassthrough, EMaterialTypes::Player}));
AddMaterial(EMaterialTypes::ProjectilePassthrough, EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
RemoveMaterial(EMaterialTypes::Solid, mgr);
GetModelData()->SetScale(oldScale);
2019-06-30 07:29:49 +00:00
x7a4_sphereCollision->AddMaterial(mgr, {EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough});
x79c_leftArmCollision->AddMaterial(mgr, {EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough});
x7a0_rightArmCollision->AddMaterial(mgr, {EMaterialTypes::AIJoint, EMaterialTypes::CameraPassthrough});
2019-06-10 08:28:33 +00:00
}
void CFlaahgra::sub801ae980(CStateManager& mgr) {
HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - x56c_.x8_);
x7d4_ = x56c_.xc_;
2019-06-18 01:39:56 +00:00
x8e4_29_getup = true;
x7d8_ = 0.f;
2019-06-10 08:28:33 +00:00
x430_damageColor = skUnkColor;
++x788_;
}
void CFlaahgra::CalculateFallDirection() {
const auto front = GetTransform().frontVector();
const auto right = x7ac_ ? GetTransform().rightVector() : -GetTransform().rightVector();
x894_fallDirection = right;
2019-06-27 01:06:03 +00:00
const rstl::reserved_vector<zeus::CVector3f, 4>& vec = x7ac_ ? x82c_ : x860_;
2019-06-27 01:06:03 +00:00
float curDist = FLT_MIN;
2019-06-27 01:06:03 +00:00
for (const zeus::CVector3f& v : vec) {
if (right.dot(v) < 0.f) {
2019-06-27 01:06:03 +00:00
continue;
}
2019-06-27 01:06:03 +00:00
float dist = front.dot(v);
if (dist > curDist) {
x894_fallDirection = v;
curDist = dist;
}
2019-06-27 01:06:03 +00:00
}
}
bool CFlaahgra::ShouldAttack(CStateManager& mgr, float) {
if (x788_ <= 0 || x788_ > 3 || x7c0_ > 0.f || mgr.GetPlayer().IsInWaterMovement() || x8e4_31_)
return false;
CPlayer& player = mgr.GetPlayer();
zeus::CVector2f diff = player.GetTranslation().toVec2f() - GetTranslation().toVec2f();
float dist = diff.magSquared();
float minSq = x2fc_minAttackRange * x2fc_minAttackRange;
float maxSq = x300_maxAttackRange * x300_maxAttackRange;
if ((player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed || dist < minSq ||
dist > maxSq) &&
(x7cc_ > 0.f || player.GetVelocity().magSquared() < 25.f))
return false;
return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), diff) < zeus::degToRad(45.f);
2019-06-27 01:06:03 +00:00
}
2019-06-19 21:11:13 +00:00
void CFlaahgra::UpdateHeadDamageVulnerability(CStateManager& mgr, bool b) {
if (TCastToPtr<CCollisionActor> head = mgr.ObjectById(x80c_headActor)) {
head->SetDamageVulnerability(b ? x56c_.x10_ : *GetDamageVulnerability());
2019-06-19 21:11:13 +00:00
}
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::FadeIn(CStateManager& mgr, EStateMsg msg, float) {
if (msg != EStateMsg::Activate)
return;
if (HealthInfo(mgr)->GetHP() > 0.f)
SendScriptMsgs(EScriptObjectState::Exited, mgr, EScriptObjectMessage::None);
2019-06-18 01:39:56 +00:00
if (!x8e4_29_getup)
2019-06-10 08:28:33 +00:00
SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None);
}
void CFlaahgra::FadeOut(CStateManager& mgr, EStateMsg msg, float) {
if (msg != EStateMsg::Activate)
return;
x7a4_sphereCollision->SetActive(mgr, true);
x79c_leftArmCollision->SetActive(mgr, true);
x7a0_rightArmCollision->SetActive(mgr, true);
x784_ = x780_;
2019-06-18 01:39:56 +00:00
x81c_ = GetModelData()->GetScale().z();
UpdateScale(1.f, x81c_, x56c_.x4_);
x8e4_26_ = false;
x7c0_ = 2.f;
x780_ = 3;
x8e4_29_getup = false;
x430_damageColor = skDamageColor;
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::NextState));
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
x8e5_29_ = false;
2019-06-10 08:28:33 +00:00
}
2019-06-20 21:22:06 +00:00
2019-06-10 08:28:33 +00:00
void CFlaahgra::UpdateCollisionManagers(float dt, CStateManager& mgr) {
x7a4_sphereCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
x79c_leftArmCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
x7a0_rightArmCollision->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
}
2019-06-20 21:22:06 +00:00
2019-06-19 01:55:38 +00:00
void CFlaahgra::UpdateSmallScaleReGrowth(float dt) {
if (x7c0_ > 0.f)
x7c0_ -= (x788_ < 2 ? dt : 1.25f * dt);
if (x7bc_ > 0.f)
x7bc_ -= dt;
if (x7d0_ > 0.f)
x7d0_ -= dt;
if (x7cc_ > 0.f)
x7cc_ -= dt;
if (!x8e4_29_getup || x7d8_ > 6.f)
return;
x430_damageColor = zeus::CColor::lerp(skUnkColor, zeus::skBlack, std::round(std::fabs(M_PIF * std::cos(x7d8_))));
2019-06-19 01:55:38 +00:00
TakeDamage({}, 0.f);
x7d8_ += dt;
}
2019-06-19 21:11:13 +00:00
void CFlaahgra::UpdateHealthInfo(CStateManager& mgr) {
float tmp = 0.f;
for (const TUniqueId& uid : x7fc_sphereColliders) {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
CHealthInfo* inf = colAct->HealthInfo(mgr);
2019-06-20 21:22:06 +00:00
tmp = zeus::max(tmp, x818_curHp - inf->GetHP());
2019-06-19 21:11:13 +00:00
}
}
if (x780_ == 3) {
2019-06-20 21:22:06 +00:00
if (!IsDizzy(mgr, 0.f))
x814_ += tmp;
else
x810_ += tmp;
2019-06-19 21:11:13 +00:00
} else {
x814_ = 0.f;
x810_ = 0.f;
}
CHealthInfo* hInfo = HealthInfo(mgr);
if (hInfo->GetHP() <= 0.f) {
Death(mgr, {}, EScriptObjectState::DeathRattle);
RemoveMaterial(EMaterialTypes::Orbit, mgr);
return;
}
for (const TUniqueId& uid : x7fc_sphereColliders) {
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(uid)) {
2019-06-20 21:22:06 +00:00
colAct->HealthInfo(mgr)->SetHP(x818_curHp);
2019-06-19 21:11:13 +00:00
}
}
}
2019-06-19 01:55:38 +00:00
void CFlaahgra::UpdateAimPosition(CStateManager& mgr, float dt) {
if (TCastToConstPtr<CCollisionActor> head = mgr.GetObjectById(x80c_headActor)) {
pas::EAnimationState animState = x450_bodyController->GetBodyStateInfo().GetCurrentStateId();
if (animState == pas::EAnimationState::GroundHit || animState == pas::EAnimationState::LieOnGround)
return;
zeus::CVector3f vec;
if (x780_ != 0 && !x8e4_28_ && !sub801e4f8())
vec = head->GetTranslation();
else
vec = GetTranslation() + zeus::CVector3f(0.f, 0.f, 3.7674999f) +
(zeus::CVector3f(0.f, 0.f, 4.1550002f) * GetModelData()->GetScale());
zeus::CVector3f diff = vec - x820_;
if (diff.canBeNormalized()) {
if (diff.magnitude() > (125.f * dt))
x820_ += ((1.f / diff.magnitude()) * diff) * (125.f * dt);
else
x820_ = vec;
}
}
}
2019-06-10 08:28:33 +00:00
void CFlaahgra::SetMaterialProperties(const std::unique_ptr<CCollisionActorManager>& actMgr, CStateManager& mgr) {
for (u32 i = 0; i < actMgr->GetNumCollisionActors(); ++i) {
TUniqueId uid = actMgr->GetCollisionDescFromIndex(i).GetCollisionActorId();
if (CCollisionActor* colAct = static_cast<CCollisionActor*>(mgr.ObjectById(uid))) {
colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Player},
{EMaterialTypes::Trigger, EMaterialTypes::CollisionActor, EMaterialTypes::Immovable}));
colAct->AddMaterial(EMaterialTypes::Trigger, EMaterialTypes::ScanPassthrough, mgr);
colAct->SetDamageVulnerability(*GetDamageVulnerability());
}
}
}
bool CFlaahgra::ShouldTurn(CStateManager& mgr, float) {
zeus::CVector2f posDiff = mgr.GetPlayer().GetTranslation().toVec2f() - GetTranslation().toVec2f();
zeus::CVector2f frontVec = x34_transform.frontVector().toVec2f();
return zeus::CVector2f::getAngleDiff(frontVec, posDiff) > zeus::degToRad(15.f);
}
void CFlaahgra::TurnAround(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x6cc_boneTracking->SetTarget(mgr.GetPlayer().GetUniqueId());
x6cc_boneTracking->SetActive(true);
x8e5_29_ = false;
} else if (msg == EStateMsg::Update) {
if (!ShouldTurn(mgr, 0.f))
return;
float dt = 0.f;
if (GetModelData()->GetAnimationData()->GetSpeedScale() > 0.f)
dt = 1.5f / GetModelData()->GetAnimationData()->GetSpeedScale();
zeus::CVector3f offset = mgr.GetPlayer().GetAimPosition(mgr, dt) - GetTranslation();
if (offset.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, offset.normalized(), 1.f));
}
} else if (msg == EStateMsg::Deactivate) {
x6cc_boneTracking->SetActive(false);
}
}
2019-06-20 21:22:06 +00:00
bool CFlaahgra::IsSphereCollider(TUniqueId uid) const {
const auto it = std::find(x7fc_sphereColliders.cbegin(), x7fc_sphereColliders.cend(), uid);
2019-06-20 21:22:06 +00:00
return it != x7fc_sphereColliders.end();
}
2019-06-18 01:39:56 +00:00
void CFlaahgra::GetUp(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
x784_ = x780_;
x8e4_28_ = true;
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup) {
x568_ = 2;
x7a8_ = (!x8e4_29_getup ? 4 : -1);
SetCollisionActorBounds(mgr, x79c_leftArmCollision, skUnkVec1);
SetCollisionActorBounds(mgr, x7a0_rightArmCollision, skUnkVec1);
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(!x8e4_29_getup)));
2019-06-18 01:39:56 +00:00
}
2019-06-20 21:22:06 +00:00
} else if (x568_ == 2 &&
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) {
2019-06-18 01:39:56 +00:00
x568_ = 4;
}
} else if (msg == EStateMsg::Deactivate) {
x7c0_ = (x8e4_29_getup ? 5.f : 0.f);
x7a8_ = -1;
x8e4_28_ = false;
x8e4_29_getup = false;
SetCollisionActorBounds(mgr, x79c_leftArmCollision, {});
SetCollisionActorBounds(mgr, x7a0_rightArmCollision, {});
x430_damageColor = skDamageColor;
}
}
2019-06-19 01:55:38 +00:00
void CFlaahgra::Growth(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
x8e4_26_ = false;
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Two));
x81c_ = GetModelData()->GetScale().z();
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate)
x568_ = 2;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Two));
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
x568_ = 4;
} else if (x8e4_26_) {
UpdateScale((x7c4_ > 0.f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f), x81c_, x56c_.x4_);
}
2020-03-13 20:22:39 +00:00
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
2019-06-19 01:55:38 +00:00
}
} else if (msg == EStateMsg::Deactivate) {
UpdateScale(1.f, x81c_, x56c_.x4_);
x8e4_26_ = false;
x780_ = 3;
x79c_leftArmCollision->SetActive(mgr, true);
x7a0_rightArmCollision->SetActive(mgr, true);
x8e4_29_getup = false;
x430_damageColor = skDamageColor;
}
}
2019-06-18 01:39:56 +00:00
void CFlaahgra::SetCollisionActorBounds(CStateManager& mgr, const std::unique_ptr<CCollisionActorManager>& colMgr,
const zeus::CVector3f& extendedBounds) {
for (u32 i = 0; i < colMgr->GetNumCollisionActors(); ++i) {
const CJointCollisionDescription& jointDesc = colMgr->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(jointDesc.GetCollisionActorId())) {
colAct->SetExtendedTouchBounds(extendedBounds);
}
}
}
2019-06-19 01:55:38 +00:00
void CFlaahgra::UpdateScale(float t, float min, float max) {
float scale = (t * (max - min) + min);
GetModelData()->SetScale(zeus::skOne3f * scale);
2019-06-19 01:55:38 +00:00
}
float CFlaahgra::GetEndActionTime() const {
2019-06-19 01:55:38 +00:00
CCharAnimTime eventTime =
GetModelData()->GetAnimationData()->GetTimeOfUserEvent(EUserEventType::EndAction, CCharAnimTime::Infinity());
if (eventTime == CCharAnimTime::Infinity())
return 0.f;
return eventTime.GetSeconds();
}
void CFlaahgra::Generate(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Generate) {
x568_ = 2;
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero));
}
} else if (x568_ == 2 &&
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Generate) {
x568_ = 4;
}
} else if (msg == EStateMsg::Deactivate) {
x7a4_sphereCollision->SetActive(mgr, true);
x7c0_ = 11.f;
}
2019-06-18 01:39:56 +00:00
}
zeus::CVector3f CFlaahgra::GetAttackTargetPos(const CStateManager& mgr) const {
2019-06-19 21:11:13 +00:00
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed)
return mgr.GetPlayer().GetMorphBall()->GetBallToWorld().origin;
return mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, -.5f + mgr.GetPlayer().GetEyeHeight());
}
2019-06-20 21:22:06 +00:00
void CFlaahgra::RattlePlayer(CStateManager& mgr, const zeus::CVector3f& vec) {
CPlayer& player = mgr.GetPlayer();
/*
zeus::CVector3f direction = vec - mgr.GetPlayer().GetTranslation();
float dir = direction.magnitude(); Unused
*/
if (player.GetSurfaceRestraint() == CPlayer::ESurfaceRestraints::Air || player.IsInWaterMovement())
return;
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) {
if (mgr.GetCameraManager()->GetFirstPersonCamera()->GetUniqueId() != mgr.GetCameraManager()->GetCurrentCameraId())
return;
mgr.GetCameraManager()->AddCameraShaker(CCameraShakeData(2.f, 0.75f), true);
} else {
player.ApplyImpulseWR((mgr.GetPlayer().GetMass() * 0.75f) * (25.f * zeus::skUp), {});
player.SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr);
}
}
void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) {
static constexpr std::array kSeverities{pas::ESeverity::Zero, pas::ESeverity::One};
2019-06-20 21:22:06 +00:00
if (msg == EStateMsg::Activate) {
x568_ = 0;
x7d4_ = 0.f;
x8e5_24_ = false;
x7f8_ = 0;
SendScriptMsgs(EScriptObjectState::Entered, mgr, EScriptObjectMessage::None);
SendScriptMsgs(EScriptObjectState::Retreat, mgr, EScriptObjectMessage::None);
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[size_t(x7ac_)]));
2019-06-20 21:22:06 +00:00
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall) {
x568_ = 2;
CalculateFallDirection();
2019-06-20 21:22:06 +00:00
UpdateHeadDamageVulnerability(mgr, true);
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCKnockDownCmd(-GetTransform().frontVector(), kSeverities[size_t(x7ac_)]));
2019-06-20 21:22:06 +00:00
}
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::LieOnGround) {
x7d4_ += arg;
if (x7d4_ >= x56c_.xc_)
x568_ = 4;
2020-03-12 22:06:01 +00:00
} else {
x450_bodyController->FaceDirection(x894_fallDirection, arg);
2019-06-20 21:22:06 +00:00
}
}
} else if (msg == EStateMsg::Deactivate) {
x8e4_27_ = false;
x7ac_ = !x7ac_;
x780_ = 3;
UpdateHeadDamageVulnerability(mgr, false);
}
}
void CFlaahgra::Dead(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = (x450_bodyController->GetFallState() != pas::EFallState::Zero ||
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall);
2019-06-20 21:22:06 +00:00
SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup)
return;
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Fall) {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCKnockDownCmd(-GetTransform().frontVector(), pas::ESeverity::Two));
} else {
x568_ = 2;
zeus::CTransform xf = zeus::lookAt(GetTranslation(), GetTranslation() + x8a0_, zeus::skUp);
xf.origin = GetTranslation();
SetTransform(xf);
SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None);
x8e5_26_ = true;
}
} else if (x568_ == 1) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup) {
x568_ = 0;
return;
}
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Two));
} else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Fall)
mgr.FreeScriptObject(GetUniqueId());
}
}
2019-06-27 01:06:03 +00:00
void CFlaahgra::Attack(CStateManager& mgr, EStateMsg msg, float arg) {
static constexpr std::array kStates1{
pas::ESeverity::Invalid, pas::ESeverity::Invalid, pas::ESeverity::Invalid,
pas::ESeverity::Two, pas::ESeverity::Invalid,
};
static constexpr std::array kSeverity{
pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, pas::ESeverity::Zero, pas::ESeverity::Invalid,
};
2019-06-27 01:06:03 +00:00
2019-06-20 21:22:06 +00:00
if (msg == EStateMsg::Activate) {
x568_ = 0;
x7a8_ = sub801ae828(mgr);
SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
2019-06-27 01:06:03 +00:00
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
x568_ = kStates1[x7a8_] != pas::ESeverity::Invalid ? 1 : 2;
2019-06-20 21:22:06 +00:00
2019-06-27 01:06:03 +00:00
if (sub801ae670()) {
SetCollisionActorBounds(mgr, x79c_leftArmCollision, skUnkVec2);
SetCollisionActorBounds(mgr, x7a0_rightArmCollision, skUnkVec2);
2019-06-27 01:06:03 +00:00
}
x798_animState = x450_bodyController->GetBodyStateInfo().GetCurrentStateId();
x78c_ = sub801ae754(mgr);
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(kSeverity[x7a8_]));
}
2019-06-20 21:22:06 +00:00
} else if (x568_ == 1) {
2019-06-27 01:06:03 +00:00
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack)
x568_ = 4;
else {
if (x798_animState != x450_bodyController->GetBodyStateInfo().GetCurrentStateId()) {
x568_ = 2;
} else {
if (!ShouldAttack(mgr, 0.f))
return;
2019-06-20 21:22:06 +00:00
2019-06-27 01:06:03 +00:00
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(kStates1[x7a8_]));
}
}
2019-06-20 21:22:06 +00:00
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack)
x568_ = 4;
else
2020-03-13 20:22:39 +00:00
x450_bodyController->GetCommandMgr().DeliverTargetVector(x78c_);
2019-06-20 21:22:06 +00:00
}
} else if (msg == EStateMsg::Deactivate) {
2019-06-20 21:27:50 +00:00
SetCollisionActorBounds(mgr, x79c_leftArmCollision, {});
SetCollisionActorBounds(mgr, x7a0_rightArmCollision, {});
2019-06-20 21:22:06 +00:00
if (sub801ae670())
x7c0_ = (1.f + x788_) / (x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime);
x7a8_ = -1;
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::NextState));
}
}
}
u32 CFlaahgra::sub801ae828(const CStateManager& mgr) const {
2019-06-20 21:22:06 +00:00
const CPlayer& player = mgr.GetPlayer();
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed) {
if (x7cc_ > 0.f || player.GetVelocity().magSquared() < 25.f)
return 3;
}
if (GetTransform().basis[0].dot(player.GetVelocity()) > 0.f)
return 1;
return 0;
}
zeus::CVector3f CFlaahgra::sub801ae754(const CStateManager& mgr) const {
2019-06-27 01:06:03 +00:00
float dt = (sub801ae650() && mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed
? 0.75f
: 0.5f);
return GetAimPosition(mgr, dt * x450_bodyController->GetAnimTimeRemaining()) - GetTranslation();
}
void CFlaahgra::Dizzy(CStateManager&, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
x7b8_ = 0.f;
x814_ = 0.f;
x8e5_30_ = false;
} else if (msg == EStateMsg::Update) {
x7b8_ += arg;
if (x7b8_ >= (x788_ < 2 ? x56c_.x144_ : -1.5f + x56c_.x144_)) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
x8e5_30_ = true;
} else {
x814_ = 0.f;
}
} else if (msg == EStateMsg::Deactivate) {
x8e5_30_ = false;
x810_ = x814_;
x7bc_ = x56c_.x148_;
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
}
}
void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
x8e4_26_ = false;
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Two));
x784_ = x780_;
2019-06-27 01:06:03 +00:00
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup)
x568_ = 2;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType::Zero));
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup)
x568_ = 4;
else if (x8e4_26_) {
UpdateScale(x7c4_ > 0.0f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f, x56c_.x4_, x56c_.x0_);
2019-06-27 01:06:03 +00:00
}
}
} else if (msg == EStateMsg::Deactivate) {
x8e4_26_ = false;
x780_ = 2;
x79c_leftArmCollision->SetActive(mgr, false);
x7a0_rightArmCollision->SetActive(mgr, false);
}
}
void CFlaahgra::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
x568_ = 2;
} else {
x7b4_ = 3;
pas::ESeverity severity;
if (x8e4_31_) {
x7b4_ = 2;
severity = pas::ESeverity::Six;
} else if (mgr.GetPlayer().GetVelocity().magSquared() > 100.f) {
if (mgr.GetPlayer().GetTransform().basis[0].magSquared() < 0.f) {
x7b4_ = 1;
severity = pas::ESeverity::Four;
x72c_ = 0;
} else {
severity = pas::ESeverity::Three;
x7b4_ = x72c_ = 0;
}
} else {
severity = pas::ESeverity::Seven;
}
2019-06-27 01:06:03 +00:00
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCProjectileAttackCmd(severity, mgr.GetPlayer().GetTranslation(), false));
}
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {
x568_ = 4;
} else {
2020-03-13 20:22:39 +00:00
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
}
}
}
2019-06-27 01:06:03 +00:00
}
void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) {
static pas::ESeverity severities[2]{pas::ESeverity::Eight, pas::ESeverity::Seven};
if (msg == EStateMsg::Activate) {
x77c_ = GetMirrorNearestPlayer(mgr);
x568_ = (x77c_ == kInvalidUniqueId ? 4 : 1);
x6cc_boneTracking->SetTarget(mgr.GetPlayer().GetUniqueId());
x6cc_boneTracking->SetActive(true);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack)
x568_ = 2;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(severities[x7b0_]));
} else if (x568_ == 1) {
if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(x77c_)) {
2019-06-27 01:06:03 +00:00
zeus::CVector3f direction = wp->GetTranslation() - GetTranslation();
if (zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), direction.toVec2f()) >
zeus::degToRad(15.f) &&
direction.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd({}, direction.normalized(), 1.f));
} else {
x568_ = 0;
x6cc_boneTracking->SetActive(false);
}
} else
x568_ = 4;
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack)
x568_ = 4;
else if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(x77c_)) {
2020-03-13 20:22:39 +00:00
x450_bodyController->GetCommandMgr().DeliverTargetVector(wp->GetTranslation() - GetTranslation());
2019-06-27 01:06:03 +00:00
}
}
} else if (msg == EStateMsg::Deactivate) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::NextState));
}
x77c_ = kInvalidUniqueId;
x7bc_ = x56c_.x148_;
x7b0_ ^= 1;
}
}
void CFlaahgra::SpecialAttack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
x8e5_24_ = false;
x7b4_ = 3;
SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
x568_ = 2;
x8e4_30_ = true;
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCProjectileAttackCmd(pas::ESeverity::Eight, mgr.GetPlayer().GetTranslation(), false));
}
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::ProjectileAttack) {}
}
}
}
2019-06-27 01:06:03 +00:00
bool CFlaahgra::CoverCheck(CStateManager& mgr, float) {
if (x7f8_ <= 0 && x7bc_ > 0.f)
2019-06-27 01:06:03 +00:00
return false;
for (TUniqueId id : x770_mirrorWaypoints) {
if (const CEntity* ent = mgr.GetObjectById(id)) {
if (ent->GetActive())
return true;
}
}
return false;
}
TUniqueId CFlaahgra::GetMirrorNearestPlayer(const CStateManager& mgr) const {
2019-06-27 01:06:03 +00:00
zeus::CVector3f playerPos = mgr.GetPlayer().GetTranslation();
TUniqueId nearId = kInvalidUniqueId;
2020-03-12 22:06:01 +00:00
float prevMag = -1.f;
2019-06-27 01:06:03 +00:00
for (TUniqueId id : x770_mirrorWaypoints) {
if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(id)) {
2019-06-27 01:06:03 +00:00
if (!wp->GetActive())
continue;
2020-03-12 22:06:01 +00:00
const float mag = (wp->GetTranslation() - playerPos).magSquared();
if (mag > prevMag) {
2019-06-27 01:06:03 +00:00
nearId = id;
2020-03-12 22:06:01 +00:00
prevMag = mag;
}
2019-06-27 01:06:03 +00:00
}
}
return nearId;
}
2019-06-20 21:22:06 +00:00
void CFlaahgra::Enraged(CStateManager&, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = 0;
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Taunt)
x568_ = 2;
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCTauntCmd(pas::ETauntType::Zero));
} else if (x568_ == 2 && x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Taunt)
x568_ = 4;
} else if (msg == EStateMsg::Deactivate) {
x7d0_ = 0.f;
}
}
CFlaahgraProjectile* CFlaahgra::CreateProjectile(const zeus::CTransform& xf, CStateManager& mgr) {
CProjectileInfo* projectileInfo = GetProjectileInfo();
if (!projectileInfo->Token() || !mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 6)) {
return nullptr;
}
CDamageInfo damageInfo = projectileInfo->GetDamage();
if (x788_ > 1) {
damageInfo.SetDamage(damageInfo.GetDamage() * 1.33f);
}
auto* projectile = new CFlaahgraProjectile(x8e4_30_, projectileInfo->Token(), xf, damageInfo, mgr.AllocateUniqueId(),
GetAreaIdAlways(), GetUniqueId());
mgr.AddObject(projectile);
return projectile;
}
CFlaahgraPlants::CFlaahgraPlants(const TToken<CGenDescription>& genDesc, const CActorParameters& actParms,
TUniqueId uid, TAreaId aId, TUniqueId owner, const zeus::CTransform& xf,
const CDamageInfo& dInfo, const zeus::CVector3f& extents)
: CActor(uid, true, "Flaahgra Plants"sv, CEntityInfo(aId, NullConnectionList), xf, CModelData::CModelDataNull(),
CMaterialList(EMaterialTypes::Projectile), actParms, kInvalidUniqueId)
, xe8_elementGen(std::make_unique<CElementGen>(genDesc))
, xf0_ownerId(owner)
, xf4_damageInfo(dInfo)
, x130_obbox(xf, extents) {
xe8_elementGen->SetOrientation(xf.getRotation());
xe8_elementGen->SetTranslation(xf.origin);
xe8_elementGen->SetModelsUseLights(true);
x110_aabox = {x130_obbox.calculateAABox(xf)};
}
2019-06-20 21:22:06 +00:00
void CFlaahgraPlants::Accept(IVisitor& visitor) { visitor.Visit(this); }
2019-06-20 21:22:06 +00:00
void CFlaahgraPlants::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CActor::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::Registered) {
xe8_elementGen->SetParticleEmission(true);
2020-08-14 04:30:41 +00:00
SetActive(true);
if (x16c_colAct == kInvalidUniqueId) {
x16c_colAct = mgr.AllocateUniqueId();
2019-06-20 21:27:50 +00:00
CCollisionActor* colAct = new CCollisionActor(x16c_colAct, GetAreaIdAlways(), GetUniqueId(),
2020-08-14 04:30:41 +00:00
x130_obbox.extents + zeus::CVector3f(0.f, 5.f, 10.f), {}, true,
0.001f, "Flaahgra Plants"sv);
colAct->SetTransform(GetTransform());
colAct->SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Player}, {EMaterialTypes::Trigger, EMaterialTypes::CollisionActor,
EMaterialTypes::NoStaticCollision, EMaterialTypes::Character}));
CMaterialList materialList = colAct->GetMaterialList();
materialList.Add(EMaterialTypes::ProjectilePassthrough);
materialList.Add(EMaterialTypes::Immovable);
colAct->SetMaterialList(materialList);
mgr.AddObject(colAct);
mgr.SetActorAreaId(*colAct, GetAreaIdAlways());
}
2019-06-20 21:27:50 +00:00
} else if (msg == EScriptObjectMessage::Deleted && x16c_colAct != kInvalidUniqueId) {
mgr.FreeScriptObject(x16c_colAct);
}
}
void CFlaahgraPlants::Think(float dt, CStateManager& mgr) {
if (GetActive()) {
xe8_elementGen->Update(dt);
x12c_lastDt = dt;
}
2019-06-19 21:11:13 +00:00
if (xe8_elementGen->IsSystemDeletable())
mgr.FreeScriptObject(GetUniqueId());
}
2019-06-20 21:22:06 +00:00
void CFlaahgraPlants::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
g_Renderer->AddParticleGen(*xe8_elementGen);
CActor::AddToRenderer(frustum, mgr);
}
void CFlaahgraPlants::Touch(CActor& act, CStateManager& mgr) {
if (act.GetUniqueId() != mgr.GetPlayer().GetUniqueId() || !x110_aabox)
return;
zeus::COBBox plObb = zeus::COBBox::FromAABox(mgr.GetPlayer().GetBoundingBox(), {});
2019-06-27 01:06:03 +00:00
if (!x130_obbox.OBBIntersectsBox(plObb))
return;
CDamageInfo dInfo = xf4_damageInfo;
float newDamage = x12c_lastDt * xf4_damageInfo.GetDamage();
dInfo.SetDamage(newDamage);
dInfo.SetRadiusDamage(newDamage);
dInfo.SetNoImmunity(true);
zeus::CVector3f diffVec = mgr.GetPlayer().GetTranslation() - GetTranslation();
mgr.ApplyDamage(GetUniqueId(), act.GetUniqueId(), GetUniqueId(), dInfo,
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}),
diffVec.dot(GetTransform().basis[0]) > 0.f ? GetTransform().basis[0] : -GetTransform().basis[0]);
}
std::optional<zeus::CAABox> CFlaahgraPlants::GetTouchBounds() const {
if (!GetActive()) {
return {};
}
return x110_aabox;
}
2019-06-10 08:28:33 +00:00
} // namespace urde::MP1