More CFlaahgra imps, initial CTryclops imps

This commit is contained in:
Phillip Stephens 2019-07-16 08:54:07 -07:00
parent 91fe17dcbb
commit 328749d1ba
23 changed files with 765 additions and 120 deletions

View File

@ -188,25 +188,22 @@ bool CAnimData::IsAdditiveAnimation(s32 idx) const {
bool CAnimData::IsAdditiveAnimationAdded(s32 idx) const {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
return search != x434_additiveAnims.cend();
}
const std::shared_ptr<CAnimTreeNode>& CAnimData::GetAdditiveAnimationTree(s32 idx) const {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
return search->second.GetAnim();
}
bool CAnimData::IsAdditiveAnimationActive(s32 idx) const {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
if (search == x434_additiveAnims.cend())
return false;
return search->second.IsActive();
@ -214,11 +211,9 @@ bool CAnimData::IsAdditiveAnimationActive(s32 idx) const {
void CAnimData::DelAdditiveAnimation(s32 idx) {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
if (search != x434_additiveAnims.cend() &&
search->second.GetPhase() != EAdditivePlaybackPhase::FadingOut &&
auto search = std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
if (search != x434_additiveAnims.cend() && search->second.GetPhase() != EAdditivePlaybackPhase::FadingOut &&
search->second.GetPhase() != EAdditivePlaybackPhase::FadedOut) {
search->second.FadeOut();
}
@ -226,26 +221,25 @@ void CAnimData::DelAdditiveAnimation(s32 idx) {
void CAnimData::AddAdditiveAnimation(s32 idx, float weight, bool active, bool fadeOut) {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
auto search = std::find_if(x434_additiveAnims.begin(), x434_additiveAnims.end(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
if (search != x434_additiveAnims.cend()) {
search->second.SetActive(active);
search->second.SetWeight(weight);
search->second.SetNeedsFadeOut(!search->second.IsActive() && fadeOut);
} else {
std::shared_ptr<CAnimTreeNode> node =
GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders());
GetAnimationManager()->GetAnimationTree(animIdx, CMetaAnimTreeBuildOrders::NoSpecialOrders());
const CAdditiveAnimationInfo& info = x0_charFactory->FindAdditiveInfo(animIdx);
x434_additiveAnims.emplace_back(std::make_pair(animIdx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut)));
x434_additiveAnims.emplace_back(
std::make_pair(animIdx, CAdditiveAnimPlayback(node, weight, active, info, fadeOut)));
}
}
float CAnimData::GetAdditiveAnimationWeight(s32 idx) const {
s32 animIdx = xc_charInfo.GetAnimationIndex(idx);
auto search =
std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
auto search = std::find_if(x434_additiveAnims.cbegin(), x434_additiveAnims.cend(),
[animIdx](const auto& pair) { return pair.first == animIdx; });
if (search != x434_additiveAnims.cend())
return search->second.GetTargetWeight();
return 0.f;
@ -541,15 +535,13 @@ void CAnimData::RecalcPoseBuilder(const CCharAnimTime* time) {
void CAnimData::RenderAuxiliary(const zeus::CFrustum& frustum) const { x120_particleDB.AddToRendererClipped(frustum); }
void CAnimData::Render(CSkinnedModel& model, const CModelFlags& drawFlags,
const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) {
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) {
SetupRender(model, drawFlags, morphEffect, morphMagnitudes);
DrawSkinnedModel(model, drawFlags);
}
void CAnimData::SetupRender(CSkinnedModel& model, const CModelFlags& drawFlags,
const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) {
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) {
if (!x220_30_poseBuilt) {
x2fc_poseBuilder.BuildNoScale(x224_pose);
x220_30_poseBuilt = true;
@ -798,8 +790,7 @@ void CAnimData::SetInfraModel(const TLockedToken<CModel>& model, const TLockedTo
}
void CAnimData::PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, const CModelFlags& drawFlags,
const std::optional<CVertexMorphEffect>& morphEffect,
const float* morphMagnitudes) {
const std::optional<CVertexMorphEffect>& morphEffect, const float* morphMagnitudes) {
model.Calculate(pose, drawFlags, morphEffect, morphMagnitudes);
}

View File

@ -2,9 +2,12 @@
#include "CAnimSourceReader.hpp"
namespace urde {
CInt32POINode::CInt32POINode()
: CPOINode("root", EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0), x38_val(0), x3c_locatorName("root") {}
: CInt32POINode(""sv, EPOIType::EmptyInt32, CCharAnimTime(), -1, false, 1.f, -1, 0, 0, "root"sv) {}
CInt32POINode::CInt32POINode(std::string_view name, EPOIType type, const CCharAnimTime& time, s32 index, bool unique, float weight, s32 charIndex,
s32 flags, s32 val, std::string_view locator)
: CPOINode(name, type, time, index, unique, weight, charIndex, flags), x38_val(val), x3c_locatorName(locator) {}
CInt32POINode::CInt32POINode(CInputStream& in)
: CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {}

View File

@ -11,6 +11,7 @@ class CInt32POINode : public CPOINode {
public:
CInt32POINode();
CInt32POINode(std::string_view, EPOIType, const CCharAnimTime&, s32, bool, float, s32, s32, s32, std::string_view);
CInt32POINode(CInputStream& in);
s32 GetValue() const { return x38_val; }
std::string_view GetLocatorName() const { return x3c_locatorName; }

View File

@ -64,7 +64,7 @@ enum class EHurledState {
Seven
};
enum class EFallState { Invalid = -1, Zero };
enum class EFallState { Invalid = -1, Zero, One };
enum class EReactionType { Invalid = -1, Zero, One, Two, Three };
@ -77,8 +77,18 @@ enum class EJumpState { Invalid = -1, IntoJump, AmbushJump, Loop, OutOfJump, Wal
enum class EStepDirection { Invalid = -1, Forward = 0, Backward = 1, Left = 2, Right = 3, Up = 4, Down = 5 };
enum class EStepType { Normal = 0, Dodge = 1, BreakDodge = 2, RollDodge = 3 };
enum class ESeverity { Invalid = -1, Zero = 0, One = 1, Two = 2, Three, Four, Seven = 7, Eight = 8 };
enum class ESeverity {
Invalid = -1,
Zero = 0,
One = 1,
Two = 2,
Three = 3,
Four = 4,
Five = 5,
Six = 6,
Seven = 7,
Eight = 8
};
enum class EGetupType { Invalid = -1, Zero = 0, One = 1, Two = 2 };

View File

@ -197,7 +197,7 @@ public:
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
float GetGravityConstant() const { return 10.f * 24.525f; }
float GetGravityConstant() const { return 10.f * CPhysicsActor::GravityConstant(); }
void SetPathFindMode(EPathFindMode mode) { x8b4_pathFindMode = mode; }

View File

@ -982,6 +982,6 @@ void CBeetle::Shock(CStateManager& mgr, float duration, float damage) {
CPathFindSearch* CBeetle::GetSearchPath() { return &x5fc_pathFindSearch; }
float CBeetle::GetGravityConstant() const { return 4.f * 24.525f; }
float CBeetle::GetGravityConstant() const { return 4.f * CPhysicsActor::GravityConstant(); }
} // namespace urde::MP1

View File

@ -76,7 +76,21 @@ CFlaahgra::CFlaahgra(TUniqueId uid, std::string_view name, const CEntityInfo& in
, x820_(xf.origin)
, x8a0_(xf.frontVector())
, x8ac_(animRes) {
x8e4_24_loaded = false;
x8e4_25_loading = false;
x8e4_26_ = false;
x8e4_27_ = false;
x8e4_28_ = false;
x8e4_29_getup = false;
x8e4_30_ = false;
x8e4_31_ = false;
x8e5_24_ = false;
x8e5_25_ = false;
x8e5_26_ = false;
x8e5_27_ = false;
x8e5_28_ = false;
x8e5_29_ = true;
x8e5_30_ = false;
x6dc_.Token().Lock();
x704_.Token().Lock();
x7dc_.SetDamage(0.5f * x7dc_.GetDamage());
@ -115,7 +129,7 @@ void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
}
case EScriptObjectMessage::Activate: {
GatherAssets(mgr);
if (x8e5_25_)
if (x8e5_27_)
break;
SetupCollisionManagers(mgr);
@ -150,10 +164,10 @@ void CFlaahgra::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
if (x7a8_ == 4)
contactDamage = x7dc_;
if (sub801ae670())
if (!sub801ae670())
contactDamage.SetDamage(0.5f * contactDamage.GetDamage());
if (x788_ == 2)
if (x788_ >= 2)
contactDamage.SetDamage(1.33f * contactDamage.GetDamage());
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(), contactDamage,
@ -266,6 +280,7 @@ void CFlaahgra::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, E
return;
}
case EUserEventType::BeginAction: {
printf("BeginAction\n");
x8e4_26_ = true;
x7c4_ = GetEndActionTime();
break;
@ -504,21 +519,26 @@ void CFlaahgra::sub801ae980(CStateManager& mgr) {
HealthInfo(mgr)->SetHP(HealthInfo(mgr)->GetHP() - x56c_.x8_);
x7d4_ = x56c_.xc_;
x8e4_29_getup = true;
x7d8_ = 0.f;
x430_damageColor = skUnkColor;
++x788_;
}
void CFlaahgra::sub801ade80() {
x894_ = (x7ac_ ? -GetTransform().basis[0] : GetTransform().basis[0]);
x894_ = (x7ac_ == 0 ? -GetTransform().basis[0] : GetTransform().basis[0]);
const rstl::reserved_vector<zeus::CVector3f, 4>& vec = (x7ac_ ? x82c_ : x860_);
const rstl::reserved_vector<zeus::CVector3f, 4>& vec = (x7ac_ == 0 ? x860_ : x82c_);
float curDist = FLT_MIN;
for (const zeus::CVector3f& v : vec) {
if (v.magSquared() < 0.f)
continue;
if (GetTransform().basis[1].dot(v) > FLT_MIN)
float dist = GetTransform().basis[1].dot(v);
if (dist > curDist) {
curDist = dist;
x894_ = v;
}
}
}
@ -539,8 +559,7 @@ bool CFlaahgra::ShouldAttack(CStateManager& mgr, float) {
(x7cc_ > 0.f || player.GetVelocity().magSquared() < 25.f))
return false;
return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), diff) > zeus::degToRad(45.f);
return zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), diff) < zeus::degToRad(45.f);
}
void CFlaahgra::UpdateHeadDamageVulnerability(CStateManager& mgr, bool b) {
@ -567,6 +586,7 @@ void CFlaahgra::FadeOut(CStateManager& mgr, EStateMsg msg, float) {
x7a4_sphereCollision->SetActive(mgr, true);
x79c_leftArmCollision->SetActive(mgr, true);
x7a0_rightArmCollision->SetActive(mgr, true);
x784_ = x780_;
x81c_ = GetModelData()->GetScale().z();
UpdateScale(1.f, x81c_, x56c_.x4_);
x8e4_26_ = false;
@ -601,7 +621,7 @@ void CFlaahgra::UpdateSmallScaleReGrowth(float dt) {
if (!x8e4_29_getup || x7d8_ > 6.f)
return;
x430_damageColor = zeus::CColor::lerp(skUnkColor, zeus::skBlack, (M_PIF * std::cos(x7d8_)));
x430_damageColor = zeus::CColor::lerp(skUnkColor, zeus::skBlack, std::round(std::fabs(M_PIF * std::cos(x7d8_))));
TakeDamage({}, 0.f);
x7d8_ += dt;
}
@ -718,7 +738,7 @@ void CFlaahgra::GetUp(CStateManager& mgr, EStateMsg msg, float) {
SetCollisionActorBounds(mgr, x79c_leftArmCollision, skUnkVec1);
SetCollisionActorBounds(mgr, x7a0_rightArmCollision, skUnkVec1);
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(x8e4_29_getup)));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGetupCmd(pas::EGetupType(!x8e4_29_getup)));
}
} else if (x568_ == 2 &&
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup) {
@ -777,7 +797,8 @@ void CFlaahgra::SetCollisionActorBounds(CStateManager& mgr, const std::unique_pt
}
}
void CFlaahgra::UpdateScale(float t, float min, float max) {
ModelData()->SetScale(zeus::skOne3f * (t * (max - min) + min));
float scale = (t * (max - min) + min);
ModelData()->SetScale(zeus::skOne3f * scale);
}
float CFlaahgra::GetEndActionTime() {
@ -838,7 +859,7 @@ void CFlaahgra::RattlePlayer(CStateManager& mgr, const zeus::CVector3f& vec) {
}
void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) {
static const pas::ESeverity kSeverities[2] {pas::ESeverity::Zero, pas::ESeverity::One};
static const pas::ESeverity kSeverities[2]{pas::ESeverity::Zero, pas::ESeverity::One};
if (msg == EStateMsg::Activate) {
x568_ = 0;
x7d4_ = 0.f;
@ -877,11 +898,8 @@ void CFlaahgra::Faint(CStateManager& mgr, EStateMsg msg, float arg) {
void CFlaahgra::Dead(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
bool r29 = true;
if (x450_bodyController->GetFallState() == pas::EFallState::Zero &&
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall)
r29 = false;
x568_ = r29;
x568_ = (x450_bodyController->GetFallState() != pas::EFallState::Zero ||
x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Fall);
SendScriptMsgs(EScriptObjectState::CloseIn, mgr, EScriptObjectMessage::None);
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
@ -915,9 +933,8 @@ static const pas::ESeverity kStates1[5]{pas::ESeverity::Invalid, pas::ESeverity:
pas::ESeverity::Two, pas::ESeverity::Invalid};
void CFlaahgra::Attack(CStateManager& mgr, EStateMsg msg, float arg) {
static const pas::ESeverity kSeverity[5] {
pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One, pas::ESeverity::Zero, pas::ESeverity::Invalid
};
static const pas::ESeverity kSeverity[5]{pas::ESeverity::Three, pas::ESeverity::Four, pas::ESeverity::One,
pas::ESeverity::Zero, pas::ESeverity::Invalid};
if (msg == EStateMsg::Activate) {
x568_ = 0;
@ -1016,6 +1033,7 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) {
x568_ = 0;
x8e4_26_ = false;
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Two));
x784_ = x780_;
} else if (msg == EStateMsg::Update) {
if (x568_ == 0) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() == pas::EAnimationState::Getup)
@ -1026,7 +1044,7 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::Getup)
x568_ = 4;
else if (x8e4_26_) {
UpdateScale(x7c4_ > 0.f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f, x56c_.x4_, x56c_.x0_);
UpdateScale(x7c4_ > 0.0f ? 1.f - (GetEndActionTime() / x7c4_) : 1.f, x56c_.x4_, x56c_.x0_);
}
}
@ -1037,8 +1055,44 @@ void CFlaahgra::Suck(CStateManager& mgr, EStateMsg msg, float) {
x7a0_rightArmCollision->SetActive(mgr, false);
}
}
void CFlaahgra::ProjectileAttack(CStateManager&, EStateMsg, float) {
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;
}
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 {
x450_bodyController->GetCommandMgr().SetTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
}
}
}
}
void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) {
static pas::ESeverity severities[2]{pas::ESeverity::Eight, pas::ESeverity::Seven};
@ -1054,7 +1108,7 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) {
else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(severities[x7b0_]));
} else if (x568_ == 1) {
if (TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(x77c_)) {
if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(x77c_)) {
zeus::CVector3f direction = wp->GetTranslation() - GetTranslation();
if (zeus::CVector2f::getAngleDiff(GetTransform().basis[1].toVec2f(), direction.toVec2f()) >
zeus::degToRad(15.f) &&
@ -1069,7 +1123,7 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) {
} else if (x568_ == 2) {
if (x450_bodyController->GetBodyStateInfo().GetCurrentStateId() != pas::EAnimationState::MeleeAttack)
x568_ = 4;
else if (TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(x77c_)) {
else if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(x77c_)) {
x450_bodyController->GetCommandMgr().SetTargetVector(wp->GetTranslation() - GetTranslation());
}
}
@ -1083,9 +1137,28 @@ void CFlaahgra::Cover(CStateManager& mgr, EStateMsg msg, float) {
x7b0_ ^= 1;
}
}
void CFlaahgra::SpecialAttack(CStateManager&, EStateMsg, float) {}
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) {}
}
}
}
bool CFlaahgra::CoverCheck(CStateManager& mgr, float) {
if (x7f8_ < 0 && x7bc_ > 0.f)
if (x7f8_ <= 0 && x7bc_ > 0.f)
return false;
for (TUniqueId id : x770_mirrorWaypoints) {
@ -1103,11 +1176,10 @@ TUniqueId CFlaahgra::GetMirrorNearestPlayer(CStateManager& mgr) {
TUniqueId nearId = kInvalidUniqueId;
for (TUniqueId id : x770_mirrorWaypoints) {
if (TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(id)) {
if (TCastToConstPtr<CActor> wp = mgr.GetObjectById(id)) {
if (!wp->GetActive())
continue;
if ((wp->GetTranslation() - playerPos).magSquared() > -1.f)
nearId = id;
}
@ -1116,22 +1188,37 @@ TUniqueId CFlaahgra::GetMirrorNearestPlayer(CStateManager& mgr) {
return nearId;
}
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;
}
}
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(new CElementGen(genDesc))
, xf0_ownerId(owner)
, x130_obbox(xf, extents) {
xe8_elementGen->SetGlobalOrientation(xf.getRotation());
xe8_elementGen->SetGlobalTranslation(xf.origin);
: CActor(uid, true, "Flaahgra Plants"sv, CEntityInfo(aId, NullConnectionList), xf, CModelData::CModelDataNull(),
CMaterialList(EMaterialTypes::Projectile), actParms, kInvalidUniqueId)
, xe8_elementGen(new CElementGen(genDesc))
, xf0_ownerId(owner)
, x130_obbox(xf, extents) {
xe8_elementGen->SetOrientation(xf.getRotation());
xe8_elementGen->SetTranslation(xf.origin);
xe8_elementGen->SetModelsUseLights(true);
x110_aabox = {x130_obbox.calculateAABox(xf)};
}
void CFlaahgraPlants::Accept(IVisitor& visitor) {
visitor.Visit(this);
}
void CFlaahgraPlants::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CFlaahgraPlants::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CActor::AcceptScriptMsg(msg, uid, mgr);

View File

@ -200,7 +200,7 @@ public:
bool AnimOver(CStateManager&, float) { return x568_ == 4; }
bool AIStage(CStateManager&, float arg) { return x780_ == u32(arg); }
bool HitSomething(CStateManager&, float arg) { return x7d0_ > 0.f; }
bool OffLine(CStateManager&, float) { return (!x8e5_29_ && !x8e5_28_); }
bool OffLine(CStateManager&, float) { return (x8e5_29_ && x8e5_28_); }
bool ShouldTurn(CStateManager&, float);
bool ShouldAttack(CStateManager&, float);
bool BreakAttack(CStateManager&, float) { return x7d4_ >= x56c_.xc_ && !x8e4_29_getup; }
@ -223,6 +223,7 @@ public:
void ProjectileAttack(CStateManager&, EStateMsg, float);
void Cover(CStateManager&, EStateMsg, float);
void SpecialAttack(CStateManager&, EStateMsg, float);
void Enraged(CStateManager&, EStateMsg, float);
};
}

View File

@ -17,11 +17,11 @@
namespace urde::MP1 {
const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / 24.525002f);
const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / 24.525002f));
const float CParasite::flt_805A8FB0 = 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant());
const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / CPhysicsActor::GravityConstant()));
short CParasite::word_805A8FC0 = 0;
const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / 24.525002f);
const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / 24.525002f);
const float CParasite::flt_805A8FB8 = 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant());
const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / CPhysicsActor::GravityConstant());
CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EBodyType bodyType,

View File

@ -142,7 +142,7 @@ void CPuddleToadGamma::ShootPlayer(CStateManager& mgr, float speed) {
for (TUniqueId id : nearList) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(id)) {
bomb->SetVelocityWR((mgr.GetActiveRandom()->Float() * 5.f + 20.f) * shootDir);
bomb->SetConstantAccelerationWR({0.f, 0.f, -24.525f});
bomb->SetConstantAccelerationWR({0.f, 0.f, -CPhysicsActor::GravityConstant()});
}
}
}

View File

@ -2,13 +2,37 @@
#include "CStateManager.hpp"
#include "World/CWorld.hpp"
#include "World/CGameArea.hpp"
#include "World/CPatternedInfo.hpp"
#include "World/CPlayer.hpp"
#include "Weapon/CBomb.hpp"
#include "TCastTo.hpp"
namespace urde::MP1 {
const CDamageVulnerability CTryclops::skVulnerabilities = CDamageVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Normal, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::Two);
CTryclops::CTryclops(urde::TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
urde::CModelData&& mData, const urde::CPatternedInfo& pInfo,
const urde::CActorParameters& actParms, float, float, float, float)
const urde::CActorParameters& actParms, float f1, float f2, float f3, float f4)
: CPatterned(ECharacter::Tryclops, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small) {}
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Small)
, x568_pathFindSearch(nullptr, 1, pInfo.GetPathfindingIndex(), 1.f, 1.f)
, x67c_(f1)
, x680_(std::cos(zeus::degToRad(0.5f * f2)))
, x684_(f3)
, x688_(f4)
, x698_24_(false)
, x698_25_(false)
, x698_26_(false)
, x698_27_dizzy(false) {
CreateShadow(false);
MakeThermalColdAndHot();
x460_knockBackController.SetAutoResetImpulse(false);
x328_30_lookAtDeathDir = false;
}
void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr);
@ -16,7 +40,417 @@ void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
if (msg == EScriptObjectMessage::Registered) {
x450_bodyController->Activate(mgr);
} else if (msg == EScriptObjectMessage::InitializedInArea) {
//x568_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
x568_pathFindSearch.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
}
}
void CTryclops::Think(float dt, CStateManager& mgr) {
CPatterned::Think(dt, mgr);
if (x400_25_alive && x68c_ > 0.f)
x68c_ -= dt;
if (mgr.GetPlayer().GetAttachedActor() != GetUniqueId() || x698_27_dizzy)
return;
x698_27_dizzy = (mgr.GetPlayer().GetAttachedActorStruggle() == 1.f && sub8025dbd0(mgr));
}
void CTryclops::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& poi, EUserEventType type, float dt) {
switch (type) {
case EUserEventType::Projectile:
if (x694_bombId == kInvalidUniqueId) {
LaunchPlayer(mgr, GetLctrTransform(poi.GetLocatorName()), (x698_27_dizzy ? 5.f : x688_));
} else {
DragBomb(mgr, GetLctrTransform(poi.GetLocatorName()));
}
return;
default:
break;
}
CPatterned::DoUserAnimEvent(mgr, poi, type, dt);
}
void CTryclops::Death(CStateManager& mgr, const zeus::CVector3f& vec, EScriptObjectState state) {
if (x400_25_alive) {
CPlayer& player = mgr.GetPlayer();
if (player.GetAttachedActor() == GetUniqueId()) {
player.SetLeaveMorphBallAllowed(true);
player.AddMaterial(EMaterialTypes::Solid, mgr);
player.DetachActorFromPlayer();
} else if (x694_bombId != kInvalidUniqueId) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(x694_bombId)) {
bomb->SetFuseDisabled(false);
bomb->SetIsBeingDragged(false);
}
x694_bombId = kInvalidUniqueId;
}
}
CPatterned::Death(mgr, vec, state);
}
void CTryclops::Patrol(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::Patrol(mgr, msg, arg);
if (msg == EStateMsg::Activate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
} else if (msg == EStateMsg::Update) {
ApplySeparation(mgr);
}
}
void CTryclops::PathFind(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::PathFind(mgr, msg, arg);
zeus::CVector3f front = GetTransform().basis[1];
if (front.dot(x450_bodyController->GetCommandMgr().GetMoveVector()) < 0.f && front.canBeNormalized()) {
x450_bodyController->GetCommandMgr().ClearLocomotionCmds();
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(front.normalized(), {}, 1.f));
}
ApplySeparation(mgr);
}
void CTryclops::SelectTarget(CStateManager&, EStateMsg, float) {}
void CTryclops::TargetPatrol(CStateManager&, EStateMsg, float) {}
void CTryclops::TargetPlayer(CStateManager&, EStateMsg, float) {}
void CTryclops::TargetCover(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Update) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
if (x694_bombId == kInvalidUniqueId)
return;
if (TCastToConstPtr<CBomb> bomb = mgr.GetObjectById(x694_bombId))
SetDestPos(bomb->GetTranslation());
else
x694_bombId = kInvalidUniqueId;
}
}
void CTryclops::Attack(CStateManager&, EStateMsg, float) {}
void CTryclops::JumpBack(CStateManager&, EStateMsg, float) {}
void CTryclops::Shuffle(CStateManager& mgr, EStateMsg msg, float arg) { PathFind(mgr, msg, arg); }
void CTryclops::TurnAround(CStateManager&, EStateMsg, float) {}
void CTryclops::Crouch(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
if (TCastToConstPtr<CActor> wp =
mgr.GetObjectById(GetWaypointForState(mgr, EScriptObjectState::Retreat, EScriptObjectMessage::Follow))) {
SetDestPos(wp->GetTranslation());
}
mgr.GetPlayer().Stop();
mgr.GetPlayer().RemoveMaterial(EMaterialTypes::Solid, mgr);
SendScriptMsgs(EScriptObjectState::Inside, mgr, EScriptObjectMessage::None);
mgr.GetPlayer().AttachActorToPlayer(GetUniqueId(), true);
mgr.GetPlayer().SetLeaveMorphBallAllowed(false);
mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus();
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Combat);
} else if (msg == EStateMsg::Update) {
DragPlayer(mgr, GetLctrTransform("ballGrab_locator"sv).origin);
} else if (msg == EStateMsg::Deactivate) {
if (mgr.GetPlayer().GetAttachedActor() == GetUniqueId())
mgr.GetPlayer().DetachActorFromPlayer();
mgr.GetPlayer().SetLeaveMorphBallAllowed(true);
mgr.GetPlayer().AddMaterial(EMaterialTypes::Solid, mgr);
}
}
void CTryclops::GetUp(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x32c_animState = EAnimState::Ready;
x698_24_ = false;
} else if (msg == EStateMsg::Update) {
TryCommand(mgr, pas::EAnimationState::MeleeAttack, &CPatterned::TryMeleeAttack, 1);
if (!x698_24_) {
GrabBomb(mgr);
}
} else if (msg == EStateMsg::Deactivate) {
x32c_animState = EAnimState::NotReady;
}
}
void CTryclops::Suck(CStateManager& mgr, EStateMsg msg, float arg) {
if (msg == EStateMsg::Activate) {
mgr.GetPlayer().SetLeaveMorphBallAllowed(false);
mgr.GetPlayer().GetMorphBall()->DisableHalfPipeStatus();
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal6);
} else if (msg == EStateMsg::Update) {
SuckPlayer(mgr, arg);
} else if (msg == EStateMsg::Deactivate) {
mgr.GetPlayer().SetLeaveMorphBallAllowed(true);
mgr.GetPlayer().AddMaterial(EMaterialTypes::Solid, mgr);
}
}
void CTryclops::Cover(CStateManager&, EStateMsg, float) {}
void CTryclops::Approach(CStateManager&, EStateMsg, float) {}
void CTryclops::PathFindEx(CStateManager& mgr, EStateMsg msg, float arg) {
CPatterned::PathFind(mgr, msg, arg);
ApplySeparation(mgr);
CPlayer& player = mgr.GetPlayer();
if (msg == EStateMsg::Activate) {
player.Stop();
player.RemoveMaterial(EMaterialTypes::Solid, mgr);
player.GetMorphBall()->DisableHalfPipeStatus();
player.AttachActorToPlayer(GetUniqueId(), true);
} else if (msg == EStateMsg::Update) {
DragPlayer(mgr, GetLctrTransform("ballGrab_locator"sv).origin);
}
}
void CTryclops::Dizzy(CStateManager&, EStateMsg, float) {}
bool CTryclops::InAttackPosition(CStateManager& mgr, float) {
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
return false;
CPlayer& player = mgr.GetPlayer();
return sub80260180(player.GetTranslation(),
player.GetTranslation() + zeus::CVector3f(0.f, 0.f, player.GetMorphBall()->GetBallRadius()),
player.GetBoundingBox(), mgr);
}
bool CTryclops::InRange(CStateManager& mgr, float) {
if (x694_bombId != kInvalidUniqueId) {
if (TCastToConstPtr<CBomb> bomb = mgr.GetObjectById(x694_bombId)) {
return sub80260180(bomb->GetTranslation(), bomb->GetTranslation(), *bomb->GetTouchBounds(), mgr);
}
}
return false;
}
bool CTryclops::InMaxRange(CStateManager& mgr, float) {
if (x694_bombId != kInvalidUniqueId)
return true;
rstl::reserved_vector<TUniqueId, 1024> nearList;
float dectRange = x3bc_detectionRange * x3bc_detectionRange;
float dectRangeHeight = x3c0_detectionHeightRange * x3c0_detectionHeightRange;
mgr.BuildNearList(nearList, {GetTranslation() - x3bc_detectionRange, GetTranslation() + x3bc_detectionRange},
CMaterialFilter::MakeInclude({EMaterialTypes::Bomb}), this);
x694_bombId = kInvalidUniqueId;
for (TUniqueId uid : nearList) {
if (TCastToConstPtr<CBomb> bomb = mgr.GetObjectById(uid)) {
if (!bomb->IsBeingDragged()) {
float dist = (bomb->GetTranslation() - GetTranslation()).magSquared();
float height = (bomb->GetTranslation().z() - GetTranslation().z());
if (dist < dectRange && (height * height) < dectRangeHeight) {
if (x568_pathFindSearch.OnPath(bomb->GetTranslation()) == CPathFindSearch::EResult::Success) {
dectRange = dist;
x694_bombId = bomb->GetUniqueId();
}
}
}
}
}
if (x694_bombId != kInvalidUniqueId) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(x694_bombId)) {
bomb->SetFuseDisabled(true);
bomb->SetIsBeingDragged(true);
return true;
}
}
return false;
}
bool CTryclops::InDetectionRange(CStateManager& mgr, float arg) {
CPlayer& player = mgr.GetPlayer();
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed ||
player.GetAttachedActor() != kInvalidUniqueId || x68c_ > 0.f || !CPatterned::InDetectionRange(mgr, arg))
return false;
return x568_pathFindSearch.OnPath(player.GetBallPosition()) == CPathFindSearch::EResult::Success;
}
bool CTryclops::SpotPlayer(CStateManager& mgr, float) {
if (x694_bombId != kInvalidUniqueId) {
CPlayer& player = mgr.GetPlayer();
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(x694_bombId)) {
if (player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) {
bool isPlayerCloser = (player.GetTranslation() - GetTranslation()).magSquared() <
(bomb->GetTranslation() - GetTranslation()).magSquared();
if (isPlayerCloser) {
bomb->SetFuseDisabled(false);
bomb->SetIsBeingDragged(false);
x694_bombId = kInvalidUniqueId;
}
return isPlayerCloser;
}
}
}
return true;
}
bool CTryclops::InPosition(CStateManager& mgr, float arg) {
if (x694_bombId != kInvalidUniqueId) {
if (TCastToConstPtr<CBomb> bomb = mgr.GetObjectById(x694_bombId)) {
return sub802600c8(bomb->GetTranslation(), arg);
}
}
return false;
}
bool CTryclops::HearShot(CStateManager& mgr, float) {
x698_26_ = false;
if (x694_bombId != kInvalidUniqueId) {
if (TCastToConstPtr<CBomb>(mgr.GetObjectById(x694_bombId))) {
x698_26_ = true;
return false;
} else
x694_bombId = kInvalidUniqueId;
}
return true;
}
bool CTryclops::CoverBlown(CStateManager&, float) {
return x568_pathFindSearch.OnPath(GetTranslation()) != CPathFindSearch::EResult::InvalidArea;
}
bool CTryclops::Inside(CStateManager& mgr, float arg) {
const zeus::CTransform xf = mgr.GetPlayer().GetTransform();
x64c_ = xf.getRotation();
return sub802600c8(xf.origin + zeus::CVector3f(0.f, 0.f, mgr.GetPlayer().GetMorphBall()->GetBallRadius()), arg);
}
bool CTryclops::ShouldRetreat(CStateManager& mgr, float) {
if (TCastToConstPtr<CActor> wp =
mgr.GetObjectById(GetWaypointForState(mgr, EScriptObjectState::Modify, EScriptObjectMessage::Next))) {
SetDestPos(wp->GetTranslation());
return true;
}
return false;
}
bool CTryclops::IsDizzy(CStateManager&, float) { return x698_27_dizzy; }
void CTryclops::LaunchPlayer(CStateManager& mgr, const zeus::CTransform& xf, float f1) {
CPlayer& player = mgr.GetPlayer();
player.SetLeaveMorphBallAllowed(true);
if (player.GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
return;
x698_24_ = true;
x68c_ = 1.5f;
player.Stop();
zeus::CTransform tmpXf = (xf * x64c_);
tmpXf.origin += zeus::CVector3f(0.f, 0.f, -0.5f);
player.Teleport(xf, mgr, false);
player.ApplyImpulseWR(f1 * (player.GetMass() * xf.basis[1].normalized()), zeus::CAxisAngle());
player.SetMoveState(CPlayer::EPlayerMovementState::ApplyJump, mgr);
player.AddMaterial(EMaterialTypes::Solid, mgr);
mgr.ApplyDamage(GetUniqueId(), player.GetUniqueId(), GetUniqueId(), GetContactDamage(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {});
}
void CTryclops::DragBomb(CStateManager& mgr, const zeus::CTransform& xf) {
if (x694_bombId != kInvalidUniqueId) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(x694_bombId)) {
bomb->SetVelocityWR((5.f * mgr.GetActiveRandom()->Float() + 20.f) * xf.basis[1].normalized());
bomb->SetConstantAccelerationWR({0.f, 0.f, -CPhysicsActor::GravityConstant()});
}
}
x698_26_ = false;
x698_24_ = true;
x694_bombId = kInvalidUniqueId;
}
void CTryclops::ApplySeparation(CStateManager& mgr) {
for (CEntity* ent : mgr.GetListeningAiObjectList()) {
if (TCastToPtr<CAi> ai = ent) {
if (ai == this || ai->GetAreaIdAlways() != GetAreaId())
continue;
zeus::CVector3f sep = x45c_steeringBehaviors.Separation(*this, ai->GetTranslation(), 8.f);
if (sep.x() != 0.f && sep.y() != 0.f && sep.z() != 0.f)
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(sep, {}, 1.f));
}
}
}
void CTryclops::GrabBomb(CStateManager& mgr) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(x694_bombId)) {
zeus::CTransform grabLctr = GetLctrTransform("ballGrab_locator"sv);
grabLctr.origin += zeus::CVector3f(0.f, 0.f, -3.f);
bomb->SetTransform(grabLctr);
}
}
void CTryclops::DragPlayer(CStateManager& mgr, const zeus::CVector3f& locOrig) {
CPlayer& player = mgr.GetPlayer();
player.Stop();
player.RemoveMaterial(EMaterialTypes::Solid, mgr);
zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv) * x64c_;
xf.origin += {0.f, 0.f, -.5f};
player.SetTransform(xf);
}
bool CTryclops::sub802600c8(const zeus::CVector3f& vec, float arg) {
return (vec - GetLctrTransform("ballGrab_locator"sv).origin).magSquared() <= arg;
}
bool CTryclops::sub80260180(const zeus::CVector3f& vec1, const zeus::CVector3f& vec2, const zeus::CAABox& bounds,
CStateManager& mgr) {
if (bounds.intersects(GetBoundingBox()))
return true;
zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv);
zeus::CVector3f tmpVec2 = vec2 - (xf.origin - (1.f * GetTransform().basis[1]));
float f28 = tmpVec2.normalized().dot(GetTransform().basis[1]);
zeus::CVector3f tmpVec4 = (vec1 - (xf.origin - (4.f * GetTransform().basis[1]))).normalized();
float f30 = tmpVec4.dot(GetTransform().basis[1]);
float f29 = tmpVec2.magnitude();
if (f29 > 2.f) {
CRayCastResult res = mgr.RayStaticIntersection(
xf.origin, (1.f / f29) * tmpVec2, f29 - mgr.GetPlayer().GetMorphBall()->GetBallRadius(),
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::Character, EMaterialTypes::Player,
EMaterialTypes::ProjectilePassthrough}));
if (res.IsValid())
return false;
}
return !(f29 >= x684_ || f28 <= 0.f || f30 <= x680_);
}
void CTryclops::SuckPlayer(CStateManager& mgr, float arg) {
if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Morphed)
return;
CPlayer& player = mgr.GetPlayer();
zeus::CTransform xf = GetLctrTransform("ballGrab_locator"sv);
zeus::CVector3f diff = (player.GetTranslation() - xf.origin);
float diffMag = diff.magnitude();
if (diffMag < 3.f) {
player.Stop();
AttractPlayer(mgr, xf.origin, arg);
} else {
player.ApplyForceWR(((x67c_ * (x684_ / (diffMag * diffMag))) * (player.GetMass() * -diff)), {});
}
}
void CTryclops::AttractPlayer(CStateManager& mgr, const zeus::CVector3f& dest, float arg) {
CPlayer& player = mgr.GetPlayer();
const float ballRad = player.GetMorphBall()->GetBallRadius();
player.SetVelocityWR(1.f / (2.f * arg) *
(dest - (player.GetTranslation() + zeus::CVector3f(0.f, 0.f, ballRad))).normalized());
}
} // namespace urde::MP1

View File

@ -1,14 +1,90 @@
#pragma once
#include "World/CPatterned.hpp"
#include "World/CPathFindSearch.hpp"
namespace urde::MP1 {
class CTryclops : public CPatterned {
static const CDamageVulnerability skVulnerabilities;
CPathFindSearch x568_pathFindSearch;
zeus::CTransform x64c_;
float x67c_;
float x680_;
float x684_;
float x688_;
float x68c_ = 0.f;
u32 x690_ = 0;
TUniqueId x694_bombId = kInvalidUniqueId;
TUniqueId x696_ = kInvalidUniqueId;
bool x698_24_ : 1;
bool x698_25_ : 1;
bool x698_26_ : 1;
bool x698_27_dizzy : 1;
bool sub8025dbd0(CStateManager&) { return false; }
void LaunchPlayer(CStateManager& mgr, const zeus::CTransform& xf, float);
void DragBomb(CStateManager& mgr, const zeus::CTransform& xf);
void ApplySeparation(CStateManager&);
void GrabBomb(CStateManager& mgr);
void DragPlayer(CStateManager& mgr, const zeus::CVector3f& locOrig);
bool sub802600c8(const zeus::CVector3f&, float);
bool sub80260180(const zeus::CVector3f&, const zeus::CVector3f&, const zeus::CAABox&, CStateManager&);
void SuckPlayer(CStateManager& mgr, float);
void AttractPlayer(CStateManager& mgr, const zeus::CVector3f& dest, float);
public:
DEFINE_PATTERNED(Tryclops)
CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CPatternedInfo&, const CActorParameters&, float, float, float, float);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
void Think(float, CStateManager&);
const CDamageVulnerability* GetDamageVulnerability() const {
if (x698_26_)
return CAi::GetDamageVulnerability();
return &skVulnerabilities;
}
const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f&, const zeus::CVector3f&,
const CDamageInfo&) const {
if (x698_26_)
return CAi::GetDamageVulnerability();
return &skVulnerabilities;
}
void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float);
void Death(CStateManager&, const zeus::CVector3f&, EScriptObjectState);
bool IsListening() const { return true; }
void Patrol(CStateManager&, EStateMsg, float);
void PathFind(CStateManager&, EStateMsg, float);
void SelectTarget(CStateManager&, EStateMsg, float);
void TargetPatrol(CStateManager&, EStateMsg, float);
void TargetPlayer(CStateManager&, EStateMsg, float);
void TargetCover(CStateManager&, EStateMsg, float);
void Attack(CStateManager&, EStateMsg, float);
void JumpBack(CStateManager&, EStateMsg, float);
void Shuffle(CStateManager&, EStateMsg, float);
void TurnAround(CStateManager&, EStateMsg, float);
void Crouch(CStateManager&, EStateMsg, float);
void GetUp(CStateManager&, EStateMsg, float);
void Suck(CStateManager&, EStateMsg, float);
void Cover(CStateManager&, EStateMsg, float);
void Approach(CStateManager&, EStateMsg, float);
void PathFindEx(CStateManager&, EStateMsg, float);
void Dizzy(CStateManager&, EStateMsg, float);
bool InAttackPosition(CStateManager&, float);
bool InRange(CStateManager&, float);
bool InMaxRange(CStateManager&, float);
bool InDetectionRange(CStateManager&, float);
bool SpotPlayer(CStateManager&, float);
bool InPosition(CStateManager&, float);
bool HearShot(CStateManager&, float);
bool CoverBlown(CStateManager&, float);
bool Inside(CStateManager&, float);
bool ShouldRetreat(CStateManager&, float);
bool IsDizzy(CStateManager&, float);
CPathFindSearch* GetSearchPath() { return &x568_pathFindSearch; }
};
} // namespace urde::MP1

View File

@ -24,9 +24,9 @@ CBomb::CBomb(const TCachedToken<CGenDescription>& particle1, const TCachedToken<
new CElementGen(particle1, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One))
, x184_particle2(
new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One))
, x18c_(particle2.GetObj())
, x18c_particle2Obj(particle2.GetObj())
, x190_24_isNotDetonated(true)
, x190_25_(false)
, x190_25_beingDragged(false)
, x190_26_disableFuse(false) {
x180_particle1->SetGlobalTranslation(xf.origin);
x184_particle2->SetGlobalTranslation(xf.origin);
@ -40,7 +40,7 @@ void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManag
x188_lightId = mgr.AllocateUniqueId();
CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false,
std::string("Bomb_PLight") + GetName().data(), GetTransform(), GetUniqueId(),
x184_particle2->GetLight(), reinterpret_cast<size_t>(x18c_), 1, 0.f);
x184_particle2->GetLight(), reinterpret_cast<size_t>(x18c_particle2Obj), 1, 0.f);
mgr.AddObject(gameLight);
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1);

View File

@ -15,9 +15,9 @@ class CBomb : public CWeapon {
std::unique_ptr<CElementGen> x180_particle1;
std::unique_ptr<CElementGen> x184_particle2;
TUniqueId x188_lightId = kInvalidUniqueId;
const CGenDescription* x18c_;
const CGenDescription* x18c_particle2Obj;
bool x190_24_isNotDetonated : 1;
bool x190_25_ : 1;
bool x190_25_beingDragged : 1;
bool x190_26_disableFuse : 1;
public:
@ -35,6 +35,9 @@ public:
std::optional<zeus::CAABox> GetTouchBounds() const;
void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; }
void SetConstantAccelerationWR(const zeus::CVector3f& acc) { x164_acceleration = acc; }
void SetFuseDisabled(bool b) { x190_26_disableFuse = false; }
void SetIsBeingDragged(bool b) { x190_25_beingDragged = b; }
bool IsBeingDragged() const { return x190_25_beingDragged; }
};
} // namespace urde

View File

@ -241,14 +241,14 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false);
if (vulnType == EVulnerability::Deflect) {
deflect = true;
EVulnerability deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode());
EDeflectType deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode());
switch (deflectType) {
case EVulnerability::Weak:
case EDeflectType::None:
deflect = false;
break;
case EVulnerability::Deflect:
case EVulnerability::Immune:
if (deflectType != EVulnerability::Deflect ||
case EDeflectType::Two:
case EDeflectType::Three:
if (deflectType != EDeflectType::Two ||
(xf0_weaponType != EWeaponType::Missile &&
(xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot))
if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player))

View File

@ -8,7 +8,7 @@ const CDamageVulnerability CDamageVulnerability::sNormalVulnerability(
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal,
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Weak);
EVulnerability::Normal, EVulnerability::Normal, EVulnerability::Normal, EDeflectType::None);
const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
@ -16,7 +16,7 @@ const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Weak);
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
/* LOL, thanks retro */
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
@ -24,7 +24,7 @@ const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Weak);
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
@ -32,7 +32,7 @@ const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::Weak);
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EDeflectType::None);
static inline bool is_not_immune(EVulnerability vuln) {
return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune;
@ -56,19 +56,19 @@ void CDamageVulnerability::ConstructNew(CInputStream& in, int propCount) {
for (int i = 15; i < propCount; ++i)
in.readUint32Big();
x5c_deflected = EVulnerability(in.readUint32Big());
x5c_deflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns2 = &x3c_chargedPower;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns2[i] = EVulnerability(in.readUint32Big());
x60_chargedDeflected = EVulnerability(in.readUint32Big());
x60_chargedDeflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns3 = &x4c_superMissile;
in.readUint32Big();
for (int i = 0; i < 4; ++i)
vulns3[i] = EVulnerability(in.readUint32Big());
x64_comboDeflected = EVulnerability(in.readUint32Big());
x64_comboDeflected = EDeflectType(in.readUint32Big());
}
CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
@ -79,9 +79,9 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
vulns[i] = EVulnerability(in.readUint32Big());
if (propCount == 15)
x5c_deflected = EVulnerability::Weak;
x5c_deflected = EDeflectType::None;
else
x5c_deflected = EVulnerability(in.readUint32Big());
x5c_deflected = EDeflectType(in.readUint32Big());
x3c_chargedPower = x0_power;
x4c_superMissile = x0_power;
@ -95,13 +95,44 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
ConstructNew(in, propCount);
}
CDamageVulnerability::CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave,
EVulnerability plasma, EVulnerability bomb, EVulnerability powerBomb,
EVulnerability missile, EVulnerability boostBall, EVulnerability phazon,
EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3,
EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2,
EDeflectType deflectType)
: x0_power(power)
, x4_ice(ice)
, x8_wave(wave)
, xc_plasma(plasma)
, x10_bomb(bomb)
, x14_powerbomb(powerBomb)
, x18_missile(missile)
, x1c_boostBall(boostBall)
, x20_phazon(phazon)
, x24_enemyWp1(enemyWp1)
, x28_enemyWp2Poison(enemyWp2)
, x2c_enemyWp3Lava(enemyWp3)
, x30_enemyWp4(enemyWp4)
, x34_unk1(v1)
, x38_unk2(v2)
, x3c_chargedPower(x0_power)
, x40_chargedIce(x4_ice)
, x44_chargedWave(x8_wave)
, x48_chargedPlasma(xc_plasma)
, x4c_superMissile(x0_power)
, x50_iceSpreader(x4_ice)
, x54_wavebuster(x8_wave)
, x58_flamethrower(xc_plasma)
, x5c_deflected(deflectType) {}
CDamageVulnerability::CDamageVulnerability(
EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb,
EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon,
EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4,
EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce,
EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader,
EVulnerability waveBuster, EVulnerability flameThrower, EVulnerability deflected)
EVulnerability waveBuster, EVulnerability flameThrower, EDeflectType deflected)
: x0_power(power)
, x4_ice(ice)
, x8_wave(wave)
@ -127,7 +158,7 @@ CDamageVulnerability::CDamageVulnerability(
, x58_flamethrower(flameThrower)
, x5c_deflected(deflected) {}
EVulnerability CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
if (mode.IsCharged())
return x60_chargedDeflected;
if (mode.IsComboed())
@ -205,9 +236,7 @@ bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect)
return true;
if (chargedVuln && mode.IsCharged())
return true;
if (comboedVuln && mode.IsComboed())
return true;
return false;
return comboedVuln && mode.IsComboed();
}
EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {

View File

@ -6,6 +6,7 @@
namespace urde {
enum class EVulnerability { Weak, Normal, Deflect, Immune, PassThrough, DirectWeak, DirectNormal, DirectImmune };
enum class EDeflectType { None, One, Two, Three, Four };
class CDamageVulnerability {
EVulnerability x0_power;
@ -34,9 +35,12 @@ class CDamageVulnerability {
EVulnerability x54_wavebuster;
EVulnerability x58_flamethrower;
EVulnerability x5c_deflected;
EVulnerability x60_chargedDeflected;
EVulnerability x64_comboDeflected;
EDeflectType x5c_deflected;
/* The following two values are hard coded to bizarre values on purpose to more closely reflect the behavior seen
* in-game.
*/
EDeflectType x60_chargedDeflected = EDeflectType(6);
EDeflectType x64_comboDeflected = EDeflectType(0x3e666666);
void ConstructNew(CInputStream& in, int propCount);
@ -47,15 +51,19 @@ class CDamageVulnerability {
public:
CDamageVulnerability(CInputStream& in);
CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma,
EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall,
EVulnerability phazon, EVulnerability enemyWp1, EVulnerability wnemyWp2, EVulnerability enemyWp3,
EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EDeflectType deflectType);
CDamageVulnerability(EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma,
EVulnerability bomb, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall,
EVulnerability phazon, EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3,
EVulnerability enemyWp4, EVulnerability v1, EVulnerability v2, EVulnerability chargedPower,
EVulnerability chargedIce, EVulnerability chargedWave, EVulnerability chargedPlasma,
EVulnerability superMissile, EVulnerability iceSpreader, EVulnerability waveBuster,
EVulnerability flameThrower, EVulnerability deflected);
EVulnerability flameThrower, EDeflectType deflected);
EVulnerability GetDeflectionType(const CWeaponMode& mode) const;
EDeflectType GetDeflectionType(const CWeaponMode& mode) const;
bool WeaponHurts(const CWeaponMode&, bool ignoreDirect) const;
bool WeaponHits(const CWeaponMode& mode, bool checkDirect) const;

View File

@ -346,7 +346,7 @@ public:
virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; }
virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255); }
virtual bool IsOnGround() const { return x328_27_onGround; }
virtual float GetGravityConstant() const { return 24.525002f; }
virtual float GetGravityConstant() const { return CPhysicsActor::GravityConstant(); }
virtual CProjectileInfo* GetProjectileInfo() { return nullptr; }
virtual void PhazeOut(CStateManager&);
virtual const std::optional<TLockedToken<CGenDescription>>& GetDeathExplosionParticle() const {

View File

@ -47,7 +47,7 @@ float CPhysicsActor::GetStepUpHeight() const { return x23c_stepUpHeight; }
float CPhysicsActor::GetStepDownHeight() const { return x240_stepDownHeight; }
float CPhysicsActor::GetWeight() const { return 24.525002f * xe8_mass; }
float CPhysicsActor::GetWeight() const { return CPhysicsActor::GravityConstant() * xe8_mass; }
void CPhysicsActor::SetPrimitiveOffset(const zeus::CVector2f& offset) { x1e8_primitiveOffset = offset; }

View File

@ -202,5 +202,6 @@ public:
void ApplyTorqueWR(const zeus::CVector3f& torque);
void UseCollisionImpulses();
static constexpr float GravityConstant() { return 9.81f * 2.5f; } /* 9.81 m/s ^ 2 is normal acceleration under earth gravity, Tallon 4 is 2.5 times that */
};
} // namespace urde

View File

@ -174,8 +174,8 @@ EWeaponCollisionResponseTypes CScriptActor::GetCollisionResponseType(const zeus:
EProjectileAttrib w) const {
const CDamageVulnerability* dVuln = GetDamageVulnerability();
if (dVuln->GetVulnerability(wMode, false) == EVulnerability::Deflect) {
EVulnerability phazonVuln = dVuln->GetDeflectionType(wMode);
if (phazonVuln < EVulnerability::PassThrough && phazonVuln >= EVulnerability::Normal)
EDeflectType deflectType = dVuln->GetDeflectionType(wMode);
if (deflectType < EDeflectType::Four && deflectType >= EDeflectType::One)
return EWeaponCollisionResponseTypes::Unknown15;
}
return CActor::GetCollisionResponseType(v1, v2, wMode, w);

View File

@ -53,7 +53,7 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity
x2d4_particleGens[0]->SetGlobalScale(particleScale);
}
x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass);
x150_momentum = zeus::CVector3f(0.f, 0.f, -CPhysicsActor::GravityConstant() * xe8_mass);
if (x90_actorLights)
x90_actorLights->SetAmbienceGenerated(true);

View File

@ -16,6 +16,7 @@
#include "GameGlobalObjects.hpp"
#include "CStateManager.hpp"
#include "CSimplePool.hpp"
#include "World/CPhysicsActor.hpp"
#include "TCastTo.hpp"
namespace urde {
@ -490,7 +491,7 @@ void CWallCrawlerSwarm::UpdateBoid(const CAreaCollisionCache& ccache, CStateMana
f28 += f25;
}
if (!found) {
boid.x30_velocity += zeus::CVector3f(0.f, 0.f, -(x558_flavor == EFlavor::Scarab ? 3.f * 24.525f : 24.525f)) * dt;
boid.x30_velocity += zeus::CVector3f(0.f, 0.f, -(x558_flavor == EFlavor::Scarab ? 3.f * CPhysicsActor::GravityConstant() : CPhysicsActor::GravityConstant())) * dt;
if (boid.x7c_remainingLaunchNotOnSurfaceFrames)
boid.x7c_remainingLaunchNotOnSurfaceFrames -= 1;
}
@ -561,7 +562,7 @@ void CWallCrawlerSwarm::UpdateBoid(const CAreaCollisionCache& ccache, CStateMana
void CWallCrawlerSwarm::LaunchBoid(CBoid& boid, const zeus::CVector3f& dir) {
zeus::CVector3f pos = boid.GetTranslation();
static float skAttackTime = std::sqrt(2.5f / 24.525f) * 2.f;
static float skAttackTime = std::sqrt(2.5f / CPhysicsActor::GravityConstant()) * 2.f;
static float skAttackVelocity = 15.f / skAttackTime;
zeus::CVector3f deltaFlat = dir - pos;
float deltaZ = deltaFlat.z();
@ -578,14 +579,14 @@ void CWallCrawlerSwarm::LaunchBoid(CBoid& boid, const zeus::CVector3f& dir) {
bool r29 = deltaZ < 0.f;
float _12c, _130;
float f25 = 0.f;
if (CSteeringBehaviors::SolveQuadratic(-24.525f, vec.z(), -deltaZ, _12c, _130))
if (CSteeringBehaviors::SolveQuadratic(-CPhysicsActor::GravityConstant(), vec.z(), -deltaZ, _12c, _130))
f25 = r29 ? _130 : _12c;
if (!r29)
f25 += deltaMag / dot;
if (f25 < 10.f) {
vec.x() = deltaMag / f25 * deltaFlat.x() * 0.6f;
vec.y() = deltaMag / f25 * deltaFlat.y() * 0.6f;
vec.z() = deltaZ / f25 - 0.5f * -24.525f * f25;
vec.z() = deltaZ / f25 - 0.5f * -CPhysicsActor::GravityConstant() * f25;
}
}
}