mirror of https://github.com/AxioDL/metaforce.git
Work on CSpacePirate
This commit is contained in:
parent
9c88971df6
commit
e1fa938127
|
@ -11,15 +11,15 @@ struct TeamAIMgr : IScriptObject
|
|||
AT_DECL_DNA_YAML
|
||||
AT_DECL_DNAV
|
||||
String<-1> name;
|
||||
Value<atUint32> unknown1;
|
||||
Value<atUint32> unknown2;
|
||||
Value<atUint32> unknown3;
|
||||
Value<atUint32> unknown4;
|
||||
Value<atUint32> unknown5;
|
||||
Value<atUint32> unknown6;
|
||||
Value<atUint32> unknown7;
|
||||
Value<float> unknown8;
|
||||
Value<float> unknown9;
|
||||
Value<atUint32> aiCount;
|
||||
Value<atUint32> meleeCount;
|
||||
Value<atUint32> projectileCount;
|
||||
Value<atUint32> unknownCount;
|
||||
Value<atUint32> maxMeleeAttackerCount;
|
||||
Value<atUint32> maxProjectileAttackerCount;
|
||||
Value<atUint32> positionMode;
|
||||
Value<float> meleeTimeInterval;
|
||||
Value<float> projectileTimeInterval;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -561,7 +561,7 @@ void CActorLights::ActivateLights(CBooModel& model) const
|
|||
if (x298_31_disableWorldLights)
|
||||
{
|
||||
zeus::CColor color(x2d4_worldLightingLevel);
|
||||
g_Renderer->SetWorldLightMultiplyColor(color);
|
||||
g_Renderer->SetGXRegister1Color(color);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,6 +25,11 @@ void CIkChain::Activate(const CAnimData& animData, const CSegId& segId, const ze
|
|||
//const TLockedToken<CCharLayoutInfo>& info = posBuilder.CharLayoutInfo();
|
||||
}
|
||||
|
||||
void CIkChain::PreRender(CAnimData& animData, const zeus::CTransform& xf, const zeus::CVector3f& scale)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CIkChain::Solve(zeus::CQuaternion& q1, zeus::CQuaternion& q2, const zeus::CVector3f& vec)
|
||||
{
|
||||
const float mag = vec.magnitude();
|
||||
|
|
|
@ -65,66 +65,68 @@ void CRagDoll::CRagDollPlaneConstraint::Update()
|
|||
}
|
||||
}
|
||||
|
||||
CRagDoll::CRagDoll(float f1, float f2, float f3, u32 flags)
|
||||
: x44_f1(f1), x48_f2(f2), x50_f3(f3)
|
||||
CRagDoll::CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags)
|
||||
: x44_normalGravity(normalGravity), x48_floatingGravity(floatingGravity), x50_overTimer(overTime)
|
||||
{
|
||||
x68_27_ = bool(flags & 0x1);
|
||||
x68_28_ = bool(flags & 0x2);
|
||||
x68_29_ = bool(flags & 0x4);
|
||||
x68_27_continueSmallMovements = bool(flags & 0x1);
|
||||
x68_28_noOverTimer = bool(flags & 0x2);
|
||||
x68_29_noAiCollision = bool(flags & 0x4);
|
||||
}
|
||||
|
||||
void CRagDoll::AccumulateForces(float dt, float f2)
|
||||
void CRagDoll::AccumulateForces(float dt, float waterTop)
|
||||
{
|
||||
float fps = 1.f / dt;
|
||||
x64_angTimer += dt;
|
||||
if (x64_angTimer > 4.f)
|
||||
x64_angTimer -= 4.f;
|
||||
float f25 = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (f2 - 0.2f);
|
||||
zeus::CVector3f f29;
|
||||
float f24 = 0.f;
|
||||
float targetZ = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (waterTop - 0.2f);
|
||||
zeus::CVector3f centerOfVolume;
|
||||
float totalVolume = 0.f;
|
||||
for (auto& particle : x4_particles)
|
||||
{
|
||||
float cubed = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||
f24 += cubed;
|
||||
f29 += particle.x4_curPos * cubed;
|
||||
float f7 = particle.x4_curPos.z - f25;
|
||||
float f8 = x48_f2;
|
||||
float f23 = 0.f;
|
||||
if (std::fabs(f7) < 0.5f)
|
||||
float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||
totalVolume += volume;
|
||||
centerOfVolume += particle.x4_curPos * volume;
|
||||
float fromTargetZ = particle.x4_curPos.z - targetZ;
|
||||
float verticalAcc = x48_floatingGravity;
|
||||
float termVelCoefficient = 0.f;
|
||||
if (std::fabs(fromTargetZ) < 0.5f)
|
||||
{
|
||||
f23 = 0.5f * f7 / 0.5f + 0.5f;
|
||||
f8 = x48_f2 * -f7 / 0.5f;
|
||||
termVelCoefficient = 0.5f * fromTargetZ / 0.5f + 0.5f;
|
||||
verticalAcc = x48_floatingGravity * -fromTargetZ / 0.5f;
|
||||
}
|
||||
else if (f7 > 0.f)
|
||||
else if (fromTargetZ > 0.f)
|
||||
{
|
||||
f8 = x44_f1;
|
||||
f23 = 1.f;
|
||||
verticalAcc = x44_normalGravity;
|
||||
termVelCoefficient = 1.f;
|
||||
}
|
||||
particle.x20_acceleration.z += f8;
|
||||
particle.x20_velocity.z += verticalAcc;
|
||||
zeus::CVector3f vel = (particle.x4_curPos - particle.x14_prevPos) * fps;
|
||||
float velMag = vel.magnitude();
|
||||
if (velMag > FLT_EPSILON)
|
||||
{
|
||||
particle.x20_acceleration -= vel * (1.f / velMag) *
|
||||
((velMag * velMag * 0.75f * (1.2f * f23 + 1000.f * (1.f - f23))) / (8000.f * particle.x10_radius));
|
||||
particle.x20_velocity -= vel * (1.f / velMag) *
|
||||
((velMag * velMag * 0.75f * (1.2f * termVelCoefficient + 1000.f *
|
||||
(1.f - termVelCoefficient))) / (8000.f * particle.x10_radius));
|
||||
}
|
||||
}
|
||||
zeus::CVector3f _c8;
|
||||
f29 = f29 / f24;
|
||||
zeus::CVector3f averageTorque;
|
||||
centerOfVolume = centerOfVolume / totalVolume;
|
||||
for (const auto& particle : x4_particles)
|
||||
{
|
||||
float cubed = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||
_c8 += (particle.x4_curPos - f29).cross(particle.x4_curPos) * cubed;
|
||||
float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||
averageTorque += (particle.x4_curPos - centerOfVolume).
|
||||
cross(particle.x4_curPos - particle.x14_prevPos) * volume;
|
||||
}
|
||||
_c8 = _c8 * (fps / f24);
|
||||
if (_c8.canBeNormalized())
|
||||
averageTorque = averageTorque * (fps / totalVolume);
|
||||
if (averageTorque.canBeNormalized())
|
||||
for (auto& particle : x4_particles)
|
||||
particle.x20_acceleration -= _c8.cross(particle.x4_curPos - f29) * 25.f;
|
||||
particle.x20_velocity -= averageTorque.cross(particle.x4_curPos - centerOfVolume) * 25.f;
|
||||
}
|
||||
|
||||
void CRagDoll::AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float f1)
|
||||
void CRagDoll::AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius)
|
||||
{
|
||||
x4_particles.emplace_back(id, curPos, f1, prevPos);
|
||||
x4_particles.emplace_back(id, curPos, radius, prevPos);
|
||||
}
|
||||
|
||||
void CRagDoll::AddLengthConstraint(int i1, int i2)
|
||||
|
@ -173,42 +175,42 @@ zeus::CAABox CRagDoll::CalculateRenderBounds() const
|
|||
|
||||
void CRagDoll::CheckStatic(float dt)
|
||||
{
|
||||
x4c_ = 0;
|
||||
x54_ = 0.f;
|
||||
float f1 = 0.5f * dt;
|
||||
float f31 = f1 * f1;
|
||||
x58_ = zeus::CVector3f::skZero;
|
||||
bool r31 = true;
|
||||
x4c_impactCount = 0;
|
||||
x54_impactVel = 0.f;
|
||||
float halfDt = 0.5f * dt;
|
||||
float halfDeltaUnitSq = halfDt * halfDt;
|
||||
x58_averageVel = zeus::CVector3f::skZero;
|
||||
bool movingSlowly = true;
|
||||
for (auto& particle : x4_particles)
|
||||
{
|
||||
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
|
||||
x58_ += delta;
|
||||
if (delta.magSquared() > f31)
|
||||
r31 = false;
|
||||
if (particle.x3c_24_nextDampVel)
|
||||
x58_averageVel += delta;
|
||||
if (delta.magSquared() > halfDeltaUnitSq)
|
||||
movingSlowly = false;
|
||||
if (particle.x3c_24_impactPending)
|
||||
{
|
||||
x4c_ += 1;
|
||||
x54_ = std::max(particle.x38_, x54_);
|
||||
x4c_impactCount += 1;
|
||||
x54_impactVel = std::max(particle.x38_impactFrameVel, x54_impactVel);
|
||||
}
|
||||
}
|
||||
if (!x4_particles.empty())
|
||||
x58_ = x58_ * (1.f / (dt * x4_particles.size()));
|
||||
x54_ /= dt;
|
||||
if (!x68_28_)
|
||||
x58_averageVel = x58_averageVel * (1.f / (dt * x4_particles.size()));
|
||||
x54_impactVel /= dt;
|
||||
if (!x68_28_noOverTimer)
|
||||
{
|
||||
x50_f3 -= dt;
|
||||
if (x50_f3 <= 0.f)
|
||||
x68_25_ = true;
|
||||
x50_overTimer -= dt;
|
||||
if (x50_overTimer <= 0.f)
|
||||
x68_25_over = true;
|
||||
}
|
||||
if (r31 && x68_24_)
|
||||
x68_25_ = true;
|
||||
x68_24_ = r31;
|
||||
if (movingSlowly && x68_24_prevMovingSlowly)
|
||||
x68_25_over = true;
|
||||
x68_24_prevMovingSlowly = movingSlowly;
|
||||
}
|
||||
|
||||
void CRagDoll::ClearForces()
|
||||
{
|
||||
for (auto& particle : x4_particles)
|
||||
particle.x20_acceleration = zeus::CVector3f::skZero;
|
||||
particle.x20_velocity = zeus::CVector3f::skZero;
|
||||
}
|
||||
|
||||
void CRagDoll::SatisfyConstraints(CStateManager& mgr)
|
||||
|
@ -223,12 +225,12 @@ void CRagDoll::SatisfyConstraints(CStateManager& mgr)
|
|||
SatisfyWorldConstraints(mgr, 2);
|
||||
}
|
||||
|
||||
bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
||||
bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int pass)
|
||||
{
|
||||
zeus::CAABox aabb;
|
||||
for (const auto& particle : x4_particles)
|
||||
{
|
||||
if (i1 == 1 || particle.x3c_24_nextDampVel)
|
||||
if (pass == 1 || particle.x3c_24_impactPending)
|
||||
{
|
||||
aabb.accumulateBounds(particle.x14_prevPos - particle.x10_radius);
|
||||
aabb.accumulateBounds(particle.x14_prevPos + particle.x10_radius);
|
||||
|
@ -239,19 +241,19 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
|||
|
||||
CAreaCollisionCache ccache(aabb);
|
||||
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
|
||||
bool ret = false;
|
||||
bool needs2ndPass = false;
|
||||
|
||||
TUniqueId bestId = kInvalidUniqueId;
|
||||
CMaterialList include;
|
||||
if (x68_29_)
|
||||
if (x68_29_noAiCollision)
|
||||
include = CMaterialList(EMaterialTypes::Solid);
|
||||
else
|
||||
include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock);
|
||||
|
||||
CMaterialList exclude;
|
||||
if (x68_29_)
|
||||
if (x68_29_noAiCollision)
|
||||
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player,
|
||||
EMaterialTypes::AIBlock, EMaterialTypes::Occluder);
|
||||
EMaterialTypes::AIBlock, EMaterialTypes::Occluder);
|
||||
else
|
||||
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player);
|
||||
|
||||
|
@ -261,7 +263,7 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
|||
|
||||
for (auto& particle : x4_particles)
|
||||
{
|
||||
if (i1 == 1 || particle.x3c_24_nextDampVel)
|
||||
if (pass == 1 || particle.x3c_24_impactPending)
|
||||
{
|
||||
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
|
||||
float deltaMag = delta.magnitude();
|
||||
|
@ -275,15 +277,15 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
|||
nearList, delta, bestId, info, d);
|
||||
if (info.IsValid())
|
||||
{
|
||||
ret = true;
|
||||
switch (i1)
|
||||
needs2ndPass = true;
|
||||
switch (pass)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
particle.x3c_24_nextDampVel = true;
|
||||
particle.x3c_24_impactPending = true;
|
||||
float dot = delta.dot(info.GetNormalLeft());
|
||||
particle.x2c_nextPosDelta = -0.125f * dot * deltaMag * info.GetNormalLeft();
|
||||
particle.x38_ = -dot * deltaMag;
|
||||
particle.x2c_impactResponseDelta = -0.125f * dot * deltaMag * info.GetNormalLeft();
|
||||
particle.x38_impactFrameVel = -dot * deltaMag;
|
||||
particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft();
|
||||
break;
|
||||
}
|
||||
|
@ -295,20 +297,20 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (!x68_27_)
|
||||
else if (!x68_27_continueSmallMovements)
|
||||
{
|
||||
particle.x4_curPos = particle.x14_prevPos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
return needs2ndPass;
|
||||
}
|
||||
|
||||
void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr)
|
||||
{
|
||||
for (auto& particle : x4_particles)
|
||||
particle.x3c_24_nextDampVel = true;
|
||||
particle.x3c_24_impactPending = true;
|
||||
SatisfyWorldConstraints(mgr, 2);
|
||||
for (auto& particle : x4_particles)
|
||||
particle.x14_prevPos = particle.x4_curPos;
|
||||
|
@ -320,15 +322,15 @@ void CRagDoll::Verlet(float dt)
|
|||
{
|
||||
zeus::CVector3f oldPos = particle.x4_curPos;
|
||||
particle.x4_curPos += (particle.x4_curPos - particle.x14_prevPos) *
|
||||
(particle.x3c_24_nextDampVel ? 0.9f : 1.f);
|
||||
particle.x4_curPos += particle.x20_acceleration * (dt * dt);
|
||||
particle.x4_curPos += particle.x2c_nextPosDelta;
|
||||
(particle.x3c_24_impactPending ? 0.9f : 1.f);
|
||||
particle.x4_curPos += particle.x20_velocity * (dt * dt);
|
||||
particle.x4_curPos += particle.x2c_impactResponseDelta;
|
||||
particle.x14_prevPos = oldPos;
|
||||
zeus::CVector3f deltaPos = particle.x4_curPos - particle.x14_prevPos;
|
||||
if (deltaPos.magSquared() > 4.f)
|
||||
particle.x4_curPos = deltaPos.normalized() * 2.f + particle.x14_prevPos;
|
||||
particle.x3c_24_nextDampVel = false;
|
||||
particle.x2c_nextPosDelta = zeus::CVector3f::skZero;
|
||||
particle.x3c_24_impactPending = false;
|
||||
particle.x2c_impactResponseDelta = zeus::CVector3f::skZero;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -337,11 +339,11 @@ void CRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData)
|
|||
// Empty
|
||||
}
|
||||
|
||||
void CRagDoll::Update(CStateManager& mgr, float dt, float f2)
|
||||
void CRagDoll::Update(CStateManager& mgr, float dt, float waterTop)
|
||||
{
|
||||
if (!x68_25_ || x68_27_)
|
||||
if (!x68_25_over || x68_27_continueSmallMovements)
|
||||
{
|
||||
AccumulateForces(dt, f2);
|
||||
AccumulateForces(dt, waterTop);
|
||||
Verlet(dt);
|
||||
SatisfyConstraints(mgr);
|
||||
ClearForces();
|
||||
|
@ -359,7 +361,7 @@ void CRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData&
|
|||
particle.x4_curPos = xf * aData->GetPose().GetOffset(particle.x0_id) * scale;
|
||||
SatisfyWorldConstraints(mgr, 2);
|
||||
for (auto& particle : x4_particles)
|
||||
particle.x3c_24_nextDampVel = false;
|
||||
particle.x3c_24_impactPending = false;
|
||||
x68_26_primed = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -22,23 +22,23 @@ protected:
|
|||
zeus::CVector3f x4_curPos;
|
||||
float x10_radius;
|
||||
zeus::CVector3f x14_prevPos;
|
||||
zeus::CVector3f x20_acceleration;
|
||||
zeus::CVector3f x2c_nextPosDelta;
|
||||
float x38_ = 0.f;
|
||||
bool x3c_24_nextDampVel : 1;
|
||||
zeus::CVector3f x20_velocity;
|
||||
zeus::CVector3f x2c_impactResponseDelta;
|
||||
float x38_impactFrameVel = 0.f;
|
||||
bool x3c_24_impactPending : 1;
|
||||
bool x3c_25_ : 1;
|
||||
public:
|
||||
CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float f1, const zeus::CVector3f& prevPos)
|
||||
: x0_id(id), x4_curPos(curPos), x10_radius(f1), x14_prevPos(prevPos)
|
||||
CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float radius, const zeus::CVector3f& prevPos)
|
||||
: x0_id(id), x4_curPos(curPos), x10_radius(radius), x14_prevPos(prevPos)
|
||||
{
|
||||
x3c_24_nextDampVel = false;
|
||||
x3c_24_impactPending = false;
|
||||
x3c_25_ = false;
|
||||
}
|
||||
CSegId GetBone() const { return x0_id; }
|
||||
const zeus::CVector3f& GetPosition() const { return x4_curPos; }
|
||||
zeus::CVector3f& Position() { return x4_curPos; }
|
||||
const zeus::CVector3f& GetAcceleration() const { return x20_acceleration; }
|
||||
zeus::CVector3f& Acceleration() { return x20_acceleration; }
|
||||
const zeus::CVector3f& GetVelocity() const { return x20_velocity; }
|
||||
zeus::CVector3f& Velocity() { return x20_velocity; }
|
||||
float GetRadius() const { return x10_radius; }
|
||||
};
|
||||
class CRagDollLengthConstraint
|
||||
|
@ -87,29 +87,29 @@ protected:
|
|||
std::vector<CRagDollLengthConstraint> x14_lengthConstraints;
|
||||
std::vector<CRagDollJointConstraint> x24_jointConstraints;
|
||||
std::vector<CRagDollPlaneConstraint> x34_planeConstraints;
|
||||
float x44_f1;
|
||||
float x48_f2;
|
||||
u32 x4c_ = 0;
|
||||
float x50_f3;
|
||||
float x54_ = 0.f;
|
||||
zeus::CVector3f x58_;
|
||||
float x44_normalGravity;
|
||||
float x48_floatingGravity;
|
||||
u32 x4c_impactCount = 0;
|
||||
float x50_overTimer;
|
||||
float x54_impactVel = 0.f;
|
||||
zeus::CVector3f x58_averageVel;
|
||||
float x64_angTimer = 0.f;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
bool x68_24_ : 1;
|
||||
bool x68_25_ : 1;
|
||||
bool x68_24_prevMovingSlowly : 1;
|
||||
bool x68_25_over : 1;
|
||||
bool x68_26_primed : 1;
|
||||
bool x68_27_ : 1;
|
||||
bool x68_28_ : 1;
|
||||
bool x68_29_ : 1;
|
||||
bool x68_27_continueSmallMovements : 1;
|
||||
bool x68_28_noOverTimer : 1;
|
||||
bool x68_29_noAiCollision : 1;
|
||||
};
|
||||
u32 _dummy = 0;
|
||||
};
|
||||
void AccumulateForces(float dt, float f2);
|
||||
void AccumulateForces(float dt, float waterTop);
|
||||
void SetNumParticles(int num) { x4_particles.reserve(num); }
|
||||
void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float f1);
|
||||
void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float radius);
|
||||
void SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); }
|
||||
void AddLengthConstraint(int i1, int i2);
|
||||
void AddMaxLengthConstraint(int i1, int i2, float length);
|
||||
|
@ -118,20 +118,24 @@ protected:
|
|||
void AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6);
|
||||
zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo,
|
||||
int i1, int i2, const zeus::CQuaternion& q);
|
||||
zeus::CAABox CalculateRenderBounds() const;
|
||||
void CheckStatic(float dt);
|
||||
void ClearForces();
|
||||
void SatisfyConstraints(CStateManager& mgr);
|
||||
bool SatisfyWorldConstraints(CStateManager& mgr, int i1);
|
||||
bool SatisfyWorldConstraints(CStateManager& mgr, int pass);
|
||||
void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr);
|
||||
void Verlet(float dt);
|
||||
public:
|
||||
virtual ~CRagDoll() = default;
|
||||
CRagDoll(float f1, float f2, float f3, u32 flags);
|
||||
CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags);
|
||||
|
||||
virtual void PreRender(const zeus::CVector3f& v, CModelData& mData);
|
||||
virtual void Update(CStateManager& mgr, float dt, float f2);
|
||||
virtual void Update(CStateManager& mgr, float dt, float waterTop);
|
||||
virtual void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
|
||||
|
||||
zeus::CAABox CalculateRenderBounds() const;
|
||||
bool IsPrimed() const { return x68_26_primed; }
|
||||
bool WillContinueSmallMovements() const { return x68_27_continueSmallMovements; }
|
||||
bool IsOver() const { return x68_25_over; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1347,7 +1347,7 @@ void CBooRenderer::PrepareDynamicLights(const std::vector<CLight>& lights)
|
|||
}
|
||||
}
|
||||
|
||||
void CBooRenderer::SetWorldLightMultiplyColor(const zeus::CColor& color)
|
||||
void CBooRenderer::SetGXRegister1Color(const zeus::CColor& color)
|
||||
{
|
||||
CGraphics::g_ColorRegs[1] = color;
|
||||
}
|
||||
|
|
|
@ -269,7 +269,7 @@ public:
|
|||
void DoThermalBlendHot();
|
||||
u32 GetStaticWorldDataSize();
|
||||
void PrepareDynamicLights(const std::vector<CLight>& lights);
|
||||
void SetWorldLightMultiplyColor(const zeus::CColor& color);
|
||||
void SetGXRegister1Color(const zeus::CColor& color);
|
||||
void SetWorldLightFadeLevel(float level);
|
||||
void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken<CTexture>& indTex,
|
||||
const zeus::CColor& indirectMod, float blurRadius,
|
||||
|
|
|
@ -105,7 +105,7 @@ public:
|
|||
virtual void DoThermalBlendHot()=0;
|
||||
virtual u32 GetStaticWorldDataSize()=0;
|
||||
virtual void PrepareDynamicLights(const std::vector<CLight>& lights)=0;
|
||||
virtual void SetWorldLightMultiplyColor(const zeus::CColor& color)=0;
|
||||
virtual void SetGXRegister1Color(const zeus::CColor& color)=0;
|
||||
virtual void SetWorldLightFadeLevel(float level)=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ void MP1::CActorContraption::ResetFlameThrowers(CStateManager& mgr)
|
|||
}
|
||||
}
|
||||
|
||||
void MP1::CActorContraption::DoUserAnimEvent(CStateManager& mgr, CInt32POINode& node, EUserEventType evType, float dt)
|
||||
void MP1::CActorContraption::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType evType, float dt)
|
||||
{
|
||||
if (evType == EUserEventType::DamageOff)
|
||||
{
|
||||
|
|
|
@ -23,7 +23,7 @@ public:
|
|||
void Accept(IVisitor &visitor);
|
||||
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &);
|
||||
void Think(float, CStateManager &);
|
||||
void DoUserAnimEvent(CStateManager &, CInt32POINode &, EUserEventType, float dt);
|
||||
void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt);
|
||||
CFlameThrower* CreateFlameThrower(std::string_view, CStateManager&);
|
||||
void ResetFlameThrowers(CStateManager& mgr);
|
||||
};
|
||||
|
|
|
@ -80,7 +80,7 @@ void CFlickerBat::Touch(CActor& act, CStateManager& mgr)
|
|||
CPatterned::Touch(act, mgr);
|
||||
}
|
||||
|
||||
void CFlickerBat::DoUserAnimEvent(CStateManager& mgr, CInt32POINode& node, EUserEventType type, float dt)
|
||||
void CFlickerBat::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt)
|
||||
{
|
||||
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public:
|
|||
void Think(float, CStateManager&);
|
||||
void Render(const CStateManager&) const;
|
||||
void Touch(CActor&, CStateManager&);
|
||||
void DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt);
|
||||
void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt);
|
||||
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
|
||||
bool CanBeShot(CStateManager&, int);
|
||||
void Patrol(CStateManager&, EStateMsg, float);
|
||||
|
|
|
@ -318,7 +318,7 @@ void CNewIntroBoss::Think(float dt, CStateManager& mgr)
|
|||
}
|
||||
}
|
||||
|
||||
void CNewIntroBoss::DoUserAnimEvent(CStateManager& mgr, CInt32POINode& node, EUserEventType event, float dt)
|
||||
void CNewIntroBoss::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt)
|
||||
{
|
||||
if (event == EUserEventType::DamageOn)
|
||||
{
|
||||
|
|
|
@ -67,7 +67,7 @@ public:
|
|||
}
|
||||
|
||||
std::experimental::optional<zeus::CAABox> GetTouchBounds() const { return {}; }
|
||||
void DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt);
|
||||
void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt);
|
||||
void Generate(CStateManager&, EStateMsg, float);
|
||||
void Attack(CStateManager&, EStateMsg, float);
|
||||
void Patrol(CStateManager&, EStateMsg, float);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -15,18 +15,18 @@ class CSpacePirate;
|
|||
class CPirateRagDoll : public CRagDoll
|
||||
{
|
||||
CSpacePirate* x6c_spacePirate;
|
||||
u16 x70_s1;
|
||||
float x74_ = 0.f;
|
||||
zeus::CVector3f x78_;
|
||||
zeus::CVector3f x84_;
|
||||
u16 x70_thudSfx;
|
||||
float x74_sfxTimer = 0.f;
|
||||
zeus::CVector3f x78_lastSFXPos;
|
||||
zeus::CVector3f x84_torsoImpulse;
|
||||
rstl::reserved_vector<TUniqueId, 4> x90_waypoints;
|
||||
rstl::reserved_vector<u32, 4> x9c_wpParticleIdxs;
|
||||
bool xb0_24_ : 1;
|
||||
bool xb0_24_initSfx : 1;
|
||||
public:
|
||||
CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 s1, u32 flags);
|
||||
CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 thudSfx, u32 flags);
|
||||
|
||||
void PreRender(const zeus::CVector3f& v, CModelData& mData);
|
||||
void Update(CStateManager& mgr, float dt, float f2);
|
||||
void Update(CStateManager& mgr, float dt, float waterTop);
|
||||
void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
|
||||
};
|
||||
|
||||
|
@ -44,23 +44,23 @@ private:
|
|||
float x8_;
|
||||
float xc_;
|
||||
float x10_;
|
||||
float x14_;
|
||||
u32 x18_;
|
||||
float x14_hearNoiseRange;
|
||||
u32 x18_flags;
|
||||
bool x1c_;
|
||||
CProjectileInfo x20_;
|
||||
CProjectileInfo x20_mainProjectileInfo;
|
||||
u16 x48_;
|
||||
CDamageInfo x4c_;
|
||||
float x68_;
|
||||
CProjectileInfo x6c_;
|
||||
float x94_;
|
||||
u16 x98_;
|
||||
float x9c_;
|
||||
float xa0_;
|
||||
u16 x98_ragdollThudSfx;
|
||||
float x9c_averageNextShotTime;
|
||||
float xa0_nextShotTimeVariation;
|
||||
u16 xa4_;
|
||||
float xa8_;
|
||||
float xa8_aimDelayTime;
|
||||
u32 xac_firstBurstCount;
|
||||
float xb0_;
|
||||
float xb4_;
|
||||
float xb0_minCloakAlpha;
|
||||
float xb4_maxCloakAlpha;
|
||||
float xb8_;
|
||||
float xbc_;
|
||||
u16 xc0_;
|
||||
|
@ -76,24 +76,24 @@ private:
|
|||
{
|
||||
struct
|
||||
{
|
||||
bool x634_24_ : 1;
|
||||
bool x634_25_ : 1;
|
||||
bool x634_24_pendingAmbush : 1;
|
||||
bool x634_25_ceilingAmbush : 1;
|
||||
bool x634_26_ : 1;
|
||||
bool x634_27_ : 1;
|
||||
bool x634_27_melee : 1;
|
||||
bool x634_28_ : 1;
|
||||
bool x634_29_ : 1;
|
||||
bool x634_29_onlyAttackInRange : 1;
|
||||
bool x634_30_ : 1;
|
||||
bool x634_31_ : 1;
|
||||
bool x635_24_ : 1;
|
||||
bool x635_25_ : 1;
|
||||
bool x635_26_ : 1;
|
||||
bool x635_27_ : 1;
|
||||
bool x635_27_shadowPirate : 1;
|
||||
bool x635_28_ : 1;
|
||||
bool x635_29_ : 1;
|
||||
bool x635_30_ : 1;
|
||||
bool x635_31_ : 1;
|
||||
bool x635_30_ragdollKeepAlive : 1;
|
||||
bool x635_31_ragdollNoAiCollision : 1;
|
||||
bool x636_24_trooper : 1;
|
||||
bool x636_25_ : 1;
|
||||
bool x636_25_hearNoise : 1;
|
||||
bool x636_26_ : 1;
|
||||
bool x636_27_ : 1;
|
||||
bool x636_28_ : 1;
|
||||
|
@ -102,19 +102,19 @@ private:
|
|||
bool x636_31_ : 1;
|
||||
bool x637_24_ : 1;
|
||||
bool x637_25_ : 1;
|
||||
bool x637_26_ : 1;
|
||||
bool x637_27_ : 1;
|
||||
bool x637_26_hearPlayerFire : 1;
|
||||
bool x637_27_inProjectilePath : 1;
|
||||
bool x637_28_ : 1;
|
||||
bool x637_29_ : 1;
|
||||
bool x637_30_ : 1;
|
||||
bool x637_31_prevInCineCam : 1;
|
||||
bool x638_24_ : 1;
|
||||
bool x638_24_pendingFrenzyChance : 1;
|
||||
bool x638_25_ : 1;
|
||||
bool x638_26_ : 1;
|
||||
bool x638_27_ : 1;
|
||||
bool x638_28_ : 1;
|
||||
bool x638_29_ : 1;
|
||||
bool x638_30_ : 1;
|
||||
bool x638_30_ragdollOver : 1;
|
||||
bool x638_31_ : 1;
|
||||
bool x639_24_ : 1;
|
||||
bool x639_25_ : 1;
|
||||
|
@ -130,22 +130,22 @@ private:
|
|||
u64 _dummy = 0;
|
||||
};
|
||||
|
||||
u32 x63c_ = 0;
|
||||
s32 x63c_frenzyFrames = 0;
|
||||
TUniqueId x640_ = kInvalidUniqueId;
|
||||
TUniqueId x642_ = kInvalidUniqueId;
|
||||
float x644_ = 1.f;
|
||||
zeus::CVector3f x648_ = zeus::CVector3f::skForward;
|
||||
zeus::CVector3f x654_;
|
||||
CPathFindSearch x660_;
|
||||
CPathFindSearch x660_pathFindSearch;
|
||||
float x744_ = 0.f;
|
||||
float x748_ = 0.f;
|
||||
u32 x74c_ = 0;
|
||||
float x750_;
|
||||
float x750_initialHP;
|
||||
float x754_ = 0.f;
|
||||
CSegId x758_headSeg;
|
||||
u32 x75c_ = 0;
|
||||
s32 x760_ = -1;
|
||||
CBoneTracking x764_;
|
||||
CBoneTracking x764_boneTracking;
|
||||
s32 x79c_ = -1;
|
||||
float x7a4_intoJumpDist = 1.f;
|
||||
float x7a8_ = 2.f;
|
||||
|
@ -157,8 +157,8 @@ private:
|
|||
CSegId x7b8_wristSeg;
|
||||
CSegId x7b9_swooshSeg;
|
||||
float x7bc_ = 1.f;
|
||||
TUniqueId x7c0_ = kInvalidUniqueId;
|
||||
CBurstFire x7c4_;
|
||||
TUniqueId x7c0_targetId = kInvalidUniqueId;
|
||||
CBurstFire x7c4_burstFire;
|
||||
float x824_ = 3.f;
|
||||
zeus::CVector3f x828_;
|
||||
s32 x834_ = -1;
|
||||
|
@ -168,20 +168,20 @@ private:
|
|||
s32 x844_ = -1;
|
||||
float x848_dodgeDist = 3.f;
|
||||
float x84c_breakDodgeDist = 3.f;
|
||||
float x850_ = FLT_MAX;
|
||||
float x854_ = FLT_MAX;
|
||||
float x858_ = 0.f;
|
||||
float x850_timeSinceHitByPlayer = FLT_MAX;
|
||||
float x854_lowHealthFrenzyTimer = FLT_MAX;
|
||||
float x858_ragdollDelayTimer = 0.f;
|
||||
std::unique_ptr<CPirateRagDoll> x85c_ragDoll;
|
||||
CIkChain x860_ikChain;
|
||||
float x8a8_ = 0.f;
|
||||
float x8ac_ = 0.f;
|
||||
float x8b0_ = 0.f;
|
||||
float x8b4_ = 0.5f;
|
||||
float x8b8_;
|
||||
float x8bc_;
|
||||
float x8a8_cloakDelayTimer = 0.f;
|
||||
float x8ac_electricParticleTimer = 0.f;
|
||||
float x8b0_cloakStepTime = 0.f;
|
||||
float x8b4_shadowPirateAlpha = 0.5f;
|
||||
float x8b8_minCloakAlpha;
|
||||
float x8bc_maxCloakAlpha;
|
||||
float x8c0_;
|
||||
float x8c4_;
|
||||
TUniqueId x8c8_ = kInvalidUniqueId;
|
||||
float x8c4_aimDelayTimer;
|
||||
TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId;
|
||||
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
|
||||
zeus::CVector2f x8d0_;
|
||||
float x8d8_ = 0.f;
|
||||
|
@ -201,11 +201,111 @@ private:
|
|||
static const SBurst skBurstsQuick[];
|
||||
static const SBurst* skBursts[];
|
||||
|
||||
static std::list<TUniqueId> mChargePlayerList;
|
||||
|
||||
void UpdateCloak(float dt, CStateManager& mgr);
|
||||
bool ShouldFrenzy(CStateManager& mgr);
|
||||
void ResetTeamAiRole(CStateManager& mgr);
|
||||
bool CheckTargetable(CStateManager& mgr);
|
||||
void FireProjectile(float dt, CStateManager& mgr);
|
||||
void UpdateAttacks(float dt, CStateManager& mgr);
|
||||
zeus::CVector3f GetTargetPos(CStateManager& mgr);
|
||||
void UpdateAimBodyState(float dt, CStateManager& mgr);
|
||||
void SetCinematicCollision(CStateManager& mgr);
|
||||
void SetNonCinematicCollision(CStateManager& mgr);
|
||||
void CheckForProjectiles(CStateManager& mgr);
|
||||
|
||||
public:
|
||||
CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
||||
const CActorParameters&, const CPatternedInfo&, CInputStream&, u32);
|
||||
|
||||
void Accept(IVisitor &visitor);
|
||||
void Think(float dt, CStateManager&);
|
||||
void Think(float dt, CStateManager& mgr);
|
||||
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
|
||||
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum);
|
||||
void Render(const CStateManager& mgr) const;
|
||||
|
||||
void CalculateRenderBounds();
|
||||
void Touch(CActor& other, CStateManager& mgr);
|
||||
zeus::CAABox GetSortingBounds(const CStateManager& mgr) const;
|
||||
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
|
||||
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
|
||||
void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info,
|
||||
EKnockBackType type, bool inDeferred, float magnitude);
|
||||
bool IsListening() const;
|
||||
bool Listen(const zeus::CVector3f&, EListenNoiseType);
|
||||
zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const;
|
||||
|
||||
void Patrol(CStateManager&, EStateMsg, float);
|
||||
void Dead(CStateManager&, EStateMsg, float);
|
||||
void PathFind(CStateManager&, EStateMsg, float);
|
||||
void TargetPatrol(CStateManager&, EStateMsg, float);
|
||||
void TargetCover(CStateManager&, EStateMsg, float);
|
||||
void Halt(CStateManager&, EStateMsg, float);
|
||||
void Run(CStateManager&, EStateMsg, float);
|
||||
void Generate(CStateManager&, EStateMsg, float);
|
||||
void Deactivate(CStateManager&, EStateMsg, float);
|
||||
void Attack(CStateManager&, EStateMsg, float);
|
||||
void JumpBack(CStateManager&, EStateMsg, float);
|
||||
void DoubleSnap(CStateManager&, EStateMsg, float);
|
||||
void Shuffle(CStateManager&, EStateMsg, float);
|
||||
void TurnAround(CStateManager&, EStateMsg, float);
|
||||
void Skid(CStateManager&, EStateMsg, float);
|
||||
void CoverAttack(CStateManager&, EStateMsg, float);
|
||||
void Crouch(CStateManager&, EStateMsg, float);
|
||||
void GetUp(CStateManager&, EStateMsg, float);
|
||||
void Taunt(CStateManager&, EStateMsg, float);
|
||||
void Flee(CStateManager&, EStateMsg, float);
|
||||
void Lurk(CStateManager&, EStateMsg, float);
|
||||
void Jump(CStateManager&, EStateMsg, float);
|
||||
void Dodge(CStateManager&, EStateMsg, float);
|
||||
void Cover(CStateManager&, EStateMsg, float);
|
||||
void Approach(CStateManager&, EStateMsg, float);
|
||||
void WallHang(CStateManager&, EStateMsg, float);
|
||||
void WallDetach(CStateManager&, EStateMsg, float);
|
||||
void Enraged(CStateManager&, EStateMsg, float);
|
||||
void SpecialAttack(CStateManager&, EStateMsg, float);
|
||||
void Bounce(CStateManager&, EStateMsg, float);
|
||||
void PathFindEx(CStateManager&, EStateMsg, float);
|
||||
|
||||
bool Leash(CStateManager&, float);
|
||||
bool OffLine(CStateManager&, float);
|
||||
bool Attacked(CStateManager&, float);
|
||||
bool InRange(CStateManager&, float);
|
||||
bool SpotPlayer(CStateManager&, float);
|
||||
bool PatternOver(CStateManager&, float);
|
||||
bool PatternShagged(CStateManager&, float);
|
||||
bool AnimOver(CStateManager&, float);
|
||||
bool ShouldAttack(CStateManager&, float);
|
||||
bool ShouldJumpBack(CStateManager&, float);
|
||||
bool Stuck(CStateManager&, float);
|
||||
bool Landed(CStateManager&, float);
|
||||
bool HearShot(CStateManager&, float);
|
||||
bool HearPlayer(CStateManager&, float);
|
||||
bool CoverCheck(CStateManager&, float);
|
||||
bool CoverFind(CStateManager&, float);
|
||||
bool CoverBlown(CStateManager&, float);
|
||||
bool CoverNearlyBlown(CStateManager&, float);
|
||||
bool CoveringFire(CStateManager&, float);
|
||||
bool LineOfSight(CStateManager&, float);
|
||||
bool AggressionCheck(CStateManager&, float);
|
||||
bool ShouldDodge(CStateManager&, float);
|
||||
bool ShouldRetreat(CStateManager&, float);
|
||||
bool ShouldCrouch(CStateManager&, float);
|
||||
bool ShouldMove(CStateManager&, float);
|
||||
bool ShotAt(CStateManager&, float);
|
||||
bool HasTargetingPoint(CStateManager&, float);
|
||||
bool ShouldWallHang(CStateManager&, float);
|
||||
bool StartAttack(CStateManager&, float);
|
||||
bool BreakAttack(CStateManager&, float);
|
||||
bool ShouldStrafe(CStateManager&, float);
|
||||
bool ShouldSpecialAttack(CStateManager&, float);
|
||||
bool LostInterest(CStateManager&, float);
|
||||
bool BounceFind(CStateManager&, float);
|
||||
|
||||
CPathFindSearch* GetSearchPath();
|
||||
u8 GetModelAlphau8(const CStateManager& mgr) const;
|
||||
float GetGravityConstant() const;
|
||||
CProjectileInfo* GetProjectileInfo();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManag
|
|||
mgr.AddObject(gameLight);
|
||||
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
|
||||
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1);
|
||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::Bomb);
|
||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode);
|
||||
return;
|
||||
}
|
||||
else if (msg == EScriptObjectMessage::Deleted)
|
||||
|
@ -166,7 +166,7 @@ void CBomb::Explode(const zeus::CVector3f& pos, CStateManager& mgr)
|
|||
{
|
||||
mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter);
|
||||
CSfxManager::AddEmitter(SFXwpn_bomb_explo, GetTranslation(), {}, true, false, 0x7f, -1);
|
||||
mgr.InformListeners(pos, EListenNoiseType::Bomb);
|
||||
mgr.InformListeners(pos, EListenNoiseType::BombExplode);
|
||||
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
|
||||
x190_24_isNotDetonated = false;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ public:
|
|||
void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; }
|
||||
void SetBurstType(s32 type) { x0_burstType = type; }
|
||||
void SetTimeToNextShot(float t) { x8_timeToNextShot = t; }
|
||||
float GetTimeToNextShot() const { return x8_timeToNextShot; }
|
||||
s32 GetBurstType() const { return x0_burstType; }
|
||||
void Start(CStateManager& mgr);
|
||||
void Update(CStateManager& mgr, float dt);
|
||||
|
|
|
@ -334,7 +334,7 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
|||
}
|
||||
|
||||
PlayImpactSound(pos, type);
|
||||
mgr.InformListeners(pos, EListenNoiseType::Projectile);
|
||||
mgr.InformListeners(pos, EListenNoiseType::ProjectileExplode);
|
||||
if (auto particle = x170_projectile.CollisionOccured(type, !done, retargetPlayer, offsetPos, normal, targetPos))
|
||||
{
|
||||
zeus::CTransform particleXf = zeus::lookAt(zeus::CVector3f::skZero, normal);
|
||||
|
|
|
@ -1533,7 +1533,7 @@ void CPlayerGun::FireSecondary(float dt, CStateManager& mgr)
|
|||
fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr);
|
||||
x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf,
|
||||
mgr, x72c_currentBeam->GetWeaponType(), targetId);
|
||||
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Character);
|
||||
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire);
|
||||
x3a0_missileExitTimer = 7.f;
|
||||
if (!x832_26_comboFiring)
|
||||
{
|
||||
|
@ -1659,7 +1659,7 @@ void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr)
|
|||
homingTarget = kInvalidUniqueId;
|
||||
x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget,
|
||||
x340_chargeBeamFactor, x340_chargeBeamFactor);
|
||||
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Character);
|
||||
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire);
|
||||
}
|
||||
|
||||
void CPlayerGun::ProcessNormalState(u32 releasedStates, u32 pressedStates, CStateManager& mgr, float dt)
|
||||
|
|
|
@ -44,7 +44,7 @@ void CPowerBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CState
|
|||
if (mgr.GetPlayerState()->IsPlayerAlive())
|
||||
{
|
||||
CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1);
|
||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::Bomb);
|
||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -420,7 +420,7 @@ void CActor::OnScanStateChanged(EScanState state, CStateManager& mgr)
|
|||
|
||||
zeus::CAABox CActor::GetSortingBounds(const CStateManager&) const { return x9c_renderBounds; }
|
||||
|
||||
void CActor::DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType event, float)
|
||||
void CActor::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType event, float dt)
|
||||
{
|
||||
if (event == EUserEventType::LoopedSoundStop)
|
||||
RemoveEmitter();
|
||||
|
|
|
@ -132,7 +132,7 @@ public:
|
|||
virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&);
|
||||
virtual void OnScanStateChanged(EScanState, CStateManager&);
|
||||
virtual zeus::CAABox GetSortingBounds(const CStateManager&) const;
|
||||
virtual void DoUserAnimEvent(CStateManager&, CInt32POINode&, EUserEventType, float dt);
|
||||
virtual void DoUserAnimEvent(CStateManager&, const CInt32POINode&, EUserEventType, float dt);
|
||||
|
||||
void RemoveEmitter();
|
||||
void SetVolume(float vol);
|
||||
|
|
|
@ -17,14 +17,16 @@ namespace urde
|
|||
|
||||
enum class EListenNoiseType
|
||||
{
|
||||
Character,
|
||||
Bomb,
|
||||
Projectile
|
||||
PlayerFire,
|
||||
BombExplode,
|
||||
ProjectileExplode
|
||||
};
|
||||
|
||||
class CAiFuncMap;
|
||||
class CStateManager;
|
||||
class CScriptWater;
|
||||
class CTeamAiRole;
|
||||
|
||||
class CAi : public CPhysicsActor
|
||||
{
|
||||
static CAiFuncMap* m_FuncMap;
|
||||
|
@ -52,12 +54,13 @@ public:
|
|||
virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {}
|
||||
virtual bool CanBeShot(const CStateManager&, int) { return true; }
|
||||
virtual bool IsListening() const { return false; }
|
||||
virtual int Listen(const zeus::CVector3f&, EListenNoiseType) { return 0; }
|
||||
virtual bool Listen(const zeus::CVector3f&, EListenNoiseType) { return 0; }
|
||||
virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||
const CWeaponMode&, EProjectileAttrib) const;
|
||||
void FluidFXThink(EFluidState, CScriptWater&, CStateManager&);
|
||||
|
||||
virtual zeus::CVector3f GetOrigin() const { return x34_transform.origin; }
|
||||
virtual zeus::CVector3f GetOrigin(const CStateManager& mgr, const CTeamAiRole& role) const
|
||||
{ return x34_transform.origin; }
|
||||
virtual void Patrol(CStateManager&, EStateMsg, float) {}
|
||||
virtual void FollowPattern(CStateManager&, EStateMsg, float) {}
|
||||
virtual void Dead(CStateManager&, EStateMsg, float) {}
|
||||
|
@ -116,7 +119,7 @@ public:
|
|||
|
||||
virtual bool InAttackPosition(CStateManager&, float) { return false; }
|
||||
virtual bool Leash(CStateManager&, float) { return false; }
|
||||
virtual bool OffLine(CStateManager&,float) { return false; }
|
||||
virtual bool OffLine(CStateManager&, float) { return false; }
|
||||
virtual bool Attacked(CStateManager&, float) { return false; }
|
||||
virtual bool PathShagged(CStateManager&, float) { return false; }
|
||||
virtual bool PathOver(CStateManager&, float) { return false; }
|
||||
|
@ -146,20 +149,20 @@ public:
|
|||
virtual bool Stuck(CStateManager&, float) { return false; }
|
||||
virtual bool NoPathNodes(CStateManager&, float) { return false; }
|
||||
virtual bool Landed(CStateManager&, float) { return false; }
|
||||
virtual bool HearShot(CStateManager&,float) { return false; }
|
||||
virtual bool HearPlayer(CStateManager&,float) { return false; }
|
||||
virtual bool HearShot(CStateManager&, float) { return false; }
|
||||
virtual bool HearPlayer(CStateManager&, float) { return false; }
|
||||
virtual bool CoverCheck(CStateManager&, float) { return false; }
|
||||
virtual bool CoverFind(CStateManager&, float) { return false; }
|
||||
virtual bool CoverBlown(CStateManager&, float) { return false; }
|
||||
virtual bool CoverNearlyBlown(CStateManager&, float) { return false; }
|
||||
virtual bool CoveringFire(CStateManager&, float) { return false; }
|
||||
virtual bool GotUp(CStateManager&, float) { return false; }
|
||||
virtual bool LineOfSight(CStateManager&,float) { return false; }
|
||||
virtual bool LineOfSight(CStateManager&, float) { return false; }
|
||||
virtual bool AggressionCheck(CStateManager&, float) { return false; }
|
||||
virtual bool AttackOver(CStateManager&, float) { return false; }
|
||||
virtual bool ShouldTaunt(CStateManager&,float) { return false; }
|
||||
virtual bool Inside(CStateManager&,float) { return false; }
|
||||
virtual bool ShouldFire(CStateManager&,float) { return false; }
|
||||
virtual bool Inside(CStateManager&, float) { return false; }
|
||||
virtual bool ShouldFire(CStateManager&, float) { return false; }
|
||||
virtual bool ShouldFlinch(CStateManager&, float) { return false; }
|
||||
virtual bool PatrolPathOver(CStateManager&, float) { return false; }
|
||||
virtual bool ShouldDodge(CStateManager&, float) { return false; }
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "Camera/CFirstPersonCamera.hpp"
|
||||
#include "World/CScriptWaypoint.hpp"
|
||||
#include "World/CScriptActorKeyframe.hpp"
|
||||
#include "Weapon/CEnergyProjectile.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
@ -1171,10 +1172,9 @@ void CPatterned::Freeze(CStateManager& mgr, const zeus::CVector3f& pos,
|
|||
|
||||
zeus::CVector3f CPatterned::GetGunEyePos() const
|
||||
{
|
||||
zeus::CVector3f origin = GetOrigin();
|
||||
zeus::CVector3f origin = GetTranslation();
|
||||
zeus::CAABox baseBox = GetBaseBoundingBox();
|
||||
origin.z = 0.6f * (baseBox.max.z - baseBox.min.z) + origin.z;
|
||||
|
||||
return origin;
|
||||
}
|
||||
|
||||
|
@ -1187,6 +1187,98 @@ void CPatterned::SetupPlayerCollision(bool v)
|
|||
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
|
||||
}
|
||||
|
||||
void CPatterned::LaunchProjectile(
|
||||
const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib,
|
||||
bool playerHoming, const std::experimental::optional<TLockedToken<CGenDescription>>& visorParticle,
|
||||
u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale)
|
||||
{
|
||||
CProjectileInfo* pInfo = GetProjectileInfo();
|
||||
if (pInfo->Token().IsLoaded())
|
||||
{
|
||||
if (mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, maxAllowed))
|
||||
{
|
||||
TUniqueId homingId = playerHoming ? mgr.GetPlayer().GetUniqueId() : kInvalidUniqueId;
|
||||
CEnergyProjectile* newProjectile = new CEnergyProjectile(true, pInfo->Token(), EWeaponType::AI,
|
||||
gunXf, EMaterialTypes::Character, pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(),
|
||||
GetUniqueId(), homingId, attrib, false, scale, visorParticle, visorSfx, sendCollideMsg);
|
||||
mgr.AddObject(newProjectile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case EUserEventType::Projectile:
|
||||
{
|
||||
zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName());
|
||||
zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
||||
if ((aimPos - lctrXf.origin).normalized().dot(lctrXf.basis[1]) > 0.f)
|
||||
{
|
||||
zeus::CTransform gunXf = zeus::lookAt(lctrXf.origin, aimPos);
|
||||
LaunchProjectile(gunXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne);
|
||||
}
|
||||
else
|
||||
{
|
||||
LaunchProjectile(lctrXf, mgr, 1, EProjectileAttrib::None, false, {}, 0xffff, false, zeus::CVector3f::skOne);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EUserEventType::DamageOn:
|
||||
{
|
||||
zeus::CTransform lctrXf = GetLctrTransform(node.GetLocatorName());
|
||||
zeus::CVector3f xfOrigin = x34_transform * (x64_modelData->GetScale() * lctrXf.origin);
|
||||
zeus::CVector3f margin = zeus::CVector3f(1.f, 1.f, 0.5f) * x64_modelData->GetScale();
|
||||
if (zeus::CAABox(xfOrigin - margin, xfOrigin + margin).intersects(mgr.GetPlayer().GetBoundingBox()))
|
||||
{
|
||||
mgr.ApplyDamage(GetUniqueId(), mgr.GetPlayer().GetUniqueId(), GetUniqueId(),
|
||||
GetContactDamage(), CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}),
|
||||
zeus::CVector3f::skZero);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EUserEventType::Delete:
|
||||
{
|
||||
if (!x400_25_alive)
|
||||
{
|
||||
if (!x400_27_fadeToDeath)
|
||||
{
|
||||
x3e8_alphaDelta = -0.333333f;
|
||||
x400_27_fadeToDeath = true;
|
||||
}
|
||||
RemoveMaterial(EMaterialTypes::Character, EMaterialTypes::Solid,
|
||||
EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
|
||||
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeathDelete(mgr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case EUserEventType::BreakLockOn:
|
||||
{
|
||||
RemoveMaterial(EMaterialTypes::Character,
|
||||
EMaterialTypes::Target, EMaterialTypes::Orbit, mgr);
|
||||
break;
|
||||
}
|
||||
case EUserEventType::BecomeShootThrough:
|
||||
{
|
||||
AddMaterial(EMaterialTypes::ProjectilePassthrough, mgr);
|
||||
break;
|
||||
}
|
||||
case EUserEventType::RemoveCollision:
|
||||
{
|
||||
RemoveMaterial(EMaterialTypes::Solid, mgr);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
CActor::DoUserAnimEvent(mgr, node, type, dt);
|
||||
}
|
||||
|
||||
void CPatterned::UpdateAlphaDelta(float dt, CStateManager& mgr)
|
||||
{
|
||||
if (x3e8_alphaDelta == 0.f)
|
||||
|
|
|
@ -408,6 +408,10 @@ public:
|
|||
CBodyController* BodyController() { return x450_bodyController.get(); }
|
||||
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
|
||||
void SetupPlayerCollision(bool);
|
||||
void LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib,
|
||||
bool playerHoming, const std::experimental::optional<TLockedToken<CGenDescription>>& visorParticle,
|
||||
u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale);
|
||||
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt);
|
||||
|
||||
void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; }
|
||||
void UpdateAlphaDelta(float dt, CStateManager& mgr);
|
||||
|
|
|
@ -688,6 +688,7 @@ public:
|
|||
float GetMoveSpeed() const { return x4f8_moveSpeed; }
|
||||
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
|
||||
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
||||
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,28 +1,435 @@
|
|||
#include "CTeamAiMgr.hpp"
|
||||
#include "TCastTo.hpp"
|
||||
#include "CStateManager.hpp"
|
||||
#include "CPlayer.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
|
||||
struct TeamAiRoleSorter
|
||||
{
|
||||
zeus::CVector3f x0_pos;
|
||||
s32 xc_type;
|
||||
bool operator()(const CTeamAiRole& a, const CTeamAiRole& b) const
|
||||
{
|
||||
float aDist = (x0_pos - a.GetTeamPosition()).magSquared();
|
||||
float bDist = (x0_pos - b.GetTeamPosition()).magSquared();
|
||||
switch (xc_type)
|
||||
{
|
||||
case 0:
|
||||
return a.GetOwnerId() < b.GetOwnerId();
|
||||
case 1:
|
||||
return aDist < bDist;
|
||||
default:
|
||||
if (a.GetTeamAiRole() == b.GetTeamAiRole())
|
||||
return aDist < bDist;
|
||||
else
|
||||
return a.GetTeamAiRole() < b.GetTeamAiRole();
|
||||
}
|
||||
}
|
||||
TeamAiRoleSorter(const zeus::CVector3f& pos, s32 type) : x0_pos(pos), xc_type(type) {}
|
||||
};
|
||||
|
||||
CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount)
|
||||
: x0_(in.readUint32Big())
|
||||
, x4_(in.readUint32Big())
|
||||
, x8_(in.readUint32Big())
|
||||
, xc_(in.readUint32Big())
|
||||
, x10_(in.readUint32Big())
|
||||
, x14_(in.readUint32Big())
|
||||
, x18_(in.readUint32Big())
|
||||
, x1c_(propCount > 8 ? in.readFloatBig() : 0.f)
|
||||
, x20_(propCount > 8 ? in.readFloatBig() : 0.f)
|
||||
: x0_aiCount(in.readUint32Big())
|
||||
, x4_meleeCount(in.readUint32Big())
|
||||
, x8_projectileCount(in.readUint32Big())
|
||||
, xc_unknownCount(in.readUint32Big())
|
||||
, x10_maxMeleeAttackerCount(in.readUint32Big())
|
||||
, x14_maxProjectileAttackerCount(in.readUint32Big())
|
||||
, x18_positionMode(in.readUint32Big())
|
||||
, x1c_meleeTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f)
|
||||
, x20_projectileTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f)
|
||||
{
|
||||
}
|
||||
|
||||
CTeamAiMgr::CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data)
|
||||
: CEntity(uid, info, true, name)
|
||||
: CEntity(uid, info, true, name), x34_data(data)
|
||||
{
|
||||
if (x34_data.x0_aiCount)
|
||||
x58_roles.reserve(x34_data.x0_aiCount);
|
||||
if (x34_data.x4_meleeCount)
|
||||
x68_meleeAttackers.reserve(x34_data.x4_meleeCount);
|
||||
if (x34_data.x8_projectileCount)
|
||||
x78_projectileAttackers.reserve(x34_data.x8_projectileCount);
|
||||
}
|
||||
|
||||
void CTeamAiMgr::Accept(IVisitor& visitor)
|
||||
{
|
||||
visitor.Visit(this);
|
||||
}
|
||||
|
||||
void CTeamAiMgr::UpdateTeamCaptain()
|
||||
{
|
||||
int maxPriority = INT_MIN;
|
||||
x8c_teamCaptainId = kInvalidUniqueId;
|
||||
for (const auto& role : x58_roles)
|
||||
{
|
||||
if (role.x18_captainPriority > maxPriority)
|
||||
{
|
||||
maxPriority = role.x18_captainPriority;
|
||||
x8c_teamCaptainId = role.GetOwnerId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::ShouldUpdateRoles(float dt)
|
||||
{
|
||||
if (x58_roles.empty())
|
||||
return false;
|
||||
|
||||
x88_timeDirty += dt;
|
||||
if (x88_timeDirty >= 1.5f)
|
||||
return true;
|
||||
|
||||
for (const auto& role : x58_roles)
|
||||
{
|
||||
if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial ||
|
||||
role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::ResetRoles(CStateManager& mgr)
|
||||
{
|
||||
for (auto& role : x58_roles)
|
||||
{
|
||||
role.x10_curRole = CTeamAiRole::ETeamAiRole::Initial;
|
||||
role.x14_roleIndex = 0;
|
||||
if (const CAi* ai = static_cast<const CAi*>(mgr.GetObjectById(role.GetOwnerId())))
|
||||
role.x1c_position = ai->GetTranslation();
|
||||
}
|
||||
}
|
||||
|
||||
void CTeamAiMgr::SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos)
|
||||
{
|
||||
TeamAiRoleSorter sorter(pos, 2);
|
||||
std::sort(x58_roles.begin(), x58_roles.end(), sorter);
|
||||
float tierStagger = 4.5f;
|
||||
for (const auto& role : x58_roles)
|
||||
{
|
||||
if (TCastToPtr<CAi> ai = mgr.ObjectById(role.GetOwnerId()))
|
||||
{
|
||||
float length = (ai->GetBaseBoundingBox().max.y - ai->GetBaseBoundingBox().min.y) * 1.5f;
|
||||
if (length > tierStagger)
|
||||
tierStagger = length;
|
||||
}
|
||||
}
|
||||
float curTierDist = tierStagger;
|
||||
int tierTeamSize = 0;
|
||||
int maxTierTeamSize = 3;
|
||||
for (auto& role : x58_roles)
|
||||
{
|
||||
if (TCastToPtr<CAi> ai = mgr.ObjectById(role.GetOwnerId()))
|
||||
{
|
||||
zeus::CVector3f delta = ai->GetTranslation() - pos;
|
||||
zeus::CVector3f newPos;
|
||||
if (delta.canBeNormalized())
|
||||
newPos = pos + delta.normalized() * curTierDist;
|
||||
else
|
||||
newPos = pos + ai->GetTransform().basis[1] * curTierDist;
|
||||
role.x1c_position = newPos;
|
||||
role.x1c_position.z = ai->GetTranslation().z;
|
||||
tierTeamSize += 1;
|
||||
if (tierTeamSize > maxTierTeamSize)
|
||||
{
|
||||
curTierDist += tierStagger;
|
||||
tierTeamSize = 0;
|
||||
maxTierTeamSize += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
TeamAiRoleSorter sorter2(pos, 0);
|
||||
std::sort(x58_roles.begin(), x58_roles.end(), sorter2);
|
||||
}
|
||||
|
||||
void CTeamAiMgr::PositionTeam(CStateManager& mgr)
|
||||
{
|
||||
zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
||||
switch (x34_data.x18_positionMode)
|
||||
{
|
||||
case 1:
|
||||
SpacingSort(mgr, aimPos);
|
||||
break;
|
||||
default:
|
||||
for (auto& role : x58_roles)
|
||||
if (TCastToPtr<CAi> ai = mgr.ObjectById(role.GetOwnerId()))
|
||||
role.x1c_position = ai->GetOrigin(mgr, role);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CTeamAiMgr::AssignRoles(CTeamAiRole::ETeamAiRole assRole, s32 count)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
s32 lastIdx = 0;
|
||||
for (auto& role : x58_roles)
|
||||
{
|
||||
if (role.GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Initial)
|
||||
{
|
||||
if (role.x4_roleA == assRole || role.x8_roleB == assRole || role.xc_roleC == assRole)
|
||||
{
|
||||
role.x10_curRole = assRole;
|
||||
role.x14_roleIndex = lastIdx++;
|
||||
if (lastIdx == count)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CTeamAiMgr::UpdateRoles(CStateManager& mgr)
|
||||
{
|
||||
ResetRoles(mgr);
|
||||
zeus::CVector3f aimPos = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
|
||||
TeamAiRoleSorter sorter(aimPos, 1);
|
||||
std::sort(x58_roles.begin(), x58_roles.end(), sorter);
|
||||
AssignRoles(CTeamAiRole::ETeamAiRole::Melee, x34_data.x4_meleeCount);
|
||||
AssignRoles(CTeamAiRole::ETeamAiRole::Projectile, x34_data.x8_projectileCount);
|
||||
AssignRoles(CTeamAiRole::ETeamAiRole::Unknown, x34_data.xc_unknownCount);
|
||||
for (auto& role : x58_roles)
|
||||
{
|
||||
if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial ||
|
||||
role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Unassigned)
|
||||
role.SetTeamAiRole(CTeamAiRole::ETeamAiRole::Unassigned);
|
||||
}
|
||||
TeamAiRoleSorter sorter2(aimPos, 0);
|
||||
std::sort(x58_roles.begin(), x58_roles.end(), sorter2);
|
||||
x88_timeDirty = 0.f;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::Think(float dt, CStateManager& mgr)
|
||||
{
|
||||
CEntity::Think(dt, mgr);
|
||||
if (ShouldUpdateRoles(dt))
|
||||
UpdateRoles(mgr);
|
||||
PositionTeam(mgr);
|
||||
x90_timeSinceMelee += dt;
|
||||
x94_timeSinceProjectile += dt;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr)
|
||||
{
|
||||
CEntity::AcceptScriptMsg(msg, objId, mgr);
|
||||
}
|
||||
|
||||
CTeamAiRole* CTeamAiMgr::GetTeamAiRole(TUniqueId aiId)
|
||||
{
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId,
|
||||
[](const auto& obj) { return obj.GetOwnerId(); });
|
||||
return search != x58_roles.end() ? &*search : nullptr;
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::IsPartOfTeam(TUniqueId aiId) const
|
||||
{
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId,
|
||||
[](const auto& obj) { return obj.GetOwnerId(); });
|
||||
return search != x58_roles.end();
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::HasTeamAiRole(TUniqueId aiId) const
|
||||
{
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId,
|
||||
[](const auto& obj) { return obj.GetOwnerId(); });
|
||||
return (search != x58_roles.end() &&
|
||||
search->GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial &&
|
||||
search->GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned);
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::IsMeleeAttacker(TUniqueId aiId) const
|
||||
{
|
||||
auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId);
|
||||
return search != x68_meleeAttackers.end();
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::CanAcceptMeleeAttacker(TUniqueId aiId) const
|
||||
{
|
||||
if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval &&
|
||||
x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount)
|
||||
return true;
|
||||
return IsMeleeAttacker(aiId);
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::AddMeleeAttacker(TUniqueId aiId)
|
||||
{
|
||||
if (x90_timeSinceMelee >= x34_data.x1c_meleeTimeInterval &&
|
||||
x68_meleeAttackers.size() < x34_data.x10_maxMeleeAttackerCount && HasTeamAiRole(aiId))
|
||||
{
|
||||
auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId);
|
||||
if (search == x68_meleeAttackers.end())
|
||||
{
|
||||
x68_meleeAttackers.insert(std::lower_bound(
|
||||
x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId), aiId);
|
||||
x90_timeSinceMelee = 0.f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::RemoveMeleeAttacker(TUniqueId aiId)
|
||||
{
|
||||
auto search = rstl::binary_find(x68_meleeAttackers.begin(), x68_meleeAttackers.end(), aiId);
|
||||
if (search != x68_meleeAttackers.end())
|
||||
x68_meleeAttackers.erase(search);
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::IsProjectileAttacker(TUniqueId aiId) const
|
||||
{
|
||||
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId);
|
||||
return search != x78_projectileAttackers.end();
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::CanAcceptProjectileAttacker(TUniqueId aiId) const
|
||||
{
|
||||
if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval &&
|
||||
x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount)
|
||||
return true;
|
||||
return IsProjectileAttacker(aiId);
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::AddProjectileAttacker(TUniqueId aiId)
|
||||
{
|
||||
if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval &&
|
||||
x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount && HasTeamAiRole(aiId))
|
||||
{
|
||||
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId);
|
||||
if (search == x78_projectileAttackers.end())
|
||||
{
|
||||
x78_projectileAttackers.insert(std::lower_bound(
|
||||
x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId), aiId);
|
||||
x94_timeSinceProjectile = 0.f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::RemoveProjectileAttacker(TUniqueId aiId)
|
||||
{
|
||||
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId);
|
||||
if (search != x78_projectileAttackers.end())
|
||||
x78_projectileAttackers.erase(search);
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA,
|
||||
CTeamAiRole::ETeamAiRole roleB, CTeamAiRole::ETeamAiRole roleC)
|
||||
{
|
||||
CTeamAiRole newRole(ai.GetUniqueId(), roleA, roleB, roleC);
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), newRole);
|
||||
if (search == x58_roles.end())
|
||||
{
|
||||
if (x58_roles.size() >= x58_roles.capacity())
|
||||
return false;
|
||||
x58_roles.insert(std::lower_bound(x58_roles.begin(), x58_roles.end(), newRole), newRole);
|
||||
}
|
||||
else
|
||||
{
|
||||
*search = newRole;
|
||||
}
|
||||
UpdateTeamCaptain();
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::RemoveTeamAiRole(TUniqueId aiId)
|
||||
{
|
||||
if (IsMeleeAttacker(aiId))
|
||||
RemoveMeleeAttacker(aiId);
|
||||
if (IsProjectileAttacker(aiId))
|
||||
RemoveProjectileAttacker(aiId);
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId,
|
||||
[](const auto& obj) { return obj.GetOwnerId(); });
|
||||
x58_roles.erase(search);
|
||||
UpdateTeamCaptain();
|
||||
}
|
||||
|
||||
void CTeamAiMgr::ClearTeamAiRole(TUniqueId aiId)
|
||||
{
|
||||
auto search = rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId,
|
||||
[](const auto& obj) { return obj.GetOwnerId(); });
|
||||
if (search != x58_roles.end())
|
||||
search->x10_curRole = CTeamAiRole::ETeamAiRole::Initial;
|
||||
}
|
||||
|
||||
s32 CTeamAiMgr::GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole testRole) const
|
||||
{
|
||||
s32 ret = 0;
|
||||
for (const auto& role : x58_roles)
|
||||
if (role.GetTeamAiRole() == testRole)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
s32 CTeamAiMgr::GetNumAssignedAiRoles() const
|
||||
{
|
||||
s32 ret = 0;
|
||||
for (const auto& role : x58_roles)
|
||||
if (role.GetTeamAiRole() > CTeamAiRole::ETeamAiRole::Initial &&
|
||||
role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Unassigned)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
CTeamAiRole* CTeamAiMgr::GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId)
|
||||
{
|
||||
if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(mgrId))
|
||||
return aimgr->GetTeamAiRole(aiId);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CTeamAiMgr::ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole)
|
||||
{
|
||||
if (TCastToPtr<CTeamAiMgr> tmgr = mgr.ObjectById(mgrId))
|
||||
{
|
||||
if (tmgr->HasTeamAiRole(aiId))
|
||||
{
|
||||
if (type == EAttackType::Melee)
|
||||
{
|
||||
if (tmgr->IsMeleeAttacker(aiId))
|
||||
tmgr->RemoveMeleeAttacker(aiId);
|
||||
}
|
||||
else if (type == EAttackType::Projectile)
|
||||
{
|
||||
if (tmgr->IsProjectileAttacker(aiId))
|
||||
tmgr->RemoveProjectileAttacker(aiId);
|
||||
}
|
||||
if (clearRole)
|
||||
tmgr->ClearTeamAiRole(aiId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId)
|
||||
{
|
||||
if (TCastToPtr<CTeamAiMgr> tmgr = mgr.ObjectById(mgrId))
|
||||
{
|
||||
if (tmgr->HasTeamAiRole(aiId))
|
||||
{
|
||||
if (type == EAttackType::Melee)
|
||||
return tmgr->CanAcceptMeleeAttacker(aiId);
|
||||
else if (type == EAttackType::Projectile)
|
||||
return tmgr->CanAcceptProjectileAttacker(aiId);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CTeamAiMgr::AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId)
|
||||
{
|
||||
if (TCastToPtr<CTeamAiMgr> tmgr = mgr.ObjectById(mgrId))
|
||||
{
|
||||
if (tmgr->HasTeamAiRole(aiId))
|
||||
{
|
||||
if (type == EAttackType::Melee)
|
||||
return tmgr->AddMeleeAttacker(aiId);
|
||||
else if (type == EAttackType::Projectile)
|
||||
return tmgr->AddProjectileAttacker(aiId);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,21 +1,61 @@
|
|||
#pragma once
|
||||
|
||||
#include "CEntity.hpp"
|
||||
#include "zeus/CVector3f.hpp"
|
||||
|
||||
namespace urde
|
||||
{
|
||||
class CStateManager;
|
||||
class CAi;
|
||||
|
||||
class CTeamAiRole
|
||||
{
|
||||
friend class CTeamAiMgr;
|
||||
public:
|
||||
enum class ETeamAiRole
|
||||
{
|
||||
Invalid = -1,
|
||||
Initial,
|
||||
Melee,
|
||||
Projectile,
|
||||
Unknown,
|
||||
Unassigned
|
||||
};
|
||||
private:
|
||||
TUniqueId x0_ownerId;
|
||||
ETeamAiRole x4_roleA = ETeamAiRole::Invalid;
|
||||
ETeamAiRole x8_roleB = ETeamAiRole::Invalid;
|
||||
ETeamAiRole xc_roleC = ETeamAiRole::Invalid;
|
||||
ETeamAiRole x10_curRole = ETeamAiRole::Invalid;
|
||||
s32 x14_roleIndex = -1;
|
||||
s32 x18_captainPriority = 0;
|
||||
zeus::CVector3f x1c_position;
|
||||
public:
|
||||
CTeamAiRole(TUniqueId ownerId, ETeamAiRole a, ETeamAiRole b, ETeamAiRole c)
|
||||
: x0_ownerId(ownerId), x4_roleA(a), x8_roleB(b), xc_roleC(c) {}
|
||||
TUniqueId GetOwnerId() const { return x0_ownerId; }
|
||||
bool HasTeamAiRole() const { return false; }
|
||||
ETeamAiRole GetTeamAiRole() const { return x10_curRole; }
|
||||
void SetTeamAiRole(ETeamAiRole role) { x10_curRole = role; }
|
||||
s32 GetRoleIndex() const { return x14_roleIndex; }
|
||||
void SetRoleIndex(s32 idx) { x14_roleIndex = idx; }
|
||||
const zeus::CVector3f& GetTeamPosition() const { return x1c_position; }
|
||||
void SetTeamPosition(const zeus::CVector3f& pos) { x1c_position = pos; }
|
||||
bool operator<(const CTeamAiRole& other) const { return x0_ownerId < other.x0_ownerId; }
|
||||
};
|
||||
|
||||
class CTeamAiData
|
||||
{
|
||||
u32 x0_;
|
||||
u32 x4_;
|
||||
u32 x8_;
|
||||
u32 xc_;
|
||||
u32 x10_;
|
||||
u32 x14_;
|
||||
u32 x18_;
|
||||
float x1c_;
|
||||
float x20_;
|
||||
friend class CTeamAiMgr;
|
||||
u32 x0_aiCount;
|
||||
u32 x4_meleeCount;
|
||||
u32 x8_projectileCount;
|
||||
u32 xc_unknownCount;
|
||||
u32 x10_maxMeleeAttackerCount;
|
||||
u32 x14_maxProjectileAttackerCount;
|
||||
u32 x18_positionMode;
|
||||
float x1c_meleeTimeInterval;
|
||||
float x20_projectileTimeInterval;
|
||||
public:
|
||||
CTeamAiData(CInputStream& in, s32 propCount);
|
||||
};
|
||||
|
@ -23,9 +63,57 @@ public:
|
|||
class CTeamAiMgr : public CEntity
|
||||
{
|
||||
public:
|
||||
CTeamAiMgr(TUniqueId, std::string_view name, const CEntityInfo&, const CTeamAiData& data);
|
||||
enum class EAttackType
|
||||
{
|
||||
Melee,
|
||||
Projectile
|
||||
};
|
||||
private:
|
||||
CTeamAiData x34_data;
|
||||
std::vector<CTeamAiRole> x58_roles;
|
||||
std::vector<TUniqueId> x68_meleeAttackers;
|
||||
std::vector<TUniqueId> x78_projectileAttackers;
|
||||
float x88_timeDirty = 0.f;
|
||||
TUniqueId x8c_teamCaptainId = kInvalidUniqueId;
|
||||
float x90_timeSinceMelee;
|
||||
float x94_timeSinceProjectile;
|
||||
|
||||
void UpdateTeamCaptain();
|
||||
bool ShouldUpdateRoles(float dt);
|
||||
void ResetRoles(CStateManager& mgr);
|
||||
void AssignRoles(CTeamAiRole::ETeamAiRole role, s32 count);
|
||||
void UpdateRoles(CStateManager& mgr);
|
||||
void SpacingSort(CStateManager& mgr, const zeus::CVector3f& pos);
|
||||
void PositionTeam(CStateManager& mgr);
|
||||
bool IsMeleeAttacker(TUniqueId aiId) const;
|
||||
bool CanAcceptMeleeAttacker(TUniqueId aiId) const;
|
||||
bool AddMeleeAttacker(TUniqueId aiId);
|
||||
void RemoveMeleeAttacker(TUniqueId aiId);
|
||||
bool IsProjectileAttacker(TUniqueId aiId) const;
|
||||
bool CanAcceptProjectileAttacker(TUniqueId aiId) const;
|
||||
bool AddProjectileAttacker(TUniqueId aiId);
|
||||
void RemoveProjectileAttacker(TUniqueId aiId);
|
||||
|
||||
public:
|
||||
CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data);
|
||||
|
||||
void Accept(IVisitor&);
|
||||
void Think(float dt, CStateManager& mgr);
|
||||
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr);
|
||||
CTeamAiRole* GetTeamAiRole(TUniqueId aiId);
|
||||
bool IsPartOfTeam(TUniqueId aiId) const;
|
||||
bool HasTeamAiRole(TUniqueId aiId) const;
|
||||
bool AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA,
|
||||
CTeamAiRole::ETeamAiRole roleB, CTeamAiRole::ETeamAiRole roleC);
|
||||
void RemoveTeamAiRole(TUniqueId aiId);
|
||||
void ClearTeamAiRole(TUniqueId aiId);
|
||||
s32 GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole role) const;
|
||||
s32 GetNumAssignedAiRoles() const;
|
||||
|
||||
static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId);
|
||||
static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole);
|
||||
static bool CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId);
|
||||
static bool AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue