2018-10-07 03:42:33 +00:00
|
|
|
#pragma once
|
2017-01-24 17:23:10 +00:00
|
|
|
|
2019-09-23 19:00:23 +00:00
|
|
|
#include <memory>
|
|
|
|
#include <string_view>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "Runtime/RetroTypes.hpp"
|
|
|
|
#include "Runtime/rstl.hpp"
|
|
|
|
#include "Runtime/Collision/CCollisionSurface.hpp"
|
|
|
|
#include "Runtime/Particle/CElementGen.hpp"
|
|
|
|
#include "Runtime/World/CActor.hpp"
|
|
|
|
#include "Runtime/World/CDamageInfo.hpp"
|
|
|
|
#include "Runtime/World/CDamageVulnerability.hpp"
|
|
|
|
|
|
|
|
#include <zeus/CAABox.hpp>
|
|
|
|
#include <zeus/CColor.hpp>
|
|
|
|
#include <zeus/CTransform.hpp>
|
|
|
|
#include <zeus/CVector3f.hpp>
|
2017-01-24 17:23:10 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
namespace urde {
|
2019-03-24 08:06:59 +00:00
|
|
|
class CAreaCollisionCache;
|
2018-12-08 05:30:43 +00:00
|
|
|
class CWallCrawlerSwarm : public CActor {
|
2017-01-24 17:23:10 +00:00
|
|
|
public:
|
2019-03-24 08:06:59 +00:00
|
|
|
enum class EFlavor {
|
|
|
|
Parasite,
|
|
|
|
Scarab,
|
|
|
|
Crab
|
|
|
|
};
|
2018-12-08 05:30:43 +00:00
|
|
|
class CBoid {
|
2019-03-24 08:06:59 +00:00
|
|
|
friend class CWallCrawlerSwarm;
|
|
|
|
zeus::CTransform x0_xf;
|
|
|
|
zeus::CVector3f x30_velocity;
|
|
|
|
TUniqueId x3c_targetWaypoint = kInvalidUniqueId;
|
|
|
|
zeus::CColor x40_ambientLighting = zeus::CColor(0.3f, 0.3f, 0.3f, 1.f);
|
|
|
|
CBoid* x44_next = nullptr;
|
|
|
|
float x48_timeToDie = 0.f;
|
|
|
|
float x4c_timeToExplode = 0.f;
|
|
|
|
CCollisionSurface x50_surface =
|
|
|
|
CCollisionSurface(zeus::CVector3f(0.f, 0.f, 1.f), zeus::CVector3f(0.f, 1.f, 0.f),
|
|
|
|
zeus::CVector3f(1.f, 0.f, 0.f), 0xffffffff);
|
|
|
|
float x78_health;
|
|
|
|
int x7c_framesNotOnSurface : 8;
|
|
|
|
int x7c_idx : 10;
|
|
|
|
int x7c_remainingLaunchNotOnSurfaceFrames : 8;
|
2017-04-07 05:35:09 +00:00
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
union {
|
|
|
|
struct {
|
|
|
|
bool x80_24_active : 1;
|
2019-03-24 08:06:59 +00:00
|
|
|
bool x80_25_inFrustum : 1;
|
|
|
|
bool x80_26_launched : 1;
|
|
|
|
bool x80_27_scarabExplodeTimerEnabled : 1;
|
|
|
|
bool x80_28_nearPlayer : 1;
|
2018-12-08 05:30:43 +00:00
|
|
|
};
|
2019-03-24 08:06:59 +00:00
|
|
|
u32 x80_ = 0;
|
2017-01-24 17:23:10 +00:00
|
|
|
};
|
|
|
|
|
2018-12-08 05:30:43 +00:00
|
|
|
public:
|
2019-03-24 08:06:59 +00:00
|
|
|
CBoid(const zeus::CTransform& xf, int idx) : x0_xf(xf) {
|
|
|
|
x7c_framesNotOnSurface = 0;
|
|
|
|
x7c_idx = idx;
|
|
|
|
}
|
|
|
|
zeus::CTransform& Transform() { return x0_xf; }
|
|
|
|
zeus::CVector3f& Translation() { return x0_xf.origin; }
|
|
|
|
const zeus::CTransform& GetTransform() const { return x0_xf; }
|
|
|
|
const zeus::CVector3f& GetTranslation() const { return x0_xf.origin; }
|
2018-12-08 05:30:43 +00:00
|
|
|
bool GetActive() const { return x80_24_active; }
|
|
|
|
};
|
2019-03-24 08:06:59 +00:00
|
|
|
class CRepulsor {
|
|
|
|
friend class CWallCrawlerSwarm;
|
|
|
|
zeus::CVector3f x0_center;
|
|
|
|
float xc_mag;
|
|
|
|
public:
|
|
|
|
CRepulsor(const zeus::CVector3f& center, float mag) : x0_center(center), xc_mag(mag) {}
|
|
|
|
};
|
2018-12-08 05:30:43 +00:00
|
|
|
|
2017-04-07 05:35:09 +00:00
|
|
|
private:
|
2019-02-24 07:15:54 +00:00
|
|
|
zeus::CAABox xe8_aabox = zeus::skNullBox;
|
2019-03-24 08:06:59 +00:00
|
|
|
s32 x100_thinkCounter = 0;
|
|
|
|
float x104_occludedTimer = 5.f;
|
2018-12-08 05:30:43 +00:00
|
|
|
std::vector<CBoid> x108_boids;
|
2019-03-24 08:06:59 +00:00
|
|
|
zeus::CVector3f x118_boundingBoxExtent;
|
|
|
|
mutable zeus::CVector3f x124_lastOrbitPosition;
|
2018-12-08 05:30:43 +00:00
|
|
|
zeus::CVector3f x130_lastKilledOffset;
|
2019-03-24 08:06:59 +00:00
|
|
|
float x13c_separationRadius;
|
|
|
|
float x140_cohesionMagnitude;
|
|
|
|
float x144_alignmentWeight;
|
|
|
|
float x148_separationMagnitude;
|
|
|
|
float x14c_moveToWaypointWeight;
|
|
|
|
float x150_attractionMagnitude;
|
|
|
|
float x154_attractionRadius;
|
|
|
|
float x158_scarabScatterXYVelocity;
|
|
|
|
float x15c_scarabTimeToExplode;
|
|
|
|
float x160_animPlaybackSpeed;
|
|
|
|
float x164_waypointGoalRadius = 3.f;
|
|
|
|
rstl::reserved_vector<CBoid*, 125> x168_partitionedBoidLists;
|
|
|
|
CBoid* x360_outlierBoidList = nullptr;
|
|
|
|
float x364_boidGenRate;
|
|
|
|
float x368_boidGenCooldownTimer = 0.f;
|
|
|
|
float x36c_crabDamageCooldownTimer = 0.f;
|
|
|
|
float x370_crabDamageCooldown;
|
|
|
|
float x374_boidRadius;
|
|
|
|
float x378_touchRadius;
|
|
|
|
float x37c_scarabBoxMargin;
|
|
|
|
float x380_playerTouchRadius;
|
|
|
|
CDamageInfo x384_crabDamage;
|
|
|
|
CDamageInfo x3a0_scarabExplodeDamage;
|
|
|
|
CHealthInfo x3bc_hInfo;
|
|
|
|
CDamageVulnerability x3c4_dVuln;
|
|
|
|
s32 x42c_lockOnIdx = -1;
|
|
|
|
/* Used to be position and normal array pointers */
|
|
|
|
//rstl::reserved_vector<std::unique_ptr<float[]>, 10> x430_;
|
|
|
|
//rstl::reserved_vector<std::unique_ptr<float[]>, 10> x484_;
|
|
|
|
rstl::reserved_vector<std::shared_ptr<CModelData>, 10> x4b0_modelDatas;
|
|
|
|
CModelData::EWhichModel x4dc_whichModel = CModelData::EWhichModel::Normal;
|
|
|
|
std::vector<CRepulsor> x4e0_doorRepulsors;
|
|
|
|
rstl::reserved_vector<TLockedToken<CGenDescription>, 4> x4f0_particleDescs;
|
|
|
|
rstl::reserved_vector<std::unique_ptr<CElementGen>, 4> x524_particleGens;
|
|
|
|
s32 x548_numBoids;
|
|
|
|
s32 x54c_maxCreatedBoids;
|
|
|
|
u32 x550_createdBoids = 0;
|
|
|
|
s32 x554_maxLaunches;
|
|
|
|
EFlavor x558_flavor;
|
|
|
|
u16 x55c_launchSfx;
|
|
|
|
u16 x55e_scatterSfx;
|
|
|
|
bool x560_24_enableLighting : 1;
|
|
|
|
bool x560_25_useSoftwareLight : 1;
|
|
|
|
bool x560_26_modelAssetDirty : 1;
|
|
|
|
|
|
|
|
void AllocateSkinnedModels(CStateManager& mgr, CModelData::EWhichModel which);
|
|
|
|
void AddDoorRepulsors(CStateManager& mgr);
|
|
|
|
void UpdateParticles(float dt);
|
|
|
|
int SelectLockOnIdx(CStateManager& mgr) const;
|
|
|
|
zeus::CAABox GetBoundingBox() const;
|
|
|
|
TUniqueId GetWaypointForState(EScriptObjectState state, CStateManager& mgr) const;
|
|
|
|
static zeus::CVector3f ProjectVectorToPlane(const zeus::CVector3f& pt, const zeus::CVector3f& plane) {
|
|
|
|
return pt - plane * pt.dot(plane);
|
|
|
|
}
|
|
|
|
static zeus::CVector3f ProjectPointToPlane(const zeus::CVector3f& p0, const zeus::CVector3f& p1,
|
|
|
|
const zeus::CVector3f& plane) {
|
|
|
|
return p0 - (p0 - p1).dot(plane) * plane;
|
|
|
|
}
|
|
|
|
bool PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& pos, const zeus::CPlane& plane) const;
|
|
|
|
bool FindBestSurface(const CAreaCollisionCache& ccache, const zeus::CVector3f& pos, float radius,
|
|
|
|
CCollisionSurface& out) const;
|
|
|
|
CCollisionSurface FindBestCollisionInBox(CStateManager& mgr, const zeus::CVector3f& wpPos) const;
|
|
|
|
void CreateBoid(CStateManager& mgr, int idx);
|
|
|
|
void ExplodeBoid(CBoid& boid, CStateManager& mgr);
|
|
|
|
void SetExplodeTimers(const zeus::CVector3f& pos, float radius, float minTime, float maxTime);
|
|
|
|
CBoid* GetListAt(const zeus::CVector3f& pos);
|
|
|
|
void BuildBoidNearList(const CBoid& boid, float radius, rstl::reserved_vector<CBoid*, 50>& nearList);
|
|
|
|
void ApplySeparation(const CBoid& boid, const rstl::reserved_vector<CBoid*, 50>& nearList,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void ApplySeparation(const CBoid& boid, const zeus::CVector3f& separateFrom, float separationRadius, float separationMagnitude,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void ScatterScarabBoid(CBoid& boid, CStateManager& mgr) const;
|
|
|
|
void MoveToWayPoint(CBoid& boid, CStateManager& mgr, zeus::CVector3f& aheadVec) const;
|
|
|
|
void ApplyCohesion(const CBoid& boid, const rstl::reserved_vector<CBoid*, 50>& nearList,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void ApplyCohesion(const CBoid& boid, const zeus::CVector3f& cohesionFrom, float cohesionRadius, float cohesionMagnitude,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void ApplyAlignment(const CBoid& boid, const rstl::reserved_vector<CBoid*, 50>& nearList,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void ApplyAttraction(const CBoid& boid, const zeus::CVector3f& attractTo, float attractionRadius, float attractionMagnitude,
|
|
|
|
zeus::CVector3f& aheadVec) const;
|
|
|
|
void UpdateBoid(const CAreaCollisionCache& ccache, CStateManager& mgr, float dt, CBoid& boid);
|
|
|
|
void LaunchBoid(CBoid& boid, const zeus::CVector3f& dir);
|
|
|
|
void AddParticle(const zeus::CTransform& xf);
|
|
|
|
void KillBoid(CBoid& boid, CStateManager& mgr, float deathRattleChance, float deadChance);
|
|
|
|
void UpdatePartition();
|
|
|
|
zeus::CVector3f FindClosestCell(const zeus::CVector3f& pos) const;
|
|
|
|
void UpdateEffects(CStateManager& mgr, CAnimData& aData, int vol);
|
|
|
|
zeus::CAABox BoxForPosition(int x, int y, int z, float f) const;
|
|
|
|
void RenderParticles() const;
|
|
|
|
zeus::CColor SoftwareLight(const CStateManager& mgr, const zeus::CAABox& aabb) const;
|
|
|
|
void HardwareLight(const CStateManager& mgr, const zeus::CAABox& aabb) const;
|
|
|
|
void RenderBoid(const CBoid* boid, u32& drawMask, bool thermalHot, const CModelFlags& flags) const;
|
2017-04-07 05:35:09 +00:00
|
|
|
|
2017-01-24 17:23:10 +00:00
|
|
|
public:
|
2019-03-24 08:06:59 +00:00
|
|
|
CWallCrawlerSwarm(TUniqueId uid, bool active, std::string_view name, const CEntityInfo& info,
|
|
|
|
const zeus::CVector3f& boundingBoxExtent, const zeus::CTransform& xf,
|
|
|
|
EFlavor flavor, const CAnimRes& animRes, s32 launchAnim, s32 attractAnim,
|
|
|
|
CAssetId part1, CAssetId part2, CAssetId part3, CAssetId part4,
|
|
|
|
const CDamageInfo& crabDamage, const CDamageInfo& scarabExplodeDamage,
|
|
|
|
float crabDamageCooldown, float boidRadius, float touchRadius,
|
|
|
|
float playerTouchRadius, u32 numBoids, u32 maxCreatedBoids,
|
|
|
|
float animPlaybackSpeed, float separationRadius, float cohesionMagnitude,
|
|
|
|
float alignmentWeight, float separationMagnitude, float moveToWaypointWeight,
|
|
|
|
float attractionMagnitude, float attractionRadius, float boidGenRate,
|
|
|
|
u32 maxLaunches, float scarabBoxMargin, float scarabScatterXYVelocity,
|
|
|
|
float scarabTimeToExplode, const CHealthInfo& hInfo,
|
|
|
|
const CDamageVulnerability& dVuln, s32 launchSfx,
|
|
|
|
s32 scatterSfx, const CActorParameters& aParams);
|
2017-01-24 17:23:10 +00:00
|
|
|
|
2019-08-09 12:45:18 +00:00
|
|
|
void Accept(IVisitor& visitor) override;
|
|
|
|
void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&) override;
|
|
|
|
void Think(float, CStateManager&) override;
|
|
|
|
void PreRender(CStateManager&, const zeus::CFrustum&) override;
|
2020-04-05 11:54:02 +00:00
|
|
|
void AddToRenderer(const zeus::CFrustum&, CStateManager&) override;
|
2020-04-09 17:28:20 +00:00
|
|
|
void Render(CStateManager&) override;
|
2019-08-09 12:45:18 +00:00
|
|
|
bool CanRenderUnsorted(const CStateManager&) const override;
|
|
|
|
void CalculateRenderBounds() override;
|
|
|
|
std::optional<zeus::CAABox> GetTouchBounds() const override;
|
|
|
|
void Touch(CActor& other, CStateManager&) override;
|
|
|
|
zeus::CVector3f GetOrbitPosition(const CStateManager&) const override;
|
|
|
|
zeus::CVector3f GetAimPosition(const CStateManager&, float) const override;
|
2019-02-18 05:47:46 +00:00
|
|
|
const zeus::CVector3f& GetLastKilledOffset() const { return x130_lastKilledOffset; }
|
2018-12-08 05:30:43 +00:00
|
|
|
void ApplyRadiusDamage(const zeus::CVector3f& pos, const CDamageInfo& info, CStateManager& stateMgr) {}
|
|
|
|
const std::vector<CBoid>& GetBoids() const { return x108_boids; }
|
2019-03-24 08:06:59 +00:00
|
|
|
int GetCurrentLockOnId() const { return x42c_lockOnIdx; }
|
2018-12-08 05:30:43 +00:00
|
|
|
bool GetLockOnLocationValid(int id) const { return id >= 0 && id < x108_boids.size() && x108_boids[id].GetActive(); }
|
|
|
|
const zeus::CVector3f& GetLockOnLocation(int id) const { return x108_boids[id].GetTranslation(); }
|
2017-01-24 17:23:10 +00:00
|
|
|
};
|
2018-12-08 05:30:43 +00:00
|
|
|
} // namespace urde
|