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_DNA_YAML
|
||||||
AT_DECL_DNAV
|
AT_DECL_DNAV
|
||||||
String<-1> name;
|
String<-1> name;
|
||||||
Value<atUint32> unknown1;
|
Value<atUint32> aiCount;
|
||||||
Value<atUint32> unknown2;
|
Value<atUint32> meleeCount;
|
||||||
Value<atUint32> unknown3;
|
Value<atUint32> projectileCount;
|
||||||
Value<atUint32> unknown4;
|
Value<atUint32> unknownCount;
|
||||||
Value<atUint32> unknown5;
|
Value<atUint32> maxMeleeAttackerCount;
|
||||||
Value<atUint32> unknown6;
|
Value<atUint32> maxProjectileAttackerCount;
|
||||||
Value<atUint32> unknown7;
|
Value<atUint32> positionMode;
|
||||||
Value<float> unknown8;
|
Value<float> meleeTimeInterval;
|
||||||
Value<float> unknown9;
|
Value<float> projectileTimeInterval;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,7 +561,7 @@ void CActorLights::ActivateLights(CBooModel& model) const
|
||||||
if (x298_31_disableWorldLights)
|
if (x298_31_disableWorldLights)
|
||||||
{
|
{
|
||||||
zeus::CColor color(x2d4_worldLightingLevel);
|
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();
|
//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)
|
void CIkChain::Solve(zeus::CQuaternion& q1, zeus::CQuaternion& q2, const zeus::CVector3f& vec)
|
||||||
{
|
{
|
||||||
const float mag = vec.magnitude();
|
const float mag = vec.magnitude();
|
||||||
|
|
|
@ -65,66 +65,68 @@ void CRagDoll::CRagDollPlaneConstraint::Update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CRagDoll::CRagDoll(float f1, float f2, float f3, u32 flags)
|
CRagDoll::CRagDoll(float normalGravity, float floatingGravity, float overTime, u32 flags)
|
||||||
: x44_f1(f1), x48_f2(f2), x50_f3(f3)
|
: x44_normalGravity(normalGravity), x48_floatingGravity(floatingGravity), x50_overTimer(overTime)
|
||||||
{
|
{
|
||||||
x68_27_ = bool(flags & 0x1);
|
x68_27_continueSmallMovements = bool(flags & 0x1);
|
||||||
x68_28_ = bool(flags & 0x2);
|
x68_28_noOverTimer = bool(flags & 0x2);
|
||||||
x68_29_ = bool(flags & 0x4);
|
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;
|
float fps = 1.f / dt;
|
||||||
x64_angTimer += dt;
|
x64_angTimer += dt;
|
||||||
if (x64_angTimer > 4.f)
|
if (x64_angTimer > 4.f)
|
||||||
x64_angTimer -= 4.f;
|
x64_angTimer -= 4.f;
|
||||||
float f25 = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (f2 - 0.2f);
|
float targetZ = std::sin(zeus::degToRad(90.f) * x64_angTimer) * 0.1f + (waterTop - 0.2f);
|
||||||
zeus::CVector3f f29;
|
zeus::CVector3f centerOfVolume;
|
||||||
float f24 = 0.f;
|
float totalVolume = 0.f;
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
{
|
{
|
||||||
float cubed = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||||
f24 += cubed;
|
totalVolume += volume;
|
||||||
f29 += particle.x4_curPos * cubed;
|
centerOfVolume += particle.x4_curPos * volume;
|
||||||
float f7 = particle.x4_curPos.z - f25;
|
float fromTargetZ = particle.x4_curPos.z - targetZ;
|
||||||
float f8 = x48_f2;
|
float verticalAcc = x48_floatingGravity;
|
||||||
float f23 = 0.f;
|
float termVelCoefficient = 0.f;
|
||||||
if (std::fabs(f7) < 0.5f)
|
if (std::fabs(fromTargetZ) < 0.5f)
|
||||||
{
|
{
|
||||||
f23 = 0.5f * f7 / 0.5f + 0.5f;
|
termVelCoefficient = 0.5f * fromTargetZ / 0.5f + 0.5f;
|
||||||
f8 = x48_f2 * -f7 / 0.5f;
|
verticalAcc = x48_floatingGravity * -fromTargetZ / 0.5f;
|
||||||
}
|
}
|
||||||
else if (f7 > 0.f)
|
else if (fromTargetZ > 0.f)
|
||||||
{
|
{
|
||||||
f8 = x44_f1;
|
verticalAcc = x44_normalGravity;
|
||||||
f23 = 1.f;
|
termVelCoefficient = 1.f;
|
||||||
}
|
}
|
||||||
particle.x20_acceleration.z += f8;
|
particle.x20_velocity.z += verticalAcc;
|
||||||
zeus::CVector3f vel = (particle.x4_curPos - particle.x14_prevPos) * fps;
|
zeus::CVector3f vel = (particle.x4_curPos - particle.x14_prevPos) * fps;
|
||||||
float velMag = vel.magnitude();
|
float velMag = vel.magnitude();
|
||||||
if (velMag > FLT_EPSILON)
|
if (velMag > FLT_EPSILON)
|
||||||
{
|
{
|
||||||
particle.x20_acceleration -= vel * (1.f / velMag) *
|
particle.x20_velocity -= vel * (1.f / velMag) *
|
||||||
((velMag * velMag * 0.75f * (1.2f * f23 + 1000.f * (1.f - f23))) / (8000.f * particle.x10_radius));
|
((velMag * velMag * 0.75f * (1.2f * termVelCoefficient + 1000.f *
|
||||||
|
(1.f - termVelCoefficient))) / (8000.f * particle.x10_radius));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zeus::CVector3f _c8;
|
zeus::CVector3f averageTorque;
|
||||||
f29 = f29 / f24;
|
centerOfVolume = centerOfVolume / totalVolume;
|
||||||
for (const auto& particle : x4_particles)
|
for (const auto& particle : x4_particles)
|
||||||
{
|
{
|
||||||
float cubed = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
float volume = particle.x10_radius * particle.x10_radius * particle.x10_radius;
|
||||||
_c8 += (particle.x4_curPos - f29).cross(particle.x4_curPos) * cubed;
|
averageTorque += (particle.x4_curPos - centerOfVolume).
|
||||||
|
cross(particle.x4_curPos - particle.x14_prevPos) * volume;
|
||||||
}
|
}
|
||||||
_c8 = _c8 * (fps / f24);
|
averageTorque = averageTorque * (fps / totalVolume);
|
||||||
if (_c8.canBeNormalized())
|
if (averageTorque.canBeNormalized())
|
||||||
for (auto& particle : x4_particles)
|
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)
|
void CRagDoll::AddLengthConstraint(int i1, int i2)
|
||||||
|
@ -173,42 +175,42 @@ zeus::CAABox CRagDoll::CalculateRenderBounds() const
|
||||||
|
|
||||||
void CRagDoll::CheckStatic(float dt)
|
void CRagDoll::CheckStatic(float dt)
|
||||||
{
|
{
|
||||||
x4c_ = 0;
|
x4c_impactCount = 0;
|
||||||
x54_ = 0.f;
|
x54_impactVel = 0.f;
|
||||||
float f1 = 0.5f * dt;
|
float halfDt = 0.5f * dt;
|
||||||
float f31 = f1 * f1;
|
float halfDeltaUnitSq = halfDt * halfDt;
|
||||||
x58_ = zeus::CVector3f::skZero;
|
x58_averageVel = zeus::CVector3f::skZero;
|
||||||
bool r31 = true;
|
bool movingSlowly = true;
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
{
|
{
|
||||||
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
|
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
|
||||||
x58_ += delta;
|
x58_averageVel += delta;
|
||||||
if (delta.magSquared() > f31)
|
if (delta.magSquared() > halfDeltaUnitSq)
|
||||||
r31 = false;
|
movingSlowly = false;
|
||||||
if (particle.x3c_24_nextDampVel)
|
if (particle.x3c_24_impactPending)
|
||||||
{
|
{
|
||||||
x4c_ += 1;
|
x4c_impactCount += 1;
|
||||||
x54_ = std::max(particle.x38_, x54_);
|
x54_impactVel = std::max(particle.x38_impactFrameVel, x54_impactVel);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!x4_particles.empty())
|
if (!x4_particles.empty())
|
||||||
x58_ = x58_ * (1.f / (dt * x4_particles.size()));
|
x58_averageVel = x58_averageVel * (1.f / (dt * x4_particles.size()));
|
||||||
x54_ /= dt;
|
x54_impactVel /= dt;
|
||||||
if (!x68_28_)
|
if (!x68_28_noOverTimer)
|
||||||
{
|
{
|
||||||
x50_f3 -= dt;
|
x50_overTimer -= dt;
|
||||||
if (x50_f3 <= 0.f)
|
if (x50_overTimer <= 0.f)
|
||||||
x68_25_ = true;
|
x68_25_over = true;
|
||||||
}
|
}
|
||||||
if (r31 && x68_24_)
|
if (movingSlowly && x68_24_prevMovingSlowly)
|
||||||
x68_25_ = true;
|
x68_25_over = true;
|
||||||
x68_24_ = r31;
|
x68_24_prevMovingSlowly = movingSlowly;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRagDoll::ClearForces()
|
void CRagDoll::ClearForces()
|
||||||
{
|
{
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
particle.x20_acceleration = zeus::CVector3f::skZero;
|
particle.x20_velocity = zeus::CVector3f::skZero;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRagDoll::SatisfyConstraints(CStateManager& mgr)
|
void CRagDoll::SatisfyConstraints(CStateManager& mgr)
|
||||||
|
@ -223,12 +225,12 @@ void CRagDoll::SatisfyConstraints(CStateManager& mgr)
|
||||||
SatisfyWorldConstraints(mgr, 2);
|
SatisfyWorldConstraints(mgr, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int pass)
|
||||||
{
|
{
|
||||||
zeus::CAABox aabb;
|
zeus::CAABox aabb;
|
||||||
for (const auto& particle : x4_particles)
|
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);
|
||||||
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);
|
CAreaCollisionCache ccache(aabb);
|
||||||
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
|
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
|
||||||
bool ret = false;
|
bool needs2ndPass = false;
|
||||||
|
|
||||||
TUniqueId bestId = kInvalidUniqueId;
|
TUniqueId bestId = kInvalidUniqueId;
|
||||||
CMaterialList include;
|
CMaterialList include;
|
||||||
if (x68_29_)
|
if (x68_29_noAiCollision)
|
||||||
include = CMaterialList(EMaterialTypes::Solid);
|
include = CMaterialList(EMaterialTypes::Solid);
|
||||||
else
|
else
|
||||||
include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock);
|
include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock);
|
||||||
|
|
||||||
CMaterialList exclude;
|
CMaterialList exclude;
|
||||||
if (x68_29_)
|
if (x68_29_noAiCollision)
|
||||||
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player,
|
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player,
|
||||||
EMaterialTypes::AIBlock, EMaterialTypes::Occluder);
|
EMaterialTypes::AIBlock, EMaterialTypes::Occluder);
|
||||||
else
|
else
|
||||||
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player);
|
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player);
|
||||||
|
|
||||||
|
@ -261,7 +263,7 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
||||||
|
|
||||||
for (auto& particle : x4_particles)
|
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;
|
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
|
||||||
float deltaMag = delta.magnitude();
|
float deltaMag = delta.magnitude();
|
||||||
|
@ -275,15 +277,15 @@ bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
|
||||||
nearList, delta, bestId, info, d);
|
nearList, delta, bestId, info, d);
|
||||||
if (info.IsValid())
|
if (info.IsValid())
|
||||||
{
|
{
|
||||||
ret = true;
|
needs2ndPass = true;
|
||||||
switch (i1)
|
switch (pass)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
{
|
{
|
||||||
particle.x3c_24_nextDampVel = true;
|
particle.x3c_24_impactPending = true;
|
||||||
float dot = delta.dot(info.GetNormalLeft());
|
float dot = delta.dot(info.GetNormalLeft());
|
||||||
particle.x2c_nextPosDelta = -0.125f * dot * deltaMag * info.GetNormalLeft();
|
particle.x2c_impactResponseDelta = -0.125f * dot * deltaMag * info.GetNormalLeft();
|
||||||
particle.x38_ = -dot * deltaMag;
|
particle.x38_impactFrameVel = -dot * deltaMag;
|
||||||
particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft();
|
particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft();
|
||||||
break;
|
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;
|
particle.x4_curPos = particle.x14_prevPos;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return needs2ndPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr)
|
void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr)
|
||||||
{
|
{
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
particle.x3c_24_nextDampVel = true;
|
particle.x3c_24_impactPending = true;
|
||||||
SatisfyWorldConstraints(mgr, 2);
|
SatisfyWorldConstraints(mgr, 2);
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
particle.x14_prevPos = particle.x4_curPos;
|
particle.x14_prevPos = particle.x4_curPos;
|
||||||
|
@ -320,15 +322,15 @@ void CRagDoll::Verlet(float dt)
|
||||||
{
|
{
|
||||||
zeus::CVector3f oldPos = particle.x4_curPos;
|
zeus::CVector3f oldPos = particle.x4_curPos;
|
||||||
particle.x4_curPos += (particle.x4_curPos - particle.x14_prevPos) *
|
particle.x4_curPos += (particle.x4_curPos - particle.x14_prevPos) *
|
||||||
(particle.x3c_24_nextDampVel ? 0.9f : 1.f);
|
(particle.x3c_24_impactPending ? 0.9f : 1.f);
|
||||||
particle.x4_curPos += particle.x20_acceleration * (dt * dt);
|
particle.x4_curPos += particle.x20_velocity * (dt * dt);
|
||||||
particle.x4_curPos += particle.x2c_nextPosDelta;
|
particle.x4_curPos += particle.x2c_impactResponseDelta;
|
||||||
particle.x14_prevPos = oldPos;
|
particle.x14_prevPos = oldPos;
|
||||||
zeus::CVector3f deltaPos = particle.x4_curPos - particle.x14_prevPos;
|
zeus::CVector3f deltaPos = particle.x4_curPos - particle.x14_prevPos;
|
||||||
if (deltaPos.magSquared() > 4.f)
|
if (deltaPos.magSquared() > 4.f)
|
||||||
particle.x4_curPos = deltaPos.normalized() * 2.f + particle.x14_prevPos;
|
particle.x4_curPos = deltaPos.normalized() * 2.f + particle.x14_prevPos;
|
||||||
particle.x3c_24_nextDampVel = false;
|
particle.x3c_24_impactPending = false;
|
||||||
particle.x2c_nextPosDelta = zeus::CVector3f::skZero;
|
particle.x2c_impactResponseDelta = zeus::CVector3f::skZero;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,11 +339,11 @@ void CRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData)
|
||||||
// Empty
|
// 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);
|
Verlet(dt);
|
||||||
SatisfyConstraints(mgr);
|
SatisfyConstraints(mgr);
|
||||||
ClearForces();
|
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;
|
particle.x4_curPos = xf * aData->GetPose().GetOffset(particle.x0_id) * scale;
|
||||||
SatisfyWorldConstraints(mgr, 2);
|
SatisfyWorldConstraints(mgr, 2);
|
||||||
for (auto& particle : x4_particles)
|
for (auto& particle : x4_particles)
|
||||||
particle.x3c_24_nextDampVel = false;
|
particle.x3c_24_impactPending = false;
|
||||||
x68_26_primed = true;
|
x68_26_primed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,23 +22,23 @@ protected:
|
||||||
zeus::CVector3f x4_curPos;
|
zeus::CVector3f x4_curPos;
|
||||||
float x10_radius;
|
float x10_radius;
|
||||||
zeus::CVector3f x14_prevPos;
|
zeus::CVector3f x14_prevPos;
|
||||||
zeus::CVector3f x20_acceleration;
|
zeus::CVector3f x20_velocity;
|
||||||
zeus::CVector3f x2c_nextPosDelta;
|
zeus::CVector3f x2c_impactResponseDelta;
|
||||||
float x38_ = 0.f;
|
float x38_impactFrameVel = 0.f;
|
||||||
bool x3c_24_nextDampVel : 1;
|
bool x3c_24_impactPending : 1;
|
||||||
bool x3c_25_ : 1;
|
bool x3c_25_ : 1;
|
||||||
public:
|
public:
|
||||||
CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float f1, const zeus::CVector3f& prevPos)
|
CRagDollParticle(CSegId id, const zeus::CVector3f& curPos, float radius, const zeus::CVector3f& prevPos)
|
||||||
: x0_id(id), x4_curPos(curPos), x10_radius(f1), x14_prevPos(prevPos)
|
: x0_id(id), x4_curPos(curPos), x10_radius(radius), x14_prevPos(prevPos)
|
||||||
{
|
{
|
||||||
x3c_24_nextDampVel = false;
|
x3c_24_impactPending = false;
|
||||||
x3c_25_ = false;
|
x3c_25_ = false;
|
||||||
}
|
}
|
||||||
CSegId GetBone() const { return x0_id; }
|
CSegId GetBone() const { return x0_id; }
|
||||||
const zeus::CVector3f& GetPosition() const { return x4_curPos; }
|
const zeus::CVector3f& GetPosition() const { return x4_curPos; }
|
||||||
zeus::CVector3f& Position() { return x4_curPos; }
|
zeus::CVector3f& Position() { return x4_curPos; }
|
||||||
const zeus::CVector3f& GetAcceleration() const { return x20_acceleration; }
|
const zeus::CVector3f& GetVelocity() const { return x20_velocity; }
|
||||||
zeus::CVector3f& Acceleration() { return x20_acceleration; }
|
zeus::CVector3f& Velocity() { return x20_velocity; }
|
||||||
float GetRadius() const { return x10_radius; }
|
float GetRadius() const { return x10_radius; }
|
||||||
};
|
};
|
||||||
class CRagDollLengthConstraint
|
class CRagDollLengthConstraint
|
||||||
|
@ -87,29 +87,29 @@ protected:
|
||||||
std::vector<CRagDollLengthConstraint> x14_lengthConstraints;
|
std::vector<CRagDollLengthConstraint> x14_lengthConstraints;
|
||||||
std::vector<CRagDollJointConstraint> x24_jointConstraints;
|
std::vector<CRagDollJointConstraint> x24_jointConstraints;
|
||||||
std::vector<CRagDollPlaneConstraint> x34_planeConstraints;
|
std::vector<CRagDollPlaneConstraint> x34_planeConstraints;
|
||||||
float x44_f1;
|
float x44_normalGravity;
|
||||||
float x48_f2;
|
float x48_floatingGravity;
|
||||||
u32 x4c_ = 0;
|
u32 x4c_impactCount = 0;
|
||||||
float x50_f3;
|
float x50_overTimer;
|
||||||
float x54_ = 0.f;
|
float x54_impactVel = 0.f;
|
||||||
zeus::CVector3f x58_;
|
zeus::CVector3f x58_averageVel;
|
||||||
float x64_angTimer = 0.f;
|
float x64_angTimer = 0.f;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool x68_24_ : 1;
|
bool x68_24_prevMovingSlowly : 1;
|
||||||
bool x68_25_ : 1;
|
bool x68_25_over : 1;
|
||||||
bool x68_26_primed : 1;
|
bool x68_26_primed : 1;
|
||||||
bool x68_27_ : 1;
|
bool x68_27_continueSmallMovements : 1;
|
||||||
bool x68_28_ : 1;
|
bool x68_28_noOverTimer : 1;
|
||||||
bool x68_29_ : 1;
|
bool x68_29_noAiCollision : 1;
|
||||||
};
|
};
|
||||||
u32 _dummy = 0;
|
u32 _dummy = 0;
|
||||||
};
|
};
|
||||||
void AccumulateForces(float dt, float f2);
|
void AccumulateForces(float dt, float waterTop);
|
||||||
void SetNumParticles(int num) { x4_particles.reserve(num); }
|
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 SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); }
|
||||||
void AddLengthConstraint(int i1, int i2);
|
void AddLengthConstraint(int i1, int i2);
|
||||||
void AddMaxLengthConstraint(int i1, int i2, float length);
|
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);
|
void AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6);
|
||||||
zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo,
|
zeus::CQuaternion BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo,
|
||||||
int i1, int i2, const zeus::CQuaternion& q);
|
int i1, int i2, const zeus::CQuaternion& q);
|
||||||
zeus::CAABox CalculateRenderBounds() const;
|
|
||||||
void CheckStatic(float dt);
|
void CheckStatic(float dt);
|
||||||
void ClearForces();
|
void ClearForces();
|
||||||
void SatisfyConstraints(CStateManager& mgr);
|
void SatisfyConstraints(CStateManager& mgr);
|
||||||
bool SatisfyWorldConstraints(CStateManager& mgr, int i1);
|
bool SatisfyWorldConstraints(CStateManager& mgr, int pass);
|
||||||
void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr);
|
void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr);
|
||||||
void Verlet(float dt);
|
void Verlet(float dt);
|
||||||
public:
|
public:
|
||||||
virtual ~CRagDoll() = default;
|
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 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);
|
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;
|
CGraphics::g_ColorRegs[1] = color;
|
||||||
}
|
}
|
||||||
|
|
|
@ -269,7 +269,7 @@ public:
|
||||||
void DoThermalBlendHot();
|
void DoThermalBlendHot();
|
||||||
u32 GetStaticWorldDataSize();
|
u32 GetStaticWorldDataSize();
|
||||||
void PrepareDynamicLights(const std::vector<CLight>& lights);
|
void PrepareDynamicLights(const std::vector<CLight>& lights);
|
||||||
void SetWorldLightMultiplyColor(const zeus::CColor& color);
|
void SetGXRegister1Color(const zeus::CColor& color);
|
||||||
void SetWorldLightFadeLevel(float level);
|
void SetWorldLightFadeLevel(float level);
|
||||||
void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken<CTexture>& indTex,
|
void DrawPhazonSuitIndirectEffect(const zeus::CColor& nonIndirectMod, const TLockedToken<CTexture>& indTex,
|
||||||
const zeus::CColor& indirectMod, float blurRadius,
|
const zeus::CColor& indirectMod, float blurRadius,
|
||||||
|
|
|
@ -105,7 +105,7 @@ public:
|
||||||
virtual void DoThermalBlendHot()=0;
|
virtual void DoThermalBlendHot()=0;
|
||||||
virtual u32 GetStaticWorldDataSize()=0;
|
virtual u32 GetStaticWorldDataSize()=0;
|
||||||
virtual void PrepareDynamicLights(const std::vector<CLight>& lights)=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;
|
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)
|
if (evType == EUserEventType::DamageOff)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,7 +23,7 @@ public:
|
||||||
void Accept(IVisitor &visitor);
|
void Accept(IVisitor &visitor);
|
||||||
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &);
|
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager &);
|
||||||
void Think(float, 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&);
|
CFlameThrower* CreateFlameThrower(std::string_view, CStateManager&);
|
||||||
void ResetFlameThrowers(CStateManager& mgr);
|
void ResetFlameThrowers(CStateManager& mgr);
|
||||||
};
|
};
|
||||||
|
|
|
@ -80,7 +80,7 @@ void CFlickerBat::Touch(CActor& act, CStateManager& mgr)
|
||||||
CPatterned::Touch(act, 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);
|
CPatterned::DoUserAnimEvent(mgr, node, type, dt);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ public:
|
||||||
void Think(float, CStateManager&);
|
void Think(float, CStateManager&);
|
||||||
void Render(const CStateManager&) const;
|
void Render(const CStateManager&) const;
|
||||||
void Touch(CActor&, CStateManager&);
|
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);
|
void Death(CStateManager& mgr, const zeus::CVector3f& direction, EScriptObjectState state);
|
||||||
bool CanBeShot(CStateManager&, int);
|
bool CanBeShot(CStateManager&, int);
|
||||||
void Patrol(CStateManager&, EStateMsg, float);
|
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)
|
if (event == EUserEventType::DamageOn)
|
||||||
{
|
{
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
std::experimental::optional<zeus::CAABox> GetTouchBounds() const { return {}; }
|
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 Generate(CStateManager&, EStateMsg, float);
|
||||||
void Attack(CStateManager&, EStateMsg, float);
|
void Attack(CStateManager&, EStateMsg, float);
|
||||||
void Patrol(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
|
class CPirateRagDoll : public CRagDoll
|
||||||
{
|
{
|
||||||
CSpacePirate* x6c_spacePirate;
|
CSpacePirate* x6c_spacePirate;
|
||||||
u16 x70_s1;
|
u16 x70_thudSfx;
|
||||||
float x74_ = 0.f;
|
float x74_sfxTimer = 0.f;
|
||||||
zeus::CVector3f x78_;
|
zeus::CVector3f x78_lastSFXPos;
|
||||||
zeus::CVector3f x84_;
|
zeus::CVector3f x84_torsoImpulse;
|
||||||
rstl::reserved_vector<TUniqueId, 4> x90_waypoints;
|
rstl::reserved_vector<TUniqueId, 4> x90_waypoints;
|
||||||
rstl::reserved_vector<u32, 4> x9c_wpParticleIdxs;
|
rstl::reserved_vector<u32, 4> x9c_wpParticleIdxs;
|
||||||
bool xb0_24_ : 1;
|
bool xb0_24_initSfx : 1;
|
||||||
public:
|
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 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);
|
void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,23 +44,23 @@ private:
|
||||||
float x8_;
|
float x8_;
|
||||||
float xc_;
|
float xc_;
|
||||||
float x10_;
|
float x10_;
|
||||||
float x14_;
|
float x14_hearNoiseRange;
|
||||||
u32 x18_;
|
u32 x18_flags;
|
||||||
bool x1c_;
|
bool x1c_;
|
||||||
CProjectileInfo x20_;
|
CProjectileInfo x20_mainProjectileInfo;
|
||||||
u16 x48_;
|
u16 x48_;
|
||||||
CDamageInfo x4c_;
|
CDamageInfo x4c_;
|
||||||
float x68_;
|
float x68_;
|
||||||
CProjectileInfo x6c_;
|
CProjectileInfo x6c_;
|
||||||
float x94_;
|
float x94_;
|
||||||
u16 x98_;
|
u16 x98_ragdollThudSfx;
|
||||||
float x9c_;
|
float x9c_averageNextShotTime;
|
||||||
float xa0_;
|
float xa0_nextShotTimeVariation;
|
||||||
u16 xa4_;
|
u16 xa4_;
|
||||||
float xa8_;
|
float xa8_aimDelayTime;
|
||||||
u32 xac_firstBurstCount;
|
u32 xac_firstBurstCount;
|
||||||
float xb0_;
|
float xb0_minCloakAlpha;
|
||||||
float xb4_;
|
float xb4_maxCloakAlpha;
|
||||||
float xb8_;
|
float xb8_;
|
||||||
float xbc_;
|
float xbc_;
|
||||||
u16 xc0_;
|
u16 xc0_;
|
||||||
|
@ -76,24 +76,24 @@ private:
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
bool x634_24_ : 1;
|
bool x634_24_pendingAmbush : 1;
|
||||||
bool x634_25_ : 1;
|
bool x634_25_ceilingAmbush : 1;
|
||||||
bool x634_26_ : 1;
|
bool x634_26_ : 1;
|
||||||
bool x634_27_ : 1;
|
bool x634_27_melee : 1;
|
||||||
bool x634_28_ : 1;
|
bool x634_28_ : 1;
|
||||||
bool x634_29_ : 1;
|
bool x634_29_onlyAttackInRange : 1;
|
||||||
bool x634_30_ : 1;
|
bool x634_30_ : 1;
|
||||||
bool x634_31_ : 1;
|
bool x634_31_ : 1;
|
||||||
bool x635_24_ : 1;
|
bool x635_24_ : 1;
|
||||||
bool x635_25_ : 1;
|
bool x635_25_ : 1;
|
||||||
bool x635_26_ : 1;
|
bool x635_26_ : 1;
|
||||||
bool x635_27_ : 1;
|
bool x635_27_shadowPirate : 1;
|
||||||
bool x635_28_ : 1;
|
bool x635_28_ : 1;
|
||||||
bool x635_29_ : 1;
|
bool x635_29_ : 1;
|
||||||
bool x635_30_ : 1;
|
bool x635_30_ragdollKeepAlive : 1;
|
||||||
bool x635_31_ : 1;
|
bool x635_31_ragdollNoAiCollision : 1;
|
||||||
bool x636_24_trooper : 1;
|
bool x636_24_trooper : 1;
|
||||||
bool x636_25_ : 1;
|
bool x636_25_hearNoise : 1;
|
||||||
bool x636_26_ : 1;
|
bool x636_26_ : 1;
|
||||||
bool x636_27_ : 1;
|
bool x636_27_ : 1;
|
||||||
bool x636_28_ : 1;
|
bool x636_28_ : 1;
|
||||||
|
@ -102,19 +102,19 @@ private:
|
||||||
bool x636_31_ : 1;
|
bool x636_31_ : 1;
|
||||||
bool x637_24_ : 1;
|
bool x637_24_ : 1;
|
||||||
bool x637_25_ : 1;
|
bool x637_25_ : 1;
|
||||||
bool x637_26_ : 1;
|
bool x637_26_hearPlayerFire : 1;
|
||||||
bool x637_27_ : 1;
|
bool x637_27_inProjectilePath : 1;
|
||||||
bool x637_28_ : 1;
|
bool x637_28_ : 1;
|
||||||
bool x637_29_ : 1;
|
bool x637_29_ : 1;
|
||||||
bool x637_30_ : 1;
|
bool x637_30_ : 1;
|
||||||
bool x637_31_prevInCineCam : 1;
|
bool x637_31_prevInCineCam : 1;
|
||||||
bool x638_24_ : 1;
|
bool x638_24_pendingFrenzyChance : 1;
|
||||||
bool x638_25_ : 1;
|
bool x638_25_ : 1;
|
||||||
bool x638_26_ : 1;
|
bool x638_26_ : 1;
|
||||||
bool x638_27_ : 1;
|
bool x638_27_ : 1;
|
||||||
bool x638_28_ : 1;
|
bool x638_28_ : 1;
|
||||||
bool x638_29_ : 1;
|
bool x638_29_ : 1;
|
||||||
bool x638_30_ : 1;
|
bool x638_30_ragdollOver : 1;
|
||||||
bool x638_31_ : 1;
|
bool x638_31_ : 1;
|
||||||
bool x639_24_ : 1;
|
bool x639_24_ : 1;
|
||||||
bool x639_25_ : 1;
|
bool x639_25_ : 1;
|
||||||
|
@ -130,22 +130,22 @@ private:
|
||||||
u64 _dummy = 0;
|
u64 _dummy = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
u32 x63c_ = 0;
|
s32 x63c_frenzyFrames = 0;
|
||||||
TUniqueId x640_ = kInvalidUniqueId;
|
TUniqueId x640_ = kInvalidUniqueId;
|
||||||
TUniqueId x642_ = kInvalidUniqueId;
|
TUniqueId x642_ = kInvalidUniqueId;
|
||||||
float x644_ = 1.f;
|
float x644_ = 1.f;
|
||||||
zeus::CVector3f x648_ = zeus::CVector3f::skForward;
|
zeus::CVector3f x648_ = zeus::CVector3f::skForward;
|
||||||
zeus::CVector3f x654_;
|
zeus::CVector3f x654_;
|
||||||
CPathFindSearch x660_;
|
CPathFindSearch x660_pathFindSearch;
|
||||||
float x744_ = 0.f;
|
float x744_ = 0.f;
|
||||||
float x748_ = 0.f;
|
float x748_ = 0.f;
|
||||||
u32 x74c_ = 0;
|
u32 x74c_ = 0;
|
||||||
float x750_;
|
float x750_initialHP;
|
||||||
float x754_ = 0.f;
|
float x754_ = 0.f;
|
||||||
CSegId x758_headSeg;
|
CSegId x758_headSeg;
|
||||||
u32 x75c_ = 0;
|
u32 x75c_ = 0;
|
||||||
s32 x760_ = -1;
|
s32 x760_ = -1;
|
||||||
CBoneTracking x764_;
|
CBoneTracking x764_boneTracking;
|
||||||
s32 x79c_ = -1;
|
s32 x79c_ = -1;
|
||||||
float x7a4_intoJumpDist = 1.f;
|
float x7a4_intoJumpDist = 1.f;
|
||||||
float x7a8_ = 2.f;
|
float x7a8_ = 2.f;
|
||||||
|
@ -157,8 +157,8 @@ private:
|
||||||
CSegId x7b8_wristSeg;
|
CSegId x7b8_wristSeg;
|
||||||
CSegId x7b9_swooshSeg;
|
CSegId x7b9_swooshSeg;
|
||||||
float x7bc_ = 1.f;
|
float x7bc_ = 1.f;
|
||||||
TUniqueId x7c0_ = kInvalidUniqueId;
|
TUniqueId x7c0_targetId = kInvalidUniqueId;
|
||||||
CBurstFire x7c4_;
|
CBurstFire x7c4_burstFire;
|
||||||
float x824_ = 3.f;
|
float x824_ = 3.f;
|
||||||
zeus::CVector3f x828_;
|
zeus::CVector3f x828_;
|
||||||
s32 x834_ = -1;
|
s32 x834_ = -1;
|
||||||
|
@ -168,20 +168,20 @@ private:
|
||||||
s32 x844_ = -1;
|
s32 x844_ = -1;
|
||||||
float x848_dodgeDist = 3.f;
|
float x848_dodgeDist = 3.f;
|
||||||
float x84c_breakDodgeDist = 3.f;
|
float x84c_breakDodgeDist = 3.f;
|
||||||
float x850_ = FLT_MAX;
|
float x850_timeSinceHitByPlayer = FLT_MAX;
|
||||||
float x854_ = FLT_MAX;
|
float x854_lowHealthFrenzyTimer = FLT_MAX;
|
||||||
float x858_ = 0.f;
|
float x858_ragdollDelayTimer = 0.f;
|
||||||
std::unique_ptr<CPirateRagDoll> x85c_ragDoll;
|
std::unique_ptr<CPirateRagDoll> x85c_ragDoll;
|
||||||
CIkChain x860_ikChain;
|
CIkChain x860_ikChain;
|
||||||
float x8a8_ = 0.f;
|
float x8a8_cloakDelayTimer = 0.f;
|
||||||
float x8ac_ = 0.f;
|
float x8ac_electricParticleTimer = 0.f;
|
||||||
float x8b0_ = 0.f;
|
float x8b0_cloakStepTime = 0.f;
|
||||||
float x8b4_ = 0.5f;
|
float x8b4_shadowPirateAlpha = 0.5f;
|
||||||
float x8b8_;
|
float x8b8_minCloakAlpha;
|
||||||
float x8bc_;
|
float x8bc_maxCloakAlpha;
|
||||||
float x8c0_;
|
float x8c0_;
|
||||||
float x8c4_;
|
float x8c4_aimDelayTimer;
|
||||||
TUniqueId x8c8_ = kInvalidUniqueId;
|
TUniqueId x8c8_teamAiMgrId = kInvalidUniqueId;
|
||||||
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
|
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
|
||||||
zeus::CVector2f x8d0_;
|
zeus::CVector2f x8d0_;
|
||||||
float x8d8_ = 0.f;
|
float x8d8_ = 0.f;
|
||||||
|
@ -201,11 +201,111 @@ private:
|
||||||
static const SBurst skBurstsQuick[];
|
static const SBurst skBurstsQuick[];
|
||||||
static const SBurst* skBursts[];
|
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:
|
public:
|
||||||
CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
||||||
const CActorParameters&, const CPatternedInfo&, CInputStream&, u32);
|
const CActorParameters&, const CPatternedInfo&, CInputStream&, u32);
|
||||||
|
|
||||||
void Accept(IVisitor &visitor);
|
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.AddObject(gameLight);
|
||||||
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
|
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
|
||||||
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1);
|
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1);
|
||||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::Bomb);
|
mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (msg == EScriptObjectMessage::Deleted)
|
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);
|
mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter);
|
||||||
CSfxManager::AddEmitter(SFXwpn_bomb_explo, GetTranslation(), {}, true, false, 0x7f, -1);
|
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);
|
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
|
||||||
x190_24_isNotDetonated = false;
|
x190_24_isNotDetonated = false;
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,7 @@ public:
|
||||||
void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; }
|
void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; }
|
||||||
void SetBurstType(s32 type) { x0_burstType = type; }
|
void SetBurstType(s32 type) { x0_burstType = type; }
|
||||||
void SetTimeToNextShot(float t) { x8_timeToNextShot = t; }
|
void SetTimeToNextShot(float t) { x8_timeToNextShot = t; }
|
||||||
|
float GetTimeToNextShot() const { return x8_timeToNextShot; }
|
||||||
s32 GetBurstType() const { return x0_burstType; }
|
s32 GetBurstType() const { return x0_burstType; }
|
||||||
void Start(CStateManager& mgr);
|
void Start(CStateManager& mgr);
|
||||||
void Update(CStateManager& mgr, float dt);
|
void Update(CStateManager& mgr, float dt);
|
||||||
|
|
|
@ -334,7 +334,7 @@ bool CEnergyProjectile::Explode(const zeus::CVector3f& pos, const zeus::CVector3
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayImpactSound(pos, type);
|
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))
|
if (auto particle = x170_projectile.CollisionOccured(type, !done, retargetPlayer, offsetPos, normal, targetPos))
|
||||||
{
|
{
|
||||||
zeus::CTransform particleXf = zeus::lookAt(zeus::CVector3f::skZero, normal);
|
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);
|
fireXf.origin += mgr.GetCameraManager()->GetGlobalCameraTranslation(mgr);
|
||||||
x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf,
|
x744_auxWeapon->Fire(dt, x834_27_underwater, x310_currentBeam, x330_chargeState, fireXf,
|
||||||
mgr, x72c_currentBeam->GetWeaponType(), targetId);
|
mgr, x72c_currentBeam->GetWeaponType(), targetId);
|
||||||
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::Character);
|
mgr.InformListeners(x4a8_gunWorldXf.origin, EListenNoiseType::PlayerFire);
|
||||||
x3a0_missileExitTimer = 7.f;
|
x3a0_missileExitTimer = 7.f;
|
||||||
if (!x832_26_comboFiring)
|
if (!x832_26_comboFiring)
|
||||||
{
|
{
|
||||||
|
@ -1659,7 +1659,7 @@ void CPlayerGun::UpdateNormalShotCycle(float dt, CStateManager& mgr)
|
||||||
homingTarget = kInvalidUniqueId;
|
homingTarget = kInvalidUniqueId;
|
||||||
x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget,
|
x72c_currentBeam->Fire(x834_27_underwater, dt, x330_chargeState, xf, mgr, homingTarget,
|
||||||
x340_chargeBeamFactor, x340_chargeBeamFactor);
|
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)
|
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())
|
if (mgr.GetPlayerState()->IsPlayerAlive())
|
||||||
{
|
{
|
||||||
CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1);
|
CSfxManager::AddEmitter(SFXsfx0710, GetTranslation(), {}, true, false, 0x7f, -1);
|
||||||
mgr.InformListeners(GetTranslation(), EListenNoiseType::Bomb);
|
mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -420,7 +420,7 @@ void CActor::OnScanStateChanged(EScanState state, CStateManager& mgr)
|
||||||
|
|
||||||
zeus::CAABox CActor::GetSortingBounds(const CStateManager&) const { return x9c_renderBounds; }
|
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)
|
if (event == EUserEventType::LoopedSoundStop)
|
||||||
RemoveEmitter();
|
RemoveEmitter();
|
||||||
|
|
|
@ -132,7 +132,7 @@ public:
|
||||||
virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&);
|
virtual void FluidFXThink(EFluidState, CScriptWater&, CStateManager&);
|
||||||
virtual void OnScanStateChanged(EScanState, CStateManager&);
|
virtual void OnScanStateChanged(EScanState, CStateManager&);
|
||||||
virtual zeus::CAABox GetSortingBounds(const CStateManager&) const;
|
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 RemoveEmitter();
|
||||||
void SetVolume(float vol);
|
void SetVolume(float vol);
|
||||||
|
|
|
@ -17,14 +17,16 @@ namespace urde
|
||||||
|
|
||||||
enum class EListenNoiseType
|
enum class EListenNoiseType
|
||||||
{
|
{
|
||||||
Character,
|
PlayerFire,
|
||||||
Bomb,
|
BombExplode,
|
||||||
Projectile
|
ProjectileExplode
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAiFuncMap;
|
class CAiFuncMap;
|
||||||
class CStateManager;
|
class CStateManager;
|
||||||
class CScriptWater;
|
class CScriptWater;
|
||||||
|
class CTeamAiRole;
|
||||||
|
|
||||||
class CAi : public CPhysicsActor
|
class CAi : public CPhysicsActor
|
||||||
{
|
{
|
||||||
static CAiFuncMap* m_FuncMap;
|
static CAiFuncMap* m_FuncMap;
|
||||||
|
@ -52,12 +54,13 @@ public:
|
||||||
virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {}
|
virtual void TakeDamage(const zeus::CVector3f& direction, float magnitude) {}
|
||||||
virtual bool CanBeShot(const CStateManager&, int) { return true; }
|
virtual bool CanBeShot(const CStateManager&, int) { return true; }
|
||||||
virtual bool IsListening() const { return false; }
|
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&,
|
virtual EWeaponCollisionResponseTypes GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&,
|
||||||
const CWeaponMode&, EProjectileAttrib) const;
|
const CWeaponMode&, EProjectileAttrib) const;
|
||||||
void FluidFXThink(EFluidState, CScriptWater&, CStateManager&);
|
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 Patrol(CStateManager&, EStateMsg, float) {}
|
||||||
virtual void FollowPattern(CStateManager&, EStateMsg, float) {}
|
virtual void FollowPattern(CStateManager&, EStateMsg, float) {}
|
||||||
virtual void Dead(CStateManager&, EStateMsg, float) {}
|
virtual void Dead(CStateManager&, EStateMsg, float) {}
|
||||||
|
@ -116,7 +119,7 @@ public:
|
||||||
|
|
||||||
virtual bool InAttackPosition(CStateManager&, float) { return false; }
|
virtual bool InAttackPosition(CStateManager&, float) { return false; }
|
||||||
virtual bool Leash(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 Attacked(CStateManager&, float) { return false; }
|
||||||
virtual bool PathShagged(CStateManager&, float) { return false; }
|
virtual bool PathShagged(CStateManager&, float) { return false; }
|
||||||
virtual bool PathOver(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 Stuck(CStateManager&, float) { return false; }
|
||||||
virtual bool NoPathNodes(CStateManager&, float) { return false; }
|
virtual bool NoPathNodes(CStateManager&, float) { return false; }
|
||||||
virtual bool Landed(CStateManager&, float) { return false; }
|
virtual bool Landed(CStateManager&, float) { return false; }
|
||||||
virtual bool HearShot(CStateManager&,float) { return false; }
|
virtual bool HearShot(CStateManager&, float) { return false; }
|
||||||
virtual bool HearPlayer(CStateManager&,float) { return false; }
|
virtual bool HearPlayer(CStateManager&, float) { return false; }
|
||||||
virtual bool CoverCheck(CStateManager&, float) { return false; }
|
virtual bool CoverCheck(CStateManager&, float) { return false; }
|
||||||
virtual bool CoverFind(CStateManager&, float) { return false; }
|
virtual bool CoverFind(CStateManager&, float) { return false; }
|
||||||
virtual bool CoverBlown(CStateManager&, float) { return false; }
|
virtual bool CoverBlown(CStateManager&, float) { return false; }
|
||||||
virtual bool CoverNearlyBlown(CStateManager&, float) { return false; }
|
virtual bool CoverNearlyBlown(CStateManager&, float) { return false; }
|
||||||
virtual bool CoveringFire(CStateManager&, float) { return false; }
|
virtual bool CoveringFire(CStateManager&, float) { return false; }
|
||||||
virtual bool GotUp(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 AggressionCheck(CStateManager&, float) { return false; }
|
||||||
virtual bool AttackOver(CStateManager&, float) { return false; }
|
virtual bool AttackOver(CStateManager&, float) { return false; }
|
||||||
virtual bool ShouldTaunt(CStateManager&,float) { return false; }
|
virtual bool ShouldTaunt(CStateManager&,float) { return false; }
|
||||||
virtual bool Inside(CStateManager&,float) { return false; }
|
virtual bool Inside(CStateManager&, float) { return false; }
|
||||||
virtual bool ShouldFire(CStateManager&,float) { return false; }
|
virtual bool ShouldFire(CStateManager&, float) { return false; }
|
||||||
virtual bool ShouldFlinch(CStateManager&, float) { return false; }
|
virtual bool ShouldFlinch(CStateManager&, float) { return false; }
|
||||||
virtual bool PatrolPathOver(CStateManager&, float) { return false; }
|
virtual bool PatrolPathOver(CStateManager&, float) { return false; }
|
||||||
virtual bool ShouldDodge(CStateManager&, float) { return false; }
|
virtual bool ShouldDodge(CStateManager&, float) { return false; }
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "Camera/CFirstPersonCamera.hpp"
|
#include "Camera/CFirstPersonCamera.hpp"
|
||||||
#include "World/CScriptWaypoint.hpp"
|
#include "World/CScriptWaypoint.hpp"
|
||||||
#include "World/CScriptActorKeyframe.hpp"
|
#include "World/CScriptActorKeyframe.hpp"
|
||||||
|
#include "Weapon/CEnergyProjectile.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -1171,10 +1172,9 @@ void CPatterned::Freeze(CStateManager& mgr, const zeus::CVector3f& pos,
|
||||||
|
|
||||||
zeus::CVector3f CPatterned::GetGunEyePos() const
|
zeus::CVector3f CPatterned::GetGunEyePos() const
|
||||||
{
|
{
|
||||||
zeus::CVector3f origin = GetOrigin();
|
zeus::CVector3f origin = GetTranslation();
|
||||||
zeus::CAABox baseBox = GetBaseBoundingBox();
|
zeus::CAABox baseBox = GetBaseBoundingBox();
|
||||||
origin.z = 0.6f * (baseBox.max.z - baseBox.min.z) + origin.z;
|
origin.z = 0.6f * (baseBox.max.z - baseBox.min.z) + origin.z;
|
||||||
|
|
||||||
return origin;
|
return origin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1187,6 +1187,98 @@ void CPatterned::SetupPlayerCollision(bool v)
|
||||||
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude));
|
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)
|
void CPatterned::UpdateAlphaDelta(float dt, CStateManager& mgr)
|
||||||
{
|
{
|
||||||
if (x3e8_alphaDelta == 0.f)
|
if (x3e8_alphaDelta == 0.f)
|
||||||
|
|
|
@ -408,6 +408,10 @@ public:
|
||||||
CBodyController* BodyController() { return x450_bodyController.get(); }
|
CBodyController* BodyController() { return x450_bodyController.get(); }
|
||||||
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
|
const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; }
|
||||||
void SetupPlayerCollision(bool);
|
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 SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; }
|
||||||
void UpdateAlphaDelta(float dt, CStateManager& mgr);
|
void UpdateAlphaDelta(float dt, CStateManager& mgr);
|
||||||
|
|
|
@ -688,6 +688,7 @@ public:
|
||||||
float GetMoveSpeed() const { return x4f8_moveSpeed; }
|
float GetMoveSpeed() const { return x4f8_moveSpeed; }
|
||||||
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
|
EPlayerOrbitRequest GetOrbitRequest() const { return x30c_orbitRequest; }
|
||||||
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
bool IsShowingCrosshairs() const { return x9c4_25_showCrosshairs; }
|
||||||
|
bool IsSidewaysDashing() const { return x37c_sidewaysDashing; }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,435 @@
|
||||||
#include "CTeamAiMgr.hpp"
|
#include "CTeamAiMgr.hpp"
|
||||||
#include "TCastTo.hpp"
|
#include "TCastTo.hpp"
|
||||||
|
#include "CStateManager.hpp"
|
||||||
|
#include "CPlayer.hpp"
|
||||||
|
|
||||||
namespace urde
|
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)
|
CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount)
|
||||||
: x0_(in.readUint32Big())
|
: x0_aiCount(in.readUint32Big())
|
||||||
, x4_(in.readUint32Big())
|
, x4_meleeCount(in.readUint32Big())
|
||||||
, x8_(in.readUint32Big())
|
, x8_projectileCount(in.readUint32Big())
|
||||||
, xc_(in.readUint32Big())
|
, xc_unknownCount(in.readUint32Big())
|
||||||
, x10_(in.readUint32Big())
|
, x10_maxMeleeAttackerCount(in.readUint32Big())
|
||||||
, x14_(in.readUint32Big())
|
, x14_maxProjectileAttackerCount(in.readUint32Big())
|
||||||
, x18_(in.readUint32Big())
|
, x18_positionMode(in.readUint32Big())
|
||||||
, x1c_(propCount > 8 ? in.readFloatBig() : 0.f)
|
, x1c_meleeTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f)
|
||||||
, x20_(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)
|
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)
|
void CTeamAiMgr::Accept(IVisitor& visitor)
|
||||||
{
|
{
|
||||||
visitor.Visit(this);
|
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
|
#pragma once
|
||||||
|
|
||||||
#include "CEntity.hpp"
|
#include "CEntity.hpp"
|
||||||
|
#include "zeus/CVector3f.hpp"
|
||||||
|
|
||||||
namespace urde
|
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
|
class CTeamAiData
|
||||||
{
|
{
|
||||||
u32 x0_;
|
friend class CTeamAiMgr;
|
||||||
u32 x4_;
|
u32 x0_aiCount;
|
||||||
u32 x8_;
|
u32 x4_meleeCount;
|
||||||
u32 xc_;
|
u32 x8_projectileCount;
|
||||||
u32 x10_;
|
u32 xc_unknownCount;
|
||||||
u32 x14_;
|
u32 x10_maxMeleeAttackerCount;
|
||||||
u32 x18_;
|
u32 x14_maxProjectileAttackerCount;
|
||||||
float x1c_;
|
u32 x18_positionMode;
|
||||||
float x20_;
|
float x1c_meleeTimeInterval;
|
||||||
|
float x20_projectileTimeInterval;
|
||||||
public:
|
public:
|
||||||
CTeamAiData(CInputStream& in, s32 propCount);
|
CTeamAiData(CInputStream& in, s32 propCount);
|
||||||
};
|
};
|
||||||
|
@ -23,9 +63,57 @@ public:
|
||||||
class CTeamAiMgr : public CEntity
|
class CTeamAiMgr : public CEntity
|
||||||
{
|
{
|
||||||
public:
|
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 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