Initial CSpacePirate and rag doll imps

This commit is contained in:
Jack Andersen 2018-11-23 22:09:35 -10:00
parent 976fe8d283
commit 9c88971df6
34 changed files with 1422 additions and 237 deletions

View File

@ -8,12 +8,17 @@ CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, CAssetId resId) : x
u32 version = in.readUint32Big(); u32 version = in.readUint32Big();
Load(in, version); Load(in, version);
for (u32 i = 0 ; i < x14_buckets.size(); ++i)
{
x14_buckets[i].x4_appearanceRange *= x8_totalDownloadTime;
}
float appearanceOffset = g_tweakGui->GetScanAppearanceDuration(); float appearanceOffset = g_tweakGui->GetScanAppearanceDuration();
for (u32 i = 0 ; i < x14_buckets.size(); ++i) for (u32 i = 0 ; i < x14_buckets.size(); ++i)
{ {
if (x14_buckets[i].x8_imagePos != -1) if (x14_buckets[i].x8_imagePos != -1)
{ {
x14_buckets[i].x4_appearanceRange += appearanceOffset; x8_totalDownloadTime += appearanceOffset;
for (u32 j = i; j < x14_buckets.size(); j++) for (u32 j = i; j < x14_buckets.size(); j++)
x14_buckets[j].x4_appearanceRange += appearanceOffset; x14_buckets[j].x4_appearanceRange += appearanceOffset;
} }

View File

@ -25,7 +25,7 @@ CActorLights::CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& act
x298_25_castShadows = true; x298_25_castShadows = true;
x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false; x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false;
x298_29_ambientChannelOverflow = ambientChannelOverflow; x298_29_ambienceGenerated = ambientChannelOverflow;
x298_30_layer2 = layer2; x298_30_layer2 = layer2;
x298_31_disableWorldLights = disableWorldLights; x298_31_disableWorldLights = disableWorldLights;
x299_24_inBrightLight = true; x299_24_inBrightLight = true;
@ -152,7 +152,7 @@ void CActorLights::AddOverflowToLights(const CLight& light, const zeus::CColor&
void CActorLights::MoveAmbienceToLights(const zeus::CColor& color) void CActorLights::MoveAmbienceToLights(const zeus::CColor& color)
{ {
if (x298_29_ambientChannelOverflow) if (x298_29_ambienceGenerated)
{ {
x288_ambientColor += color * 0.333333f; x288_ambientColor += color * 0.333333f;
x288_ambientColor.a = 1.f; x288_ambientColor.a = 1.f;
@ -342,7 +342,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea&
float overflowMag = 0.f; float overflowMag = 0.f;
/* Max significant lights */ /* Max significant lights */
int maxAreaLights = !x298_29_ambientChannelOverflow ? x2b8_maxAreaLights - 1 : x2b8_maxAreaLights; int maxAreaLights = !x298_29_ambienceGenerated ? x2b8_maxAreaLights - 1 : x2b8_maxAreaLights;
x0_areaLights.clear(); x0_areaLights.clear();
/* Filter for performing final light visibility test */ /* Filter for performing final light visibility test */
@ -415,7 +415,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea&
else else
{ {
/* Overflow light */ /* Overflow light */
if (!x298_29_ambientChannelOverflow && value.x10_colorMag > 0.001f) if (!x298_29_ambienceGenerated && value.x10_colorMag > 0.001f)
{ {
/* Average parameters into final light */ /* Average parameters into final light */
MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag); MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag);
@ -430,7 +430,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea&
} }
/* Finalize overflow lights */ /* Finalize overflow lights */
if (!x298_29_ambientChannelOverflow) if (!x298_29_ambienceGenerated)
AddOverflowToLights(overflowLight, overflowLightColor, overflowMag); AddOverflowToLights(overflowLight, overflowLightColor, overflowMag);
else else
MoveAmbienceToLights(overflowAmbColor); MoveAmbienceToLights(overflowAmbColor);

View File

@ -29,7 +29,7 @@ class CActorLights
bool x298_26_hasAreaLights : 1; bool x298_26_hasAreaLights : 1;
bool x298_27_findShadowLight : 1; bool x298_27_findShadowLight : 1;
bool x298_28_inArea : 1; bool x298_28_inArea : 1;
bool x298_29_ambientChannelOverflow : 1; bool x298_29_ambienceGenerated : 1;
bool x298_30_layer2 : 1; bool x298_30_layer2 : 1;
bool x298_31_disableWorldLights : 1; bool x298_31_disableWorldLights : 1;
bool x299_24_inBrightLight : 1; bool x299_24_inBrightLight : 1;
@ -75,7 +75,7 @@ public:
void SetCastShadows(bool v) { x298_25_castShadows = v; } void SetCastShadows(bool v) { x298_25_castShadows = v; }
void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; }
void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; } void SetShadowDynamicRangeThreshold(float t) { x2d0_shadowDynamicRangeThreshold = t; }
void SetAmbientChannelOverflow(bool v) { x298_29_ambientChannelOverflow = v; } void SetAmbienceGenerated(bool v) { x298_29_ambienceGenerated = v; }
void DisableAreaLights(); void DisableAreaLights();
void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } void SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; }
void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; }

View File

@ -214,6 +214,7 @@ public:
static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags);
void PreRender(); void PreRender();
void BuildPose(); void BuildPose();
const CPoseAsTransforms& GetPose() const { return x224_pose; }
static void PrimitiveSetToTokenVector(const std::set<CPrimitive>& primSet, static void PrimitiveSetToTokenVector(const std::set<CPrimitive>& primSet,
std::vector<CToken>& tokensOut, bool preLock); std::vector<CToken>& tokensOut, bool preLock);
void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set<CPrimitive>& primsOut) const; void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set<CPrimitive>& primsOut) const;
@ -242,7 +243,7 @@ public:
void SubstituteModelData(const TCachedToken<CSkinnedModel>& model); void SubstituteModelData(const TCachedToken<CSkinnedModel>& model);
static void FreeCache(); static void FreeCache();
static void InitializeCache(); static void InitializeCache();
const CHierarchyPoseBuilder& GetPoseBuilder() const { return x2fc_poseBuilder; } CHierarchyPoseBuilder& PoseBuilder() { return x2fc_poseBuilder; }
const CParticleDatabase& GetParticleDB() const { return x120_particleDB; } const CParticleDatabase& GetParticleDB() const { return x120_particleDB; }
CParticleDatabase& GetParticleDB() { return x120_particleDB; } CParticleDatabase& GetParticleDB() { return x120_particleDB; }
void SetParticleCEXTValue(std::string_view name, int idx, float value); void SetParticleCEXTValue(std::string_view name, int idx, float value);
@ -257,6 +258,8 @@ public:
TLockedToken<CMorphableSkinnedModel>& IceModel() { return xe4_iceModelData; } TLockedToken<CMorphableSkinnedModel>& IceModel() { return xe4_iceModelData; }
const TLockedToken<CMorphableSkinnedModel>& GetIceModel() const { return xe4_iceModelData; } const TLockedToken<CMorphableSkinnedModel>& GetIceModel() const { return xe4_iceModelData; }
void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; }
void MarkPoseDirty() { x220_30_poseBuilt = false; }
}; };
} }

View File

@ -28,7 +28,7 @@ CSegId CCharLayoutInfo::GetSegIdFromString(std::string_view name) const
if (it == x18_segIdMap.end()) if (it == x18_segIdMap.end())
return {}; return {};
return (*it).second; return it->second;
} }
void CCharLayoutNode::Bone::read(CInputStream& in) void CCharLayoutNode::Bone::read(CInputStream& in)

View File

@ -51,6 +51,7 @@ public:
void BuildNoScale(CPoseAsTransforms& pose); void BuildNoScale(CPoseAsTransforms& pose);
void Insert(const CSegId& boneId, const zeus::CQuaternion& quat); void Insert(const CSegId& boneId, const zeus::CQuaternion& quat);
void Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset); void Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset);
TSegIdMap<CTreeNode>& GetTreeMap() { return x38_treeMap; }
}; };
} }

View File

@ -15,10 +15,10 @@ class CIkChain
CSegId x0_; CSegId x0_;
CSegId x1_; CSegId x1_;
CSegId x2_; CSegId x2_;
zeus::CVector3f x4_; zeus::CVector3f x4_ = zeus::CVector3f::skForward;
zeus::CVector3f x10_; zeus::CVector3f x10_ = zeus::CVector3f::skForward;
float x1c_; float x1c_ = 1.f;
float x20_; float x20_ = 1.f;
zeus::CQuaternion x24_; zeus::CQuaternion x24_;
zeus::CVector3f x34_; zeus::CVector3f x34_;
float x40_time = 0.f; float x40_time = 0.f;
@ -29,7 +29,7 @@ class CIkChain
{ {
bool x44_24_activated : 1; bool x44_24_activated : 1;
}; };
u8 x44_dummy = 0; u32 x44_dummy = 0;
}; };
public: public:
CIkChain() = default; CIkChain() = default;

View File

@ -91,6 +91,7 @@ set(CHARACTER_SOURCES
CGroundMovement.hpp CGroundMovement.cpp CGroundMovement.hpp CGroundMovement.cpp
CSteeringBehaviors.hpp CSteeringBehaviors.cpp CSteeringBehaviors.hpp CSteeringBehaviors.cpp
CBodyStateInfo.hpp CBodyStateInfo.cpp CBodyStateInfo.hpp CBodyStateInfo.cpp
CBoneTracking.hpp CBoneTracking.cpp) CBoneTracking.hpp CBoneTracking.cpp
CRagDoll.hpp CRagDoll.cpp)
runtime_add_list(Character CHARACTER_SOURCES) runtime_add_list(Character CHARACTER_SOURCES)

View File

@ -0,0 +1,366 @@
#include "CRagDoll.hpp"
#include "Collision/CMetroidAreaCollider.hpp"
#include "Collision/CGameCollision.hpp"
#include "Collision/CMaterialFilter.hpp"
#include "Collision/CCollidableSphere.hpp"
#include "Collision/CCollisionInfo.hpp"
#include "CStateManager.hpp"
namespace urde
{
void CRagDoll::CRagDollLengthConstraint::Update()
{
zeus::CVector3f delta = x4_p2->x4_curPos - x0_p1->x4_curPos;
float magSq = delta.magSquared();
float lenSq = x8_length * x8_length;
bool doSolve = true;
switch (xc_ineqType)
{
case 1: // Min
doSolve = magSq < lenSq;
break;
case 2: // Max
doSolve = magSq > lenSq;
break;
default:
break;
}
if (!doSolve)
return;
zeus::CVector3f solveVec = delta * (lenSq / (magSq + lenSq) - 0.5f);
x0_p1->x4_curPos -= solveVec;
x4_p2->x4_curPos += solveVec;
}
void CRagDoll::CRagDollJointConstraint::Update()
{
// L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle
zeus::CVector3f P4ToP5 = x10_p5->x4_curPos - xc_p4->x4_curPos; // L_hip->L_knee
zeus::CVector3f cross = P4ToP5.cross(
(x8_p3->x4_curPos - x0_p1->x4_curPos).cross(x4_p2->x4_curPos - x0_p1->x4_curPos));
// L_hip->L_knee X (L_hip->L_shoulder X L_hip->R_shoulder)
if (cross.canBeNormalized())
{
zeus::CVector3f hipUp = cross.cross(P4ToP5).normalized();
float dot = (x14_p6->x4_curPos - x10_p5->x4_curPos).dot(hipUp);
if (dot > 0.f)
{
zeus::CVector3f solveVec = 0.5f * dot * hipUp;
x14_p6->x4_curPos -= solveVec;
x10_p5->x4_curPos += solveVec;
}
}
}
void CRagDoll::CRagDollPlaneConstraint::Update()
{
zeus::CVector3f P1ToP2 = (x4_p2->x4_curPos - x0_p1->x4_curPos).normalized();
float dot = P1ToP2.dot(xc_p4->x4_curPos - x8_p3->x4_curPos);
if (dot < 0.f)
{
zeus::CVector3f solveVec = 0.5f * dot * P1ToP2;
xc_p4->x4_curPos -= solveVec;
x10_p5->x4_curPos += solveVec;
}
}
CRagDoll::CRagDoll(float f1, float f2, float f3, u32 flags)
: x44_f1(f1), x48_f2(f2), x50_f3(f3)
{
x68_27_ = bool(flags & 0x1);
x68_28_ = bool(flags & 0x2);
x68_29_ = bool(flags & 0x4);
}
void CRagDoll::AccumulateForces(float dt, float f2)
{
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;
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)
{
f23 = 0.5f * f7 / 0.5f + 0.5f;
f8 = x48_f2 * -f7 / 0.5f;
}
else if (f7 > 0.f)
{
f8 = x44_f1;
f23 = 1.f;
}
particle.x20_acceleration.z += f8;
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));
}
}
zeus::CVector3f _c8;
f29 = f29 / f24;
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;
}
_c8 = _c8 * (fps / f24);
if (_c8.canBeNormalized())
for (auto& particle : x4_particles)
particle.x20_acceleration -= _c8.cross(particle.x4_curPos - f29) * 25.f;
}
void CRagDoll::AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float f1)
{
x4_particles.emplace_back(id, curPos, f1, prevPos);
}
void CRagDoll::AddLengthConstraint(int i1, int i2)
{
x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2],
(x4_particles[i1].x4_curPos - x4_particles[i2].x4_curPos).magnitude(), 0);
}
void CRagDoll::AddMaxLengthConstraint(int i1, int i2, float length)
{
x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 2);
}
void CRagDoll::AddMinLengthConstraint(int i1, int i2, float length)
{
x14_lengthConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], length, 1);
}
void CRagDoll::AddJointConstraint(int i1, int i2, int i3, int i4, int i5, int i6)
{
x24_jointConstraints.emplace_back(&x4_particles[i1], &x4_particles[i2], &x4_particles[i3],
&x4_particles[i4], &x4_particles[i5], &x4_particles[i6]);
}
zeus::CQuaternion CRagDoll::BoneAlign(CHierarchyPoseBuilder& pb, const CCharLayoutInfo& charInfo,
int i1, int i2, const zeus::CQuaternion& q)
{
zeus::CVector3f fromParent = charInfo.GetFromParentUnrotated(x4_particles[i2].x0_id);
zeus::CVector3f delta = x4_particles[i2].x4_curPos - x4_particles[i1].x4_curPos;
delta = q.inverse().transform(delta);
zeus::CQuaternion ret = zeus::CQuaternion::shortestRotationArc(fromParent, delta);
pb.GetTreeMap()[x4_particles[i1].x0_id].x4_rotation = ret;
return ret;
}
zeus::CAABox CRagDoll::CalculateRenderBounds() const
{
zeus::CAABox aabb;
for (const auto& particle : x4_particles)
{
aabb.accumulateBounds(zeus::CAABox(particle.x4_curPos - particle.x10_radius,
particle.x4_curPos + particle.x10_radius));
}
return aabb;
}
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;
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)
{
x4c_ += 1;
x54_ = std::max(particle.x38_, x54_);
}
}
if (!x4_particles.empty())
x58_ = x58_ * (1.f / (dt * x4_particles.size()));
x54_ /= dt;
if (!x68_28_)
{
x50_f3 -= dt;
if (x50_f3 <= 0.f)
x68_25_ = true;
}
if (r31 && x68_24_)
x68_25_ = true;
x68_24_ = r31;
}
void CRagDoll::ClearForces()
{
for (auto& particle : x4_particles)
particle.x20_acceleration = zeus::CVector3f::skZero;
}
void CRagDoll::SatisfyConstraints(CStateManager& mgr)
{
for (auto& length : x14_lengthConstraints)
length.Update();
for (auto& joint : x24_jointConstraints)
joint.Update();
for (auto& plane : x34_planeConstraints)
plane.Update();
if (SatisfyWorldConstraints(mgr, 1))
SatisfyWorldConstraints(mgr, 2);
}
bool CRagDoll::SatisfyWorldConstraints(CStateManager& mgr, int i1)
{
zeus::CAABox aabb;
for (const auto& particle : x4_particles)
{
if (i1 == 1 || particle.x3c_24_nextDampVel)
{
aabb.accumulateBounds(particle.x14_prevPos - particle.x10_radius);
aabb.accumulateBounds(particle.x14_prevPos + particle.x10_radius);
aabb.accumulateBounds(particle.x4_curPos - particle.x10_radius);
aabb.accumulateBounds(particle.x4_curPos + particle.x10_radius);
}
}
CAreaCollisionCache ccache(aabb);
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
bool ret = false;
TUniqueId bestId = kInvalidUniqueId;
CMaterialList include;
if (x68_29_)
include = CMaterialList(EMaterialTypes::Solid);
else
include = CMaterialList(EMaterialTypes::Solid, EMaterialTypes::AIBlock);
CMaterialList exclude;
if (x68_29_)
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player,
EMaterialTypes::AIBlock, EMaterialTypes::Occluder);
else
exclude = CMaterialList(EMaterialTypes::Character, EMaterialTypes::Player);
rstl::reserved_vector<TUniqueId, 1024> nearList;
CMaterialFilter filter = CMaterialFilter::MakeIncludeExclude(include, exclude);
mgr.BuildNearList(nearList, aabb, filter, nullptr);
for (auto& particle : x4_particles)
{
if (i1 == 1 || particle.x3c_24_nextDampVel)
{
zeus::CVector3f delta = particle.x4_curPos - particle.x14_prevPos;
float deltaMag = delta.magnitude();
if (deltaMag > 0.0001f)
{
delta = delta * (1.f / deltaMag);
double d = deltaMag;
CCollidableSphere sphere(zeus::CSphere(particle.x14_prevPos, particle.x10_radius), include);
CCollisionInfo info;
CGameCollision::DetectCollision_Cached_Moving(mgr, ccache, sphere, {}, filter,
nearList, delta, bestId, info, d);
if (info.IsValid())
{
ret = true;
switch (i1)
{
case 1:
{
particle.x3c_24_nextDampVel = true;
float dot = delta.dot(info.GetNormalLeft());
particle.x2c_nextPosDelta = -0.125f * dot * deltaMag * info.GetNormalLeft();
particle.x38_ = -dot * deltaMag;
particle.x4_curPos += float(0.0001f - (deltaMag - d) * dot) * info.GetNormalLeft();
break;
}
case 2:
particle.x4_curPos = float(d - 0.0001) * delta + particle.x14_prevPos;
break;
default:
break;
}
}
}
else if (!x68_27_)
{
particle.x4_curPos = particle.x14_prevPos;
}
}
}
return ret;
}
void CRagDoll::SatisfyWorldConstraintsOnConstruction(CStateManager& mgr)
{
for (auto& particle : x4_particles)
particle.x3c_24_nextDampVel = true;
SatisfyWorldConstraints(mgr, 2);
for (auto& particle : x4_particles)
particle.x14_prevPos = particle.x4_curPos;
}
void CRagDoll::Verlet(float dt)
{
for (auto& particle : x4_particles)
{
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.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;
}
}
void CRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData)
{
// Empty
}
void CRagDoll::Update(CStateManager& mgr, float dt, float f2)
{
if (!x68_25_ || x68_27_)
{
AccumulateForces(dt, f2);
Verlet(dt);
SatisfyConstraints(mgr);
ClearForces();
CheckStatic(dt);
}
}
void CRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData)
{
zeus::CVector3f scale = mData.GetScale();
CAnimData* aData = mData.AnimationData();
aData->BuildPose();
for (auto& particle : x4_particles)
if (particle.x0_id != 0xff)
particle.x4_curPos = xf * aData->GetPose().GetOffset(particle.x0_id) * scale;
SatisfyWorldConstraints(mgr, 2);
for (auto& particle : x4_particles)
particle.x3c_24_nextDampVel = false;
x68_26_primed = true;
}
}

View File

@ -0,0 +1,137 @@
#pragma once
#include "RetroTypes.hpp"
#include "zeus/CVector3f.hpp"
#include "zeus/CQuaternion.hpp"
#include "zeus/CAABox.hpp"
#include "CSegId.hpp"
namespace urde
{
class CHierarchyPoseBuilder;
class CCharLayoutInfo;
class CModelData;
class CStateManager;
class CRagDoll
{
protected:
class CRagDollParticle
{
friend class CRagDoll;
CSegId x0_id;
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;
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)
{
x3c_24_nextDampVel = 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; }
float GetRadius() const { return x10_radius; }
};
class CRagDollLengthConstraint
{
friend class CRagDoll;
CRagDollParticle* x0_p1;
CRagDollParticle* x4_p2;
float x8_length;
int xc_ineqType;
public:
CRagDollLengthConstraint(CRagDollParticle* p1, CRagDollParticle* p2, float f1, int i1)
: x0_p1(p1), x4_p2(p2), x8_length(f1), xc_ineqType(i1) {}
void Update();
float GetLength() const { return x8_length; }
};
class CRagDollJointConstraint
{
friend class CRagDoll;
CRagDollParticle* x0_p1; // Shoulder plane 0
CRagDollParticle* x4_p2; // Shoulder plane 1
CRagDollParticle* x8_p3; // Shoulder plane 2
CRagDollParticle* xc_p4; // Shoulder
CRagDollParticle* x10_p5; // Elbow
CRagDollParticle* x14_p6; // Wrist
public:
CRagDollJointConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3,
CRagDollParticle* p4, CRagDollParticle* p5, CRagDollParticle* p6)
: x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5), x14_p6(p6) {}
void Update();
};
class CRagDollPlaneConstraint
{
friend class CRagDoll;
CRagDollParticle* x0_p1;
CRagDollParticle* x4_p2;
CRagDollParticle* x8_p3;
CRagDollParticle* xc_p4;
CRagDollParticle* x10_p5;
public:
CRagDollPlaneConstraint(CRagDollParticle* p1, CRagDollParticle* p2, CRagDollParticle* p3,
CRagDollParticle* p4, CRagDollParticle* p5)
: x0_p1(p1), x4_p2(p2), x8_p3(p3), xc_p4(p4), x10_p5(p5) {}
void Update();
};
std::vector<CRagDollParticle> x4_particles;
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 x64_angTimer = 0.f;
union
{
struct
{
bool x68_24_ : 1;
bool x68_25_ : 1;
bool x68_26_primed : 1;
bool x68_27_ : 1;
bool x68_28_ : 1;
bool x68_29_ : 1;
};
u32 _dummy = 0;
};
void AccumulateForces(float dt, float f2);
void SetNumParticles(int num) { x4_particles.reserve(num); }
void AddParticle(CSegId id, const zeus::CVector3f& prevPos, const zeus::CVector3f& curPos, float f1);
void SetNumLengthConstraints(int num) { x14_lengthConstraints.reserve(num); }
void AddLengthConstraint(int i1, int i2);
void AddMaxLengthConstraint(int i1, int i2, float length);
void AddMinLengthConstraint(int i1, int i2, float length);
void SetNumJointConstraints(int num) { x24_jointConstraints.reserve(num); }
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);
void SatisfyWorldConstraintsOnConstruction(CStateManager& mgr);
void Verlet(float dt);
public:
virtual ~CRagDoll() = default;
CRagDoll(float f1, float f2, float f3, u32 flags);
virtual void PreRender(const zeus::CVector3f& v, CModelData& mData);
virtual void Update(CStateManager& mgr, float dt, float f2);
virtual void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
};
}

View File

@ -30,6 +30,7 @@ zeus::CVector3f CGuiCamera::ConvertToScreenSpace(const zeus::CVector3f& vec) con
zeus::CMatrix4f mat = CGraphics::CalculatePerspectiveMatrix(m_proj.xbc_fov, m_proj.xc0_aspect, zeus::CMatrix4f mat = CGraphics::CalculatePerspectiveMatrix(m_proj.xbc_fov, m_proj.xc0_aspect,
m_proj.xc4_znear, m_proj.xc8_zfar, m_proj.xc4_znear, m_proj.xc8_zfar,
false); false);
local = zeus::CVector3f(local.x, local.z, -local.y);
return mat.multiplyOneOverW(local); return mat.multiplyOneOverW(local);
} }

View File

@ -95,6 +95,29 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f
x50_typeEnable = enable; x50_typeEnable = enable;
x54_chFadeTime = std::max(chFadeTime, 0.0001f); x54_chFadeTime = std::max(chFadeTime, 0.0001f);
x58_chRate = std::max(chRate, 1.f); x58_chRate = std::max(chRate, 1.f);
if (enable)
{
if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer())
{
float chStartTime = 0.f;
for (s32 i=0 ; i<buf->GetPrimitiveCount() ; ++i)
{
for (const std::pair<float, int>& p : x40_primStartTimes)
{
if (p.second < i)
continue;
if (p.second != i)
break;
chStartTime = p.first;
break;
}
buf->SetPrimitiveOpacity(i,
std::min(std::max(0.f, (x3c_curTime - chStartTime) / x54_chFadeTime), 1.f));
chStartTime += 1.f / x58_chRate;
}
}
}
} }
void CGuiTextSupport::Update(float dt) void CGuiTextSupport::Update(float dt)

View File

@ -21,8 +21,10 @@ void CScanDisplay::CDataDot::Update(float dt)
if (x20_remTime > 0.f) if (x20_remTime > 0.f)
{ {
x20_remTime = std::max(0.f, x20_remTime - dt); x20_remTime = std::max(0.f, x20_remTime - dt);
float d = x20_remTime / x1c_transDur; float d = 0.f;
xc_curPos = (x14_targetPos * (x4_startPos * d)) + (1.f - x1c_transDur > 0.f ? d : 0.f); if (x1c_transDur > 0.f)
d = x20_remTime / x1c_transDur;
xc_curPos = zeus::CVector2f::lerp(x14_targetPos, x4_startPos, d);
} }
if (x24_alpha > x28_desiredAlpha) if (x24_alpha > x28_desiredAlpha)
@ -32,7 +34,7 @@ void CScanDisplay::CDataDot::Update(float dt)
} }
else if (x24_alpha < x28_desiredAlpha) else if (x24_alpha < x28_desiredAlpha)
{ {
float tmp = 2.0 * dt + x24_alpha; float tmp = 2.f * dt + x24_alpha;
x24_alpha = std::min(tmp, x28_desiredAlpha); x24_alpha = std::min(tmp, x28_desiredAlpha);
} }
} }
@ -243,7 +245,8 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo,
} }
state.second->SetTextureID0(bucket.x0_texture, g_SimplePool); state.second->SetTextureID0(bucket.x0_texture, g_SimplePool);
state.second->SetFlashFactor(0.f); state.second->SetFlashFactor(0.f);
if (scanTime >= GetDownloadStartTime(i)) float startTime = GetDownloadStartTime(i);
if (scanTime >= startTime)
x170_paneStates[i].first = 0.f; x170_paneStates[i].first = 0.f;
else else
x170_paneStates[i].first = -1.f; x170_paneStates[i].first = -1.f;
@ -400,6 +403,7 @@ void CScanDisplay::Update(float dt, float scanningTime)
if (tmp == 0.f) if (tmp == 0.f)
{ {
dot.SetDotState(CDataDot::EDotState::Done); dot.SetDotState(CDataDot::EDotState::Done);
dot.SetDesiredAlpha(0.f);
CSfxManager::SfxStart(SFXui_scan_pane_reveal, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); CSfxManager::SfxStart(SFXui_scan_pane_reveal, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
x170_paneStates[i].first = g_tweakGui->GetScanPaneFadeOutTime() + g_tweakGui->GetScanPaneFadeInTime(); x170_paneStates[i].first = g_tweakGui->GetScanPaneFadeOutTime() + g_tweakGui->GetScanPaneFadeInTime();
} }
@ -423,12 +427,14 @@ void CScanDisplay::Update(float dt, float scanningTime)
float tmp = dot.GetTransitionFactor(); float tmp = dot.GetTransitionFactor();
if (tmp == 0.f) if (tmp == 0.f)
{ {
float posRand = g_tweakGui->GetScanDataDotPosRandMagnitude(); float vpRatio = g_Viewport.xc_height / 480.f;
float posRand = g_tweakGui->GetScanDataDotPosRandMagnitude() * vpRatio;
float durMin = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMin() : g_tweakGui->GetScanDataDotSeekDurationMin(); float durMin = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMin() : g_tweakGui->GetScanDataDotSeekDurationMin();
float durMax = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMax() : g_tweakGui->GetScanDataDotSeekDurationMax(); float durMax = dot.GetDotState() == CDataDot::EDotState::Hold ? g_tweakGui->GetScanDataDotHoldDurationMax() : g_tweakGui->GetScanDataDotSeekDurationMax();
zeus::CVector2f vec(dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().x : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand), zeus::CVector2f vec(dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().x : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand),
dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().y : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand)); dot.GetDotState() == CDataDot::EDotState::Hold ? dot.GetCurrPosition().y : (posRand * (rand() / float(RAND_MAX)) - 0.5f * posRand));
dot.StartTransitionTo(vec, (durMax - durMin) * (rand() / float(RAND_MAX)) + durMin); float dur = (durMax - durMin) * (rand() / float(RAND_MAX)) + durMin;
dot.StartTransitionTo(vec, dur);
dot.SetDotState(dot.GetDotState() == CDataDot::EDotState::Hold ? CDataDot::EDotState::Seek : CDataDot::EDotState::Hold); dot.SetDotState(dot.GetDotState() == CDataDot::EDotState::Hold ? CDataDot::EDotState::Seek : CDataDot::EDotState::Hold);
} }
break; break;
@ -436,7 +442,8 @@ void CScanDisplay::Update(float dt, float scanningTime)
case CDataDot::EDotState::RevealPane: case CDataDot::EDotState::RevealPane:
case CDataDot::EDotState::Done: case CDataDot::EDotState::Done:
{ {
zeus::CVector3f screenPos = xa0_selHud.GetFrameCamera()->ConvertToScreenSpace(x170_paneStates[i].second->GetWorldPosition()); const zeus::CVector3f& panePos = x170_paneStates[i].second->GetWorldPosition();
zeus::CVector3f screenPos = xa0_selHud.GetFrameCamera()->ConvertToScreenSpace(panePos);
zeus::CVector2f viewportCoords(screenPos.x * g_Viewport.x8_width * 0.5f, zeus::CVector2f viewportCoords(screenPos.x * g_Viewport.x8_width * 0.5f,
screenPos.y * g_Viewport.xc_height * 0.5f); screenPos.y * g_Viewport.xc_height * 0.5f);
dot.SetDestPosition(viewportCoords); dot.SetDestPosition(viewportCoords);
@ -485,7 +492,8 @@ void CScanDisplay::Draw() const
g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f);
// Additive alpha // Additive alpha
float vpRatio = g_Viewport.xc_height / 480.f;
for (const CDataDot& dot : xbc_dataDots) for (const CDataDot& dot : xbc_dataDots)
dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius()); dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius() * vpRatio);
} }
} }

View File

@ -72,7 +72,7 @@ CFireFlea::CFireFlea(TUniqueId uid, std::string_view name, const CEntityInfo& in
: CPatterned(ECharacter::FireFlea, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::FireFlea, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Small) EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Small)
, x56c_(f1) , x56c_(f1)
, xd8c_pathFind(nullptr, 2, pInfo.GetParticle1Frames(), 1.f, 1.f) , xd8c_pathFind(nullptr, 2, pInfo.GetPathfindingIndex(), 1.f, 1.f)
{ {
CMaterialFilter filter = GetMaterialFilter(); CMaterialFilter filter = GetMaterialFilter();
filter.ExcludeList().Add(EMaterialTypes::Character); filter.ExcludeList().Add(EMaterialTypes::Character);

View File

@ -1,5 +1,8 @@
#include "CSpacePirate.hpp" #include "CSpacePirate.hpp"
#include "Character/CCharLayoutInfo.hpp" #include "Character/CCharLayoutInfo.hpp"
#include "Character/CPASAnimParmData.hpp"
#include "World/CScriptWaypoint.hpp"
#include "World/CPatternedInfo.hpp"
#include "TCastTo.hpp" #include "TCastTo.hpp"
namespace urde::MP1 namespace urde::MP1
@ -10,21 +13,455 @@ CSpacePirate::CSpacePirateData::CSpacePirateData(urde::CInputStream& in, u32 pro
, x48_(CSfxManager::TranslateSFXID(in.readUint32Big())), x4c_(in), x68_(in.readFloatBig()), x6c_(in) , x48_(CSfxManager::TranslateSFXID(in.readUint32Big())), x4c_(in), x68_(in.readFloatBig()), x6c_(in)
, x94_(in.readFloatBig()), x98_(CSfxManager::TranslateSFXID(in.readUint32Big())), x9c_(in.readFloatBig()) , x94_(in.readFloatBig()), x98_(CSfxManager::TranslateSFXID(in.readUint32Big())), x9c_(in.readFloatBig())
, xa0_(in.readFloatBig()), xa4_(CSfxManager::TranslateSFXID(in.readUint32Big())), xa8_(in.readFloatBig()) , xa0_(in.readFloatBig()), xa4_(CSfxManager::TranslateSFXID(in.readUint32Big())), xa8_(in.readFloatBig())
, xac_(in.readUint32Big()), xb0_(in.readFloatBig()), xb4_(in.readFloatBig()), xb8_(in.readFloatBig()) , xac_firstBurstCount(in.readUint32Big()), xb0_(in.readFloatBig()), xb4_(in.readFloatBig()), xb8_(in.readFloatBig())
, xbc_(in.readFloatBig()), xc0_(CSfxManager::TranslateSFXID(in.readUint32Big())) , xbc_(in.readFloatBig()), xc0_(CSfxManager::TranslateSFXID(in.readUint32Big()))
, xc2_(CSfxManager::TranslateSFXID(in.readUint32Big())), xc4_(propCount > 35 ? in.readFloatBig() : 0.2f) , xc2_(CSfxManager::TranslateSFXID(in.readUint32Big())), xc4_(propCount > 35 ? in.readFloatBig() : 0.2f)
, xc8_(propCount > 36 ? in.readFloatBig() : 8.f) , xc8_(propCount > 36 ? in.readFloatBig() : 8.f)
{ {}
static const std::string_view skParts[] =
{
"Collar"sv,
"Neck_1"sv,
"R_shoulder"sv,
"R_elbow"sv,
"R_wrist"sv,
"L_shoulder"sv,
"L_elbow"sv,
"L_wrist"sv,
"R_hip"sv,
"R_knee"sv,
"R_ankle"sv,
"L_hip"sv,
"L_knee"sv,
"L_ankle"sv
};
static const float skRadii[] =
{
0.45f,
0.52f,
0.35f,
0.1f,
0.15f,
0.35f,
0.1f,
0.15f,
0.15f,
0.15f,
0.15f,
0.15f,
0.15f,
0.15f
};
CPirateRagDoll::CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 s1, u32 flags)
: CRagDoll(-sp->GetGravityConstant(), -3.f, 8.f, flags), x6c_spacePirate(sp), x70_s1(s1)
{
xb0_24_ = true;
x6c_spacePirate->RemoveMaterial(EMaterialTypes::Solid, EMaterialTypes::AIBlock,
EMaterialTypes::GroundCollider, mgr);
x6c_spacePirate->HealthInfo(mgr)->SetHP(-1.f);
SetNumParticles(14);
SetNumLengthConstraints(47);
SetNumJointConstraints(4);
zeus::CVector3f scale = x6c_spacePirate->GetModelData()->GetScale();
CAnimData* aData = x6c_spacePirate->ModelData()->AnimationData();
aData->BuildPose();
zeus::CVector3f center = x6c_spacePirate->GetBoundingBox().center();
for (int i = 0; i < 14; ++i)
{
CSegId id = aData->GetLocatorSegId(skParts[i]);
AddParticle(id, center, x6c_spacePirate->GetTransform() * (aData->GetPose().GetOffset(id) * scale),
skRadii[i] * scale.z);
}
SatisfyWorldConstraintsOnConstruction(mgr);
AddLengthConstraint(0, 1);
AddLengthConstraint(0, 2);
AddLengthConstraint(0, 8);
AddLengthConstraint(0, 11);
AddLengthConstraint(0, 5);
AddLengthConstraint(2, 3);
AddLengthConstraint(3, 4);
AddLengthConstraint(5, 6);
AddLengthConstraint(6, 7);
AddLengthConstraint(2, 5);
AddLengthConstraint(2, 8);
AddLengthConstraint(2, 11);
AddLengthConstraint(5, 8);
AddLengthConstraint(5, 11);
AddLengthConstraint(8, 11);
AddLengthConstraint(8, 9);
AddLengthConstraint(9, 10);
AddLengthConstraint(11, 12);
AddLengthConstraint(12, 13);
AddMinLengthConstraint(1, 8, x14_lengthConstraints[2].GetLength());
AddMinLengthConstraint(1, 11, x14_lengthConstraints[3].GetLength());
AddMinLengthConstraint(1, 2, x14_lengthConstraints[1].GetLength() * 0.9f);
AddMinLengthConstraint(1, 5, x14_lengthConstraints[4].GetLength() * 0.9f);
AddMinLengthConstraint(1, 4, x14_lengthConstraints[0].GetLength() * 2.5f);
AddMinLengthConstraint(1, 7, x14_lengthConstraints[0].GetLength() * 2.5f);
AddMinLengthConstraint(4, 2, x14_lengthConstraints[5].GetLength());
AddMinLengthConstraint(7, 5, x14_lengthConstraints[7].GetLength());
AddMinLengthConstraint(3, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength());
AddMinLengthConstraint(6, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength());
AddMinLengthConstraint(4, 5, x14_lengthConstraints[5].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength());
AddMinLengthConstraint(7, 2, x14_lengthConstraints[7].GetLength() * 0.5f + x14_lengthConstraints[9].GetLength());
AddMinLengthConstraint(4, 7, x14_lengthConstraints[9].GetLength());
AddMinLengthConstraint(4, 8, x14_lengthConstraints[14].GetLength());
AddMinLengthConstraint(7, 11, x14_lengthConstraints[14].GetLength());
AddMinLengthConstraint(10, 8, x14_lengthConstraints[15].GetLength());
AddMinLengthConstraint(13, 11, x14_lengthConstraints[17].GetLength());
AddMinLengthConstraint(9, 2, x14_lengthConstraints[15].GetLength() * 0.707f + x14_lengthConstraints[10].GetLength());
AddMinLengthConstraint(12, 5, x14_lengthConstraints[17].GetLength() * 0.707f + x14_lengthConstraints[13].GetLength());
AddMinLengthConstraint(9, 11, x14_lengthConstraints[15].GetLength());
AddMinLengthConstraint(12, 8, x14_lengthConstraints[17].GetLength());
AddMinLengthConstraint(10, 0, x14_lengthConstraints[2].GetLength() + x14_lengthConstraints[15].GetLength());
AddMinLengthConstraint(13, 0, x14_lengthConstraints[3].GetLength() + x14_lengthConstraints[17].GetLength());
AddMinLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength());
AddMinLengthConstraint(9, 12, x14_lengthConstraints[14].GetLength());
AddMinLengthConstraint(10, 12, x14_lengthConstraints[14].GetLength());
AddMinLengthConstraint(13, 9, x14_lengthConstraints[14].GetLength());
AddMaxLengthConstraint(10, 13, x14_lengthConstraints[14].GetLength() * 5.f);
AddJointConstraint(8, 2, 5, 8, 9, 10); // R_hip, R_shoulder, L_shoulder, R_hip, R_knee, R_ankle
AddJointConstraint(11, 2, 5, 11, 12, 13); // L_hip, R_shoulder, L_shoulder, L_hip, L_knee, L_ankle
AddJointConstraint(2, 11, 5, 2, 3, 4); // R_shoulder, L_hip, L_shoulder, R_shoulder, R_elbow, R_wrist
AddJointConstraint(5, 2, 8, 5, 6, 7); // L_shoulder, R_shoulder, R_hip, L_shoulder, L_elbow, R_wrist
for (const auto& conn : x6c_spacePirate->GetConnectionList())
{
if (conn.x0_state == EScriptObjectState::Modify && conn.x4_msg == EScriptObjectMessage::Follow)
{
TUniqueId wpId = mgr.GetIdForScript(conn.x8_objId);
if (TCastToConstPtr<CScriptWaypoint> wp = mgr.GetObjectById(wpId))
{
x90_waypoints.push_back(wpId);
x9c_wpParticleIdxs.push_back(wp->GetAnimation());
if (x90_waypoints.size() == 4)
break;
}
}
}
} }
void CPirateRagDoll::PreRender(const zeus::CVector3f& v, CModelData& mData)
{
if (!x68_25_ || x68_27_)
{
CAnimData* aData = mData.AnimationData();
for (CSegId id : aData->GetCharLayoutInfo().GetSegIdList().GetList())
if (aData->GetCharLayoutInfo().GetRootNode()->GetBoneMap()[id].x10_children.size() > 1)
aData->PoseBuilder().GetTreeMap()[id].x4_rotation = zeus::CQuaternion::skNoRotation;
CSegId rootId = aData->GetLocatorSegId("Skeleton_Root"sv);
aData->PoseBuilder().GetTreeMap()[rootId].x14_offset =
(0.5f * (x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) - v) / mData.GetScale();
zeus::CVector3f _7c = x4_particles[2].GetPosition() - x4_particles[5].GetPosition();
zeus::CVector3f _88 =
(x4_particles[0].GetPosition() -
(x4_particles[8].GetPosition() + x4_particles[11].GetPosition()) * 0.5f).normalized();
zeus::CVector3f _x94 = _88.cross(_7c).normalized();
zeus::CQuaternion _a4(zeus::CMatrix3f(_x94.cross(_88), _x94, _88).transposed());
aData->PoseBuilder().GetTreeMap()[rootId].x4_rotation = _a4;
if (x6c_spacePirate->x7b4_ == kInvalidUniqueId)
{
zeus::CVector3f _b0 = aData->GetCharLayoutInfo().GetFromParentUnrotated(x4_particles[1].GetBone());
aData->PoseBuilder().GetTreeMap()[x4_particles[1].GetBone()] = zeus::CQuaternion::shortestRotationArc(_b0,
_a4.inverse().transform(x4_particles[1].GetPosition() - x4_particles[0].GetPosition()));
}
BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 3, 4,
_a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 2, 3, _a4));
BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 6, 7,
_a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 5, 6, _a4));
BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 9, 10,
_a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 8, 9, _a4));
BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 12, 13,
_a4 * BoneAlign(aData->PoseBuilder(), aData->GetCharLayoutInfo(), 11, 12, _a4));
zeus::CQuaternion q;
q.rotateX(zeus::degToRad(-70.f));
aData->PoseBuilder().GetTreeMap()[x4_particles[10].GetBone()].x4_rotation = q;
aData->PoseBuilder().GetTreeMap()[x4_particles[13].GetBone()].x4_rotation = q;
aData->MarkPoseDirty();
}
}
void CPirateRagDoll::Update(CStateManager& mgr, float dt, float f2in)
{
if (!x68_25_ || x68_27_)
{
if (x6c_spacePirate->x7b4_ != kInvalidUniqueId)
{
float f2 = x4_particles[2].GetPosition().z - x4_particles[5].GetPosition().z;
if (f2 * f2 > 0.0625f)
{
zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f);
x4_particles[2].Position() -= vec;
x4_particles[5].Position() += vec;
}
f2 = x4_particles[0].GetPosition().z -
(x4_particles[8].GetPosition().z + x4_particles[11].GetPosition().z) * 0.5f;
if (f2 * f2 > 0.0625f)
{
zeus::CVector3f vec(0.f, 0.f, ((f2 > 0.f) ? f2 - 0.25f : f2 + 0.25f) * 0.1f);
x4_particles[0].Position() -= vec;
x4_particles[8].Position() += vec;
x4_particles[11].Position() += vec;
}
}
zeus::CVector3f _54 =
x4_particles[8].GetPosition() * 0.25f +
x4_particles[11].GetPosition() * 0.25f + x4_particles[0].GetPosition() * 0.5f;
_54.z =
std::min(x4_particles[0].GetPosition().z - x4_particles[0].GetRadius(),
std::min(x4_particles[8].GetPosition().z - x4_particles[8].GetRadius(),
x4_particles[11].GetPosition().z - x4_particles[11].GetRadius()));
if (_54.z < 0.5f + f2in)
x84_ = x84_ * 1000.f;
zeus::CVector3f vec = x84_ * 0.333f * (1.f / x6c_spacePirate->GetMass());
x4_particles[11].Acceleration() += vec;
x4_particles[8].Acceleration() += vec;
x4_particles[0].Acceleration() += vec;
x84_ = zeus::CVector3f::skZero;
CRagDoll::Update(mgr, dt, f2in);
auto particleIdxIt = x9c_wpParticleIdxs.begin();
for (TUniqueId id : x90_waypoints)
{
if (const CScriptWaypoint* wp = static_cast<const CScriptWaypoint*>(mgr.GetObjectById(id)))
if (wp->GetActive())
x4_particles[*particleIdxIt].Position() = wp->GetTranslation();
++particleIdxIt;
}
zeus::CVector3f _60 =
x4_particles[8].GetPosition() * 0.25f +
x4_particles[11].GetPosition() * 0.25f + x4_particles[0].GetPosition() * 0.5f;
_60.z =
std::min(x4_particles[0].GetPosition().z - x4_particles[0].GetRadius(),
std::min(x4_particles[8].GetPosition().z - x4_particles[8].GetRadius(),
x4_particles[11].GetPosition().z - x4_particles[11].GetRadius()));
x6c_spacePirate->SetTransform({});
x6c_spacePirate->SetTranslation(_60);
x6c_spacePirate->SetVelocityWR((_60 - _54) * (1.f / dt));
x74_ -= dt;
if (x54_ > 2.5f && x74_ < 0.f &&
(xb0_24_ || (x6c_spacePirate->GetTranslation() - x78_).magSquared() > 0.1f))
{
CSfxManager::AddEmitter(x70_s1, x6c_spacePirate->GetTranslation(), zeus::CVector3f::skZero,
std::min(25.f * x54_, 127.f) / 127.f, true, false, 0x7f, kInvalidAreaId);
x74_ = mgr.GetActiveRandom()->Float() * 0.222f + 0.222f;
xb0_24_ = false;
x78_ = x6c_spacePirate->GetTranslation();
}
}
else
{
x6c_spacePirate->SetMomentumWR(zeus::CVector3f::skZero);
x6c_spacePirate->Stop();
}
}
void CPirateRagDoll::Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData)
{
const auto& aabb = x6c_spacePirate->GetBaseBoundingBox();
zeus::CVector3f newMax = aabb.max;
newMax.z = (aabb.max.z - aabb.min.z) * 0.5f + aabb.min.z;
x6c_spacePirate->SetBoundingBox({aabb.min, newMax});
CRagDoll::Prime(mgr, xf, mData);
}
const SBurst CSpacePirate::skBurstsQuick[] =
{
{20, {3, 4, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {2, 3, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {6, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {1, 2, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {7, 6, 5, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsStandard[] =
{
{15, {5, 3, 2, 1, -1, 0, 0, 0}, 0.100000, 0.050000},
{20, {1, 2, 3, 4, -1, 0, 0, 0}, 0.100000, 0.050000},
{20, {7, 6, 5, 4, -1, 0, 0, 0}, 0.100000, 0.050000},
{15, {3, 4, 5, 6, -1, 0, 0, 0}, 0.100000, 0.050000},
{15, {6, 5, 4, 3, -1, 0, 0, 0}, 0.100000, 0.050000},
{15, {2, 3, 4, 5, -1, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsFrenzied[] =
{
{40, {1, 2, 3, 4, 5, 6, -1, 0}, 0.100000, 0.050000},
{40, {7, 6, 5, 4, 3, 2, -1, 0}, 0.100000, 0.050000},
{10, {2, 3, 4, 5, 4, 3, -1, 0}, 0.100000, 0.050000},
{10, {6, 5, 4, 3, 4, 5, -1, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsJumping[] =
{
{20, {16, 4, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{40, {5, 7, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{40, {1, 10, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsInjured[] =
{
{15, {16, 1, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {3, 4, 6, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{25, {7, 5, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{25, {2, 6, 4, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{15, {7, 5, 3, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsSeated[] =
{
{35, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{35, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{30, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsQuickOOV[] =
{
{10, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{30, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{30, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{10, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsStandardOOV[] =
{
{26, {16, 8, 11, 14, -1, 0, 0, 0}, 0.100000, 0.050000},
{26, {16, 13, 11, 12, -1, 0, 0, 0}, 0.100000, 0.050000},
{16, {9, 11, 13, 10, -1, 0, 0, 0}, 0.100000, 0.050000},
{16, {14, 13, 12, 11, -1, 0, 0, 0}, 0.100000, 0.050000},
{8, {10, 11, 12, 13, -1, 0, 0, 0}, 0.100000, 0.050000},
{8, {6, 8, 11, 13, -1, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsFrenziedOOV[] =
{
{40, {1, 16, 14, 12, 10, 11, -1, 0}, 0.100000, 0.050000},
{40, {9, 11, 12, 13, 11, 7, -1, 0}, 0.100000, 0.050000},
{10, {8, 10, 11, 12, 13, 12, -1, 0}, 0.100000, 0.050000},
{10, {15, 13, 12, 10, 12, 9, -1, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsJumpingOOV[] =
{
{40, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{40, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{20, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsInjuredOOV[] =
{
{30, {9, 11, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{10, {13, 12, 10, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{15, {9, 11, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{15, {14, 10, 12, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{30, {16, 15, 13, -1, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst CSpacePirate::skBurstsSeatedOOV[] =
{
{35, {7, 13, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{35, {9, 1, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{30, {16, 12, -1, 0, 0, 0, 0, 0}, 0.100000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
};
const SBurst* CSpacePirate::skBursts[] =
{
skBurstsQuick,
skBurstsStandard,
skBurstsFrenzied,
skBurstsJumping,
skBurstsInjured,
skBurstsSeated,
skBurstsQuickOOV,
skBurstsStandardOOV,
skBurstsFrenziedOOV,
skBurstsJumpingOOV,
skBurstsInjuredOOV,
skBurstsSeatedOOV,
nullptr
};
CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CSpacePirate::CSpacePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo, CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo,
CInputStream& in, u32 propCount) CInputStream& in, u32 propCount)
: CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, : CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::Medium) EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::Medium)
, x568_(in, propCount) , x568_pirateData(in, propCount), x660_(nullptr, 0x1, pInfo.GetPathfindingIndex(), 1.f, 1.f),
x750_(pInfo.GetHealthInfo().GetHP()),
x764_(*x64_modelData->AnimationData(), "Head_1"sv, 1.22173f, 3.14159f, false),
x7c4_(skBursts, x568_pirateData.xac_firstBurstCount),
x8b8_(x568_pirateData.xb0_), x8bc_(x568_pirateData.xb4_),
x8c0_(x568_pirateData.xb8_), x8c4_(x568_pirateData.xa8_)
{ {
x634_24_ = bool(x568_pirateData.x18_ & 0x1);
x634_25_ = bool(x568_pirateData.x18_ & 0x2);
x634_26_ = bool(x568_pirateData.x18_ & 0x4);
x634_27_ = bool(x568_pirateData.x18_ & 0x8);
x634_28_ = bool(x568_pirateData.x18_ & 0x10);
x634_29_ = bool(x568_pirateData.x18_ & 0x20);
x634_30_ = bool(x568_pirateData.x18_ & 0x40);
x634_31_ = bool(x568_pirateData.x18_ & 0x80);
x635_24_ = bool(x568_pirateData.x18_ & 0x200);
x635_25_ = bool(x568_pirateData.x18_ & 0x400);
x635_26_ = bool(x568_pirateData.x18_ & 0x1000);
x635_27_ = bool(x568_pirateData.x18_ & 0x2000);
x635_28_ = bool(x568_pirateData.x18_ & 0x4000);
x635_29_ = bool(x568_pirateData.x18_ & 0x8000);
x635_30_ = bool(x568_pirateData.x18_ & 0x10000);
x635_31_ = bool(x568_pirateData.x18_ & 0x20000);
x636_24_trooper = bool(x568_pirateData.x18_ & 0x40000);
x758_headSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Head_1"sv);
x7b6_gunSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_gun_LCTR"sv);
x7b7_elbowSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_elbow"sv);
x7b8_wristSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("R_wrist"sv);
x7b9_swooshSeg = x64_modelData->GetAnimationData()->GetLocatorSegId("Swoosh_LCTR"sv);
if (!x634_29_)
{
x7a4_intoJumpDist = GetAnimationDistance(CPASAnimParmData(13,
CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(0)));
x848_dodgeDist = GetAnimationDistance(CPASAnimParmData(3,
CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(1)));
x84c_breakDodgeDist = GetAnimationDistance(CPASAnimParmData(3,
CPASAnimParm::FromEnum(3), CPASAnimParm::FromEnum(2)));
}
else
{
x450_bodyController->BodyStateInfo().SetLocoAnimChangeAtEndOfAnimOnly(true);
}
const auto& baseAABB = GetBaseBoundingBox();
x7a8_ = (baseAABB.max.z - baseAABB.min.z) * 0.6f;
if (x90_actorLights)
x90_actorLights->SetAmbienceGenerated(false);
x460_knockBackController.sub80233d40(3, 3.f, FLT_MAX);
x460_knockBackController.SetLocomotionDuringElectrocution(true);
if (x634_29_)
x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Small);
else if (x636_24_trooper && GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false))
x460_knockBackController.SetKnockBackVariant(EKnockBackVariant::Large);
if (!x450_bodyController->HasBodyState(pas::EAnimationState::AdditiveAim))
x634_27_ = true;
if (x636_24_trooper)
{
if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Plasma), false))
x8cc_trooperColor = zeus::CColor(0.996f, 0.f, 0.157f, 1.f);
else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Ice), false))
x8cc_trooperColor = zeus::CColor::skWhite;
else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Power), false))
x8cc_trooperColor = zeus::CColor(0.992f, 0.937f, 0.337f, 1.f);
else if (GetDamageVulnerability()->WeaponHurts(CWeaponMode(EWeaponType::Wave), false))
x8cc_trooperColor = zeus::CColor(0.776f, 0.054f, 1.f, 1.f);
}
} }
void CSpacePirate::Accept(IVisitor &visitor) void CSpacePirate::Accept(IVisitor &visitor)
@ -39,6 +476,72 @@ void CSpacePirate::Think(float dt, CStateManager& mgr)
if (!x450_bodyController->GetActive()) if (!x450_bodyController->GetActive())
x450_bodyController->Activate(mgr); x450_bodyController->Activate(mgr);
#if 0
bool inCineCam = mgr.GetCameraManager()->IsInCinematicCamera();
if (inCineCam && !x637_31_prevInCineCam)
sub_801283a8(mgr);
else if (!inCineCam && x637_31_prevInCineCam && !x635_31_)
CreateCollisionActor(mgr);
x637_31_prevInCineCam = inCineCam;
float steeringSpeed = x748_ == 0.f ? x644_ : 0.f;
x450_bodyController->GetCommandMgr().SetSteeringSpeedRange(steeringSpeed, steeringSpeed);
x744_ = std::max(x744_ - dt, 0.f);
if (x400_25_alive)
{
x850_ += dt;
x854_ += dt;
if (x637_27_)
{
x854_ = 0.f;
x637_27_ = false;
}
if (x400_24_hitByPlayerProjectile)
{
x850_ = 0.f;
x400_24_hitByPlayerProjectile = false;
}
}
sub_8012169c(dt, mgr);
if (!x450_bodyController->IsFrozen())
{
if (x400_25_alive)
{
x748_ = std::max(x748_ - dt, 0.f);
if (x637_28_)
x7ac_ += dt;
else
x7ac_ = 0.f;
x838_ = std::max(x838_ - dt, 0.f);
x8c0_ = std::max(x8c0_ - dt, 0.f);
CheckForProjectiles(mgr);
}
sub_80121214(dt, mgr);
sub_8012102c(dt, mgr);
x860_ikChain.Update(dt);
}
if (x634_24_)
{
x634_24_ = false;
if (x634_25_)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal6);
else
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
x330_stateMachineState.SetState(mgr, *this, GetStateMachine(), "Ambushing"sv);
}
bool r29 = x85c_ragDoll == 0;
if (r29 || )
{
}
#endif
CPatterned::Think(dt, mgr); CPatterned::Think(dt, mgr);
} }

View File

@ -2,18 +2,43 @@
#include "World/CPatterned.hpp" #include "World/CPatterned.hpp"
#include "Weapon/CProjectileInfo.hpp" #include "Weapon/CProjectileInfo.hpp"
#include "Character/CBoneTracking.hpp"
#include "Character/CIkChain.hpp"
#include "Character/CRagDoll.hpp"
#include "World/CPathFindSearch.hpp"
#include "Weapon/CBurstFire.hpp"
namespace urde::MP1 namespace urde::MP1
{ {
class CSpacePirate;
class CPirateRagDoll : public CRagDoll
{
CSpacePirate* x6c_spacePirate;
u16 x70_s1;
float x74_ = 0.f;
zeus::CVector3f x78_;
zeus::CVector3f x84_;
rstl::reserved_vector<TUniqueId, 4> x90_waypoints;
rstl::reserved_vector<u32, 4> x9c_wpParticleIdxs;
bool xb0_24_ : 1;
public:
CPirateRagDoll(CStateManager& mgr, CSpacePirate* sp, u16 s1, u32 flags);
void PreRender(const zeus::CVector3f& v, CModelData& mData);
void Update(CStateManager& mgr, float dt, float f2);
void Prime(CStateManager& mgr, const zeus::CTransform& xf, CModelData& mData);
};
class CSpacePirate : public CPatterned class CSpacePirate : public CPatterned
{ {
friend class CPirateRagDoll;
public: public:
DEFINE_PATTERNED(SpacePirate) DEFINE_PATTERNED(SpacePirate)
private: private:
class CSpacePirateData class CSpacePirateData
{ {
friend class CSpacePirate;
float x0_; float x0_;
float x4_; float x4_;
float x8_; float x8_;
@ -33,7 +58,7 @@ private:
float xa0_; float xa0_;
u16 xa4_; u16 xa4_;
float xa8_; float xa8_;
u32 xac_; u32 xac_firstBurstCount;
float xb0_; float xb0_;
float xb4_; float xb4_;
float xb8_; float xb8_;
@ -46,7 +71,7 @@ private:
CSpacePirateData(CInputStream&, u32); CSpacePirateData(CInputStream&, u32);
}; };
CSpacePirateData x568_; CSpacePirateData x568_pirateData;
union union
{ {
struct struct
@ -67,11 +92,115 @@ private:
bool x635_29_ : 1; bool x635_29_ : 1;
bool x635_30_ : 1; bool x635_30_ : 1;
bool x635_31_ : 1; bool x635_31_ : 1;
bool x636_24_trooper : 1;
bool x636_25_ : 1;
bool x636_26_ : 1;
bool x636_27_ : 1;
bool x636_28_ : 1;
bool x636_29_ : 1;
bool x636_30_ : 1;
bool x636_31_ : 1;
bool x637_24_ : 1;
bool x637_25_ : 1;
bool x637_26_ : 1;
bool x637_27_ : 1;
bool x637_28_ : 1;
bool x637_29_ : 1;
bool x637_30_ : 1;
bool x637_31_prevInCineCam : 1;
bool x638_24_ : 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_31_ : 1;
bool x639_24_ : 1;
bool x639_25_ : 1;
bool x639_26_ : 1;
bool x639_27_ : 1;
bool x639_28_ : 1;
bool x639_29_ : 1;
bool x639_30_ : 1;
bool x639_31_ : 1;
bool x63a_24_ : 1;
}; };
u32 _dummy = 0; u64 _dummy = 0;
}; };
u32 x63c_ = 0;
TUniqueId x640_ = kInvalidUniqueId;
TUniqueId x642_ = kInvalidUniqueId;
float x644_ = 1.f;
zeus::CVector3f x648_ = zeus::CVector3f::skForward;
zeus::CVector3f x654_;
CPathFindSearch x660_;
float x744_ = 0.f;
float x748_ = 0.f;
u32 x74c_ = 0;
float x750_;
float x754_ = 0.f;
CSegId x758_headSeg;
u32 x75c_ = 0;
s32 x760_ = -1;
CBoneTracking x764_;
s32 x79c_ = -1;
float x7a4_intoJumpDist = 1.f;
float x7a8_ = 2.f;
float x7ac_ = 0.f;
u32 x7b0_ = 0;
TUniqueId x7b4_ = kInvalidUniqueId;
CSegId x7b6_gunSeg;
CSegId x7b7_elbowSeg;
CSegId x7b8_wristSeg;
CSegId x7b9_swooshSeg;
float x7bc_ = 1.f;
TUniqueId x7c0_ = kInvalidUniqueId;
CBurstFire x7c4_;
float x824_ = 3.f;
zeus::CVector3f x828_;
s32 x834_ = -1;
float x838_ = 0.f;
s32 x83c_ = -1;
TUniqueId x840_ = kInvalidUniqueId;
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;
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 x8c0_;
float x8c4_;
TUniqueId x8c8_ = kInvalidUniqueId;
zeus::CColor x8cc_trooperColor = zeus::CColor::skWhite;
zeus::CVector2f x8d0_;
float x8d8_ = 0.f;
float x8dc_ = 0.f;
static const SBurst skBurstsSeatedOOV[];
static const SBurst skBurstsInjuredOOV[];
static const SBurst skBurstsJumpingOOV[];
static const SBurst skBurstsFrenziedOOV[];
static const SBurst skBurstsStandardOOV[];
static const SBurst skBurstsQuickOOV[];
static const SBurst skBurstsSeated[];
static const SBurst skBurstsInjured[];
static const SBurst skBurstsJumping[];
static const SBurst skBurstsFrenzied[];
static const SBurst skBurstsStandard[];
static const SBurst skBurstsQuick[];
static const SBurst* skBursts[];
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);

View File

@ -124,34 +124,28 @@ bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPo
if (!x14_planePrecomputed) if (!x14_planePrecomputed)
{ {
/* Compute Hesse normal form of plane (for penetration testing) */ /* Compute Hesse normal form of plane (for penetration testing) */
x8_planeNormal->GetValue(frame, ((zeus::CVector3f&)x18_planeValidatedNormal)); x8_planeNormal->GetValue(frame, const_cast<zeus::CVector3f&>(x18_planeValidatedNormal));
((zeus::CVector3f&)x18_planeValidatedNormal).normalize(); const_cast<zeus::CVector3f&>(x18_planeValidatedNormal).normalize();
zeus::CVector3f a; zeus::CVector3f a;
x4_planePoint->GetValue(frame, a); x4_planePoint->GetValue(frame, a);
(float&)(x24_planeD) = x18_planeValidatedNormal.dot(a); const_cast<float&>(x24_planeD) = x18_planeValidatedNormal.dot(a);
} }
float dot = x18_planeValidatedNormal.dot(pPos); float dot = x18_planeValidatedNormal.dot(pPos);
if ((dot - x24_planeD) <= 0.0f) if (dot - x24_planeD > 0.0f)
{
if (x15_dieOnPenetrate)
return true;
}
else
return false; return false;
else if (x15_dieOnPenetrate)
return true;
/* Deflection event */ /* Deflection event */
if (pVel.magSquared() > 0.0f) if (pVel.dot(x18_planeValidatedNormal) >= 0.0f)
return false; return false;
zeus::CVector3f delta = pPos - pVel; zeus::CVector3f delta = pPos - pVel;
pPos += zeus::CVector3f{(-((((delta.z * ((delta.x * (delta.y * x18_planeValidatedNormal.y)) pPos += (-(delta.dot(x18_planeValidatedNormal) - x24_planeD) / pVel.dot(x18_planeValidatedNormal) - 1.f) * pVel;
+ ((pVel.x * (x18_planeValidatedNormal.y * pVel.y)) + x18_planeValidatedNormal.x))) + x18_planeValidatedNormal.z) - x24_planeD)) /
((pVel.z * ((pVel.x * (x18_planeValidatedNormal.y * pVel.y)) + x18_planeValidatedNormal.x)) + x18_planeValidatedNormal.z)) - (
(x18_planeValidatedNormal.z * ((x18_planeValidatedNormal.x * (x18_planeValidatedNormal.y * pVel.y)) + pVel.x)) + pVel.z)} * pVel;
float d = 0.0f; float d = 0.0f;
x10_restitution->GetValue(frame, d); x10_restitution->GetValue(frame, d);
@ -159,7 +153,7 @@ bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPo
float c = 0.0f; float c = 0.0f;
xc_friction->GetValue(frame, c); xc_friction->GetValue(frame, c);
pVel -= zeus::CVector3f{(1.0f + c) * ((x18_planeValidatedNormal.z * (x18_planeValidatedNormal.x * (x18_planeValidatedNormal.y * pVel.y)) + pVel.x) + pVel.x)} * x18_planeValidatedNormal; pVel -= (1.f + c) * x18_planeValidatedNormal.dot(pVel) * x18_planeValidatedNormal;
return false; return false;
} }

View File

@ -1,78 +1,108 @@
#include "CBurstFire.hpp" #include "CBurstFire.hpp"
#include "GameGlobalObjects.hpp"
namespace urde namespace urde
{ {
CBurstFire::CBurstFire(SBurst** bursts, s32 firstIndex) CBurstFire::CBurstFire(const SBurst** burstDefs, s32 firstBurstCount)
: x10_(firstIndex) : x10_firstBurstCounter(firstBurstCount)
{ {
SBurst** burst = bursts; while (*burstDefs)
while (1)
{ {
if (!*burst) x1c_burstDefs.push_back(*burstDefs);
break; ++burstDefs;
x18_bursts.push_back(*burst);
++burst;
} }
} }
void CBurstFire::Update(CStateManager&, float) void CBurstFire::Update(CStateManager& mgr, float dt)
{ {
x14_24_shouldFire = false;
if (x18_curBursts)
{
x8_timeToNextShot -= dt;
if (x8_timeToNextShot < 0.f)
{
x4_angleIdx += 1;
if (x18_curBursts->x4_shotAngles[x4_angleIdx] > 0)
{
x14_24_shouldFire = true;
x8_timeToNextShot = x18_curBursts->x24_timeToNextShot;
x8_timeToNextShot += (mgr.GetActiveRandom()->Float() - 0.5f) *
x18_curBursts->x28_timeToNextShotVariance;
}
else
{
x18_curBursts = nullptr;
}
}
}
} }
zeus::CVector3f CBurstFire::GetDistanceCompensatedError(float, float) const zeus::CVector3f CBurstFire::GetDistanceCompensatedError(float dist, float maxErrDist) const
{ {
return {}; float xErr = GetMaxXError();
float zErr = GetMaxZError();
xErr = std::min(xErr, dist / maxErrDist * xErr);
zErr = std::min(zErr, dist / maxErrDist * zErr);
return GetError(xErr, zErr);
} }
void CBurstFire::SetFirstBurst(bool) void CBurstFire::Start(CStateManager& mgr)
{ {
s32 burstIdx = -1;
const SBurst* bursts = x1c_burstDefs[x0_burstType];
if (x10_firstBurstCounter-- > 0)
{
burstIdx = xc_firstBurstIdx < 0 ? 0 : xc_firstBurstIdx;
}
else
{
int random = mgr.GetActiveRandom()->Range(0, 100);
int advanceAccum = 0;
do
{
burstIdx += 1;
s32 advanceWeight = bursts[burstIdx].x0_randomSelectionWeight;
if (advanceWeight == 0)
{
advanceAccum = 100;
burstIdx -= 1;
}
advanceAccum += advanceWeight;
} while (random > advanceAccum);
}
x18_curBursts = &bursts[burstIdx];
x4_angleIdx = -1;
x8_timeToNextShot = 0.f;
x14_24_shouldFire = false;
} }
bool CBurstFire::IsBurstSet() const zeus::CVector3f CBurstFire::GetError(float xMag, float zMag) const
{ {
return false; zeus::CVector3f ret;
} if (x14_24_shouldFire && x18_curBursts)
{
void CBurstFire::SetTimeToNextShot(float) s32 r0 = x18_curBursts->x4_shotAngles[x4_angleIdx];
{ if (x14_25_avoidAccuracy && (r0 == 4 || r0 == 12))
r0 = x4_angleIdx > 0 ? x18_curBursts->x4_shotAngles[x4_angleIdx - 1] :
} x18_curBursts->x4_shotAngles[x4_angleIdx + 1];
if (r0 > 0)
bool CBurstFire::ShouldFire() const {
{ float angle = r0 * zeus::degToRad(-22.5f);
return false; ret.x = std::cos(angle) * xMag;
} ret.z = std::sin(angle) * zMag;
}
void CBurstFire::Start(CStateManager&) }
{ return ret;
}
void CBurstFire::GetError(float, float) const
{
} }
float CBurstFire::GetMaxXError() const float CBurstFire::GetMaxXError() const
{ {
return 0; return g_tweakPlayer->GetPlayerXYHalfExtent() * 3.625f + 0.2f;
} }
float CBurstFire::GetMaxZError() const float CBurstFire::GetMaxZError() const
{ {
return 0; return g_tweakPlayer->GetEyeOffset();
} }
void CBurstFire::GetError() const
{
}
void CBurstFire::SetFirstBurstIndex(s32)
{
}
} }

View File

@ -6,53 +6,42 @@ namespace urde
{ {
struct SBurst struct SBurst
{ {
u32 x0_; s32 x0_randomSelectionWeight;
u32 x4_; s32 x4_shotAngles[8];
u32 x8_; float x24_timeToNextShot;
s32 xc_; float x28_timeToNextShotVariance;
s32 x10_;
u32 x14_;
u32 x18_;
u32 x1c_;
u32 x20_;
float x24_;
float x28_;
}; };
class CBurstFire class CBurstFire
{ {
friend class CScriptGunTurret; s32 x0_burstType = -1;
s32 x0_ = -1; s32 x4_angleIdx = -1;
s32 x4_ = -1; float x8_timeToNextShot = 0.f;
float x8_ = 0.f; s32 xc_firstBurstIdx = 0;
u32 xc_ = 0; s32 x10_firstBurstCounter;
s32 x10_;
union union
{ {
struct { bool x14_24_ : 1; bool x14_25_ : 1; }; struct { bool x14_24_shouldFire : 1; bool x14_25_avoidAccuracy : 1; };
u32 _dummy = 0; u32 _dummy = 0;
}; };
rstl::reserved_vector<SBurst*, 16> x18_bursts; const SBurst* x18_curBursts = nullptr;
rstl::reserved_vector<const SBurst*, 16> x1c_burstDefs;
public: public:
CBurstFire(SBurst**, s32); CBurstFire(const SBurst** burstDefs, s32 firstBurstCount);
void SetFirstBurst(bool); void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; }
void SetBurstType(s32 type) { x0_ = type; } void SetBurstType(s32 type) { x0_burstType = type; }
bool IsBurstSet() const; void SetTimeToNextShot(float t) { x8_timeToNextShot = t; }
void SetTimeToNextShot(float); s32 GetBurstType() const { return x0_burstType; }
bool ShouldFire() const; void Start(CStateManager& mgr);
s32 GetBurstType() const { return x0_; } void Update(CStateManager& mgr, float dt);
void Start(CStateManager&); zeus::CVector3f GetError(float xMag, float zMag) const;
void Update(CStateManager&, float); zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const;
void Update();
void GetError(float, float) const;
zeus::CVector3f GetDistanceCompensatedError(float, float) const;
float GetMaxXError() const; float GetMaxXError() const;
float GetMaxZError() const; float GetMaxZError() const;
void GetError() const; void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; }
void SetFirstBurstIndex(s32); bool ShouldFire() const { return x14_24_shouldFire; }
bool IsBurstSet() const { return x18_curBursts != nullptr; }
bool GetX14_24() const { return x14_24_; }
}; };
} }

View File

@ -4,7 +4,7 @@ set(WEAPON_SOURCES
CGunController.hpp CGunController.cpp CGunController.hpp CGunController.cpp
CGunMotion.hpp CGunMotion.cpp CGunMotion.hpp CGunMotion.cpp
CGrappleArm.hpp CGrappleArm.cpp CGrappleArm.hpp CGrappleArm.cpp
CWeaponMode.hpp CWeaponMode.cpp CWeaponMode.hpp
CPlayerGun.hpp CPlayerGun.cpp CPlayerGun.hpp CPlayerGun.cpp
CGunWeapon.hpp CGunWeapon.cpp CGunWeapon.hpp CGunWeapon.cpp
CAuxWeapon.hpp CAuxWeapon.cpp CAuxWeapon.hpp CAuxWeapon.cpp

View File

@ -1,28 +0,0 @@
#include "CWeaponMode.hpp"
#include "DataSpec/DNACommon/Tweaks/ITweakPlayerGun.hpp"
namespace urde
{
CWeaponMode::CWeaponMode(EWeaponType type, bool charged, bool comboed, bool instaKill)
: x0_weaponType(type), x4_24_charged(charged), x4_25_comboed(comboed), x4_26_instantKill(instaKill)
{
}
CWeaponMode CWeaponMode::Invalid() { return CWeaponMode(EWeaponType::None); }
CWeaponMode CWeaponMode::Phazon() { return CWeaponMode(EWeaponType::Phazon); }
CWeaponMode CWeaponMode::Plasma() { return CWeaponMode(EWeaponType::Plasma); }
CWeaponMode CWeaponMode::Wave() { return CWeaponMode(EWeaponType::Wave); }
CWeaponMode CWeaponMode::BoostBall() { return CWeaponMode(EWeaponType::BoostBall); }
CWeaponMode CWeaponMode::Ice() { return CWeaponMode(EWeaponType::Ice); }
CWeaponMode CWeaponMode::Power() { return CWeaponMode(EWeaponType::Power); }
CWeaponMode CWeaponMode::Bomb() { return CWeaponMode(EWeaponType::Bomb); }
CWeaponMode CWeaponMode::PowerBomb() { return CWeaponMode(EWeaponType::PowerBomb); }
}

View File

@ -13,21 +13,22 @@ class CWeaponMode
public: public:
CWeaponMode() { x4_24_charged = false; x4_25_comboed = false; x4_26_instantKill = false; } CWeaponMode() { x4_24_charged = false; x4_25_comboed = false; x4_26_instantKill = false; }
CWeaponMode(EWeaponType, bool charged = false, bool comboed = false, bool instaKill = false); CWeaponMode(EWeaponType type, bool charged = false, bool comboed = false, bool instaKill = false)
: x0_weaponType(type), x4_24_charged(charged), x4_25_comboed(comboed), x4_26_instantKill(instaKill) {}
EWeaponType GetType() const { return x0_weaponType; } EWeaponType GetType() const { return x0_weaponType; }
bool IsCharged() const { return x4_24_charged; } bool IsCharged() const { return x4_24_charged; }
bool IsComboed() const { return x4_25_comboed; } bool IsComboed() const { return x4_25_comboed; }
bool IsInstantKill() const { return x4_26_instantKill; } bool IsInstantKill() const { return x4_26_instantKill; }
static CWeaponMode Invalid(); static CWeaponMode Invalid() { return CWeaponMode(EWeaponType::None); }
static CWeaponMode Phazon(); static CWeaponMode Phazon() { return CWeaponMode(EWeaponType::Phazon); }
static CWeaponMode Plasma(); static CWeaponMode Plasma() { return CWeaponMode(EWeaponType::Plasma); }
static CWeaponMode Wave(); static CWeaponMode Wave() { return CWeaponMode(EWeaponType::Wave); }
static CWeaponMode BoostBall(); static CWeaponMode BoostBall() { return CWeaponMode(EWeaponType::BoostBall); }
static CWeaponMode Ice(); static CWeaponMode Ice() { return CWeaponMode(EWeaponType::Ice); }
static CWeaponMode Power(); static CWeaponMode Power() { return CWeaponMode(EWeaponType::Power); }
static CWeaponMode Bomb(); static CWeaponMode Bomb() { return CWeaponMode(EWeaponType::Bomb); }
static CWeaponMode PowerBomb(); static CWeaponMode PowerBomb() { return CWeaponMode(EWeaponType::PowerBomb); }
}; };
} }

View File

@ -605,7 +605,7 @@ void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& pare
x64_flinchRemTime -= dt; x64_flinchRemTime -= dt;
if (TickDeferredTimer(dt)) if (TickDeferredTimer(dt))
DoDeferredKnockBack(mgr, parent); DoDeferredKnockBack(mgr, parent);
if (x82_26_ && parent.BodyController()->IsElectrocuting()) if (x82_26_locomotionDuringElectrocution && parent.BodyController()->IsElectrocuting())
parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion));
} }

View File

@ -122,7 +122,7 @@ private:
bool x81_31_ : 1; // t bool x81_31_ : 1; // t
bool x82_24_ : 1; // t bool x82_24_ : 1; // t
bool x82_25_inDeferredKnockBack : 1; bool x82_25_inDeferredKnockBack : 1;
bool x82_26_ : 1; bool x82_26_locomotionDuringElectrocution : 1;
}; };
u32 dummy = 0; u32 dummy = 0;
}; };
@ -155,6 +155,7 @@ public:
void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; } void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; }
void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; } void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; }
void SetX82_24(bool b) { x82_24_ = b; } void SetX82_24(bool b) { x82_24_ = b; }
void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; }
const KnockBackParms& GetActiveParms() const { return x4_activeParms; } const KnockBackParms& GetActiveParms() const { return x4_activeParms; }
EKnockBackVariant GetVariant() const { return x0_variant; } EKnockBackVariant GetVariant() const { return x0_variant; }
float GetFlinchRemTime() const { return x64_flinchRemTime; } float GetFlinchRemTime() const { return x64_flinchRemTime; }

View File

@ -1597,6 +1597,19 @@ EScriptObjectState CPatterned::GetDesiredAttackState(CStateManager& mgr) const
return EScriptObjectState::Attack; return EScriptObjectState::Attack;
} }
float CPatterned::GetAnimationDistance(const CPASAnimParmData& data) const
{
auto bestAnim =
x64_modelData->GetAnimationData()->GetCharacterInfo().GetPASDatabase().FindBestAnimation(data, -1);
float dist = 1.f;
if (bestAnim.first > FLT_EPSILON)
{
dist = x64_modelData->GetAnimationData()->GetAnimationDuration(bestAnim.second) *
x64_modelData->GetAnimationData()->GetAverageVelocity(bestAnim.second);
}
return dist;
}
void CPatterned::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) void CPatterned::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum)
{ {
if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal)

View File

@ -308,6 +308,7 @@ protected:
void UpdatePatternDestPos(CStateManager& mgr); void UpdatePatternDestPos(CStateManager& mgr);
void SetupPattern(CStateManager& mgr); void SetupPattern(CStateManager& mgr);
EScriptObjectState GetDesiredAttackState(CStateManager& mgr) const; EScriptObjectState GetDesiredAttackState(CStateManager& mgr) const;
float GetAnimationDistance(const CPASAnimParmData& data) const;
public: public:
CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor, CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor,
const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData,

View File

@ -36,7 +36,7 @@ CPatternedInfo::CPatternedInfo(CInputStream& in, u32 pcount)
, x100_intoFreezeDur(in.readFloatBig()) , x100_intoFreezeDur(in.readFloatBig())
, x104_outofFreezeDur(in.readFloatBig()) , x104_outofFreezeDur(in.readFloatBig())
, x108_(in.readFloatBig()) , x108_(in.readFloatBig())
, x10c_particle1Frames(in.readUint32Big()) , x10c_pathfindingIndex(in.readUint32Big())
, x110_particle1Scale(zeus::CVector3f::ReadBig(in)) , x110_particle1Scale(zeus::CVector3f::ReadBig(in))
, x11c_particle1(in) , x11c_particle1(in)
, x120_electric(in) , x120_electric(in)

View File

@ -45,7 +45,7 @@ class CPatternedInfo
float x104_outofFreezeDur; float x104_outofFreezeDur;
float x108_; float x108_;
u32 x10c_particle1Frames; u32 x10c_pathfindingIndex;
zeus::CVector3f x110_particle1Scale; zeus::CVector3f x110_particle1Scale;
CAssetId x11c_particle1; CAssetId x11c_particle1;
@ -64,7 +64,8 @@ public:
float GetHalfExtent() const { return xc4_halfExtent; } float GetHalfExtent() const { return xc4_halfExtent; }
float GetHeight() const { return xc8_height; } float GetHeight() const { return xc8_height; }
u32 GetParticle1Frames() const { return x10c_particle1Frames; } u32 GetPathfindingIndex() const { return x10c_pathfindingIndex; }
const CHealthInfo& GetHealthInfo() const { return x54_healthInfo; }
}; };
} }

View File

@ -1138,7 +1138,7 @@ void CPlayer::UpdateScanningState(const CFinalInput& input, CStateManager& mgr,
if (scanTime >= 1.f) if (scanTime >= 1.f)
{ {
x9c6_30_newScanScanning = false; x9c6_30_newScanScanning = false;
scanTime = 0.f; scanTime = 1.f;
} }
else else
{ {

View File

@ -51,7 +51,7 @@ CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntity
x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass); x150_momentum = zeus::CVector3f(0.f, 0.f, -24.525f * xe8_mass);
if (x90_actorLights) if (x90_actorLights)
x90_actorLights->SetAmbientChannelOverflow(true); x90_actorLights->SetAmbienceGenerated(true);
} }
CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CScriptDebris::CScriptDebris(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,

View File

@ -59,71 +59,77 @@ CScriptGunTurretData::CScriptGunTurretData(CInputStream& in, s32 propCount)
{ {
} }
SBurst CScriptGunTurret::skOOVBurst4InfoTemplate[5] = const SBurst CScriptGunTurret::skBurst2InfoTemplate[] =
{ {
{3, 1, 2, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {3, {1, 2, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{3, 7, 6, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {3, {7, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{4, 3, 5, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {4, {3, 5, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{60, 16, 4, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {60, {16, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{30, 4, 4, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {4, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst CScriptGunTurret::skOOVBurst3InfoTemplate[5] = const SBurst CScriptGunTurret::skBurst3InfoTemplate[] =
{ {
{30, 4, 5, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {4, 5, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{30, 2, 3, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {2, 3, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{30, 3, 4, 5, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {3, 4, 5, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{5, 16, 1, 2, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {5, {16, 1, 2, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{5, 8, 7, 6, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {5, {8, 7, 6, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst CScriptGunTurret::skOOVBurst2InfoTemplate[7] = const SBurst CScriptGunTurret::skBurst4InfoTemplate[] =
{ {
{5, 16, 1, 2, 3, 0, 0, 0, 0, 0.15f, 0.05f}, {5, {16, 1, 2, 3, 0, 0, 0, 0}, 0.150000, 0.050000},
{5, 9, 8, 7, 6, 0, 0, 0, 0, 0.15f, 0.05f}, {5, {9, 8, 7, 6, 0, 0, 0, 0}, 0.150000, 0.050000},
{15, 2, 3, 4, 5, 0, 0, 0, 0, 0.15f, 0.05f}, {15, {2, 3, 4, 5, 0, 0, 0, 0}, 0.150000, 0.050000},
{15, 5, 4, 3, 2, 0, 0, 0, 0, 0.15f, 0.05f}, {15, {5, 4, 3, 2, 0, 0, 0, 0}, 0.150000, 0.050000},
{15, 10, 11, 4, 13, 0, 0, 0, 0, 0.15f, 0.05f}, {15, {10, 11, 4, 13, 0, 0, 0, 0}, 0.150000, 0.050000},
{15, 14, 13, 4, 11, 0, 0, 0, 0, 0.15f, 0.05f}, {15, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000},
{30, 2, 4, 4, 6, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {2, 4, 4, 6, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst CScriptGunTurret::skBurst4InfoTemplate[5] = const SBurst CScriptGunTurret::skOOVBurst2InfoTemplate[] =
{ {
{20, 16, 15, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {16, 15, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 8, 9, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {8, 9, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 13, 11, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {13, 11, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 2, 6, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {2, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 3, 4, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {3, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst CScriptGunTurret::skBurst3InfoTemplate[5] = const SBurst CScriptGunTurret::skOOVBurst3InfoTemplate[] =
{ {
{10, 14, 4, 10, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {14, 4, 10, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{10, 15, 13, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {15, 13, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{10, 9, 11, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {9, 11, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{35, 15, 13, 11, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {35, {15, 13, 11, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{35, 9, 11, 13, -1, 0, 0, 0, 0, 0.15f, 0.05f}, {35, {9, 11, 13, -1, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst CScriptGunTurret::skBurst2InfoTemplate[6] = const SBurst CScriptGunTurret::skOOVBurst4InfoTemplate[] =
{ {
{10, 14, 13, 4, 11, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000},
{30, 1, 15, 13, 11, 0, 0, 0, 0, 0.15f, 0.05f}, {30, {1, 15, 13, 11, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 16, 15, 14, 13, 0, 0, 0, 0, 0.15f, 0.05f}, {20, {16, 15, 14, 13, 0, 0, 0, 0}, 0.150000, 0.050000},
{10, 8, 9, 11, 4, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {8, 9, 11, 4, 0, 0, 0, 0}, 0.150000, 0.050000},
{10, 1, 15, 13, 4, 0, 0, 0, 0, 0.15f, 0.05f}, {10, {1, 15, 13, 4, 0, 0, 0, 0}, 0.150000, 0.050000},
{20, 8, 9, 10, 11, 0, 0, 0, 0, 0.15f, 0.05f} {20, {8, 9, 10, 11, 0, 0, 0, 0}, 0.150000, 0.050000},
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
}; };
SBurst* CScriptGunTurret::skBursts[] = const SBurst* CScriptGunTurret::skBursts[] =
{ {
skOOVBurst4InfoTemplate,
skOOVBurst3InfoTemplate,
skOOVBurst2InfoTemplate,
skBurst4InfoTemplate,
skBurst3InfoTemplate,
skBurst2InfoTemplate, skBurst2InfoTemplate,
skBurst3InfoTemplate,
skBurst4InfoTemplate,
skOOVBurst2InfoTemplate,
skOOVBurst3InfoTemplate,
skOOVBurst4InfoTemplate,
nullptr nullptr
}; };
@ -324,7 +330,7 @@ void CScriptGunTurret::Think(float dt, CStateManager& mgr)
} }
else if (x258_type == ETurretComponent::Gun) else if (x258_type == ETurretComponent::Gun)
{ {
UpdatGunParticles(dt, mgr); UpdateGunParticles(dt, mgr);
SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true);
MoveToOR(deltas.x0_posDelta, dt); MoveToOR(deltas.x0_posDelta, dt);
RotateToOR(deltas.xc_rotDelta, dt); RotateToOR(deltas.xc_rotDelta, dt);
@ -512,7 +518,7 @@ void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr)
x53c_ = 0.f; x53c_ = 0.f;
} }
void CScriptGunTurret::UpdatGunParticles(float dt, CStateManager& mgr) void CScriptGunTurret::UpdateGunParticles(float dt, CStateManager& mgr)
{ {
CGameLight* light = nullptr; CGameLight* light = nullptr;
if (x498_lightId != kInvalidUniqueId) if (x498_lightId != kInvalidUniqueId)
@ -1104,7 +1110,7 @@ void CScriptGunTurret::sub80216594(CStateManager& mgr)
{ {
u32 r3 = x2d4_data.x90_ - 2; u32 r3 = x2d4_data.x90_ - 2;
x3a4_burstFire.SetBurstType(r3); x3a4_burstFire.SetBurstType(r3);
x3a4_burstFire.xc_ = x2d4_data.x94_; x3a4_burstFire.SetFirstBurstIndex(x2d4_data.x94_);
} }
@ -1115,7 +1121,7 @@ void CScriptGunTurret::sub80216594(CStateManager& mgr)
bool CScriptGunTurret::sub80217950(CStateManager& mgr) bool CScriptGunTurret::sub80217950(CStateManager& mgr)
{ {
if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.GetX14_24()) if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.ShouldFire())
return sub80217ad8(mgr); return sub80217ad8(mgr);
return false; return false;

View File

@ -70,13 +70,13 @@ public:
class CScriptGunTurret : public CPhysicsActor class CScriptGunTurret : public CPhysicsActor
{ {
static SBurst skOOVBurst4InfoTemplate[5]; static const SBurst skOOVBurst4InfoTemplate[];
static SBurst skOOVBurst3InfoTemplate[5]; static const SBurst skOOVBurst3InfoTemplate[];
static SBurst skOOVBurst2InfoTemplate[7]; static const SBurst skOOVBurst2InfoTemplate[];
static SBurst skBurst4InfoTemplate[5]; static const SBurst skBurst4InfoTemplate[];
static SBurst skBurst3InfoTemplate[5]; static const SBurst skBurst3InfoTemplate[];
static SBurst skBurst2InfoTemplate[6]; static const SBurst skBurst2InfoTemplate[];
static SBurst* skBursts[]; static const SBurst* skBursts[];
public: public:
enum class ETurretComponent enum class ETurretComponent
{ {
@ -175,7 +175,7 @@ public:
void sub802189c8(); void sub802189c8();
void UpdateGunCollisionManager(float, CStateManager&); void UpdateGunCollisionManager(float, CStateManager&);
void GetUnFreezeSoundId(float, CStateManager&); void GetUnFreezeSoundId(float, CStateManager&);
void UpdatGunParticles(float, CStateManager&); void UpdateGunParticles(float, CStateManager&);
void sub80219938(s32, CStateManager&); void sub80219938(s32, CStateManager&);
void sub802196c4(s32, CStateManager&, float); void sub802196c4(s32, CStateManager&, float);
void sub802195bc(s32, CStateManager&, float); void sub802195bc(s32, CStateManager&, float);

View File

@ -96,7 +96,7 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view n
x90_actorLights->DisableAreaLights(); x90_actorLights->DisableAreaLights();
x90_actorLights->SetMaxDynamicLights(4); x90_actorLights->SetMaxDynamicLights(4);
x90_actorLights->SetCastShadows(false); x90_actorLights->SetCastShadows(false);
x90_actorLights->SetAmbientChannelOverflow(false); x90_actorLights->SetAmbienceGenerated(false);
x90_actorLights->SetFindNearestDynamicLights(true); x90_actorLights->SetFindNearestDynamicLights(true);
x148_24_detectCamera = true; x148_24_detectCamera = true;
CalculateRenderBounds(); CalculateRenderBounds();

2
hecl

@ -1 +1 @@
Subproject commit 5fece8ddb1a58e23e0957232964bc91a007cf123 Subproject commit 14b54ca6c20a5b20eb4ccd23f1194fb3f6c2f984