Work on CParasite

This commit is contained in:
Jack Andersen 2018-11-12 23:20:11 -10:00
parent bf3636a16e
commit 660e7cd239
17 changed files with 755 additions and 358 deletions

View File

@ -17,24 +17,24 @@ struct Parasite : IScriptObject
Value<atVec3f> scale; Value<atVec3f> scale;
PatternedInfo patternedInfo; PatternedInfo patternedInfo;
ActorParameters actorParameters; ActorParameters actorParameters;
Value<float> unknown2; Value<float> maxTelegraphReactDist;
Value<float> unknown3; Value<float> advanceWpRadius;
Value<float> unknown4; Value<float> unknown4;
Value<float> unknown5; Value<float> alignAngVel;
Value<float> unknown6; Value<float> unknown6;
Value<float> unknown7; Value<float> stuckTimeThreshold;
Value<float> unknown8; Value<float> collisionCloseMargin;
Value<float> unknown9; Value<float> parasiteSearchRadius;
Value<float> unknown10; Value<float> parasiteSeparationDist;
Value<float> unknown11; Value<float> parasiteSeparationWeight;
Value<float> unknown12; Value<float> parasiteAlignmentWeight;
Value<float> unknown13; Value<float> parasiteCohesionWeight;
Value<float> unknown14; Value<float> destinationSeekWeight;
Value<float> unknown15; Value<float> forwardMoveWeight;
Value<float> unknown16; Value<float> playerSeparationDist;
Value<float> unknown17; Value<float> playerSeparationWeight;
Value<float> unknown18; Value<float> playerObstructionMinDist;
Value<bool> unknown19; Value<bool> disableMove;
void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const void addCMDLRigPairs(PAKRouter<PAKBridge>& pakRouter, CharacterAssociations<UniqueID32>& charAssoc) const
{ {

View File

@ -202,7 +202,7 @@ private:
EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass; EThermalDrawFlag xf34_thermalFlag = EThermalDrawFlag::Bypass;
TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId; TUniqueId xf38_skipCineSpecialFunc = kInvalidUniqueId;
std::list<u32> xf3c_; std::list<u32> xf3c_;
std::list<TUniqueId> xf54_parasiteTelegraphs; std::list<TUniqueId> xf54_activeParasites;
TUniqueId xf6c_playerActorHead = kInvalidUniqueId; TUniqueId xf6c_playerActorHead = kInvalidUniqueId;
u32 xf70_ = 0; u32 xf70_ = 0;
@ -470,7 +470,7 @@ public:
} }
TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; } TUniqueId GetPlayerActorHead() const { return xf6c_playerActorHead; }
void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; } void SetPlayerActorHead(TUniqueId id) { xf6c_playerActorHead = id; }
std::list<TUniqueId>& GetParasiteTelegraphs() { return xf54_parasiteTelegraphs; } std::list<TUniqueId>& GetActiveParasites() { return xf54_activeParasites; }
std::shared_ptr<CWorldLayerState>& WorldLayerStateNC() { return x8c8_worldLayerState; } std::shared_ptr<CWorldLayerState>& WorldLayerStateNC() { return x8c8_worldLayerState; }
static float g_EscapeShakeCountdown; static float g_EscapeShakeCountdown;
static bool g_EscapeShakeCountdownInit; static bool g_EscapeShakeCountdownInit;

View File

@ -284,8 +284,8 @@ class CBCLocomotionCmd
zeus::CVector3f xc_face; zeus::CVector3f xc_face;
float x18_weight; float x18_weight;
public: public:
CBCLocomotionCmd(const zeus::CVector3f& v1, const zeus::CVector3f& v2, float f) CBCLocomotionCmd(const zeus::CVector3f& move, const zeus::CVector3f& face, float weight)
: x0_move(v1), xc_face(v2), x18_weight(f) {} : x0_move(move), xc_face(face), x18_weight(weight) {}
const zeus::CVector3f& GetMoveVector() const { return x0_move; } const zeus::CVector3f& GetMoveVector() const { return x0_move; }
const zeus::CVector3f& GetFaceVector() const { return xc_face; } const zeus::CVector3f& GetFaceVector() const { return xc_face; }
float GetWeight() const { return x18_weight; } float GetWeight() const { return x18_weight; }

View File

@ -3,16 +3,125 @@
#include "World/CActor.hpp" #include "World/CActor.hpp"
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "CMaterialList.hpp" #include "CMaterialList.hpp"
#include "Collision/CCollisionActor.hpp"
namespace urde namespace urde
{ {
CCollisionActorManager::CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area, CCollisionActorManager::CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area,
const std::vector<CJointCollisionDescription>& descs, bool b1) const std::vector<CJointCollisionDescription>& descs, bool active)
: x0_jointDescriptions(descs) : x10_ownerId(owner)
, x10_ownerId(owner) , x12_active(active)
, x12_(b1)
{ {
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(x10_ownerId))
{
zeus::CTransform xf = act->GetTransform();
const CAnimData* animData = act->GetModelData()->GetAnimationData();
zeus::CVector3f scale = act->GetModelData()->GetScale();
zeus::CTransform scaleXf = zeus::CTransform::Scale(scale);
x0_jointDescriptions.reserve(descs.size());
for (const CJointCollisionDescription& desc : descs)
{
CJointCollisionDescription modDesc = desc;
modDesc.ScaleAllBounds(scale);
zeus::CTransform locXf = GetWRLocatorTransform(*animData, modDesc.GetPivotId(), xf, scaleXf);
if (modDesc.GetNextId() != 0xff)
{
zeus::CTransform locXf2 = GetWRLocatorTransform(*animData, modDesc.GetNextId(), xf, scaleXf);
float dist = (locXf2.origin - locXf.origin).magnitude();
if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize)
{
if (dist <= FLT_EPSILON)
continue;
zeus::CVector3f bounds = modDesc.GetBounds();
bounds.y += dist;
CCollisionActor* newAct =
new CCollisionActor(mgr.AllocateUniqueId(), area, x10_ownerId, bounds,
zeus::CVector3f(0.f, 0.5f * dist, 0.f), active, modDesc.GetMass());
if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero)
{
newAct->SetTransform(locXf);
}
else
{
zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized();
zeus::CVector3f upVector = locXf.basis[2];
if (zeus::close_enough(std::fabs(delta.dot(upVector)), 1.f))
upVector = locXf.basis[1];
newAct->SetTransform(zeus::lookAt(locXf.origin, locXf.origin + delta, upVector));
}
mgr.AddObject(newAct);
x0_jointDescriptions.push_back(desc);
}
else
{
TUniqueId newId = mgr.AllocateUniqueId();
CCollisionActor* newAct =
new CCollisionActor(newId, area, x10_ownerId,
active, modDesc.GetRadius(), modDesc.GetMass());
newAct->SetTransform(locXf);
mgr.AddObject(newAct);
x0_jointDescriptions.push_back(CJointCollisionDescription::
SphereCollision(modDesc.GetPivotId(), modDesc.GetRadius(), modDesc.GetName(), 0.001f));
x0_jointDescriptions.back().SetCollisionActorId(newId);
u32 numSeps = u32(dist / modDesc.GetMaxSeparation());
if (numSeps)
{
x0_jointDescriptions.reserve(x0_jointDescriptions.capacity() + numSeps);
float pitch = dist / float(numSeps + 1);
for (u32 i = 0; i < numSeps; ++i)
{
float separation = pitch * float(i + 1);
x0_jointDescriptions.push_back(CJointCollisionDescription::
SphereSubdivideCollision(modDesc.GetPivotId(), modDesc.GetNextId(), modDesc.GetRadius(),
separation, CJointCollisionDescription::EOrientationType::One,
modDesc.GetName(), 0.001f));
TUniqueId newId2 = mgr.AllocateUniqueId();
CCollisionActor* newAct2 =
new CCollisionActor(newId2, area, x10_ownerId,
active, modDesc.GetRadius(), modDesc.GetMass());
if (modDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero)
{
newAct2->SetTransform(
zeus::CTransform::Translate(locXf.origin + separation * locXf.basis[1]));
}
else
{
zeus::CVector3f delta = (locXf2.origin - locXf.origin).normalized();
zeus::CVector3f upVector = locXf.basis[2];
if (zeus::close_enough(
std::fabs(delta.dot(upVector)), 1.f))
upVector = locXf.basis[1];
zeus::CTransform lookAt = zeus::lookAt(zeus::CVector3f::skZero, delta, upVector);
newAct2->SetTransform(
zeus::CTransform::Translate(lookAt.basis[1] * separation + locXf.origin));
}
mgr.AddObject(newAct2);
x0_jointDescriptions.back().SetCollisionActorId(newId2);
}
}
}
}
else
{
TUniqueId newId = mgr.AllocateUniqueId();
CCollisionActor* newAct;
if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::Sphere)
newAct = new CCollisionActor(newId, area, x10_ownerId, active,
modDesc.GetRadius(), modDesc.GetMass());
else if (modDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB)
newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(),
modDesc.GetPivotPoint(), active, modDesc.GetMass());
else
newAct = new CCollisionActor(newId, area, x10_ownerId, modDesc.GetBounds(),
active, modDesc.GetMass());
newAct->SetTransform(locXf);
mgr.AddObject(newAct);
x0_jointDescriptions.push_back(desc);
x0_jointDescriptions.back().SetCollisionActorId(newId);
}
}
}
} }
void CCollisionActorManager::Destroy(CStateManager& mgr) const void CCollisionActorManager::Destroy(CStateManager& mgr) const
@ -20,23 +129,21 @@ void CCollisionActorManager::Destroy(CStateManager& mgr) const
for (const CJointCollisionDescription& desc : x0_jointDescriptions) for (const CJointCollisionDescription& desc : x0_jointDescriptions)
mgr.FreeScriptObject(desc.GetCollisionActorId()); mgr.FreeScriptObject(desc.GetCollisionActorId());
const_cast<CCollisionActorManager&>(*this).x13_ = true; const_cast<CCollisionActorManager&>(*this).x13_destroyed = true;
} }
void CCollisionActorManager::SetActive(CStateManager& mgr, bool active) void CCollisionActorManager::SetActive(CStateManager& mgr, bool active)
{ {
for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) for (const CJointCollisionDescription& jDesc : x0_jointDescriptions)
{ {
TCastToPtr<CActor> act(mgr.ObjectById(jDesc.GetCollisionActorId())); if (TCastToPtr<CActor> act = mgr.ObjectById(jDesc.GetCollisionActorId()))
if (act)
{ {
bool curActive = act->GetActive(); bool curActive = act->GetActive();
if (curActive != active) if (curActive != active)
act->SetActive(active); act->SetActive(active);
if (!curActive) if (!curActive)
Update(0.f, mgr, EUpdateOptions::One); Update(0.f, mgr, EUpdateOptions::WorldSpace);
} }
} }
} }
@ -44,26 +151,89 @@ void CCollisionActorManager::SetActive(CStateManager& mgr, bool active)
void CCollisionActorManager::AddMaterial(CStateManager& mgr, const CMaterialList& list) void CCollisionActorManager::AddMaterial(CStateManager& mgr, const CMaterialList& list)
{ {
for (const CJointCollisionDescription& jDesc : x0_jointDescriptions) for (const CJointCollisionDescription& jDesc : x0_jointDescriptions)
{ if (TCastToPtr<CActor> act = mgr.ObjectById(jDesc.GetCollisionActorId()))
TCastToPtr<CActor> act(mgr.ObjectById(jDesc.GetCollisionActorId()));
if (act)
act->AddMaterial(list); act->AddMaterial(list);
}
void CCollisionActorManager::SetMovable(CStateManager& mgr, bool movable)
{
if (x14_movable == movable)
return;
x14_movable = movable;
for (const CJointCollisionDescription& jDesc : x0_jointDescriptions)
{
if (TCastToPtr<CCollisionActor> act = mgr.ObjectById(jDesc.GetCollisionActorId()))
{
act->SetMovable(x14_movable);
act->SetUseInSortedLists(x14_movable);
}
} }
} }
u32 CCollisionActorManager::GetNumCollisionActors() const void CCollisionActorManager::Update(float dt, CStateManager& mgr, EUpdateOptions opts)
{ {
return x0_jointDescriptions.size(); if (!x14_movable)
SetMovable(mgr, true);
if (x12_active)
{
if (TCastToPtr<CActor> act = mgr.ObjectById(x10_ownerId))
{
const CAnimData& animData = *act->GetModelData()->GetAnimationData();
zeus::CTransform actXf = act->GetTransform();
zeus::CTransform scaleXf = zeus::CTransform::Scale(act->GetModelData()->GetScale());
for (const CJointCollisionDescription& jDesc : x0_jointDescriptions)
{
if (TCastToPtr<CCollisionActor> cAct = mgr.ObjectById(jDesc.GetCollisionActorId()))
{
zeus::CTransform pivotXf = GetWRLocatorTransform(animData, jDesc.GetPivotId(), actXf, scaleXf);
zeus::CVector3f origin = pivotXf.origin;
if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBB ||
jDesc.GetType() == CJointCollisionDescription::ECollisionType::OBBAutoSize)
{
if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero)
{
cAct->SetTransform(zeus::CQuaternion(pivotXf.basis).toTransform(cAct->GetTranslation()));
}
else
{
zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf);
cAct->SetTransform(
zeus::CQuaternion(zeus::lookAt(pivotXf.origin, nextXf.origin, pivotXf.basis[2]).basis).
toTransform(cAct->GetTranslation()));
}
}
else if (jDesc.GetType() == CJointCollisionDescription::ECollisionType::SphereSubdivide)
{
if (jDesc.GetOrientationType() == CJointCollisionDescription::EOrientationType::Zero)
{
origin += jDesc.GetMaxSeparation() * pivotXf.basis[1];
}
else
{
zeus::CTransform nextXf = GetWRLocatorTransform(animData, jDesc.GetNextId(), actXf, scaleXf);
origin += zeus::lookAt(origin, nextXf.origin, pivotXf.basis[2]).basis[1] *
jDesc.GetMaxSeparation();
}
}
if (opts == EUpdateOptions::ObjectSpace)
cAct->MoveToOR(cAct->GetTransform().transposeRotate(origin - cAct->GetTranslation()), dt);
else
cAct->SetTranslation(origin);
}
}
}
}
} }
CJointCollisionDescription CCollisionActorManager::GetCollisionDescFromIndex(u32 idx) const zeus::CTransform CCollisionActorManager::GetWRLocatorTransform(const CAnimData& animData, CSegId id,
{ const zeus::CTransform& worldXf,
return x0_jointDescriptions[idx]; const zeus::CTransform& localXf)
}
void CCollisionActorManager::Update(float, CStateManager&, CCollisionActorManager::EUpdateOptions) const
{ {
zeus::CTransform locXf = animData.GetLocatorTransform(id, nullptr);
zeus::CVector3f origin = worldXf * (localXf * locXf.origin);
locXf = worldXf.multiplyIgnoreTranslation(locXf);
locXf.origin = origin;
return locXf;
} }
} }

View File

@ -15,26 +15,30 @@ class CCollisionActorManager
public: public:
enum class EUpdateOptions enum class EUpdateOptions
{ {
Zero, ObjectSpace,
One WorldSpace
}; };
private: private:
std::vector<CJointCollisionDescription> x0_jointDescriptions; std::vector<CJointCollisionDescription> x0_jointDescriptions;
TUniqueId x10_ownerId; TUniqueId x10_ownerId;
bool x12_; bool x12_active;
bool x13_ = false; bool x13_destroyed = false;
bool x14_ = true; bool x14_movable = true;
public: public:
CCollisionActorManager(CStateManager&, TUniqueId, TAreaId, const std::vector<CJointCollisionDescription>&, bool); CCollisionActorManager(CStateManager& mgr, TUniqueId owner, TAreaId area,
const std::vector<CJointCollisionDescription>& descs, bool active);
void Update(float, CStateManager&, EUpdateOptions) const; void Update(float dt, CStateManager& mgr, CCollisionActorManager::EUpdateOptions opts);
void Destroy(CStateManager&) const; void Destroy(CStateManager& mgr) const;
void SetActive(CStateManager&, bool); void SetActive(CStateManager& mgr, bool active);
void AddMaterial(CStateManager&, const CMaterialList&); void AddMaterial(CStateManager& mgr, const CMaterialList& list);
void SetMovable(CStateManager& mgr, bool movable);
u32 GetNumCollisionActors() const; u32 GetNumCollisionActors() const { return x0_jointDescriptions.size(); }
CJointCollisionDescription GetCollisionDescFromIndex(u32) const; const CJointCollisionDescription& GetCollisionDescFromIndex(u32 i) const { return x0_jointDescriptions[i]; }
zeus::CTransform GetWRLocatorTransform(const CAnimData&, CSegId, const zeus::CTransform&, const zeus::CTransform&); static zeus::CTransform GetWRLocatorTransform(const CAnimData& animData, CSegId id,
const zeus::CTransform& worldXf,
const zeus::CTransform& localXf);
}; };
} }

View File

@ -3,57 +3,68 @@
namespace urde namespace urde
{ {
CJointCollisionDescription::CJointCollisionDescription(ECollisionType colType, CSegId seg1, CSegId seg2, CJointCollisionDescription::CJointCollisionDescription(ECollisionType colType, CSegId pivotId, CSegId nextId,
const zeus::CVector3f& v1, const zeus::CVector3f& v2, float f1, const zeus::CVector3f& bounds, const zeus::CVector3f& pivotPoint,
float f2, EOrientationType orientType, std::string_view name, float radius, float maxSeparation, EOrientationType orientType,
float f3) std::string_view name, float mass)
: x0_colType(colType) : x0_colType(colType)
, x4_orientType(orientType) , x4_orientType(orientType)
, x8_(seg1) , x8_pivotId(pivotId)
, x9_(seg2) , x9_nextId(nextId)
, xc_(v1) , xc_bounds(bounds)
, x18_(v2) , x18_pivotPoint(pivotPoint)
, x24_(f1) , x24_radius(radius)
, x28_(f2) , x28_maxSeparation(maxSeparation)
, x2c_name(name) , x2c_name(name)
, x40_(f3) , x40_mass(mass)
{ {
} }
CJointCollisionDescription CJointCollisionDescription::SphereSubdivideCollision(CSegId seg1, CSegId seg2, float f1, CJointCollisionDescription
float f2, EOrientationType orientType, CJointCollisionDescription::SphereSubdivideCollision(CSegId pivotId, CSegId nextId, float radius,
std::string_view name, float f3) float maxSeparation, EOrientationType orientType,
std::string_view name, float mass)
{ {
return CJointCollisionDescription(ECollisionType::SphereSubdivide, seg1, seg2, zeus::CVector3f::skZero, return CJointCollisionDescription(ECollisionType::SphereSubdivide, pivotId, nextId, zeus::CVector3f::skZero,
zeus::CVector3f::skZero, f1, f2, orientType, name, f3); zeus::CVector3f::skZero, radius, maxSeparation, orientType, name, mass);
} }
CJointCollisionDescription CJointCollisionDescription::SphereCollision(CSegId segId, float f1, std::string_view name, float f2) CJointCollisionDescription
CJointCollisionDescription::SphereCollision(CSegId pivotId, float radius, std::string_view name, float mass)
{ {
return CJointCollisionDescription(ECollisionType::Sphere, segId, -1, zeus::CVector3f::skZero, return CJointCollisionDescription(ECollisionType::Sphere, pivotId, {}, zeus::CVector3f::skZero,
zeus::CVector3f::skZero, f1, 0.f, EOrientationType::Zero, name, f2); zeus::CVector3f::skZero, radius, 0.f, EOrientationType::Zero, name, mass);
} }
CJointCollisionDescription CJointCollisionDescription::AABoxCollision(CSegId segId, const zeus::CVector3f& v1, CJointCollisionDescription
std::string_view name, float f1) CJointCollisionDescription::AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds,
std::string_view name, float mass)
{ {
return CJointCollisionDescription(ECollisionType::AABox, segId, -1, v1, zeus::CVector3f::skZero, 0.f, 0.f, return CJointCollisionDescription(ECollisionType::AABox, pivotId, {}, bounds, zeus::CVector3f::skZero,
EOrientationType::Zero, name, f1); 0.f, 0.f, EOrientationType::Zero, name, mass);
} }
CJointCollisionDescription CJointCollisionDescription::OBBCollision(CSegId segId, const zeus::CVector3f& v1, CJointCollisionDescription
const zeus::CVector3f& v2, std::string_view name, CJointCollisionDescription::OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds,
float f1) EOrientationType orientType, std::string_view name, float mass)
{ {
return CJointCollisionDescription(ECollisionType::OBB, segId, -1, v1, v2, 0.f, 0.f, EOrientationType::Zero, name, return CJointCollisionDescription(ECollisionType::OBBAutoSize, pivotId, nextId, bounds, zeus::CVector3f::skZero,
f1); 0.f, 0.f, orientType, name, mass);
}
CJointCollisionDescription
CJointCollisionDescription::OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds,
const zeus::CVector3f& pivotPoint, std::string_view name, float mass)
{
return CJointCollisionDescription(ECollisionType::OBB, pivotId, {}, bounds, pivotPoint, 0.f, 0.f,
EOrientationType::Zero, name, mass);
} }
void CJointCollisionDescription::ScaleAllBounds(const zeus::CVector3f& scale) void CJointCollisionDescription::ScaleAllBounds(const zeus::CVector3f& scale)
{ {
xc_ *= scale; xc_bounds *= scale;
x24_ *= scale.x; x24_radius *= scale.x;
x28_ *= scale.x; x28_maxSeparation *= scale.x;
x18_ *= scale; x18_pivotPoint *= scale;
} }
} }

View File

@ -26,40 +26,42 @@ public:
private: private:
ECollisionType x0_colType; ECollisionType x0_colType;
EOrientationType x4_orientType; EOrientationType x4_orientType;
CSegId x8_; CSegId x8_pivotId;
CSegId x9_; CSegId x9_nextId;
zeus::CVector3f xc_; zeus::CVector3f xc_bounds;
zeus::CVector3f x18_; zeus::CVector3f x18_pivotPoint;
float x24_; float x24_radius;
float x28_; float x28_maxSeparation;
std::string x2c_name; std::string x2c_name;
TUniqueId x3c_actorId = kInvalidUniqueId; TUniqueId x3c_actorId = kInvalidUniqueId;
float x40_; float x40_mass;
public: public:
CJointCollisionDescription(ECollisionType, CSegId, CSegId, const zeus::CVector3f&, const zeus::CVector3f&, float, CJointCollisionDescription(ECollisionType, CSegId, CSegId, const zeus::CVector3f&, const zeus::CVector3f&, float,
float, EOrientationType, std::string_view, float); float, EOrientationType, std::string_view, float);
static CJointCollisionDescription SphereSubdivideCollision(CSegId pivotId, CSegId nextId, float radius,
float maxSeparation, EOrientationType orientType,
std::string_view name, float mass);
static CJointCollisionDescription SphereCollision(CSegId pivotId, float radius, std::string_view name, float mass);
static CJointCollisionDescription AABoxCollision(CSegId pivotId, const zeus::CVector3f& bounds,
std::string_view name, float mass);
static CJointCollisionDescription OBBAutoSizeCollision(CSegId pivotId, CSegId nextId, const zeus::CVector3f& bounds,
EOrientationType orientType, std::string_view, float mass);
static CJointCollisionDescription OBBCollision(CSegId pivotId, const zeus::CVector3f& bounds,
const zeus::CVector3f& pivotPoint, std::string_view name, float mass);
std::string_view GetName() const { return x2c_name; } std::string_view GetName() const { return x2c_name; }
TUniqueId GetCollisionActorId() const { return x3c_actorId; } TUniqueId GetCollisionActorId() const { return x3c_actorId; }
static CJointCollisionDescription SphereSubdivideCollision(CSegId, CSegId, float, float, void SetCollisionActorId(TUniqueId id) { x3c_actorId = id; }
EOrientationType, std::string_view, float); const zeus::CVector3f& GetBounds() const { return xc_bounds; }
static CJointCollisionDescription SphereCollision(CSegId, float, std::string_view, float); float GetRadius() const { return x24_radius; }
static CJointCollisionDescription AABoxCollision(CSegId, zeus::CVector3f const&, std::string_view, float); float GetMaxSeparation() const { return x28_maxSeparation; }
static CJointCollisionDescription OBBAutoSizeCollision(CSegId, CSegId, const zeus::CVector3f&, EOrientationType,
std::string_view, float);
static CJointCollisionDescription OBBCollision(CSegId, const zeus::CVector3f&, const zeus::CVector3f&,
std::string_view, float);
zeus::CVector3f GetPivotPoint() const;
float GetRadius() const;
void SetCollisionActorId(TUniqueId);
EOrientationType GetOrientationType() const { return x4_orientType; } EOrientationType GetOrientationType() const { return x4_orientType; }
float GetMass() const; float GetMass() const { return x40_mass; }
zeus::CAABox GetBounds() const; const zeus::CVector3f& GetPivotPoint() const { return x18_pivotPoint; }
void GetType() const; ECollisionType GetType() const { return x0_colType; }
void GetNextId() const; CSegId GetNextId() const { return x9_nextId; }
void GetPivotId() const; CSegId GetPivotId() const { return x8_pivotId; }
void ScaleAllBounds(const zeus::CVector3f&); void ScaleAllBounds(const zeus::CVector3f& scale);
void GetTween() const;
}; };
} }

View File

@ -126,6 +126,9 @@ public:
void AddLeaf(const CAreaOctTree::Node& node); void AddLeaf(const CAreaOctTree::Node& node);
u32 GetNumLeaves() const { return x4_nodeCache.size(); } u32 GetNumLeaves() const { return x4_nodeCache.size(); }
bool HasCacheOverflowed() const { return x908_24_overflow; } bool HasCacheOverflowed() const { return x908_24_overflow; }
const CAreaOctTree& GetOctTree() const { return x0_octTree; }
rstl::reserved_vector<CAreaOctTree::Node, 64>::iterator begin() { return x4_nodeCache.begin(); }
rstl::reserved_vector<CAreaOctTree::Node, 64>::iterator end() { return x4_nodeCache.end(); }
}; };
static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb, static void BuildOctreeLeafCache(const CAreaOctTree::Node& root, const zeus::CAABox& aabb,
CMetroidAreaCollider::COctreeLeafCache& cache); CMetroidAreaCollider::COctreeLeafCache& cache);

View File

@ -6,12 +6,14 @@
#include "World/CGameArea.hpp" #include "World/CGameArea.hpp"
#include "World/CPlayer.hpp" #include "World/CPlayer.hpp"
#include "World/CScriptWaypoint.hpp" #include "World/CScriptWaypoint.hpp"
#include "World/CScriptDoor.hpp"
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "GameGlobalObjects.hpp" #include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
#include "Graphics/CSkinnedModel.hpp" #include "Graphics/CSkinnedModel.hpp"
#include "Collision/CGameCollision.hpp" #include "Collision/CGameCollision.hpp"
#include "Collision/CCollisionActor.hpp"
namespace urde::MP1 namespace urde::MP1
{ {
@ -24,33 +26,39 @@ const float CParasite::skRetreatVelocity = 3.f / 2.f * std::sqrt(2.5f / 24.52500
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,
float f1, float f2, float f3, float f4, float f5, float f6, float f7, float f8, float f9, float maxTelegraphReactDist, float advanceWpRadius, float f3, float alignAngVel, float f5,
float f10, float f11, float f12, float f13, float f14, float f15, float f16, float f17, float f18, float stuckTimeThreshold, float collisionCloseMargin, float parasiteSearchRadius,
bool b1, EWalkerType wType, const CDamageVulnerability& dVuln,const CDamageInfo& parInfo, u16 sfxId1, float parasiteSeparationDist, float parasiteSeparationWeight, float parasiteAlignmentWeight,
u16 sfxId2, u16 sfxId3, CAssetId modelRes, CAssetId skinRes, float f19, const CActorParameters &aParams) float parasiteCohesionWeight, float destinationSeekWeight, float forwardMoveWeight,
float playerSeparationDist, float playerSeparationWeight, float playerObstructionMinDist,
float haltDelay, bool disableMove, EWalkerType wType, const CDamageVulnerability& dVuln,
const CDamageInfo& parInfo, u16 haltSfx, u16 getUpSfx, u16 crouchSfx, CAssetId modelRes,
CAssetId skinRes, float iceZoomerJointHP,
const CActorParameters& aParams)
: CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer, : CWallWalker(ECharacter::Parasite, uid, name, flavor, info, xf, std::move(mData), pInfo, EMovementType::Flyer,
EColliderType::Zero, bodyType, aParams, f7, f4, EKnockBackVariant::Small, f2, wType, f17, b1) EColliderType::Zero, bodyType, aParams, collisionCloseMargin, alignAngVel, EKnockBackVariant::Small,
, x64c_(dVuln) advanceWpRadius, wType, playerObstructionMinDist, disableMove)
, x6b4_(parInfo) , x64c_oculusHaltDVuln(dVuln)
, x6d0_(f1) , x6b4_oculusHaltDInfo(parInfo)
, x6d0_maxTelegraphReactDist(maxTelegraphReactDist)
, x6d4_(f3) , x6d4_(f3)
, x6dc_(f5) , x6dc_(f5)
, x6e0_(f6) , x6e0_stuckTimeThreshold(stuckTimeThreshold)
, x6e4_(f8) , x6e4_parasiteSearchRadius(parasiteSearchRadius)
, x6e8_(f9) , x6e8_parasiteSeparationDist(parasiteSeparationDist)
, x6ec_(f10) , x6ec_parasiteSeparationWeight(parasiteSeparationWeight)
, x6f0_(f11) , x6f0_parasiteAlignmentWeight(parasiteAlignmentWeight)
, x6f4_(f12) , x6f4_parasiteCohesionWeight(parasiteCohesionWeight)
, x6f8_(f13) , x6f8_destinationSeekWeight(destinationSeekWeight)
, x6fc_(f14) , x6fc_forwardMoveWeight(forwardMoveWeight)
, x700_(f15) , x700_playerSeparationDist(playerSeparationDist)
, x704_(f16) , x704_playerSeparationWeight(playerSeparationWeight)
, x708_(pInfo.GetHeight() * 0.5f) , x708_unmorphedRadius(pInfo.GetHeight() * 0.5f)
, x710_(f18) , x710_haltDelay(haltDelay)
, x714_(f19) , x714_iceZoomerJointHP(iceZoomerJointHP)
, x73c_haltSfx(CSfxManager::TranslateSFXID(sfxId1)) , x73c_haltSfx(CSfxManager::TranslateSFXID(haltSfx))
, x73e_getUpSfx(CSfxManager::TranslateSFXID(sfxId2)) , x73e_getUpSfx(CSfxManager::TranslateSFXID(getUpSfx))
, x740_crouchSfx(CSfxManager::TranslateSFXID(sfxId3)) , x740_crouchSfx(CSfxManager::TranslateSFXID(crouchSfx))
{ {
x742_28_onGround = true; x742_28_onGround = true;
x742_30_attackOver = true; x742_30_attackOver = true;
@ -85,33 +93,114 @@ CParasite::CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, c
void CParasite::Accept(IVisitor &visitor) { visitor.Visit(this); } void CParasite::Accept(IVisitor &visitor) { visitor.Visit(this); }
void CParasite::SetupIceZoomerCollision(CStateManager& mgr)
{
std::vector<CJointCollisionDescription> descs;
descs.reserve(2);
descs.push_back(CJointCollisionDescription::SphereCollision(
x64_modelData->GetAnimationData()->GetLocatorSegId("Ice_LCTR"sv), 0.4f, "Ice_LCTR"sv, 0.001f));
RemoveMaterial(EMaterialTypes::Solid, mgr);
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
x620_collisionActorManager =
std::make_unique<CCollisionActorManager>(mgr, GetUniqueId(), GetAreaIdAlways(),
descs, GetActive());
}
void CParasite::SetupIceZoomerVulnerability(CStateManager& mgr, const CDamageVulnerability& dVuln,
const CHealthInfo& hInfo)
{
for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i)
{
const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor> act = mgr.ObjectById(cDesc.GetCollisionActorId()))
{
act->SetDamageVulnerability(dVuln);
*act->HealthInfo(mgr) = hInfo;
}
}
}
void CParasite::AddDoorRepulsors(CStateManager& mgr)
{
u32 doorCount = 0;
for (CEntity* ent : mgr.GetPhysicsActorObjectList())
if (TCastToPtr<CScriptDoor> door = ent)
if (door->GetAreaIdAlways() == GetAreaIdAlways())
++doorCount;
x5d8_doorRepulsors.reserve(doorCount);
for (CEntity* ent : mgr.GetPhysicsActorObjectList())
if (TCastToPtr<CScriptDoor> door = ent)
if (door->GetAreaIdAlways() == GetAreaIdAlways())
{
if (auto tb = door->GetTouchBounds())
{
float diagMag = (tb->min - tb->max).magnitude() * 0.75f;
x5d8_doorRepulsors.emplace_back(tb->center(), diagMag);
}
}
}
static TUniqueId lastParasite = kInvalidUniqueId;
void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) void CParasite::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr)
{ {
CPatterned::AcceptScriptMsg(msg, uid, mgr); CPatterned::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::Registered) switch (msg)
{ {
case EScriptObjectMessage::Registered:
x450_bodyController->Activate(mgr); x450_bodyController->Activate(mgr);
/* TODO: Finish 8015A0E8*/ mgr.GetActiveParasites().push_back(GetUniqueId());
} CActor::CreateShadow(false);
else if (msg == EScriptObjectMessage::Deleted) x604_activeSpeed = x3b4_speed;
{ CPhysicsActor::SetBoundingBox(
//mgr.xf54_.sub80125d88(GetUniqueId()); zeus::CAABox(zeus::CVector3f(-x590_colSphere.GetSphere().radius),
if (x5d0_walkerType != EWalkerType::IceZoomer) zeus::CVector3f(x590_colSphere.GetSphere().radius)));
lastParasite = GetUniqueId();
AddDoorRepulsors(mgr);
if (x5d0_walkerType == EWalkerType::IceZoomer)
{
SetupIceZoomerCollision(mgr);
SetupIceZoomerVulnerability(mgr, x64c_oculusHaltDVuln,
CHealthInfo(x714_iceZoomerJointHP, HealthInfo(mgr)->GetKnockbackResistance()));
}
break;
case EScriptObjectMessage::Deleted:
mgr.GetActiveParasites().remove(GetUniqueId());
if (x5d0_walkerType == EWalkerType::IceZoomer)
DestroyActorManager(mgr); DestroyActorManager(mgr);
} break;
else if (msg == EScriptObjectMessage::Jumped && x742_25_jumpVelDirty) case EScriptObjectMessage::Jumped:
{ if (x742_25_jumpVelDirty)
UpdateJumpVelocity(); {
x742_25_jumpVelDirty = false; UpdateJumpVelocity();
} x742_25_jumpVelDirty = false;
else if (msg == EScriptObjectMessage::Activate) }
{ break;
x5d6_27_ = false; case EScriptObjectMessage::Activate:
if (x5d0_walkerType != EWalkerType::Parasite) x5d6_27_disableMove = false;
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
} break;
else if (msg == EScriptObjectMessage::SuspendedMove) case EScriptObjectMessage::InvulnDamage:
{ if (x5d0_walkerType == EWalkerType::Oculus)
{
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(uid))
{
float distSq = (act->GetTranslation() - GetTranslation()).magSquared();
auto tb = GetTouchBounds();
float maxComp = std::max(std::max(tb->max.y - tb->min.y, tb->max.z - tb->min.z), tb->max.x - tb->min.x);
float maxCompSq = maxComp * maxComp + 1.f;
if (distSq < maxCompSq * maxCompSq)
x743_26_oculusShotAt = true;
}
}
break;
case EScriptObjectMessage::SuspendedMove:
if (x620_collisionActorManager)
x620_collisionActorManager->SetMovable(mgr, false);
break;
default:
break;
} }
} }
@ -121,60 +210,83 @@ void CParasite::PreThink(float dt, CStateManager& mgr)
x743_26_oculusShotAt = false; x743_26_oculusShotAt = false;
} }
void CParasite::UpdateCollisionActors(float dt, CStateManager& mgr)
{
x620_collisionActorManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
if (!x743_25_vulnerable)
{
float totalHP = 0.f;
for (u32 i = 0; i < x620_collisionActorManager->GetNumCollisionActors(); ++i)
{
const CJointCollisionDescription& cDesc = x620_collisionActorManager->GetCollisionDescFromIndex(i);
if (TCastToPtr<CCollisionActor> cact = mgr.ObjectById(cDesc.GetCollisionActorId()))
totalHP += cact->HealthInfo(mgr)->GetHP();
}
if (totalHP <= 0.f)
{
x743_25_vulnerable = true;
AddMaterial(EMaterialTypes::Solid, mgr);
RemoveMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
DestroyActorManager(mgr);
x64_modelData->AnimationData()->SubstituteModelData(x624_extraModel);
}
}
}
void CParasite::Think(float dt, CStateManager& mgr) void CParasite::Think(float dt, CStateManager& mgr)
{ {
if (!GetActive()) if (!GetActive())
return; return;
++x5d4_; ++x5d4_thinkCounter;
if (x5d0_walkerType == EWalkerType::IceZoomer) if (x5d0_walkerType == EWalkerType::IceZoomer)
UpdateCollisionActors(mgr); UpdateCollisionActors(dt, mgr);
x5d6_26_ = false; x5d6_26_playerObstructed = false;
CGameArea* area = mgr.WorldNC()->GetArea(GetAreaIdAlways()); CGameArea* area = mgr.WorldNC()->GetArea(GetAreaIdAlways());
CGameArea::EOcclusionState r6 = CGameArea::EOcclusionState::Occluded; CGameArea::EOcclusionState r6 = CGameArea::EOcclusionState::Occluded;
if (area->IsPostConstructed()) if (area->IsPostConstructed())
r6 = area->GetPostConstructed()->x10dc_occlusionState; r6 = area->GetPostConstructed()->x10dc_occlusionState;
if (r6 != CGameArea::EOcclusionState::Visible) if (r6 != CGameArea::EOcclusionState::Visible)
x5d6_26_ = true; x5d6_26_playerObstructed = true;
if (!x5d6_26_) if (!x5d6_26_playerObstructed)
{ {
zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation(); zeus::CVector3f plVec = mgr.GetPlayer().GetTranslation();
float distance = (GetTranslation() - plVec).magnitude() ; float distance = (GetTranslation() - plVec).magnitude() ;
if (distance > x5c4_) if (distance > x5c4_playerObstructionMinDist)
{ {
CRayCastResult res = mgr.RayStaticIntersection(plVec, (GetTranslation() - plVec).normalized(), distance, CRayCastResult res = mgr.RayStaticIntersection(plVec, (GetTranslation() - plVec).normalized(), distance,
CMaterialFilter::skPassEverything); CMaterialFilter::skPassEverything);
if (res.IsValid()) if (res.IsValid())
x5d6_26_ = true; x5d6_26_playerObstructed = true;
} }
} }
if (x5d6_26_) if (x5d6_26_playerObstructed)
{ {
xf8_24_movable = x5d6_26_; xf8_24_movable = x5d6_26_playerObstructed;
return; return;
} }
xf8_24_movable = !xf8_24_movable; xf8_24_movable = !xf8_24_movable;
if (!x5d6_27_) if (!x5d6_27_disableMove)
{ {
if (x450_bodyController->IsFrozen()) if (x450_bodyController->IsFrozen())
{ {
if ((GetTranslation() - x614_).magSquared() < 0.3f /* <- Used to be a static variable */ * dt) if ((GetTranslation() - x614_lastStuckPos).magSquared() < 0.3f /* <- Used to be a static variable */ * dt)
x60c_ += dt; x60c_stuckTime += dt;
else else
x60c_ = 0.f; x60c_stuckTime = 0.f;
x614_ = GetTranslation(); x614_lastStuckPos = GetTranslation();
if (x608_ > 0.f) if (x608_telegraphRemTime > 0.f)
x608_ -= dt; x608_telegraphRemTime -= dt;
else else
x608_ = 0.f; x608_telegraphRemTime = 0.f;
} }
} }
@ -185,7 +297,7 @@ void CParasite::Think(float dt, CStateManager& mgr)
if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver) if (pl->GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed && !x742_30_attackOver)
radius = x590_colSphere.GetSphere().radius; radius = x590_colSphere.GetSphere().radius;
else else
radius = x708_; radius = x708_unmorphedRadius;
zeus::CAABox aabox{GetTranslation() - radius, GetTranslation() + radius}; zeus::CAABox aabox{GetTranslation() - radius, GetTranslation() + radius};
auto plBox = pl->GetTouchBounds(); auto plBox = pl->GetTouchBounds();
@ -209,14 +321,14 @@ void CParasite::Think(float dt, CStateManager& mgr)
CWallWalker::Think(dt, mgr); CWallWalker::Think(dt, mgr);
if (x5d6_27_) if (x5d6_27_disableMove)
return; return;
if (x450_bodyController->IsFrozen()) if (x450_bodyController->IsFrozen())
return; return;
x3b4_speed = x604_; x3b4_speed = x604_activeSpeed;
if (x5d6_24_) if (x5d6_24_alignToFloor)
AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt); AlignToFloor(mgr, x590_colSphere.GetSphere().radius, GetTranslation() + 2.f * dt * x138_velocity, dt);
x742_27_landed = false; x742_27_landed = false;
@ -232,11 +344,11 @@ const CDamageVulnerability* CParasite::GetDamageVulnerability() const
switch (x5d0_walkerType) switch (x5d0_walkerType)
{ {
case EWalkerType::Oculus: case EWalkerType::Oculus:
if (x743_24_) if (x743_24_halted)
return &x64c_; return &x64c_oculusHaltDVuln;
break; break;
case EWalkerType::IceZoomer: case EWalkerType::IceZoomer:
if (!x743_25_) if (!x743_25_vulnerable)
return &CDamageVulnerability::ImmuneVulnerabilty(); return &CDamageVulnerability::ImmuneVulnerabilty();
break; break;
default: default:
@ -245,6 +357,13 @@ const CDamageVulnerability* CParasite::GetDamageVulnerability() const
return CAi::GetDamageVulnerability(); return CAi::GetDamageVulnerability();
} }
CDamageInfo CParasite::GetContactDamage() const
{
if (x5d0_walkerType == EWalkerType::Oculus && x743_24_halted)
return x6b4_oculusHaltDInfo;
return CPatterned::GetContactDamage();
}
void CParasite::Touch(CActor& actor, CStateManager& mgr) void CParasite::Touch(CActor& actor, CStateManager& mgr)
{ {
CPatterned::Touch(actor, mgr); CPatterned::Touch(actor, mgr);
@ -262,7 +381,7 @@ void CParasite::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CSta
{ {
for (const auto& info : list) for (const auto& info : list)
{ {
if (!x5d6_24_ && info.GetMaterialLeft().Intersection(testList) == 0) if (!x5d6_24_alignToFloor && info.GetMaterialLeft().Intersection(testList) == 0)
{ {
OrientToSurfaceNormal(info.GetNormalLeft(), 360.f); OrientToSurfaceNormal(info.GetNormalLeft(), 360.f);
CPhysicsActor::Stop(); CPhysicsActor::Stop();
@ -288,30 +407,30 @@ void CParasite::Patrol(CStateManager& mgr, EStateMsg msg, float dt)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x742_26_ = true; x742_26_ = true;
x5d6_24_ = true; x5d6_24_alignToFloor = true;
if (!x5d6_27_ && x5d0_walkerType == EWalkerType::Parasite) if (!x5d6_27_disableMove && x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
SetMomentumWR(zeus::CVector3f::skZero); SetMomentumWR(zeus::CVector3f::skZero);
x5d6_25_ = false; x5d6_25_hasAlignSurface = false;
xf8_24_movable = false; xf8_24_movable = false;
break; break;
case EStateMsg::Update: case EStateMsg::Update:
if (x5bc_ > 0.f) if (x5bc_patrolPauseRemTime > 0.f)
{ {
x5bc_ -= dt; x5bc_patrolPauseRemTime -= dt;
if (x5bc_ <= 0.f) if (x5bc_patrolPauseRemTime <= 0.f)
{ {
if (x5d0_walkerType == EWalkerType::Parasite) if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
x5bc_ = 0.f; x5bc_patrolPauseRemTime = 0.f;
} }
} }
GotoNextWaypoint(mgr); GotoNextWaypoint(mgr);
if (x5bc_ <= 0.f && !x5d6_27_) if (x5bc_patrolPauseRemTime <= 0.f && !x5d6_27_disableMove)
DoFlockingBehavior(mgr); DoFlockingBehavior(mgr);
break; break;
case EStateMsg::Deactivate: case EStateMsg::Deactivate:
x5d6_24_ = false; x5d6_24_alignToFloor = false;
xf8_24_movable = true; xf8_24_movable = true;
break; break;
default: default:
@ -328,13 +447,14 @@ void CParasite::DoFlockingBehavior(CStateManager& mgr)
{ {
zeus::CVector3f upVec = x34_transform.basis[2]; zeus::CVector3f upVec = x34_transform.basis[2];
rstl::reserved_vector<TUniqueId, 1024> _834; rstl::reserved_vector<TUniqueId, 1024> _834;
zeus::CAABox aabb(GetTranslation() - x6e4_, GetTranslation() + x6e4_); zeus::CAABox aabb(GetTranslation() - x6e4_parasiteSearchRadius,
if (x5d4_ % 6 == 0) GetTranslation() + x6e4_parasiteSearchRadius);
if ((x5d4_thinkCounter % 6) == 0)
{ {
rstl::reserved_vector<TUniqueId, 1024> nearList; rstl::reserved_vector<TUniqueId, 1024> nearList;
static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character); static CMaterialFilter filter = CMaterialFilter::MakeInclude(EMaterialTypes::Character);
CParasite* closestParasite = nullptr; CParasite* closestParasite = nullptr;
float minDistSq = 2.f + x6e8_ * x6e8_; float minDistSq = 2.f + x6e8_parasiteSeparationDist * x6e8_parasiteSeparationDist;
mgr.BuildNearList(nearList, aabb, filter, nullptr); mgr.BuildNearList(nearList, aabb, filter, nullptr);
for (TUniqueId id : nearList) for (TUniqueId id : nearList)
{ {
@ -352,25 +472,28 @@ void CParasite::DoFlockingBehavior(CStateManager& mgr)
} }
} }
} }
if (closestParasite && x6ec_ > 0.f && x6e8_ > 0.f) if (closestParasite && x6ec_parasiteSeparationWeight > 0.f && x6e8_parasiteSeparationDist > 0.f)
x628_ = x45c_steeringBehaviors.Separation(*this, closestParasite->GetTranslation(), x6e8_) * x604_; x628_parasiteSeparationMove = x45c_steeringBehaviors.Separation(*this, closestParasite->GetTranslation(),
x6e8_parasiteSeparationDist) * x604_activeSpeed;
else else
x628_ = zeus::CVector3f::skZero; x628_parasiteSeparationMove = zeus::CVector3f::skZero;
x634_ = x45c_steeringBehaviors.Cohesion(*this, _834, 0.6f, mgr) * x604_; x634_parasiteCohesionMove = x45c_steeringBehaviors.Cohesion(*this, _834, 0.6f, mgr) * x604_activeSpeed;
x640_ = x45c_steeringBehaviors.Alignment(*this, _834, mgr) * x604_; x640_parasiteAlignmentMove = x45c_steeringBehaviors.Alignment(*this, _834, mgr) * x604_activeSpeed;
} }
if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() < x700_ * x700_) if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() <
x700_playerSeparationDist * x700_playerSeparationDist)
{ {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x45c_steeringBehaviors.Separation(*this, mgr.GetPlayer().GetTranslation(), x700_), upVec) * x604_, x45c_steeringBehaviors.Separation(*this, mgr.GetPlayer().GetTranslation(),
zeus::CVector3f::skZero, x704_)); x700_playerSeparationDist), upVec) * x604_activeSpeed,
zeus::CVector3f::skZero, x704_playerSeparationWeight));
} }
if (x628_ != zeus::CVector3f::skZero) if (x628_parasiteSeparationMove != zeus::CVector3f::skZero)
{ {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x628_, upVec), zeus::CVector3f::skZero, x6ec_)); x628_parasiteSeparationMove, upVec), zeus::CVector3f::skZero, x6ec_parasiteSeparationWeight));
} }
for (const auto& r : x5d8_doorRepulsors) for (const auto& r : x5d8_doorRepulsors)
@ -378,23 +501,23 @@ void CParasite::DoFlockingBehavior(CStateManager& mgr)
if ((r.GetVector() - GetTranslation()).magSquared() < r.GetFloat() * r.GetFloat()) if ((r.GetVector() - GetTranslation()).magSquared() < r.GetFloat() * r.GetFloat())
{ {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x45c_steeringBehaviors.Separation(*this, r.GetVector(), r.GetFloat()) * x604_, upVec), x45c_steeringBehaviors.Separation(*this, r.GetVector(), r.GetFloat()) * x604_activeSpeed, upVec),
zeus::CVector3f::skZero, 1.f)); zeus::CVector3f::skZero, 1.f));
} }
} }
if (x608_ <= 0.f) if (x608_telegraphRemTime <= 0.f)
{ {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x634_, upVec), zeus::CVector3f::skZero, x6f4_)); x634_parasiteCohesionMove, upVec), zeus::CVector3f::skZero, x6f4_parasiteCohesionWeight));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(ProjectVectorToPlane(
x640_, upVec), zeus::CVector3f::skZero, x6f0_)); x640_parasiteAlignmentMove, upVec), zeus::CVector3f::skZero, x6f0_parasiteAlignmentWeight));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(
ProjectVectorToPlane(ProjectVectorToPlane( ProjectVectorToPlane(ProjectVectorToPlane(
x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec) * x604_, upVec), x45c_steeringBehaviors.Seek(*this, x2e0_destPos), upVec) * x604_activeSpeed, upVec),
zeus::CVector3f::skZero, x6f8_)); zeus::CVector3f::skZero, x6f8_destinationSeekWeight));
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(
x34_transform.basis[1] * x604_, zeus::CVector3f::skZero, x6fc_)); x34_transform.basis[1] * x604_activeSpeed, zeus::CVector3f::skZero, x6fc_forwardMoveWeight));
} }
} }
@ -404,7 +527,7 @@ void CParasite::PathFind(CStateManager& mgr, EStateMsg msg, float dt)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x742_26_ = true; x742_26_ = true;
x5d6_24_ = true; x5d6_24_alignToFloor = true;
if (x5d0_walkerType == EWalkerType::Parasite) if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
SetMomentumWR(zeus::CVector3f::skZero); SetMomentumWR(zeus::CVector3f::skZero);
@ -416,7 +539,7 @@ void CParasite::PathFind(CStateManager& mgr, EStateMsg msg, float dt)
break; break;
case EStateMsg::Deactivate: case EStateMsg::Deactivate:
xf8_24_movable = true; xf8_24_movable = true;
x5d6_24_ = false; x5d6_24_alignToFloor = false;
x742_26_ = false; x742_26_ = false;
break; break;
default: default:
@ -429,11 +552,11 @@ void CParasite::TargetPlayer(CStateManager& mgr, EStateMsg msg, float dt)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x5f8_ = mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.5f); x5f8_targetPos = mgr.GetPlayer().GetTranslation() + zeus::CVector3f(0.f, 0.f, 1.5f);
break; break;
case EStateMsg::Update: case EStateMsg::Update:
x450_bodyController->FaceDirection3D( x450_bodyController->FaceDirection3D(
ProjectVectorToPlane(x5f8_ - GetTranslation(), x34_transform.basis[2]), ProjectVectorToPlane(x5f8_targetPos - GetTranslation(), x34_transform.basis[2]),
x34_transform.basis[1], 2.f); x34_transform.basis[1], 2.f);
break; break;
default: default:
@ -513,10 +636,10 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x330_stateMachineState.SetDelay(x710_); x330_stateMachineState.SetDelay(x710_haltDelay);
x32c_animState = EAnimState::One; x32c_animState = EAnimState::One;
x743_24_ = true; x743_24_halted = true;
x5d6_24_ = true; x5d6_24_alignToFloor = true;
if (x5d0_walkerType == EWalkerType::Geemer) if (x5d0_walkerType == EWalkerType::Geemer)
CSfxManager::AddEmitter(x73c_haltSfx, GetTranslation(), zeus::CVector3f::skZero, CSfxManager::AddEmitter(x73c_haltSfx, GetTranslation(), zeus::CVector3f::skZero,
true, false, 0x7f, kInvalidAreaId); true, false, 0x7f, kInvalidAreaId);
@ -528,8 +651,8 @@ void CParasite::Halt(CStateManager& mgr, EStateMsg msg, float)
case EStateMsg::Deactivate: case EStateMsg::Deactivate:
x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState)); x450_bodyController->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::ExitState));
x32c_animState = EAnimState::Zero; x32c_animState = EAnimState::Zero;
x743_24_ = false; x743_24_halted = false;
x5d6_24_ = false; x5d6_24_alignToFloor = false;
break; break;
default: default:
break; break;
@ -546,20 +669,20 @@ void CParasite::Generate(CStateManager&, EStateMsg msg, float)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x5e8_ = 0; x5e8_stateProgress = 0;
break; break;
case EStateMsg::Update: case EStateMsg::Update:
switch (x5e8_) switch (x5e8_stateProgress)
{ {
case 0: case 0:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 1; x5e8_stateProgress = 1;
else else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero));
break; break;
case 1: case 1:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 2; x5e8_stateProgress = 2;
break; break;
default: default:
break; break;
@ -575,15 +698,15 @@ void CParasite::Deactivate(CStateManager& mgr, EStateMsg msg, float)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x5e8_ = 0; x5e8_stateProgress = 0;
SendScriptMsgs(EScriptObjectState::UNKS2, mgr, EScriptObjectMessage::None); SendScriptMsgs(EScriptObjectState::DeactivateState, mgr, EScriptObjectMessage::None);
mgr.FreeScriptObject(GetUniqueId()); mgr.FreeScriptObject(GetUniqueId());
break; break;
case EStateMsg::Update: case EStateMsg::Update:
if (x5e8_ == 0) if (x5e8_stateProgress == 0)
{ {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate)
x5e8_ = 1; x5e8_stateProgress = 1;
else else
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::One));
} }
@ -598,41 +721,41 @@ void CParasite::Attack(CStateManager& mgr, EStateMsg msg, float)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
x608_ = 0.f; x608_telegraphRemTime = 0.f;
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed)
{ {
float rz = mgr.GetActiveRandom()->Float(); float rz = mgr.GetActiveRandom()->Float();
float ry = mgr.GetActiveRandom()->Float(); float ry = mgr.GetActiveRandom()->Float();
float rx = mgr.GetActiveRandom()->Float(); float rx = mgr.GetActiveRandom()->Float();
x5f8_ = (zeus::CVector3f(rx, ry, rz) - 0.5f) * 0.5f + mgr.GetPlayer().GetTranslation(); x5f8_targetPos = (zeus::CVector3f(rx, ry, rz) - 0.5f) * 0.5f + mgr.GetPlayer().GetTranslation();
} }
else else
{ {
float rz = mgr.GetActiveRandom()->Float(); float rz = mgr.GetActiveRandom()->Float();
float ry = mgr.GetActiveRandom()->Float(); float ry = mgr.GetActiveRandom()->Float();
float rx = mgr.GetActiveRandom()->Float(); float rx = mgr.GetActiveRandom()->Float();
x5f8_ = (zeus::CVector3f(rx, ry, rz) + mgr.GetPlayer().GetTranslation() - GetTranslation()) x5f8_targetPos = (zeus::CVector3f(rx, ry, rz) + mgr.GetPlayer().GetTranslation() - GetTranslation())
.normalized() * 15.f + GetTranslation(); .normalized() * 15.f + GetTranslation();
} }
FaceTarget(x5f8_); FaceTarget(x5f8_targetPos);
x5e8_ = 0; x5e8_stateProgress = 0;
x742_30_attackOver = false; x742_30_attackOver = false;
x742_24_ = false; x742_24_receivedTelegraph = false;
x742_28_onGround = false; x742_28_onGround = false;
break; break;
case EStateMsg::Update: case EStateMsg::Update:
switch (x5e8_) switch (x5e8_stateProgress)
{ {
case 0: case 0:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump) if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Jump)
{ {
x5e8_ = 1; x5e8_stateProgress = 1;
} }
else else
{ {
x742_25_jumpVelDirty = true; x742_25_jumpVelDirty = true;
FaceTarget(x5f8_); FaceTarget(x5f8_targetPos);
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_, pas::EJumpType::Normal)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::Normal));
} }
break; break;
default: default:
@ -675,20 +798,21 @@ void CParasite::TelegraphAttack(CStateManager& mgr, EStateMsg msg, float)
switch (msg) switch (msg)
{ {
case EStateMsg::Activate: case EStateMsg::Activate:
for (auto it = mgr.GetParasiteTelegraphs().begin(); it != mgr.GetParasiteTelegraphs().end();) for (auto it = mgr.GetActiveParasites().begin(); it != mgr.GetActiveParasites().end();)
{ {
CParasite* other = CPatterned::CastTo<CParasite>(mgr.ObjectById(*it)); CParasite* other = CPatterned::CastTo<CParasite>(mgr.ObjectById(*it));
if (!other) if (!other)
{ {
it = mgr.GetParasiteTelegraphs().erase(it); it = mgr.GetActiveParasites().erase(it);
continue; continue;
} }
if (other != this && other->IsAlive() && if (other != this && other->IsAlive() &&
(other->GetTranslation() - GetTranslation()).magSquared() < x6d0_ * x6d0_) (other->GetTranslation() - GetTranslation()).magSquared() <
x6d0_maxTelegraphReactDist * x6d0_maxTelegraphReactDist)
{ {
other->x742_24_ = true; other->x742_24_receivedTelegraph = true;
other->x608_ = mgr.GetActiveRandom()->Float() * 0.5f + 0.5f; other->x608_telegraphRemTime = mgr.GetActiveRandom()->Float() * 0.5f + 0.5f;
other->x5f8_ = GetTranslation(); other->x5f8_targetPos = GetTranslation();
} }
++it; ++it;
} }
@ -707,7 +831,7 @@ void CParasite::Jump(CStateManager& mgr, EStateMsg msg, float)
AddMaterial(EMaterialTypes::GroundCollider, mgr); AddMaterial(EMaterialTypes::GroundCollider, mgr);
SetMomentumWR({0.f, 0.f, -GetWeight()}); SetMomentumWR({0.f, 0.f, -GetWeight()});
x742_28_onGround = false; x742_28_onGround = false;
x5d6_24_ = false; x5d6_24_alignToFloor = false;
x742_27_landed = false; x742_27_landed = false;
x743_27_inJump = true; x743_27_inJump = true;
break; break;
@ -744,13 +868,13 @@ void CParasite::Retreat(CStateManager& mgr, EStateMsg msg, float)
dir.normalize(); dir.normalize();
else else
dir = mgr.GetPlayer().GetTransform().basis[1]; dir = mgr.GetPlayer().GetTransform().basis[1];
x5f8_ = GetTranslation() - dir * 3.f; x5f8_targetPos = GetTranslation() - dir * 3.f;
FaceTarget(x5f8_); FaceTarget(x5f8_targetPos);
x5e8_ = 0; x5e8_stateProgress = 0;
x742_27_landed = false; x742_27_landed = false;
x742_28_onGround = false; x742_28_onGround = false;
x742_25_jumpVelDirty = true; x742_25_jumpVelDirty = true;
x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_, pas::EJumpType::One)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCJumpCmd(x5f8_targetPos, pas::EJumpType::One));
break; break;
} }
case EStateMsg::Update: case EStateMsg::Update:
@ -764,13 +888,13 @@ void CParasite::Retreat(CStateManager& mgr, EStateMsg msg, float)
bool CParasite::AnimOver(CStateManager&, float) bool CParasite::AnimOver(CStateManager&, float)
{ {
return x5e8_ == 2; return x5e8_stateProgress == 2;
} }
bool CParasite::ShouldAttack(CStateManager& mgr, float arg) bool CParasite::ShouldAttack(CStateManager& mgr, float arg)
{ {
bool shouldAttack = false; bool shouldAttack = false;
if (x742_24_ && x608_ > 0.1f) if (x742_24_receivedTelegraph && x608_telegraphRemTime > 0.1f)
shouldAttack = true; shouldAttack = true;
if (!TooClose(mgr, arg) && InMaxRange(mgr, arg)) if (!TooClose(mgr, arg) && InMaxRange(mgr, arg))
return shouldAttack || InDetectionRange(mgr, 0.f); return shouldAttack || InDetectionRange(mgr, 0.f);
@ -790,14 +914,14 @@ bool CParasite::CloseToWall(CStateManager& mgr)
bool CParasite::HitSomething(CStateManager& mgr, float) bool CParasite::HitSomething(CStateManager& mgr, float)
{ {
if (x5d4_ & 0x1) if (x5d4_thinkCounter & 0x1)
return true; return true;
return x5b8_ < 270.f && CloseToWall(mgr); return x5b8_tumbleAngle < 270.f && CloseToWall(mgr);
} }
bool CParasite::Stuck(CStateManager&, float) bool CParasite::Stuck(CStateManager&, float)
{ {
return x60c_ > x6e0_; return x60c_stuckTime > x6e0_stuckTimeThreshold;
} }
bool CParasite::Landed(CStateManager&, float) bool CParasite::Landed(CStateManager&, float)
@ -845,7 +969,7 @@ void CParasite::UpdateWalkerAnimation(CStateManager& mgr, float dt)
void CParasite::DestroyActorManager(CStateManager& mgr) void CParasite::DestroyActorManager(CStateManager& mgr)
{ {
//x620_->Destroy(mgr); x620_collisionActorManager->Destroy(mgr);
} }
void CParasite::UpdateJumpVelocity() void CParasite::UpdateJumpVelocity()
@ -865,8 +989,8 @@ void CParasite::UpdateJumpVelocity()
} }
float f30 = x150_momentum.z / xe8_mass; float f30 = x150_momentum.z / xe8_mass;
float f31 = x5f8_.z - GetTranslation().z; float f31 = x5f8_targetPos.z - GetTranslation().z;
zeus::CVector3f vec2 = x5f8_ - GetTranslation(); zeus::CVector3f vec2 = x5f8_targetPos - GetTranslation();
vec2.z = 0.f; vec2.z = 0.f;
float f29 = vec2.magnitude(); float f29 = vec2.magnitude();
@ -895,8 +1019,4 @@ void CParasite::UpdateJumpVelocity()
SetVelocityWR(vec); SetVelocityWR(vec);
} }
void CParasite::AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float)
{
}
} // namespace urde::MP1 } // namespace urde::MP1

View File

@ -26,38 +26,36 @@ class CParasite : public CWallWalker
static const float flt_805A8FB8; static const float flt_805A8FB8;
static const float skRetreatVelocity; static const float skRetreatVelocity;
std::vector<CRepulsor> x5d8_doorRepulsors; std::vector<CRepulsor> x5d8_doorRepulsors;
s32 x5e8_ = -1; s32 x5e8_stateProgress = -1;
float x5ec_ = 0.f; zeus::CVector3f x5ec_;
float x5f0_ = 0.f; zeus::CVector3f x5f8_targetPos;
float x5f4_ = 0.f; float x604_activeSpeed = 1.f;
zeus::CVector3f x5f8_; float x608_telegraphRemTime = 0.f;
float x604_ = 1.f; float x60c_stuckTime = 0.f;
float x608_ = 0.f; zeus::CVector3f x614_lastStuckPos;
float x60c_ = 0.f; std::unique_ptr<CCollisionActorManager> x620_collisionActorManager;
zeus::CVector3f x614_;
std::unique_ptr<CCollisionActorManager> x620_ = 0;
TLockedToken<CSkinnedModel> x624_extraModel; TLockedToken<CSkinnedModel> x624_extraModel;
zeus::CVector3f x628_; zeus::CVector3f x628_parasiteSeparationMove;
zeus::CVector3f x634_; zeus::CVector3f x634_parasiteCohesionMove;
zeus::CVector3f x640_; zeus::CVector3f x640_parasiteAlignmentMove;
CDamageVulnerability x64c_; CDamageVulnerability x64c_oculusHaltDVuln;
CDamageInfo x6b4_; CDamageInfo x6b4_oculusHaltDInfo;
float x6d0_; float x6d0_maxTelegraphReactDist;
float x6d4_; float x6d4_;
float x6dc_; float x6dc_;
float x6e0_; float x6e0_stuckTimeThreshold;
float x6e4_; float x6e4_parasiteSearchRadius;
float x6e8_; float x6e8_parasiteSeparationDist;
float x6ec_; float x6ec_parasiteSeparationWeight;
float x6f0_; float x6f0_parasiteAlignmentWeight;
float x6f4_; float x6f4_parasiteCohesionWeight;
float x6f8_; float x6f8_destinationSeekWeight;
float x6fc_; float x6fc_forwardMoveWeight;
float x700_; float x700_playerSeparationDist;
float x704_; float x704_playerSeparationWeight;
float x708_; float x708_unmorphedRadius;
float x710_; float x710_haltDelay;
float x714_; float x714_iceZoomerJointHP;
float x718_ = 0.f; float x718_ = 0.f;
float x71c_ = 0.f; float x71c_ = 0.f;
float x720_ = 0.f; float x720_ = 0.f;
@ -74,7 +72,7 @@ class CParasite : public CWallWalker
{ {
struct struct
{ {
bool x742_24_ : 1; bool x742_24_receivedTelegraph : 1;
bool x742_25_jumpVelDirty : 1; bool x742_25_jumpVelDirty : 1;
bool x742_26_ : 1; bool x742_26_ : 1;
bool x742_27_landed : 1; bool x742_27_landed : 1;
@ -82,8 +80,8 @@ class CParasite : public CWallWalker
bool x742_29_ : 1; bool x742_29_ : 1;
bool x742_30_attackOver : 1; bool x742_30_attackOver : 1;
bool x742_31_ : 1; bool x742_31_ : 1;
bool x743_24_ : 1; bool x743_24_halted : 1;
bool x743_25_ : 1; bool x743_25_vulnerable : 1;
bool x743_26_oculusShotAt : 1; bool x743_26_oculusShotAt : 1;
bool x743_27_inJump : 1; bool x743_27_inJump : 1;
}; };
@ -95,13 +93,26 @@ class CParasite : public CWallWalker
TUniqueId GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr); TUniqueId GetClosestWaypointForState(EScriptObjectState state, CStateManager& mgr);
void UpdatePFDestination(CStateManager& mgr); void UpdatePFDestination(CStateManager& mgr);
void DoFlockingBehavior(CStateManager& mgr); void DoFlockingBehavior(CStateManager& mgr);
void SetupIceZoomerCollision(CStateManager& mgr);
void SetupIceZoomerVulnerability(CStateManager& mgr, const CDamageVulnerability& dVuln,
const CHealthInfo& hInfo);
void AddDoorRepulsors(CStateManager& mgr);
void UpdateCollisionActors(float dt, CStateManager& mgr);
void DestroyActorManager(CStateManager& mgr);
void UpdateJumpVelocity();
public: public:
DEFINE_PATTERNED(Parasite) DEFINE_PATTERNED(Parasite)
CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, CParasite(TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo &info,
const zeus::CTransform& xf, CModelData&& mData, const CPatternedInfo&, EBodyType, float, float, float, const zeus::CTransform &xf, CModelData &&mData, const CPatternedInfo &pInfo, EBodyType bodyType,
float, float, float, float, float, float, float, float, float, float, float, float, float, float, float, float maxTelegraphReactDist, float advanceWpRadius, float f3, float alignAngVel, float f5,
bool, EWalkerType wType, const CDamageVulnerability&, const CDamageInfo&, u16, u16, u16, CAssetId, CAssetId, float, float stuckTimeThreshold, float collisionCloseMargin, float parasiteSearchRadius,
const CActorParameters&); float parasiteSeparationDist, float parasiteSeparationWeight, float parasiteAlignmentWeight,
float parasiteCohesionWeight, float destinationSeekWeight, float forwardMoveWeight,
float playerSeparationDist, float playerSeparationWeight, float playerObstructionMinDist,
float haltDelay, bool disableMove, EWalkerType wType, const CDamageVulnerability& dVuln,
const CDamageInfo& parInfo, u16 haltSfx, u16 getUpSfx, u16 crouchSfx, CAssetId modelRes,
CAssetId skinRes, float iceZoomerJointHP,
const CActorParameters& aParams);
void Accept(IVisitor&); void Accept(IVisitor&);
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&);
@ -109,6 +120,7 @@ public:
void Think(float dt, CStateManager& mgr); void Think(float dt, CStateManager& mgr);
void Render(const CStateManager&) const; void Render(const CStateManager&) const;
const CDamageVulnerability* GetDamageVulnerability() const; const CDamageVulnerability* GetDamageVulnerability() const;
CDamageInfo GetContactDamage() const;
void Touch(CActor& actor, CStateManager&); void Touch(CActor& actor, CStateManager&);
zeus::CVector3f GetAimPosition(const CStateManager&, float) const; zeus::CVector3f GetAimPosition(const CStateManager&, float) const;
void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&); void CollidedWith(TUniqueId uid, const CCollisionInfoList&, CStateManager&);
@ -139,16 +151,5 @@ public:
void ThinkAboutMove(float); void ThinkAboutMove(float);
bool IsOnGround() const; bool IsOnGround() const;
virtual void UpdateWalkerAnimation(CStateManager&, float); virtual void UpdateWalkerAnimation(CStateManager&, float);
void DestroyActorManager(CStateManager& mgr);
void UpdateJumpVelocity();
void UpdateCollisionActors(CStateManager&) {}
CDamageInfo GetContactDamage() const
{
if (x5d0_walkerType == EWalkerType::Oculus && x743_24_)
return x6b4_;
return CPatterned::GetContactDamage();
}
void AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float);
}; };
} }

View File

@ -485,7 +485,7 @@ void CScriptGunTurret::UpdateGunCollisionManager(float dt, CStateManager& mgr)
if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x4a0_)) if (TCastToPtr<CCollisionActor> colAct = mgr.ObjectById(x4a0_))
colAct->SetActive(mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed); colAct->SetActive(mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed);
x49c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::Zero); x49c_collisionManager->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
} }
void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr) void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr)

View File

@ -3,6 +3,8 @@
#include "CStateManager.hpp" #include "CStateManager.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
#include "CScriptWaypoint.hpp" #include "CScriptWaypoint.hpp"
#include "Collision/CMetroidAreaCollider.hpp"
#include "Collision/CGameCollision.hpp"
namespace urde namespace urde
{ {
@ -10,19 +12,20 @@ CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, E
const CEntityInfo& eInfo, const zeus::CTransform& xf, const CEntityInfo& eInfo, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType, CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType,
EColliderType colType, EBodyType bType, const CActorParameters& aParms, EColliderType colType, EBodyType bType, const CActorParameters& aParms,
float f1, float f2, EKnockBackVariant kbVariant, float f3, EWalkerType wType, float f4, bool b1) float collisionCloseMargin, float alignAngVel, EKnockBackVariant kbVariant,
float advanceWpRadius, EWalkerType wType, float playerObstructionMinDist, bool disableMove)
: CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, kbVariant) : CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, kbVariant)
, x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material) , x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material)
, x5b0_collisionCloseMargin(f1) , x5b0_collisionCloseMargin(collisionCloseMargin)
, x5b4_(f2) , x5b4_alignAngVel(alignAngVel)
, x5c0_advanceWpRadius(f3) , x5c0_advanceWpRadius(advanceWpRadius)
, x5c4_(f4) , x5c4_playerObstructionMinDist(playerObstructionMinDist)
, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv)) , x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv))
, x5d0_walkerType(wType) , x5d0_walkerType(wType)
, x5d6_24_(false) , x5d6_24_alignToFloor(false)
, x5d6_25_(false) , x5d6_25_hasAlignSurface(false)
, x5d6_26_(false) , x5d6_26_playerObstructed(false)
, x5d6_27_(b1) , x5d6_27_disableMove(disableMove)
, x5d6_28_addBendingWeight(true) , x5d6_28_addBendingWeight(true)
, x5d6_29_applyBendingHack(false) , x5d6_29_applyBendingHack(false)
{ {
@ -39,6 +42,74 @@ void CWallWalker::OrientToSurfaceNormal(const zeus::CVector3f& normal, float cla
SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation())); SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation()));
} }
bool CWallWalker::PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point)
{
zeus::CVector3f normal = surf.GetNormal();
zeus::CVector3f projPt = ProjectPointToPlane(point, surf.GetVert(0), normal);
for (int i = 0; i < 3; ++i)
{
zeus::CVector3f projDelta = projPt - surf.GetVert(i);
zeus::CVector3f edge = surf.GetVert((i + 2) % 3) - surf.GetVert(i);
if (projDelta.cross(edge).dot(normal) < 0.f)
return false;
}
return true;
}
void CWallWalker::AlignToFloor(CStateManager& mgr, float radius, const zeus::CVector3f& newPos, float dt)
{
bool hasSurface = false;
float margin = radius + x5b0_collisionCloseMargin;
zeus::CAABox aabb(newPos - margin, newPos + margin);
CAreaCollisionCache ccache(aabb);
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
if (x5d6_25_hasAlignSurface)
x5d6_25_hasAlignSurface = PointOnSurface(x568_alignNormal, newPos);
if (!x5d6_25_hasAlignSurface || !(x5d4_thinkCounter & 0x3))
{
for (auto& leaf : ccache)
{
for (auto& node : leaf)
{
CAreaOctTree::TriListReference triArr = node.GetTriangleArray();
for (u16 i = 0; i < triArr.GetSize(); ++i)
{
u16 triIdx = triArr.GetAt(i);
CCollisionSurface surf = leaf.GetOctTree().GetMasterListTriangle(triIdx);
if (std::fabs(surf.GetPlane().pointToPlaneDist(newPos)) < margin &&
PointOnSurface(surf, newPos))
{
x568_alignNormal = surf;
hasSurface = true;
}
}
}
}
x5d6_25_hasAlignSurface = hasSurface;
}
if (x5d6_25_hasAlignSurface)
{
OrientToSurfaceNormal(x568_alignNormal.GetNormal(), x5b4_alignAngVel * dt);
x5b8_tumbleAngle = 0.f;
x5d6_28_addBendingWeight = false;
}
else
{
float angDelta = zeus::radToDeg(x138_velocity.magnitude()) / x590_colSphere.GetSphere().radius * dt;
OrientToSurfaceNormal(x34_transform.basis[1], angDelta);
if (x450_bodyController->HasBodyState(pas::EAnimationState::Step))
{
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Down, pas::EStepType::Normal));
}
else
{
x5d6_28_addBendingWeight = true;
}
x5b8_tumbleAngle += angDelta;
}
}
void CWallWalker::GotoNextWaypoint(CStateManager& mgr) void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
{ {
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj)) if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj))
@ -49,7 +120,7 @@ void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
x2dc_destObj = wp->NextWaypoint(mgr); x2dc_destObj = wp->NextWaypoint(mgr);
if (!zeus::close_enough(wp->GetPause(), 0.f)) if (!zeus::close_enough(wp->GetPause(), 0.f))
{ {
x5bc_ = wp->GetPause(); x5bc_patrolPauseRemTime = wp->GetPause();
if (x5d0_walkerType == EWalkerType::Parasite) if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
} }
@ -62,16 +133,17 @@ void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
void CWallWalker::PreThink(float dt, CStateManager& mgr) void CWallWalker::PreThink(float dt, CStateManager& mgr)
{ {
CPatterned::PreThink(dt, mgr); CPatterned::PreThink(dt, mgr);
if (!GetActive() || x5d6_26_ || x5bc_ > 0.f || x5d6_27_ || x450_bodyController->IsFrozen() || !x5d6_24_) if (!GetActive() || x5d6_26_playerObstructed || x5bc_patrolPauseRemTime > 0.f || x5d6_27_disableMove ||
x450_bodyController->IsFrozen() || !x5d6_24_alignToFloor)
return; return;
zeus::CQuaternion quat(GetTransform().buildMatrix3f()); zeus::CQuaternion quat(GetTransform().buildMatrix3f());
AddMotionState(PredictMotion(dt)); AddMotionState(PredictMotion(dt));
zeus::CQuaternion quat2(GetTransform().buildMatrix3f()); zeus::CQuaternion quat2(GetTransform().buildMatrix3f());
ClearForcesAndTorques(); ClearForcesAndTorques();
if (x5d6_25_) if (x5d6_25_hasAlignSurface)
{ {
zeus::CPlane plane = x568_.GetPlane(); zeus::CPlane plane = x568_alignNormal.GetPlane();
const float futureDt = (10.f * dt); const float futureDt = (10.f * dt);
SetTranslation(GetTranslation() * (1.f - futureDt) + SetTranslation(GetTranslation() * (1.f - futureDt) +
(((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) - (((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) -
@ -136,7 +208,7 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
x2dc_destObj = wp->NextWaypoint(mgr); x2dc_destObj = wp->NextWaypoint(mgr);
if (std::fabs(wp->GetPause()) > 0.00001f) if (std::fabs(wp->GetPause()) > 0.00001f)
{ {
x5bc_ = wp->GetPause(); x5bc_patrolPauseRemTime = wp->GetPause();
if (x5d0_walkerType == EWalkerType::Parasite) if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived); mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
@ -146,4 +218,5 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
SetDestPos(wpPos); SetDestPos(wpPos);
} }
} }
} }

View File

@ -18,36 +18,46 @@ public:
Seedling = 4 Seedling = 4
}; };
protected: protected:
CCollisionSurface x568_ = CCollisionSurface(zeus::CVector3f(), CCollisionSurface x568_alignNormal = CCollisionSurface(zeus::CVector3f(),
zeus::CVector3f::skForward, zeus::CVector3f::skForward,
zeus::CVector3f::skRight, -1); zeus::CVector3f::skRight, -1);
CCollidableSphere x590_colSphere; CCollidableSphere x590_colSphere;
float x5b0_collisionCloseMargin; float x5b0_collisionCloseMargin;
float x5b4_; float x5b4_alignAngVel;
float x5b8_ = 0.f; float x5b8_tumbleAngle = 0.f;
float x5bc_ = 0.f; float x5bc_patrolPauseRemTime = 0.f;
float x5c0_advanceWpRadius; float x5c0_advanceWpRadius;
float x5c4_; float x5c4_playerObstructionMinDist;
float x5c8_bendingHackWeight = 0.f; float x5c8_bendingHackWeight = 0.f;
s32 x5cc_bendingHackAnim; s32 x5cc_bendingHackAnim;
EWalkerType x5d0_walkerType; EWalkerType x5d0_walkerType;
s16 x5d4_ = 0; s16 x5d4_thinkCounter = 0;
bool x5d6_24_ : 1; bool x5d6_24_alignToFloor : 1;
bool x5d6_25_ : 1; bool x5d6_25_hasAlignSurface : 1;
bool x5d6_26_ : 1; bool x5d6_26_playerObstructed : 1;
bool x5d6_27_ : 1; bool x5d6_27_disableMove : 1;
bool x5d6_28_addBendingWeight : 1; bool x5d6_28_addBendingWeight : 1;
bool x5d6_29_applyBendingHack : 1; bool x5d6_29_applyBendingHack : 1;
static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& v0, const zeus::CVector3f& v1) static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& pt, const zeus::CVector3f& plane)
{ {
return v0 - v1 * v0.dot(v1); return pt - plane * pt.dot(plane);
}
static zeus::CVector3f ProjectPointToPlane(const zeus::CVector3f& p0, const zeus::CVector3f& p1,
const zeus::CVector3f& plane)
{
return p0 - (p0 - p1).dot(plane) * plane;
} }
void OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle); void OrientToSurfaceNormal(const zeus::CVector3f& normal, float clampAngle);
static bool PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point);
void AlignToFloor(CStateManager&, float, const zeus::CVector3f&, float);
void GotoNextWaypoint(CStateManager& mgr); void GotoNextWaypoint(CStateManager& mgr);
public: public:
CWallWalker(ECharacter, TUniqueId, std::string_view, EFlavorType, const CEntityInfo&, const zeus::CTransform&, CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, EFlavorType flavType,
CModelData&&, const CPatternedInfo&, EMovementType, EColliderType, EBodyType, const CEntityInfo& eInfo, const zeus::CTransform& xf,
const CActorParameters&, float, float, EKnockBackVariant, float, EWalkerType wType, float, bool); CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType,
EColliderType colType, EBodyType bType, const CActorParameters& aParms,
float collisionCloseMargin, float alignAngVel, EKnockBackVariant kbVariant,
float advanceWpRadius, EWalkerType wType, float playerObstructionMinDist, bool disableMove);
void PreThink(float, CStateManager&); void PreThink(float, CStateManager&);
void Think(float, CStateManager&); void Think(float, CStateManager&);

View File

@ -1898,24 +1898,24 @@ CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int pr
CPatternedInfo pInfo(in, pcount.second); CPatternedInfo pInfo(in, pcount.second);
CActorParameters aParms = LoadActorParameters(in); CActorParameters aParms = LoadActorParameters(in);
float f1 = in.readFloatBig(); float maxTelegraphReactDist = in.readFloatBig();
float f2 = in.readFloatBig(); float advanceWpRadius = in.readFloatBig();
float f3 = in.readFloatBig(); float f3 = in.readFloatBig();
float f4 = in.readFloatBig(); float alignAngVel = in.readFloatBig();
float f5 = in.readFloatBig(); float f5 = in.readFloatBig();
float f6 = in.readFloatBig(); float stuckTimeThreshold = in.readFloatBig();
float f7 = in.readFloatBig(); float collisionCloseMargin = in.readFloatBig();
float f8 = in.readFloatBig(); float parasiteSearchRadius = in.readFloatBig();
float f9 = in.readFloatBig(); float parasiteSeparationDist = in.readFloatBig();
float f10 = in.readFloatBig(); float parasiteSeparationWeight = in.readFloatBig();
float f11 = in.readFloatBig(); float parasiteAlignmentWeight = in.readFloatBig();
float f12 = in.readFloatBig(); float parasiteCohesionWeight = in.readFloatBig();
float f13 = in.readFloatBig(); float destinationSeekWeight = in.readFloatBig();
float f14 = in.readFloatBig(); float forwardMoveWeight = in.readFloatBig();
float f15 = in.readFloatBig(); float playerSeparationDist = in.readFloatBig();
float f16 = in.readFloatBig(); float playerSeparationWeight = in.readFloatBig();
float f17 = in.readFloatBig(); float playerObstructionMinDist = in.readFloatBig();
bool b1 = in.readBool(); bool disableMove = in.readBool();
if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS')) if (g_ResFactory->GetResourceTypeById(pInfo.GetAnimationParameters().GetACSFile()) != SBIG('ANCS'))
return nullptr; return nullptr;
@ -1923,8 +1923,11 @@ CEntity* ScriptLoader::LoadParasite(CStateManager& mgr, CInputStream& in, int pr
CModelData mData( CModelData mData(
CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true)); CAnimRes(animParms.GetACSFile(), animParms.GetCharacter(), scale, animParms.GetInitialAnimation(), true));
return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo, return new MP1::CParasite(mgr.AllocateUniqueId(), name, flavor, info, xf, std::move(mData), pInfo,
EBodyType::WallWalker, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15, EBodyType::WallWalker, maxTelegraphReactDist, advanceWpRadius, f3, alignAngVel, f5,
f16, f17, 0.f, b1, CWallWalker::EWalkerType::Parasite, stuckTimeThreshold, collisionCloseMargin, parasiteSearchRadius, parasiteSeparationDist,
parasiteSeparationWeight, parasiteAlignmentWeight, parasiteCohesionWeight,
destinationSeekWeight, forwardMoveWeight, playerSeparationDist, playerSeparationWeight,
playerObstructionMinDist, 0.f, disableMove, CWallWalker::EWalkerType::Parasite,
CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(), CDamageVulnerability::NormalVulnerabilty(), CDamageInfo(),
-1, -1, -1, {}, {}, 0.f, aParms); -1, -1, -1, {}, {}, 0.f, aParms);
} }

View File

@ -161,7 +161,7 @@ std::string_view ScriptObjectStateToStr(EScriptObjectState state)
case EScriptObjectState::Dead: return "Dead"sv; case EScriptObjectState::Dead: return "Dead"sv;
case EScriptObjectState::CameraPath: return "CameraPath"sv; case EScriptObjectState::CameraPath: return "CameraPath"sv;
case EScriptObjectState::CameraTarget: return "CameraTarget"sv; case EScriptObjectState::CameraTarget: return "CameraTarget"sv;
case EScriptObjectState::UNKS2: return "UNKS2"sv; case EScriptObjectState::DeactivateState: return "DeactivateState"sv;
case EScriptObjectState::Play: return "Play"sv; case EScriptObjectState::Play: return "Play"sv;
case EScriptObjectState::MassiveDeath: return "DeathExplosion"sv; case EScriptObjectState::MassiveDeath: return "DeathExplosion"sv;
case EScriptObjectState::DeathRattle: return "DeathRattle"sv; case EScriptObjectState::DeathRattle: return "DeathRattle"sv;

View File

@ -157,7 +157,7 @@ enum class EScriptObjectState
Dead = 14, Dead = 14,
CameraPath = 15, CameraPath = 15,
CameraTarget = 16, CameraTarget = 16,
UNKS2 = 17, DeactivateState = 17,
Play = 18, Play = 18,
MassiveDeath = 19, MassiveDeath = 19,
DeathRattle = 20, DeathRattle = 20,

@ -1 +1 @@
Subproject commit de445734f8909b6eba9680a1c66f9807f48a931a Subproject commit 90665dd3d12e659f88ee46b2c7bd2873fefa4c90