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

View File

@ -2,9 +2,12 @@
#include "CAnimSourceReader.hpp" #include "CAnimSourceReader.hpp"
namespace urde { namespace urde {
CInt32POINode::CInt32POINode() 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) CInt32POINode::CInt32POINode(CInputStream& in)
: CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {} : CPOINode(in), x38_val(in.readUint32Big()), x3c_locatorName(in.readString()) {}

View File

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

View File

@ -64,7 +64,7 @@ enum class EHurledState {
Seven Seven
}; };
enum class EFallState { Invalid = -1, Zero }; enum class EFallState { Invalid = -1, Zero, One };
enum class EReactionType { Invalid = -1, Zero, One, Two, Three }; 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 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 EStepType { Normal = 0, Dodge = 1, BreakDodge = 2, RollDodge = 3 };
enum class ESeverity {
enum class ESeverity { Invalid = -1, Zero = 0, One = 1, Two = 2, Three, Four, Seven = 7, Eight = 8 }; 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 }; 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); 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; } 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; } 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 } // namespace urde::MP1

View File

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

View File

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

View File

@ -17,11 +17,11 @@
namespace urde::MP1 { namespace urde::MP1 {
const float CParasite::flt_805A8FB0 = 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 / 24.525002f)); const float CParasite::skAttackVelocity = 15.f / 2.f * (std::sqrt(2.5f / CPhysicsActor::GravityConstant()));
short CParasite::word_805A8FC0 = 0; short CParasite::word_805A8FC0 = 0;
const float CParasite::flt_805A8FB8 = 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 / 24.525002f); 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, CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo& pInfo, EBodyType bodyType, 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) { for (TUniqueId id : nearList) {
if (TCastToPtr<CBomb> bomb = mgr.ObjectById(id)) { if (TCastToPtr<CBomb> bomb = mgr.ObjectById(id)) {
bomb->SetVelocityWR((mgr.GetActiveRandom()->Float() * 5.f + 20.f) * shootDir); 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 "CStateManager.hpp"
#include "World/CWorld.hpp" #include "World/CWorld.hpp"
#include "World/CGameArea.hpp" #include "World/CGameArea.hpp"
#include "World/CPatternedInfo.hpp"
#include "World/CPlayer.hpp"
#include "Weapon/CBomb.hpp"
#include "TCastTo.hpp"
namespace urde::MP1 { 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, CTryclops::CTryclops(urde::TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
urde::CModelData&& mData, const urde::CPatternedInfo& pInfo, 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, : 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) { void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CPatterned::AcceptScriptMsg(msg, uid, mgr); CPatterned::AcceptScriptMsg(msg, uid, mgr);
@ -16,7 +40,417 @@ void CTryclops::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateM
if (msg == EScriptObjectMessage::Registered) { if (msg == EScriptObjectMessage::Registered) {
x450_bodyController->Activate(mgr); x450_bodyController->Activate(mgr);
} else if (msg == EScriptObjectMessage::InitializedInArea) { } 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 } // namespace urde::MP1

View File

@ -1,14 +1,90 @@
#pragma once #pragma once
#include "World/CPatterned.hpp" #include "World/CPatterned.hpp"
#include "World/CPathFindSearch.hpp"
namespace urde::MP1 { namespace urde::MP1 {
class CTryclops : public CPatterned { 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: public:
DEFINE_PATTERNED(Tryclops) DEFINE_PATTERNED(Tryclops)
CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, CTryclops(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
const CPatternedInfo&, const CActorParameters&, float, float, float, float); const CPatternedInfo&, const CActorParameters&, float, float, float, float);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); 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 } // 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)) new CElementGen(particle1, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One))
, x184_particle2( , x184_particle2(
new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One)) new CElementGen(particle2, CElementGen::EModelOrientationType::Normal, CElementGen::EOptionalSystemFlags::One))
, x18c_(particle2.GetObj()) , x18c_particle2Obj(particle2.GetObj())
, x190_24_isNotDetonated(true) , x190_24_isNotDetonated(true)
, x190_25_(false) , x190_25_beingDragged(false)
, x190_26_disableFuse(false) { , x190_26_disableFuse(false) {
x180_particle1->SetGlobalTranslation(xf.origin); x180_particle1->SetGlobalTranslation(xf.origin);
x184_particle2->SetGlobalTranslation(xf.origin); x184_particle2->SetGlobalTranslation(xf.origin);
@ -40,7 +40,7 @@ void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManag
x188_lightId = mgr.AllocateUniqueId(); x188_lightId = mgr.AllocateUniqueId();
CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false, CGameLight* gameLight = new CGameLight(x188_lightId, GetAreaIdAlways(), false,
std::string("Bomb_PLight") + GetName().data(), GetTransform(), GetUniqueId(), 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.AddObject(gameLight);
mgr.AddWeaponId(xec_ownerId, xf0_weaponType); mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1); 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> x180_particle1;
std::unique_ptr<CElementGen> x184_particle2; std::unique_ptr<CElementGen> x184_particle2;
TUniqueId x188_lightId = kInvalidUniqueId; TUniqueId x188_lightId = kInvalidUniqueId;
const CGenDescription* x18c_; const CGenDescription* x18c_particle2Obj;
bool x190_24_isNotDetonated : 1; bool x190_24_isNotDetonated : 1;
bool x190_25_ : 1; bool x190_25_beingDragged : 1;
bool x190_26_disableFuse : 1; bool x190_26_disableFuse : 1;
public: public:
@ -35,6 +35,9 @@ public:
std::optional<zeus::CAABox> GetTouchBounds() const; std::optional<zeus::CAABox> GetTouchBounds() const;
void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; } void SetVelocityWR(const zeus::CVector3f& vel) { x158_velocity = vel; }
void SetConstantAccelerationWR(const zeus::CVector3f& acc) { x164_acceleration = acc; } 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 } // 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); EVulnerability vulnType = dVuln.GetVulnerability(x12c_curDamageInfo.GetWeaponMode(), false);
if (vulnType == EVulnerability::Deflect) { if (vulnType == EVulnerability::Deflect) {
deflect = true; deflect = true;
EVulnerability deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode()); EDeflectType deflectType = dVuln.GetDeflectionType(x12c_curDamageInfo.GetWeaponMode());
switch (deflectType) { switch (deflectType) {
case EVulnerability::Weak: case EDeflectType::None:
deflect = false; deflect = false;
break; break;
case EVulnerability::Deflect: case EDeflectType::Two:
case EVulnerability::Immune: case EDeflectType::Three:
if (deflectType != EVulnerability::Deflect || if (deflectType != EDeflectType::Two ||
(xf0_weaponType != EWeaponType::Missile && (xf0_weaponType != EWeaponType::Missile &&
(xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot)) (xe8_projectileAttribs & EProjectileAttrib::ComboShot) != EProjectileAttrib::ComboShot))
if (xf8_filter.GetExcludeList().HasMaterial(EMaterialTypes::Player)) 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::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( const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, 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::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 */ /* LOL, thanks retro */
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability( const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, 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::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( const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, 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::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) { static inline bool is_not_immune(EVulnerability vuln) {
return vuln != EVulnerability::Immune && vuln != EVulnerability::DirectImmune; 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) for (int i = 15; i < propCount; ++i)
in.readUint32Big(); in.readUint32Big();
x5c_deflected = EVulnerability(in.readUint32Big()); x5c_deflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns2 = &x3c_chargedPower; EVulnerability* vulns2 = &x3c_chargedPower;
in.readUint32Big(); in.readUint32Big();
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
vulns2[i] = EVulnerability(in.readUint32Big()); vulns2[i] = EVulnerability(in.readUint32Big());
x60_chargedDeflected = EVulnerability(in.readUint32Big()); x60_chargedDeflected = EDeflectType(in.readUint32Big());
EVulnerability* vulns3 = &x4c_superMissile; EVulnerability* vulns3 = &x4c_superMissile;
in.readUint32Big(); in.readUint32Big();
for (int i = 0; i < 4; ++i) for (int i = 0; i < 4; ++i)
vulns3[i] = EVulnerability(in.readUint32Big()); vulns3[i] = EVulnerability(in.readUint32Big());
x64_comboDeflected = EVulnerability(in.readUint32Big()); x64_comboDeflected = EDeflectType(in.readUint32Big());
} }
CDamageVulnerability::CDamageVulnerability(CInputStream& in) { CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
@ -79,9 +79,9 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
vulns[i] = EVulnerability(in.readUint32Big()); vulns[i] = EVulnerability(in.readUint32Big());
if (propCount == 15) if (propCount == 15)
x5c_deflected = EVulnerability::Weak; x5c_deflected = EDeflectType::None;
else else
x5c_deflected = EVulnerability(in.readUint32Big()); x5c_deflected = EDeflectType(in.readUint32Big());
x3c_chargedPower = x0_power; x3c_chargedPower = x0_power;
x4c_superMissile = x0_power; x4c_superMissile = x0_power;
@ -95,13 +95,44 @@ CDamageVulnerability::CDamageVulnerability(CInputStream& in) {
ConstructNew(in, propCount); 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( CDamageVulnerability::CDamageVulnerability(
EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb, EVulnerability power, EVulnerability ice, EVulnerability wave, EVulnerability plasma, EVulnerability bomb,
EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon, EVulnerability powerBomb, EVulnerability missile, EVulnerability boostBall, EVulnerability phazon,
EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4, EVulnerability enemyWp1, EVulnerability enemyWp2, EVulnerability enemyWp3, EVulnerability enemyWp4,
EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce, EVulnerability v1, EVulnerability v2, EVulnerability chargedPower, EVulnerability chargedIce,
EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader, EVulnerability chargedWave, EVulnerability chargedPlasma, EVulnerability superMissile, EVulnerability iceSpreader,
EVulnerability waveBuster, EVulnerability flameThrower, EVulnerability deflected) EVulnerability waveBuster, EVulnerability flameThrower, EDeflectType deflected)
: x0_power(power) : x0_power(power)
, x4_ice(ice) , x4_ice(ice)
, x8_wave(wave) , x8_wave(wave)
@ -127,7 +158,7 @@ CDamageVulnerability::CDamageVulnerability(
, x58_flamethrower(flameThrower) , x58_flamethrower(flameThrower)
, x5c_deflected(deflected) {} , x5c_deflected(deflected) {}
EVulnerability CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const { EDeflectType CDamageVulnerability::GetDeflectionType(const CWeaponMode& mode) const {
if (mode.IsCharged()) if (mode.IsCharged())
return x60_chargedDeflected; return x60_chargedDeflected;
if (mode.IsComboed()) if (mode.IsComboed())
@ -205,9 +236,7 @@ bool CDamageVulnerability::WeaponHits(const CWeaponMode& mode, bool checkDirect)
return true; return true;
if (chargedVuln && mode.IsCharged()) if (chargedVuln && mode.IsCharged())
return true; return true;
if (comboedVuln && mode.IsComboed()) return comboedVuln && mode.IsComboed();
return true;
return false;
} }
EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const { EVulnerability CDamageVulnerability::GetVulnerability(const CWeaponMode& mode, bool ignoreDirect) const {

View File

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

View File

@ -346,7 +346,7 @@ public:
virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; } virtual CDamageInfo GetContactDamage() const { return x404_contactDamage; }
virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255); } virtual u8 GetModelAlphau8(const CStateManager&) const { return u8(x42c_color.a() * 255); }
virtual bool IsOnGround() const { return x328_27_onGround; } 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 CProjectileInfo* GetProjectileInfo() { return nullptr; }
virtual void PhazeOut(CStateManager&); virtual void PhazeOut(CStateManager&);
virtual const std::optional<TLockedToken<CGenDescription>>& GetDeathExplosionParticle() const { 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::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; } void CPhysicsActor::SetPrimitiveOffset(const zeus::CVector2f& offset) { x1e8_primitiveOffset = offset; }

View File

@ -202,5 +202,6 @@ public:
void ApplyTorqueWR(const zeus::CVector3f& torque); void ApplyTorqueWR(const zeus::CVector3f& torque);
void UseCollisionImpulses(); 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 } // namespace urde

View File

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

View File

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