From 9c88971df657182e8f5d8837a72ca60fd7eb740e Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Fri, 23 Nov 2018 22:09:35 -1000 Subject: [PATCH] Initial CSpacePirate and rag doll imps --- Runtime/CScannableObjectInfo.cpp | 7 +- Runtime/Character/CActorLights.cpp | 10 +- Runtime/Character/CActorLights.hpp | 4 +- Runtime/Character/CAnimData.hpp | 5 +- Runtime/Character/CCharLayoutInfo.cpp | 2 +- Runtime/Character/CHierarchyPoseBuilder.hpp | 1 + Runtime/Character/CIkChain.hpp | 10 +- Runtime/Character/CMakeLists.txt | 3 +- Runtime/Character/CRagDoll.cpp | 366 ++++++++++++++ Runtime/Character/CRagDoll.hpp | 137 ++++++ Runtime/GuiSys/CGuiCamera.cpp | 1 + Runtime/GuiSys/CGuiTextSupport.cpp | 23 + Runtime/GuiSys/CScanDisplay.cpp | 24 +- Runtime/MP1/World/CFireFlea.cpp | 2 +- Runtime/MP1/World/CSpacePirate.cpp | 513 +++++++++++++++++++- Runtime/MP1/World/CSpacePirate.hpp | 137 +++++- Runtime/Particle/CModVectorElement.cpp | 24 +- Runtime/Weapon/CBurstFire.cpp | 126 +++-- Runtime/Weapon/CBurstFire.hpp | 59 +-- Runtime/Weapon/CMakeLists.txt | 2 +- Runtime/Weapon/CWeaponMode.cpp | 28 -- Runtime/Weapon/CWeaponMode.hpp | 21 +- Runtime/World/CKnockBackController.cpp | 2 +- Runtime/World/CKnockBackController.hpp | 3 +- Runtime/World/CPatterned.cpp | 13 + Runtime/World/CPatterned.hpp | 1 + Runtime/World/CPatternedInfo.cpp | 2 +- Runtime/World/CPatternedInfo.hpp | 5 +- Runtime/World/CPlayer.cpp | 2 +- Runtime/World/CScriptDebris.cpp | 2 +- Runtime/World/CScriptGunTurret.cpp | 104 ++-- Runtime/World/CScriptGunTurret.hpp | 16 +- Runtime/World/CScriptWater.cpp | 2 +- hecl | 2 +- 34 files changed, 1422 insertions(+), 237 deletions(-) create mode 100644 Runtime/Character/CRagDoll.cpp create mode 100644 Runtime/Character/CRagDoll.hpp delete mode 100644 Runtime/Weapon/CWeaponMode.cpp diff --git a/Runtime/CScannableObjectInfo.cpp b/Runtime/CScannableObjectInfo.cpp index dbadf3fab..5c32a3cd0 100644 --- a/Runtime/CScannableObjectInfo.cpp +++ b/Runtime/CScannableObjectInfo.cpp @@ -8,12 +8,17 @@ CScannableObjectInfo::CScannableObjectInfo(CInputStream& in, CAssetId resId) : x u32 version = in.readUint32Big(); Load(in, version); + for (u32 i = 0 ; i < x14_buckets.size(); ++i) + { + x14_buckets[i].x4_appearanceRange *= x8_totalDownloadTime; + } + float appearanceOffset = g_tweakGui->GetScanAppearanceDuration(); for (u32 i = 0 ; i < x14_buckets.size(); ++i) { 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++) x14_buckets[j].x4_appearanceRange += appearanceOffset; } diff --git a/Runtime/Character/CActorLights.cpp b/Runtime/Character/CActorLights.cpp index fe68b77aa..8a525b13d 100644 --- a/Runtime/Character/CActorLights.cpp +++ b/Runtime/Character/CActorLights.cpp @@ -25,7 +25,7 @@ CActorLights::CActorLights(u32 areaUpdateFramePeriod, const zeus::CVector3f& act x298_25_castShadows = true; x298_28_inArea = (!disableWorldLights && maxAreaLights > 0) ? true : false; - x298_29_ambientChannelOverflow = ambientChannelOverflow; + x298_29_ambienceGenerated = ambientChannelOverflow; x298_30_layer2 = layer2; x298_31_disableWorldLights = disableWorldLights; x299_24_inBrightLight = true; @@ -152,7 +152,7 @@ void CActorLights::AddOverflowToLights(const CLight& light, const zeus::CColor& void CActorLights::MoveAmbienceToLights(const zeus::CColor& color) { - if (x298_29_ambientChannelOverflow) + if (x298_29_ambienceGenerated) { x288_ambientColor += color * 0.333333f; x288_ambientColor.a = 1.f; @@ -342,7 +342,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& float overflowMag = 0.f; /* 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(); /* Filter for performing final light visibility test */ @@ -415,7 +415,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& else { /* 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 */ MergeOverflowLight(overflowLight, overflowLightColor, light, value.x10_colorMag); @@ -430,7 +430,7 @@ bool CActorLights::BuildAreaLightList(const CStateManager& mgr, const CGameArea& } /* Finalize overflow lights */ - if (!x298_29_ambientChannelOverflow) + if (!x298_29_ambienceGenerated) AddOverflowToLights(overflowLight, overflowLightColor, overflowMag); else MoveAmbienceToLights(overflowAmbColor); diff --git a/Runtime/Character/CActorLights.hpp b/Runtime/Character/CActorLights.hpp index 922bc6d6d..57c699b3f 100644 --- a/Runtime/Character/CActorLights.hpp +++ b/Runtime/Character/CActorLights.hpp @@ -29,7 +29,7 @@ class CActorLights bool x298_26_hasAreaLights : 1; bool x298_27_findShadowLight : 1; bool x298_28_inArea : 1; - bool x298_29_ambientChannelOverflow : 1; + bool x298_29_ambienceGenerated : 1; bool x298_30_layer2 : 1; bool x298_31_disableWorldLights : 1; bool x299_24_inBrightLight : 1; @@ -75,7 +75,7 @@ public: void SetCastShadows(bool v) { x298_25_castShadows = v; } void SetFindShadowLight(bool v) { x298_27_findShadowLight = v; } 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 SetMaxDynamicLights(int l) { x2bc_maxDynamicLights = l; } void SetFindNearestDynamicLights(bool v) { x29a_findNearestDynamicLights = v; } diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index a8595975c..274d7630f 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -214,6 +214,7 @@ public: static void DrawSkinnedModel(CSkinnedModel& model, const CModelFlags& flags); void PreRender(); void BuildPose(); + const CPoseAsTransforms& GetPose() const { return x224_pose; } static void PrimitiveSetToTokenVector(const std::set& primSet, std::vector& tokensOut, bool preLock); void GetAnimationPrimitives(const CAnimPlaybackParms& parms, std::set& primsOut) const; @@ -242,7 +243,7 @@ public: void SubstituteModelData(const TCachedToken& model); static void FreeCache(); static void InitializeCache(); - const CHierarchyPoseBuilder& GetPoseBuilder() const { return x2fc_poseBuilder; } + CHierarchyPoseBuilder& PoseBuilder() { return x2fc_poseBuilder; } const CParticleDatabase& GetParticleDB() const { return x120_particleDB; } CParticleDatabase& GetParticleDB() { return x120_particleDB; } void SetParticleCEXTValue(std::string_view name, int idx, float value); @@ -257,6 +258,8 @@ public: TLockedToken& IceModel() { return xe4_iceModelData; } const TLockedToken& GetIceModel() const { return xe4_iceModelData; } void SetParticleLightIdx(s32 idx) { x21c_particleLightIdx = idx; } + + void MarkPoseDirty() { x220_30_poseBuilt = false; } }; } diff --git a/Runtime/Character/CCharLayoutInfo.cpp b/Runtime/Character/CCharLayoutInfo.cpp index b85791c86..126a499f1 100644 --- a/Runtime/Character/CCharLayoutInfo.cpp +++ b/Runtime/Character/CCharLayoutInfo.cpp @@ -28,7 +28,7 @@ CSegId CCharLayoutInfo::GetSegIdFromString(std::string_view name) const if (it == x18_segIdMap.end()) return {}; - return (*it).second; + return it->second; } void CCharLayoutNode::Bone::read(CInputStream& in) diff --git a/Runtime/Character/CHierarchyPoseBuilder.hpp b/Runtime/Character/CHierarchyPoseBuilder.hpp index 29aa99ac1..01efc1884 100644 --- a/Runtime/Character/CHierarchyPoseBuilder.hpp +++ b/Runtime/Character/CHierarchyPoseBuilder.hpp @@ -51,6 +51,7 @@ public: void BuildNoScale(CPoseAsTransforms& pose); void Insert(const CSegId& boneId, const zeus::CQuaternion& quat); void Insert(const CSegId& boneId, const zeus::CQuaternion& quat, const zeus::CVector3f& offset); + TSegIdMap& GetTreeMap() { return x38_treeMap; } }; } diff --git a/Runtime/Character/CIkChain.hpp b/Runtime/Character/CIkChain.hpp index bce60d11b..45d3be9c5 100644 --- a/Runtime/Character/CIkChain.hpp +++ b/Runtime/Character/CIkChain.hpp @@ -15,10 +15,10 @@ class CIkChain CSegId x0_; CSegId x1_; CSegId x2_; - zeus::CVector3f x4_; - zeus::CVector3f x10_; - float x1c_; - float x20_; + zeus::CVector3f x4_ = zeus::CVector3f::skForward; + zeus::CVector3f x10_ = zeus::CVector3f::skForward; + float x1c_ = 1.f; + float x20_ = 1.f; zeus::CQuaternion x24_; zeus::CVector3f x34_; float x40_time = 0.f; @@ -29,7 +29,7 @@ class CIkChain { bool x44_24_activated : 1; }; - u8 x44_dummy = 0; + u32 x44_dummy = 0; }; public: CIkChain() = default; diff --git a/Runtime/Character/CMakeLists.txt b/Runtime/Character/CMakeLists.txt index 416c24443..653f4e391 100644 --- a/Runtime/Character/CMakeLists.txt +++ b/Runtime/Character/CMakeLists.txt @@ -91,6 +91,7 @@ set(CHARACTER_SOURCES CGroundMovement.hpp CGroundMovement.cpp CSteeringBehaviors.hpp CSteeringBehaviors.cpp CBodyStateInfo.hpp CBodyStateInfo.cpp - CBoneTracking.hpp CBoneTracking.cpp) + CBoneTracking.hpp CBoneTracking.cpp + CRagDoll.hpp CRagDoll.cpp) runtime_add_list(Character CHARACTER_SOURCES) diff --git a/Runtime/Character/CRagDoll.cpp b/Runtime/Character/CRagDoll.cpp new file mode 100644 index 000000000..efed3d28e --- /dev/null +++ b/Runtime/Character/CRagDoll.cpp @@ -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 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; +} + +} diff --git a/Runtime/Character/CRagDoll.hpp b/Runtime/Character/CRagDoll.hpp new file mode 100644 index 000000000..1979e199e --- /dev/null +++ b/Runtime/Character/CRagDoll.hpp @@ -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 x4_particles; + std::vector x14_lengthConstraints; + std::vector x24_jointConstraints; + std::vector 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); +}; + +} diff --git a/Runtime/GuiSys/CGuiCamera.cpp b/Runtime/GuiSys/CGuiCamera.cpp index a80b1456c..32f10dc3a 100644 --- a/Runtime/GuiSys/CGuiCamera.cpp +++ b/Runtime/GuiSys/CGuiCamera.cpp @@ -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, m_proj.xc4_znear, m_proj.xc8_zfar, false); + local = zeus::CVector3f(local.x, local.z, -local.y); return mat.multiplyOneOverW(local); } diff --git a/Runtime/GuiSys/CGuiTextSupport.cpp b/Runtime/GuiSys/CGuiTextSupport.cpp index f7df76c73..9c51ea128 100644 --- a/Runtime/GuiSys/CGuiTextSupport.cpp +++ b/Runtime/GuiSys/CGuiTextSupport.cpp @@ -95,6 +95,29 @@ void CGuiTextSupport::SetTypeWriteEffectOptions(bool enable, float chFadeTime, f x50_typeEnable = enable; x54_chFadeTime = std::max(chFadeTime, 0.0001f); x58_chRate = std::max(chRate, 1.f); + if (enable) + { + if (CTextRenderBuffer* buf = GetCurrentPageRenderBuffer()) + { + float chStartTime = 0.f; + for (s32 i=0 ; iGetPrimitiveCount() ; ++i) + { + for (const std::pair& 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) diff --git a/Runtime/GuiSys/CScanDisplay.cpp b/Runtime/GuiSys/CScanDisplay.cpp index 6aac652f1..734bfd085 100644 --- a/Runtime/GuiSys/CScanDisplay.cpp +++ b/Runtime/GuiSys/CScanDisplay.cpp @@ -21,8 +21,10 @@ void CScanDisplay::CDataDot::Update(float dt) if (x20_remTime > 0.f) { x20_remTime = std::max(0.f, x20_remTime - dt); - float d = x20_remTime / x1c_transDur; - xc_curPos = (x14_targetPos * (x4_startPos * d)) + (1.f - x1c_transDur > 0.f ? d : 0.f); + float 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) @@ -32,7 +34,7 @@ void CScanDisplay::CDataDot::Update(float dt) } 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); } } @@ -243,7 +245,8 @@ void CScanDisplay::StartScan(TUniqueId id, const CScannableObjectInfo& scanInfo, } state.second->SetTextureID0(bucket.x0_texture, g_SimplePool); state.second->SetFlashFactor(0.f); - if (scanTime >= GetDownloadStartTime(i)) + float startTime = GetDownloadStartTime(i); + if (scanTime >= startTime) x170_paneStates[i].first = 0.f; else x170_paneStates[i].first = -1.f; @@ -400,6 +403,7 @@ void CScanDisplay::Update(float dt, float scanningTime) if (tmp == 0.f) { dot.SetDotState(CDataDot::EDotState::Done); + dot.SetDesiredAlpha(0.f); CSfxManager::SfxStart(SFXui_scan_pane_reveal, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); 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(); 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 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), 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); } break; @@ -436,7 +442,8 @@ void CScanDisplay::Update(float dt, float scanningTime) case CDataDot::EDotState::RevealPane: 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, screenPos.y * g_Viewport.xc_height * 0.5f); dot.SetDestPosition(viewportCoords); @@ -485,7 +492,8 @@ void CScanDisplay::Draw() const g_Renderer->SetViewportOrtho(true, -4096.f, 4096.f); // Additive alpha + float vpRatio = g_Viewport.xc_height / 480.f; for (const CDataDot& dot : xbc_dataDots) - dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius()); + dot.Draw(g_tweakGuiColors->GetScanDataDotColor(), g_tweakGui->GetScanDataDotRadius() * vpRatio); } } diff --git a/Runtime/MP1/World/CFireFlea.cpp b/Runtime/MP1/World/CFireFlea.cpp index 45262f809..438d99a79 100644 --- a/Runtime/MP1/World/CFireFlea.cpp +++ b/Runtime/MP1/World/CFireFlea.cpp @@ -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, EMovementType::Flyer, EColliderType::One, EBodyType::NewFlyer, actParms, EKnockBackVariant::Small) , 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(); filter.ExcludeList().Add(EMaterialTypes::Character); diff --git a/Runtime/MP1/World/CSpacePirate.cpp b/Runtime/MP1/World/CSpacePirate.cpp index b609ea895..ff65dfbd5 100644 --- a/Runtime/MP1/World/CSpacePirate.cpp +++ b/Runtime/MP1/World/CSpacePirate.cpp @@ -1,5 +1,8 @@ #include "CSpacePirate.hpp" #include "Character/CCharLayoutInfo.hpp" +#include "Character/CPASAnimParmData.hpp" +#include "World/CScriptWaypoint.hpp" +#include "World/CPatternedInfo.hpp" #include "TCastTo.hpp" 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) , x94_(in.readFloatBig()), x98_(CSfxManager::TranslateSFXID(in.readUint32Big())), x9c_(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())) , xc2_(CSfxManager::TranslateSFXID(in.readUint32Big())), xc4_(propCount > 35 ? in.readFloatBig() : 0.2f) , 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 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(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, CModelData&& mData, const CActorParameters& aParams, const CPatternedInfo& pInfo, CInputStream& in, u32 propCount) -: CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, EMovementType::Ground, - EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::Medium) -, x568_(in, propCount) +: CPatterned(ECharacter::SpacePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, + EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, aParams, EKnockBackVariant::Medium) +, 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) @@ -39,6 +476,72 @@ void CSpacePirate::Think(float dt, CStateManager& mgr) if (!x450_bodyController->GetActive()) 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); } diff --git a/Runtime/MP1/World/CSpacePirate.hpp b/Runtime/MP1/World/CSpacePirate.hpp index b6b69e705..13090f6f5 100644 --- a/Runtime/MP1/World/CSpacePirate.hpp +++ b/Runtime/MP1/World/CSpacePirate.hpp @@ -2,18 +2,43 @@ #include "World/CPatterned.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 { +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 x90_waypoints; + rstl::reserved_vector 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 { + friend class CPirateRagDoll; public: DEFINE_PATTERNED(SpacePirate) - private: class CSpacePirateData { + friend class CSpacePirate; float x0_; float x4_; float x8_; @@ -33,7 +58,7 @@ private: float xa0_; u16 xa4_; float xa8_; - u32 xac_; + u32 xac_firstBurstCount; float xb0_; float xb4_; float xb8_; @@ -46,7 +71,7 @@ private: CSpacePirateData(CInputStream&, u32); }; - CSpacePirateData x568_; + CSpacePirateData x568_pirateData; union { struct @@ -67,11 +92,115 @@ private: bool x635_29_ : 1; bool x635_30_ : 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 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: CSpacePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&, const CActorParameters&, const CPatternedInfo&, CInputStream&, u32); diff --git a/Runtime/Particle/CModVectorElement.cpp b/Runtime/Particle/CModVectorElement.cpp index f7f165713..1f9075304 100644 --- a/Runtime/Particle/CModVectorElement.cpp +++ b/Runtime/Particle/CModVectorElement.cpp @@ -124,34 +124,28 @@ bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPo if (!x14_planePrecomputed) { /* Compute Hesse normal form of plane (for penetration testing) */ - x8_planeNormal->GetValue(frame, ((zeus::CVector3f&)x18_planeValidatedNormal)); - ((zeus::CVector3f&)x18_planeValidatedNormal).normalize(); + x8_planeNormal->GetValue(frame, const_cast(x18_planeValidatedNormal)); + const_cast(x18_planeValidatedNormal).normalize(); zeus::CVector3f a; x4_planePoint->GetValue(frame, a); - (float&)(x24_planeD) = x18_planeValidatedNormal.dot(a); + const_cast(x24_planeD) = x18_planeValidatedNormal.dot(a); } float dot = x18_planeValidatedNormal.dot(pPos); - if ((dot - x24_planeD) <= 0.0f) - { - if (x15_dieOnPenetrate) - return true; - } - else + if (dot - x24_planeD > 0.0f) return false; + else if (x15_dieOnPenetrate) + return true; /* Deflection event */ - if (pVel.magSquared() > 0.0f) + if (pVel.dot(x18_planeValidatedNormal) >= 0.0f) return false; zeus::CVector3f delta = pPos - pVel; - pPos += zeus::CVector3f{(-((((delta.z * ((delta.x * (delta.y * x18_planeValidatedNormal.y)) - + ((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; + pPos += (-(delta.dot(x18_planeValidatedNormal) - x24_planeD) / pVel.dot(x18_planeValidatedNormal) - 1.f) * pVel; float d = 0.0f; x10_restitution->GetValue(frame, d); @@ -159,7 +153,7 @@ bool CMVEBounce::GetValue(int frame, zeus::CVector3f& pVel, zeus::CVector3f& pPo float c = 0.0f; 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; } diff --git a/Runtime/Weapon/CBurstFire.cpp b/Runtime/Weapon/CBurstFire.cpp index dff9fea9a..565683951 100644 --- a/Runtime/Weapon/CBurstFire.cpp +++ b/Runtime/Weapon/CBurstFire.cpp @@ -1,78 +1,108 @@ #include "CBurstFire.hpp" +#include "GameGlobalObjects.hpp" namespace urde { -CBurstFire::CBurstFire(SBurst** bursts, s32 firstIndex) - : x10_(firstIndex) +CBurstFire::CBurstFire(const SBurst** burstDefs, s32 firstBurstCount) +: x10_firstBurstCounter(firstBurstCount) { - SBurst** burst = bursts; - while (1) + while (*burstDefs) { - if (!*burst) - break; - - x18_bursts.push_back(*burst); - ++burst; + x1c_burstDefs.push_back(*burstDefs); + ++burstDefs; } } -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; -} - -void CBurstFire::SetTimeToNextShot(float) -{ - -} - -bool CBurstFire::ShouldFire() const -{ - return false; -} - -void CBurstFire::Start(CStateManager&) -{ - -} - -void CBurstFire::GetError(float, float) const -{ - + zeus::CVector3f ret; + if (x14_24_shouldFire && x18_curBursts) + { + 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) + { + float angle = r0 * zeus::degToRad(-22.5f); + ret.x = std::cos(angle) * xMag; + ret.z = std::sin(angle) * zMag; + } + } + return ret; } float CBurstFire::GetMaxXError() const { - return 0; + return g_tweakPlayer->GetPlayerXYHalfExtent() * 3.625f + 0.2f; } float CBurstFire::GetMaxZError() const { - return 0; + return g_tweakPlayer->GetEyeOffset(); } -void CBurstFire::GetError() const -{ - -} - -void CBurstFire::SetFirstBurstIndex(s32) -{ - -} } diff --git a/Runtime/Weapon/CBurstFire.hpp b/Runtime/Weapon/CBurstFire.hpp index 4f44019f9..9457174fc 100644 --- a/Runtime/Weapon/CBurstFire.hpp +++ b/Runtime/Weapon/CBurstFire.hpp @@ -6,53 +6,42 @@ namespace urde { struct SBurst { - u32 x0_; - u32 x4_; - u32 x8_; - s32 xc_; - s32 x10_; - u32 x14_; - u32 x18_; - u32 x1c_; - u32 x20_; - float x24_; - float x28_; + s32 x0_randomSelectionWeight; + s32 x4_shotAngles[8]; + float x24_timeToNextShot; + float x28_timeToNextShotVariance; }; class CBurstFire { - friend class CScriptGunTurret; - s32 x0_ = -1; - s32 x4_ = -1; - float x8_ = 0.f; - u32 xc_ = 0; - s32 x10_; + s32 x0_burstType = -1; + s32 x4_angleIdx = -1; + float x8_timeToNextShot = 0.f; + s32 xc_firstBurstIdx = 0; + s32 x10_firstBurstCounter; union { - struct { bool x14_24_ : 1; bool x14_25_ : 1; }; + struct { bool x14_24_shouldFire : 1; bool x14_25_avoidAccuracy : 1; }; u32 _dummy = 0; }; - rstl::reserved_vector x18_bursts; + const SBurst* x18_curBursts = nullptr; + rstl::reserved_vector x1c_burstDefs; public: - CBurstFire(SBurst**, s32); + CBurstFire(const SBurst** burstDefs, s32 firstBurstCount); - void SetFirstBurst(bool); - void SetBurstType(s32 type) { x0_ = type; } - bool IsBurstSet() const; - void SetTimeToNextShot(float); - bool ShouldFire() const; - s32 GetBurstType() const { return x0_; } - void Start(CStateManager&); - void Update(CStateManager&, float); - void Update(); - void GetError(float, float) const; - zeus::CVector3f GetDistanceCompensatedError(float, float) const; + void SetAvoidAccuracy(bool b) { x14_25_avoidAccuracy = b; } + void SetBurstType(s32 type) { x0_burstType = type; } + void SetTimeToNextShot(float t) { x8_timeToNextShot = t; } + s32 GetBurstType() const { return x0_burstType; } + void Start(CStateManager& mgr); + void Update(CStateManager& mgr, float dt); + zeus::CVector3f GetError(float xMag, float zMag) const; + zeus::CVector3f GetDistanceCompensatedError(float dist, float maxErrDist) const; float GetMaxXError() const; float GetMaxZError() const; - void GetError() const; - void SetFirstBurstIndex(s32); - - bool GetX14_24() const { return x14_24_; } + void SetFirstBurstIndex(s32 idx) { xc_firstBurstIdx = idx; } + bool ShouldFire() const { return x14_24_shouldFire; } + bool IsBurstSet() const { return x18_curBursts != nullptr; } }; } diff --git a/Runtime/Weapon/CMakeLists.txt b/Runtime/Weapon/CMakeLists.txt index 62ee0219b..323153a7c 100644 --- a/Runtime/Weapon/CMakeLists.txt +++ b/Runtime/Weapon/CMakeLists.txt @@ -4,7 +4,7 @@ set(WEAPON_SOURCES CGunController.hpp CGunController.cpp CGunMotion.hpp CGunMotion.cpp CGrappleArm.hpp CGrappleArm.cpp - CWeaponMode.hpp CWeaponMode.cpp + CWeaponMode.hpp CPlayerGun.hpp CPlayerGun.cpp CGunWeapon.hpp CGunWeapon.cpp CAuxWeapon.hpp CAuxWeapon.cpp diff --git a/Runtime/Weapon/CWeaponMode.cpp b/Runtime/Weapon/CWeaponMode.cpp deleted file mode 100644 index ef34be257..000000000 --- a/Runtime/Weapon/CWeaponMode.cpp +++ /dev/null @@ -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); } -} diff --git a/Runtime/Weapon/CWeaponMode.hpp b/Runtime/Weapon/CWeaponMode.hpp index 6358326e9..f6776cd70 100644 --- a/Runtime/Weapon/CWeaponMode.hpp +++ b/Runtime/Weapon/CWeaponMode.hpp @@ -13,21 +13,22 @@ class CWeaponMode public: 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; } bool IsCharged() const { return x4_24_charged; } bool IsComboed() const { return x4_25_comboed; } bool IsInstantKill() const { return x4_26_instantKill; } - static CWeaponMode Invalid(); - static CWeaponMode Phazon(); - static CWeaponMode Plasma(); - static CWeaponMode Wave(); - static CWeaponMode BoostBall(); - static CWeaponMode Ice(); - static CWeaponMode Power(); - static CWeaponMode Bomb(); - static CWeaponMode PowerBomb(); + static CWeaponMode Invalid() { return CWeaponMode(EWeaponType::None); } + static CWeaponMode Phazon() { return CWeaponMode(EWeaponType::Phazon); } + static CWeaponMode Plasma() { return CWeaponMode(EWeaponType::Plasma); } + static CWeaponMode Wave() { return CWeaponMode(EWeaponType::Wave); } + static CWeaponMode BoostBall() { return CWeaponMode(EWeaponType::BoostBall); } + static CWeaponMode Ice() { return CWeaponMode(EWeaponType::Ice); } + static CWeaponMode Power() { return CWeaponMode(EWeaponType::Power); } + static CWeaponMode Bomb() { return CWeaponMode(EWeaponType::Bomb); } + static CWeaponMode PowerBomb() { return CWeaponMode(EWeaponType::PowerBomb); } }; } diff --git a/Runtime/World/CKnockBackController.cpp b/Runtime/World/CKnockBackController.cpp index 9a6de5bbd..d5e6b4dfa 100644 --- a/Runtime/World/CKnockBackController.cpp +++ b/Runtime/World/CKnockBackController.cpp @@ -605,7 +605,7 @@ void CKnockBackController::Update(float dt, CStateManager& mgr, CPatterned& pare x64_flinchRemTime -= dt; if (TickDeferredTimer(dt)) DoDeferredKnockBack(mgr, parent); - if (x82_26_ && parent.BodyController()->IsElectrocuting()) + if (x82_26_locomotionDuringElectrocution && parent.BodyController()->IsElectrocuting()) parent.BodyController()->GetCommandMgr().DeliverCmd(CBodyStateCmd(EBodyStateCmd::Locomotion)); } diff --git a/Runtime/World/CKnockBackController.hpp b/Runtime/World/CKnockBackController.hpp index 62352e4ce..8bd7beaae 100644 --- a/Runtime/World/CKnockBackController.hpp +++ b/Runtime/World/CKnockBackController.hpp @@ -122,7 +122,7 @@ private: bool x81_31_ : 1; // t bool x82_24_ : 1; // t bool x82_25_inDeferredKnockBack : 1; - bool x82_26_ : 1; + bool x82_26_locomotionDuringElectrocution : 1; }; u32 dummy = 0; }; @@ -155,6 +155,7 @@ public: void SetEnableExplodeDeath(bool b) { x81_29_enableExplodeDeath = b; } void SetEnableLaggedBurnDeath(bool b) { x81_30_enableLaggedBurnDeath = b; } void SetX82_24(bool b) { x82_24_ = b; } + void SetLocomotionDuringElectrocution(bool b) { x82_26_locomotionDuringElectrocution = b; } const KnockBackParms& GetActiveParms() const { return x4_activeParms; } EKnockBackVariant GetVariant() const { return x0_variant; } float GetFlinchRemTime() const { return x64_flinchRemTime; } diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index 425514d56..7279026ee 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -1597,6 +1597,19 @@ EScriptObjectState CPatterned::GetDesiredAttackState(CStateManager& mgr) const 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) { if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Thermal) diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index d34f4b348..4b3fa9200 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -308,6 +308,7 @@ protected: void UpdatePatternDestPos(CStateManager& mgr); void SetupPattern(CStateManager& mgr); EScriptObjectState GetDesiredAttackState(CStateManager& mgr) const; + float GetAnimationDistance(const CPASAnimParmData& data) const; public: CPatterned(ECharacter character, TUniqueId uid, std::string_view name, EFlavorType flavor, const CEntityInfo& info, const zeus::CTransform& xf, CModelData&& mData, diff --git a/Runtime/World/CPatternedInfo.cpp b/Runtime/World/CPatternedInfo.cpp index 8ca5cb01b..a51b74a4a 100644 --- a/Runtime/World/CPatternedInfo.cpp +++ b/Runtime/World/CPatternedInfo.cpp @@ -36,7 +36,7 @@ CPatternedInfo::CPatternedInfo(CInputStream& in, u32 pcount) , x100_intoFreezeDur(in.readFloatBig()) , x104_outofFreezeDur(in.readFloatBig()) , x108_(in.readFloatBig()) -, x10c_particle1Frames(in.readUint32Big()) +, x10c_pathfindingIndex(in.readUint32Big()) , x110_particle1Scale(zeus::CVector3f::ReadBig(in)) , x11c_particle1(in) , x120_electric(in) diff --git a/Runtime/World/CPatternedInfo.hpp b/Runtime/World/CPatternedInfo.hpp index 272a53069..436f207ec 100644 --- a/Runtime/World/CPatternedInfo.hpp +++ b/Runtime/World/CPatternedInfo.hpp @@ -45,7 +45,7 @@ class CPatternedInfo float x104_outofFreezeDur; float x108_; - u32 x10c_particle1Frames; + u32 x10c_pathfindingIndex; zeus::CVector3f x110_particle1Scale; CAssetId x11c_particle1; @@ -64,7 +64,8 @@ public: float GetHalfExtent() const { return xc4_halfExtent; } 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; } }; } diff --git a/Runtime/World/CPlayer.cpp b/Runtime/World/CPlayer.cpp index 38cd508d7..6ac02eebf 100644 --- a/Runtime/World/CPlayer.cpp +++ b/Runtime/World/CPlayer.cpp @@ -1138,7 +1138,7 @@ void CPlayer::UpdateScanningState(const CFinalInput& input, CStateManager& mgr, if (scanTime >= 1.f) { x9c6_30_newScanScanning = false; - scanTime = 0.f; + scanTime = 1.f; } else { diff --git a/Runtime/World/CScriptDebris.cpp b/Runtime/World/CScriptDebris.cpp index 8fe7ac4f6..0662fc3c4 100644 --- a/Runtime/World/CScriptDebris.cpp +++ b/Runtime/World/CScriptDebris.cpp @@ -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); 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, diff --git a/Runtime/World/CScriptGunTurret.cpp b/Runtime/World/CScriptGunTurret.cpp index f06018593..c0db4c91c 100644 --- a/Runtime/World/CScriptGunTurret.cpp +++ b/Runtime/World/CScriptGunTurret.cpp @@ -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, 7, 6, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {4, 3, 5, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {60, 16, 4, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {30, 4, 4, -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.150000, 0.050000}, + {4, {3, 5, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {60, {16, 4, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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, 2, 3, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {30, 3, 4, 5, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {5, 16, 1, 2, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {5, 8, 7, 6, -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.150000, 0.050000}, + {30, {3, 4, 5, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {5, {16, 1, 2, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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, 9, 8, 7, 6, 0, 0, 0, 0, 0.15f, 0.05f}, - {15, 2, 3, 4, 5, 0, 0, 0, 0, 0.15f, 0.05f}, - {15, 5, 4, 3, 2, 0, 0, 0, 0, 0.15f, 0.05f}, - {15, 10, 11, 4, 13, 0, 0, 0, 0, 0.15f, 0.05f}, - {15, 14, 13, 4, 11, 0, 0, 0, 0, 0.15f, 0.05f}, - {30, 2, 4, 4, 6, 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.150000, 0.050000}, + {15, {2, 3, 4, 5, 0, 0, 0, 0}, 0.150000, 0.050000}, + {15, {5, 4, 3, 2, 0, 0, 0, 0}, 0.150000, 0.050000}, + {15, {10, 11, 4, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, + {15, {14, 13, 4, 11, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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, 8, 9, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {20, 13, 11, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {20, 2, 6, -1, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {20, 3, 4, -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.150000, 0.050000}, + {20, {13, 11, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {20, {2, 6, -1, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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, 15, 13, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {10, 9, 11, 4, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {35, 15, 13, 11, -1, 0, 0, 0, 0, 0.15f, 0.05f}, - {35, 9, 11, 13, -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.150000, 0.050000}, + {10, {9, 11, 4, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {35, {15, 13, 11, -1, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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}, - {30, 1, 15, 13, 11, 0, 0, 0, 0, 0.15f, 0.05f}, - {20, 16, 15, 14, 13, 0, 0, 0, 0, 0.15f, 0.05f}, - {10, 8, 9, 11, 4, 0, 0, 0, 0, 0.15f, 0.05f}, - {10, 1, 15, 13, 4, 0, 0, 0, 0, 0.15f, 0.05f}, - {20, 8, 9, 10, 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.150000, 0.050000}, + {20, {16, 15, 14, 13, 0, 0, 0, 0}, 0.150000, 0.050000}, + {10, {8, 9, 11, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, + {10, {1, 15, 13, 4, 0, 0, 0, 0}, 0.150000, 0.050000}, + {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, + skBurst3InfoTemplate, + skBurst4InfoTemplate, + skOOVBurst2InfoTemplate, + skOOVBurst3InfoTemplate, + skOOVBurst4InfoTemplate, nullptr }; @@ -324,7 +330,7 @@ void CScriptGunTurret::Think(float dt, CStateManager& mgr) } else if (x258_type == ETurretComponent::Gun) { - UpdatGunParticles(dt, mgr); + UpdateGunParticles(dt, mgr); SAdvancementDeltas deltas = UpdateAnimation(dt, mgr, true); MoveToOR(deltas.x0_posDelta, dt); RotateToOR(deltas.xc_rotDelta, dt); @@ -512,7 +518,7 @@ void CScriptGunTurret::GetUnFreezeSoundId(float dt, CStateManager& mgr) x53c_ = 0.f; } -void CScriptGunTurret::UpdatGunParticles(float dt, CStateManager& mgr) +void CScriptGunTurret::UpdateGunParticles(float dt, CStateManager& mgr) { CGameLight* light = nullptr; if (x498_lightId != kInvalidUniqueId) @@ -1104,7 +1110,7 @@ void CScriptGunTurret::sub80216594(CStateManager& mgr) { u32 r3 = x2d4_data.x90_ - 2; 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) { - if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.GetX14_24()) + if (x520_ == 9 && x534_ <= 0.f && x3a4_burstFire.ShouldFire()) return sub80217ad8(mgr); return false; diff --git a/Runtime/World/CScriptGunTurret.hpp b/Runtime/World/CScriptGunTurret.hpp index 7e835ec78..66269325c 100644 --- a/Runtime/World/CScriptGunTurret.hpp +++ b/Runtime/World/CScriptGunTurret.hpp @@ -70,13 +70,13 @@ public: class CScriptGunTurret : public CPhysicsActor { - static SBurst skOOVBurst4InfoTemplate[5]; - static SBurst skOOVBurst3InfoTemplate[5]; - static SBurst skOOVBurst2InfoTemplate[7]; - static SBurst skBurst4InfoTemplate[5]; - static SBurst skBurst3InfoTemplate[5]; - static SBurst skBurst2InfoTemplate[6]; - static SBurst* skBursts[]; + static const SBurst skOOVBurst4InfoTemplate[]; + static const SBurst skOOVBurst3InfoTemplate[]; + static const SBurst skOOVBurst2InfoTemplate[]; + static const SBurst skBurst4InfoTemplate[]; + static const SBurst skBurst3InfoTemplate[]; + static const SBurst skBurst2InfoTemplate[]; + static const SBurst* skBursts[]; public: enum class ETurretComponent { @@ -175,7 +175,7 @@ public: void sub802189c8(); void UpdateGunCollisionManager(float, CStateManager&); void GetUnFreezeSoundId(float, CStateManager&); - void UpdatGunParticles(float, CStateManager&); + void UpdateGunParticles(float, CStateManager&); void sub80219938(s32, CStateManager&); void sub802196c4(s32, CStateManager&, float); void sub802195bc(s32, CStateManager&, float); diff --git a/Runtime/World/CScriptWater.cpp b/Runtime/World/CScriptWater.cpp index 7891cf135..e01e20835 100644 --- a/Runtime/World/CScriptWater.cpp +++ b/Runtime/World/CScriptWater.cpp @@ -96,7 +96,7 @@ CScriptWater::CScriptWater(CStateManager& mgr, TUniqueId uid, std::string_view n x90_actorLights->DisableAreaLights(); x90_actorLights->SetMaxDynamicLights(4); x90_actorLights->SetCastShadows(false); - x90_actorLights->SetAmbientChannelOverflow(false); + x90_actorLights->SetAmbienceGenerated(false); x90_actorLights->SetFindNearestDynamicLights(true); x148_24_detectCamera = true; CalculateRenderBounds(); diff --git a/hecl b/hecl index 5fece8ddb..14b54ca6c 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 5fece8ddb1a58e23e0957232964bc91a007cf123 +Subproject commit 14b54ca6c20a5b20eb4ccd23f1194fb3f6c2f984