mirror of
https://github.com/AxioDL/metaforce.git
synced 2025-08-08 13:39:05 +00:00
Merge pull request #287 from AxioDL/elitepirate
Elite Pirate implementation
This commit is contained in:
commit
a4a7888338
1
.clang-tidy
Normal file
1
.clang-tidy
Normal file
@ -0,0 +1 @@
|
|||||||
|
Checks: '*,-misc-unused-parameters,-modernize-use-trailing-return-type,-readability-named-parameter,-readability-convert-member-functions-to-static,-readability-uppercase-literal-suffix,-readability-magic-numbers,-hicpp-uppercase-literal-suffix,-hicpp-signed-bitwise,-cppcoreguidelines-avoid-magic-numbers,-cppcoreguidelines-pro-type-static-cast-downcast,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-owning-memory,-cppcoreguidelines-pro-type-union-access,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cppcoreguidelines-non-private-member-variables-in-classes,-fuchsia-*,-google-runtime-references'
|
@ -68,7 +68,7 @@ enum class EFallState { Invalid = -1, Zero, One , Two};
|
|||||||
|
|
||||||
enum class EReactionType { Invalid = -1, Zero, One, Two, Three };
|
enum class EReactionType { Invalid = -1, Zero, One, Two, Three };
|
||||||
|
|
||||||
enum class EAdditiveReactionType { Invalid = -1, Electrocution, One, Two, IceBreakout };
|
enum class EAdditiveReactionType { Invalid = -1, Electrocution, One, Two, IceBreakout, Four, Five, Six, Seven };
|
||||||
|
|
||||||
enum class EJumpType { Normal, One, Ambush };
|
enum class EJumpType { Normal, One, Ambush };
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ enum class ELoopState { Invalid = -1, Begin, Loop, End };
|
|||||||
|
|
||||||
enum class ELoopAttackType { Invalid = -1 };
|
enum class ELoopAttackType { Invalid = -1 };
|
||||||
|
|
||||||
enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four };
|
enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four, Five };
|
||||||
|
|
||||||
enum class ESlideType { Invalid = -1, Zero = 0 };
|
enum class ESlideType { Invalid = -1, Zero = 0 };
|
||||||
|
|
||||||
|
208
Runtime/MP1/World/CBouncyGrenade.cpp
Normal file
208
Runtime/MP1/World/CBouncyGrenade.cpp
Normal file
@ -0,0 +1,208 @@
|
|||||||
|
#include "Runtime/MP1/World/CBouncyGrenade.hpp"
|
||||||
|
|
||||||
|
#include "Runtime/CPlayerState.hpp"
|
||||||
|
#include "Runtime/CSimplePool.hpp"
|
||||||
|
#include "Runtime/CStateManager.hpp"
|
||||||
|
#include "Runtime/GameGlobalObjects.hpp"
|
||||||
|
#include "Runtime/Graphics/CBooRenderer.hpp"
|
||||||
|
#include "Runtime/World/CPlayer.hpp"
|
||||||
|
#include "Runtime/Collision/CCollisionActor.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
CBouncyGrenade::CBouncyGrenade(TUniqueId uid, std::string_view name, const CEntityInfo& info,
|
||||||
|
const zeus::CTransform& xf, CModelData&& mData, const CActorParameters& actParams,
|
||||||
|
TUniqueId parentId, const SBouncyGrenadeData& data, float velocity,
|
||||||
|
float explodePlayerDistance)
|
||||||
|
: CPhysicsActor(uid, true, name, info, xf, std::move(mData), {EMaterialTypes::Projectile, EMaterialTypes::Solid},
|
||||||
|
mData.GetBounds(), SMoverData{data.GetUnkStruct().GetMass()}, actParams, 0.3f, 0.1f)
|
||||||
|
, x258_data(data)
|
||||||
|
, x294_numBounces(data.GetNumBounces())
|
||||||
|
, x298_parentId(parentId)
|
||||||
|
, x2a0_elementGen1(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.GetElementGenId1()})))
|
||||||
|
, x2a4_elementGen2(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.GetElementGenId2()})))
|
||||||
|
, x2a8_elementGen3(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.GetElementGenId3()})))
|
||||||
|
, x2ac_elementGen4(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.GetElementGenId4()})))
|
||||||
|
, x2b0_explodePlayerDistance(explodePlayerDistance)
|
||||||
|
, x2b4_24_exploded(false)
|
||||||
|
, x2b4_25_(false) {
|
||||||
|
SetMomentumWR({0.f, 0.f, -GravityConstant() * GetMass()});
|
||||||
|
SetVelocityWR(velocity * xf.frontVector());
|
||||||
|
x2a0_elementGen1->SetParticleEmission(false);
|
||||||
|
x2a4_elementGen2->SetParticleEmission(false);
|
||||||
|
x2a8_elementGen3->SetParticleEmission(false);
|
||||||
|
x2ac_elementGen4->SetParticleEmission(true);
|
||||||
|
CMaterialFilter filter = GetMaterialFilter();
|
||||||
|
filter.ExcludeList().Add(EMaterialTypes::Character);
|
||||||
|
SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(filter.IncludeList(), filter.ExcludeList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBouncyGrenade::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
|
||||||
|
CActor::AddToRenderer(frustum, mgr);
|
||||||
|
if (!x2b4_24_exploded) {
|
||||||
|
g_Renderer->AddParticleGen(*x2ac_elementGen4);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto visor = mgr.GetPlayerState()->GetActiveVisor(mgr);
|
||||||
|
if (visor == CPlayerState::EPlayerVisor::Combat || visor == CPlayerState::EPlayerVisor::Scan) {
|
||||||
|
g_Renderer->AddParticleGen(*x2a0_elementGen1);
|
||||||
|
} else if (visor == CPlayerState::EPlayerVisor::XRay || visor == CPlayerState::EPlayerVisor::Thermal) {
|
||||||
|
g_Renderer->AddParticleGen(*x2a8_elementGen3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBouncyGrenade::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) {
|
||||||
|
constexpr auto matList = CMaterialList{
|
||||||
|
EMaterialTypes::Solid,
|
||||||
|
EMaterialTypes::Ceiling,
|
||||||
|
EMaterialTypes::Floor,
|
||||||
|
EMaterialTypes::Character,
|
||||||
|
};
|
||||||
|
|
||||||
|
bool shouldExplode = false;
|
||||||
|
if (x298_parentId != id) {
|
||||||
|
const CEntity* const entity = mgr.GetObjectById(id);
|
||||||
|
if (entity != nullptr) {
|
||||||
|
if (TCastToConstPtr<CCollisionActor> actor = entity) {
|
||||||
|
shouldExplode = actor->GetOwnerId() != x298_parentId;
|
||||||
|
} else {
|
||||||
|
shouldExplode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (shouldExplode) {
|
||||||
|
Explode(mgr, id);
|
||||||
|
} else {
|
||||||
|
for (const auto& info : list) {
|
||||||
|
if (info.GetMaterialLeft().SharesMaterials(matList)) {
|
||||||
|
if (x294_numBounces == 0) {
|
||||||
|
Explode(mgr, kInvalidUniqueId);
|
||||||
|
} else {
|
||||||
|
const zeus::CVector3f* normal = &info.GetNormalLeft();
|
||||||
|
if (GetVelocity().dot(info.GetNormalLeft()) > 0.f) {
|
||||||
|
normal = &info.GetNormalRight();
|
||||||
|
}
|
||||||
|
const zeus::CVector3f impulse =
|
||||||
|
(x258_data.GetUnkStruct().GetSpeed() * GetConstantForce().magnitude()) * *normal;
|
||||||
|
const zeus::CVector3f angle = -x258_data.GetUnkStruct().GetSpeed() * GetAngularMomentum();
|
||||||
|
ApplyImpulseWR(impulse, angle);
|
||||||
|
CSfxManager::AddEmitter(x258_data.GetBounceSfx(), GetTranslation(), zeus::skUp, false, false, 0x7f,
|
||||||
|
GetAreaIdAlways());
|
||||||
|
--x294_numBounces;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CPhysicsActor::CollidedWith(id, list, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<zeus::CAABox> CBouncyGrenade::GetTouchBounds() const { return GetModelData()->GetBounds(GetTransform()); }
|
||||||
|
|
||||||
|
void CBouncyGrenade::Render(const CStateManager& mgr) const {
|
||||||
|
if (!x2b4_24_exploded) {
|
||||||
|
GetModelData()->Render(mgr, GetTransform(), nullptr, {0, 0, 3, zeus::skWhite});
|
||||||
|
} else if (mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::XRay) {
|
||||||
|
CGraphics::SetFog(ERglFogMode::PerspLin, 0.f, 75.f, zeus::skBlack);
|
||||||
|
x2a4_elementGen2->Render();
|
||||||
|
mgr.SetupFogForArea(GetAreaIdAlways());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBouncyGrenade::Think(float dt, CStateManager& mgr) {
|
||||||
|
if (GetActive()) {
|
||||||
|
const zeus::CTransform& orientation = GetTransform().getRotation();
|
||||||
|
const zeus::CVector3f& translation = GetTranslation();
|
||||||
|
const zeus::CVector3f& scale = GetModelData()->GetScale();
|
||||||
|
auto UpdateElementGen = [ orientation, translation, scale, dt ](CElementGen & gen) constexpr {
|
||||||
|
gen.SetOrientation(orientation);
|
||||||
|
gen.SetGlobalTranslation(translation);
|
||||||
|
gen.SetGlobalScale(scale);
|
||||||
|
gen.Update(dt);
|
||||||
|
};
|
||||||
|
if (x2b4_24_exploded) {
|
||||||
|
Stop();
|
||||||
|
UpdateElementGen(*x2a0_elementGen1);
|
||||||
|
UpdateElementGen(*x2a4_elementGen2);
|
||||||
|
UpdateElementGen(*x2a8_elementGen3);
|
||||||
|
} else {
|
||||||
|
UpdateElementGen(*x2ac_elementGen4);
|
||||||
|
}
|
||||||
|
x29c_ += dt;
|
||||||
|
if (x29c_ > 0.3f) {
|
||||||
|
x2b4_25_ = true;
|
||||||
|
}
|
||||||
|
const zeus::CVector3f& playerDistance = mgr.GetPlayer().GetTranslation() +
|
||||||
|
zeus::CVector3f{0.f, 0.f, 0.5f * mgr.GetPlayer().GetEyeHeight()} -
|
||||||
|
translation;
|
||||||
|
if (playerDistance.magSquared() < x2b0_explodePlayerDistance * x2b0_explodePlayerDistance) {
|
||||||
|
Explode(mgr, kInvalidUniqueId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x2a0_elementGen1->IsSystemDeletable() && x2a4_elementGen2->IsSystemDeletable() &&
|
||||||
|
x2a8_elementGen3->IsSystemDeletable()) {
|
||||||
|
mgr.FreeScriptObject(GetUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBouncyGrenade::Touch(CActor& act, CStateManager& mgr) { CActor::Touch(act, mgr); }
|
||||||
|
|
||||||
|
void CBouncyGrenade::Explode(CStateManager& mgr, TUniqueId uid) {
|
||||||
|
if (x2b4_24_exploded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
x2b4_24_exploded = true;
|
||||||
|
CSfxManager::AddEmitter(x258_data.GetExplodeSfx(), GetTranslation(), zeus::skUp, false, false, 0x7f,
|
||||||
|
GetAreaIdAlways());
|
||||||
|
x2a0_elementGen1->SetParticleEmission(true);
|
||||||
|
x2a4_elementGen2->SetParticleEmission(true);
|
||||||
|
x2a8_elementGen3->SetParticleEmission(true);
|
||||||
|
x2ac_elementGen4->SetParticleEmission(false);
|
||||||
|
|
||||||
|
const CDamageInfo& dInfo = x258_data.GetDamageInfo();
|
||||||
|
{
|
||||||
|
bool isParent = x298_parentId == uid;
|
||||||
|
if (TCastToConstPtr<CCollisionActor> actor = mgr.GetObjectById(uid)) {
|
||||||
|
isParent = x298_parentId == actor->GetOwnerId();
|
||||||
|
}
|
||||||
|
if (uid != kInvalidUniqueId && !isParent) {
|
||||||
|
mgr.ApplyDamage(GetUniqueId(), uid, GetUniqueId(), dInfo, CMaterialFilter::MakeInclude({EMaterialTypes::Solid}),
|
||||||
|
zeus::skZero3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float radius = dInfo.GetRadius();
|
||||||
|
if (radius > 1.f) {
|
||||||
|
const zeus::CVector3f& pos = GetTranslation();
|
||||||
|
const CMaterialFilter filter = CMaterialFilter::MakeInclude({EMaterialTypes::Player, EMaterialTypes::Character});
|
||||||
|
rstl::reserved_vector<TUniqueId, 1024> nearList;
|
||||||
|
mgr.BuildNearList(nearList, {pos - radius, pos + radius}, filter, nullptr);
|
||||||
|
|
||||||
|
for (const auto& id : nearList) {
|
||||||
|
bool isParent = x298_parentId == id;
|
||||||
|
if (TCastToConstPtr<CCollisionActor> cActor = mgr.GetObjectById(id)) {
|
||||||
|
isParent = x298_parentId == cActor->GetOwnerId();
|
||||||
|
}
|
||||||
|
if (isParent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto* actor = static_cast<const CActor*>(mgr.GetObjectById(id));
|
||||||
|
if (actor == nullptr) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float magnitude = (actor->GetTranslation() - GetTranslation()).magnitude();
|
||||||
|
if (radius <= magnitude) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
float scale = (radius - magnitude) / radius;
|
||||||
|
const CDamageInfo info{dInfo.GetWeaponMode(), scale * dInfo.GetDamage(), radius,
|
||||||
|
scale * dInfo.GetKnockBackPower()};
|
||||||
|
mgr.ApplyDamage(GetUniqueId(), id, GetUniqueId(), info, CMaterialFilter::MakeInclude({EMaterialTypes::Solid}),
|
||||||
|
zeus::skZero3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace urde::MP1
|
90
Runtime/MP1/World/CBouncyGrenade.hpp
Normal file
90
Runtime/MP1/World/CBouncyGrenade.hpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Runtime/World/CPhysicsActor.hpp"
|
||||||
|
#include "Runtime/World/CDamageInfo.hpp"
|
||||||
|
#include "Runtime/Particle/CElementGen.hpp"
|
||||||
|
|
||||||
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
||||||
|
|
||||||
|
#include <zeus/CTransform.hpp>
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
struct SGrenadeUnknownStruct {
|
||||||
|
private:
|
||||||
|
float x0_mass;
|
||||||
|
float x4_speed; // wrong name probably
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SGrenadeUnknownStruct(CInputStream& in) : x0_mass(in.readFloatBig()), x4_speed(in.readFloatBig()) {}
|
||||||
|
|
||||||
|
[[nodiscard]] float GetMass() const { return x0_mass; }
|
||||||
|
[[nodiscard]] float GetSpeed() const { return x4_speed; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SBouncyGrenadeData {
|
||||||
|
private:
|
||||||
|
SGrenadeUnknownStruct x0_;
|
||||||
|
CDamageInfo x8_damageInfo;
|
||||||
|
CAssetId x24_elementGenId1;
|
||||||
|
CAssetId x28_elementGenId2;
|
||||||
|
CAssetId x2c_elementGenId3;
|
||||||
|
CAssetId x30_elementGenId4;
|
||||||
|
u32 x34_numBounces;
|
||||||
|
u16 x38_bounceSfx;
|
||||||
|
u16 x3a_explodeSfx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SBouncyGrenadeData(const SGrenadeUnknownStruct& unkStruct, const CDamageInfo& damageInfo, CAssetId w1, CAssetId w2,
|
||||||
|
CAssetId w3, CAssetId w4, u32 w5, u16 s1, u16 s2)
|
||||||
|
: x0_(unkStruct)
|
||||||
|
, x8_damageInfo(damageInfo)
|
||||||
|
, x24_elementGenId1(w1)
|
||||||
|
, x28_elementGenId2(w2)
|
||||||
|
, x2c_elementGenId3(w3)
|
||||||
|
, x30_elementGenId4(w4)
|
||||||
|
, x34_numBounces(w5)
|
||||||
|
, x38_bounceSfx(s1)
|
||||||
|
, x3a_explodeSfx(s2){};
|
||||||
|
|
||||||
|
[[nodiscard]] const SGrenadeUnknownStruct& GetUnkStruct() const { return x0_; }
|
||||||
|
[[nodiscard]] const CDamageInfo& GetDamageInfo() const { return x8_damageInfo; }
|
||||||
|
[[nodiscard]] CAssetId GetElementGenId1() const { return x24_elementGenId1; }
|
||||||
|
[[nodiscard]] CAssetId GetElementGenId2() const { return x28_elementGenId2; }
|
||||||
|
[[nodiscard]] CAssetId GetElementGenId3() const { return x2c_elementGenId3; }
|
||||||
|
[[nodiscard]] CAssetId GetElementGenId4() const { return x30_elementGenId4; }
|
||||||
|
[[nodiscard]] u32 GetNumBounces() const { return x34_numBounces; }
|
||||||
|
[[nodiscard]] u16 GetBounceSfx() const { return x38_bounceSfx; }
|
||||||
|
[[nodiscard]] u16 GetExplodeSfx() const { return x3a_explodeSfx; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CBouncyGrenade : public CPhysicsActor {
|
||||||
|
private:
|
||||||
|
SBouncyGrenadeData x258_data;
|
||||||
|
u32 x294_numBounces;
|
||||||
|
TUniqueId x298_parentId;
|
||||||
|
float x29c_ = 0.f;
|
||||||
|
std::unique_ptr<CElementGen> x2a0_elementGen1;
|
||||||
|
std::unique_ptr<CElementGen> x2a4_elementGen2;
|
||||||
|
std::unique_ptr<CElementGen> x2a8_elementGen3;
|
||||||
|
std::unique_ptr<CElementGen> x2ac_elementGen4;
|
||||||
|
float x2b0_explodePlayerDistance;
|
||||||
|
bool x2b4_24_exploded : 1;
|
||||||
|
bool x2b4_25_ : 1;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CBouncyGrenade(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
CModelData&& mData, const CActorParameters& actParams, TUniqueId parentId,
|
||||||
|
const SBouncyGrenadeData& data, float velocity, float explodePlayerDistance);
|
||||||
|
|
||||||
|
void Accept(IVisitor& visitor) override { visitor.Visit(this); }
|
||||||
|
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override;
|
||||||
|
void CollidedWith(TUniqueId id, const CCollisionInfoList& list, CStateManager& mgr) override;
|
||||||
|
[[nodiscard]] std::optional<zeus::CAABox> GetTouchBounds() const override;
|
||||||
|
void Render(const CStateManager& mgr) const override;
|
||||||
|
void Think(float dt, CStateManager& mgr) override;
|
||||||
|
void Touch(CActor& act, CStateManager& mgr) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Explode(CStateManager& mgr, TUniqueId uid);
|
||||||
|
};
|
||||||
|
} // namespace urde::MP1
|
File diff suppressed because it is too large
Load Diff
@ -1,59 +1,229 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string_view>
|
#include "Runtime/Character/CBoneTracking.hpp"
|
||||||
|
#include "Runtime/Collision/CCollisionActorManager.hpp"
|
||||||
#include "Runtime/RetroTypes.hpp"
|
#include "Runtime/Collision/CJointCollisionDescription.hpp"
|
||||||
|
#include "Runtime/MP1/World/CGrenadeLauncher.hpp"
|
||||||
|
#include "Runtime/MP1/World/CShockWave.hpp"
|
||||||
#include "Runtime/World/CActorParameters.hpp"
|
#include "Runtime/World/CActorParameters.hpp"
|
||||||
#include "Runtime/World/CAnimationParameters.hpp"
|
#include "Runtime/World/CAnimationParameters.hpp"
|
||||||
|
#include "Runtime/World/CPathFindSearch.hpp"
|
||||||
#include "Runtime/World/CPatterned.hpp"
|
#include "Runtime/World/CPatterned.hpp"
|
||||||
|
|
||||||
namespace urde::MP1 {
|
namespace urde::MP1 {
|
||||||
class CElitePirateData {
|
class CElitePirateData {
|
||||||
float x0_;
|
private:
|
||||||
float x4_;
|
float x0_tauntInterval;
|
||||||
|
float x4_tauntVariance;
|
||||||
float x8_;
|
float x8_;
|
||||||
float xc_;
|
float xc_;
|
||||||
float x10_;
|
float x10_attackChance;
|
||||||
float x14_;
|
float x14_shotAtTime;
|
||||||
float x18_;
|
float x18_shotAtTimeVariance;
|
||||||
float x1c_;
|
float x1c_;
|
||||||
CAssetId x20_;
|
CAssetId x20_;
|
||||||
s16 x24_;
|
u16 x24_sfxAbsorb;
|
||||||
CActorParameters x28_;
|
CActorParameters x28_launcherActParams;
|
||||||
CAnimationParameters x90_;
|
CAnimationParameters x90_launcherAnimParams;
|
||||||
CAssetId x9c_;
|
CAssetId x9c_;
|
||||||
s16 xa0_;
|
u16 xa0_;
|
||||||
CAssetId xa4_;
|
CAssetId xa4_;
|
||||||
CDamageInfo xa8_;
|
CDamageInfo xa8_;
|
||||||
float xc4_;
|
float xc4_launcherHp;
|
||||||
CAssetId xc8_;
|
CAssetId xc8_;
|
||||||
CAssetId xcc_;
|
CAssetId xcc_;
|
||||||
CAssetId xd0_;
|
CAssetId xd0_;
|
||||||
CAssetId xd4_;
|
CAssetId xd4_;
|
||||||
float xd8_;
|
SGrenadeUnknownStruct xd8_;
|
||||||
float xdc_;
|
SGrenadeTrajectoryInfo xe0_trajectoryInfo;
|
||||||
float xe0_;
|
u32 xf0_grenadeNumBounces;
|
||||||
float xe4_;
|
u16 xf4_;
|
||||||
float xe8_;
|
u16 xf6_;
|
||||||
float xec_;
|
|
||||||
u32 xf0_;
|
|
||||||
u32 xf4_;
|
|
||||||
CAssetId xf8_;
|
CAssetId xf8_;
|
||||||
CDamageInfo xfc_;
|
CDamageInfo xfc_;
|
||||||
CAssetId x118_;
|
CAssetId x118_;
|
||||||
s16 x11c_;
|
u16 x11c_;
|
||||||
bool x11e_;
|
bool x11e_;
|
||||||
bool x11f_;
|
bool x11f_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CElitePirateData(CInputStream&, u32 propCount);
|
CElitePirateData(CInputStream&, u32 propCount);
|
||||||
|
|
||||||
|
[[nodiscard]] float GetTauntInterval() const { return x0_tauntInterval; }
|
||||||
|
[[nodiscard]] float GetTauntVariance() const { return x4_tauntVariance; }
|
||||||
|
[[nodiscard]] float GetAttackChance() const { return x10_attackChance; }
|
||||||
|
[[nodiscard]] float GetShotAtTime() const { return x14_shotAtTime; }
|
||||||
|
[[nodiscard]] float GetShotAtTimeVariance() const { return x18_shotAtTimeVariance; }
|
||||||
|
[[nodiscard]] float GetX1C() const { return x1c_; }
|
||||||
|
[[nodiscard]] CAssetId GetX20() const { return x20_; }
|
||||||
|
[[nodiscard]] u16 GetSFXAbsorb() const { return x24_sfxAbsorb; }
|
||||||
|
[[nodiscard]] const CActorParameters& GetLauncherActParams() const { return x28_launcherActParams; }
|
||||||
|
[[nodiscard]] const CAnimationParameters& GetLauncherAnimParams() const { return x90_launcherAnimParams; }
|
||||||
|
[[nodiscard]] float GetLauncherHP() const { return xc4_launcherHp; }
|
||||||
|
[[nodiscard]] const SGrenadeTrajectoryInfo& GetGrenadeTrajectoryInfo() const { return xe0_trajectoryInfo; }
|
||||||
|
[[nodiscard]] CAssetId GetXF8() const { return xf8_; }
|
||||||
|
[[nodiscard]] const CDamageInfo& GetXFC() const { return xfc_; }
|
||||||
|
[[nodiscard]] CAssetId GetX118() const { return x118_; }
|
||||||
|
[[nodiscard]] u16 GetX11C() const { return x11c_; }
|
||||||
|
[[nodiscard]] bool GetX11E() const { return x11e_; }
|
||||||
|
[[nodiscard]] bool GetX11F() const { return x11f_; }
|
||||||
|
|
||||||
|
[[nodiscard]] SBouncyGrenadeData GetBouncyGrenadeData() const {
|
||||||
|
return {xd8_, xa8_, xc8_, xcc_, xd0_, xd4_, xf0_grenadeNumBounces, xf4_, xf6_};
|
||||||
|
}
|
||||||
|
[[nodiscard]] SGrenadeLauncherData GetGrenadeLauncherData() const {
|
||||||
|
return {GetBouncyGrenadeData(), xa4_, x9c_, xa0_, xe0_trajectoryInfo};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CElitePirate : public CPatterned {
|
class CElitePirate : public CPatterned {
|
||||||
|
private:
|
||||||
|
struct SUnknownStruct {
|
||||||
|
private:
|
||||||
|
float x0_;
|
||||||
|
rstl::reserved_vector<zeus::CVector3f, 16> x4_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SUnknownStruct(float f) : x0_(f * f) {}
|
||||||
|
zeus::CVector3f GetValue(const zeus::CVector3f& v1, const zeus::CVector3f& v2);
|
||||||
|
void AddValue(const zeus::CVector3f& vec);
|
||||||
|
void Clear() { x4_.clear(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class EState {
|
||||||
|
Invalid = -1,
|
||||||
|
Zero = 0,
|
||||||
|
One = 1,
|
||||||
|
Two = 2,
|
||||||
|
Over = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
EState x568_state = EState::Invalid;
|
||||||
|
CDamageVulnerability x56c_vulnerability;
|
||||||
|
std::unique_ptr<CCollisionActorManager> x5d4_collisionActorMgr;
|
||||||
|
CElitePirateData x5d8_data;
|
||||||
|
CBoneTracking x6f8_boneTracking;
|
||||||
|
std::unique_ptr<CCollisionActorManager> x730_collisionActorMgrHead;
|
||||||
|
// s32 x734_;
|
||||||
|
CCollidableAABox x738_collisionAabb;
|
||||||
|
std::optional<TLockedToken<CGenDescription>> x760_energyAbsorbDesc;
|
||||||
|
TUniqueId x770_collisionHeadId = kInvalidUniqueId;
|
||||||
|
TUniqueId x772_launcherId = kInvalidUniqueId;
|
||||||
|
rstl::reserved_vector<TUniqueId, 7> x774_collisionRJointIds;
|
||||||
|
rstl::reserved_vector<TUniqueId, 7> x788_collisionLJointIds;
|
||||||
|
TUniqueId x79c_ = kInvalidUniqueId;
|
||||||
|
float x7a0_initialSpeed;
|
||||||
|
float x7a4_steeringSpeed = 1.f;
|
||||||
|
float x7a8_pathShaggedTime = 0.f;
|
||||||
|
float x7ac_energyAbsorbCooldown = 0.f;
|
||||||
|
float x7b0_ = 1.f;
|
||||||
|
float x7b4_hp = 0.f;
|
||||||
|
float x7b8_attackTimer = 0.f;
|
||||||
|
float x7bc_tauntTimer = 0.f;
|
||||||
|
float x7c0_shotAtTimer = 0.f;
|
||||||
|
float x7c4_absorbUpdateTimer = 0.f;
|
||||||
|
s32 x7c8_currAnimId = -1;
|
||||||
|
u32 x7cc_activeMaterialSet = 0;
|
||||||
|
CPathFindSearch x7d0_pathFindSearch;
|
||||||
|
zeus::CVector3f x8b4_targetDestPos;
|
||||||
|
SUnknownStruct x8c0_;
|
||||||
|
bool x988_24_damageOn : 1;
|
||||||
|
bool x988_25_attackingRightClaw : 1;
|
||||||
|
bool x988_26_attackingLeftClaw : 1;
|
||||||
|
bool x988_27_shotAt : 1;
|
||||||
|
bool x988_28_alert : 1;
|
||||||
|
bool x988_29_shockWaveAnim : 1;
|
||||||
|
bool x988_30_calledForBackup : 1;
|
||||||
|
bool x988_31_running : 1;
|
||||||
|
bool x989_24_onPath : 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DEFINE_PATTERNED(ElitePirate)
|
DEFINE_PATTERNED(ElitePirate)
|
||||||
|
|
||||||
CElitePirate(TUniqueId, std::string_view, const CEntityInfo&, const zeus::CTransform&, CModelData&&,
|
CElitePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
const CPatternedInfo&, const CActorParameters&, const CElitePirateData&);
|
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
|
||||||
|
CElitePirateData data);
|
||||||
|
|
||||||
|
void Accept(IVisitor& visitor) override;
|
||||||
|
void Think(float dt, CStateManager& mgr) override;
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
|
||||||
|
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
|
||||||
|
const CDamageVulnerability* GetDamageVulnerability() const override;
|
||||||
|
const CDamageVulnerability* GetDamageVulnerability(const zeus::CVector3f& pos, const zeus::CVector3f& dir,
|
||||||
|
const CDamageInfo& dInfo) const override;
|
||||||
|
zeus::CVector3f GetOrbitPosition(const CStateManager& mgr) const override;
|
||||||
|
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const override;
|
||||||
|
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
|
||||||
|
const CCollisionPrimitive* GetCollisionPrimitive() const override;
|
||||||
|
void KnockBack(const zeus::CVector3f&, CStateManager& mgr, const CDamageInfo& info, EKnockBackType type,
|
||||||
|
bool inDeferred, float magnitude) override;
|
||||||
|
void TakeDamage(const zeus::CVector3f&, float arg) override;
|
||||||
|
void Patrol(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void PathFind(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Halt(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Run(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Generate(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Attack(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Taunt(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void Cover(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
void CallForBackup(CStateManager& mgr, EStateMsg msg, float dt) override;
|
||||||
|
bool TooClose(CStateManager& mgr, float arg) override;
|
||||||
|
bool InDetectionRange(CStateManager& mgr, float arg) override;
|
||||||
|
bool SpotPlayer(CStateManager& mgr, float arg) override;
|
||||||
|
bool AnimOver(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldAttack(CStateManager& mgr, float arg) override;
|
||||||
|
bool InPosition(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldTurn(CStateManager& mgr, float arg) override;
|
||||||
|
bool AggressionCheck(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldTaunt(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldFire(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShotAt(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldSpecialAttack(CStateManager& mgr, float arg) override;
|
||||||
|
bool ShouldCallForBackup(CStateManager& mgr, float arg) override;
|
||||||
|
CPathFindSearch* GetSearchPath() override;
|
||||||
|
virtual bool HasWeakPointHead() const { return true; }
|
||||||
|
virtual bool IsElitePirate() const { return true; }
|
||||||
|
virtual void SetupHealthInfo(CStateManager& mgr);
|
||||||
|
virtual void SetLaunchersActive(CStateManager& mgr, bool val);
|
||||||
|
virtual SShockWaveData GetShockWaveData() const {
|
||||||
|
return {x5d8_data.GetXF8(), x5d8_data.GetXFC(), x5d8_data.GetX118(), x5d8_data.GetX11C()};
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetupPathFindSearch();
|
||||||
|
void SetShotAt(bool val, CStateManager& mgr);
|
||||||
|
bool IsArmClawCollider(TUniqueId uid, const rstl::reserved_vector<TUniqueId, 7>& vec) const;
|
||||||
|
void AddSphereCollisionList(const SSphereJointInfo* joints, size_t count,
|
||||||
|
std::vector<CJointCollisionDescription>& outJoints) const;
|
||||||
|
void AddCollisionList(const SJointInfo* joints, size_t count,
|
||||||
|
std::vector<CJointCollisionDescription>& outJoints) const;
|
||||||
|
void SetupCollisionManager(CStateManager& mgr);
|
||||||
|
void SetupCollisionActorInfo(CStateManager& mgr);
|
||||||
|
bool IsArmClawCollider(std::string_view name, std::string_view locator, const SJointInfo* info, size_t infoCount);
|
||||||
|
void CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid);
|
||||||
|
void ApplyDamageToHead(CStateManager& mgr, TUniqueId uid);
|
||||||
|
void CreateEnergyAbsorb(CStateManager& mgr, const zeus::CTransform& xf);
|
||||||
|
void SetupLauncherHealthInfo(CStateManager& mgr, TUniqueId uid);
|
||||||
|
void SetLauncherActive(CStateManager& mgr, bool val, TUniqueId uid);
|
||||||
|
zeus::CVector3f GetLockOnPosition(const CActor* actor) const;
|
||||||
|
bool CanKnockBack(const CDamageInfo& info) const;
|
||||||
|
void UpdateDestPos(CStateManager& mgr);
|
||||||
|
void CheckAttackChance(CStateManager& mgr);
|
||||||
|
void AttractProjectiles(CStateManager& mgr);
|
||||||
|
void UpdateAbsorbBodyState(CStateManager& mgr, float dt);
|
||||||
|
bool IsAttractingEnergy();
|
||||||
|
void UpdateTimers(float dt);
|
||||||
|
void UpdatePositionHistory();
|
||||||
|
void UpdateActorTransform(CStateManager& mgr, TUniqueId& uid, std::string_view name);
|
||||||
|
void UpdateHealthInfo(CStateManager& mgr);
|
||||||
|
void ExtendTouchBounds(const CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 7>& uids,
|
||||||
|
const zeus::CVector3f& vec) const;
|
||||||
|
bool ShouldFireFromLauncher(CStateManager& mgr, TUniqueId launcherId);
|
||||||
|
bool ShouldCallForBackupFromLauncher(const CStateManager& mgr, TUniqueId uid) const;
|
||||||
|
bool IsClosestEnergyAttractor(const CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 1024>& charNearList,
|
||||||
|
const zeus::CVector3f& projectilePos) const;
|
||||||
};
|
};
|
||||||
} // namespace urde::MP1
|
} // namespace urde
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
namespace urde::MP1 {
|
namespace urde::MP1 {
|
||||||
namespace {
|
namespace {
|
||||||
constexpr std::array<SBurst, 6> skBurst1{{
|
constexpr std::array<SBurst, 6> skBurstsFlying{{
|
||||||
{4, {3, 4, 11, 12, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{4, {3, 4, 11, 12, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
{20, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{20, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
{20, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{20, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
@ -30,7 +30,7 @@ constexpr std::array<SBurst, 6> skBurst1{{
|
|||||||
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
constexpr std::array<SBurst, 6> skBurst2{{
|
constexpr std::array<SBurst, 6> skBurstsFlyingOutOfView{{
|
||||||
{5, {3, 4, 8, 12, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{5, {3, 4, 8, 12, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
{10, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{10, {2, 3, 4, 5, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
{10, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f},
|
{10, {10, 11, 12, 13, -1, 0, 0, 0}, 0.1f, 0.05f},
|
||||||
@ -39,7 +39,7 @@ constexpr std::array<SBurst, 6> skBurst2{{
|
|||||||
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
constexpr std::array<SBurst, 5> skBurst3{{
|
constexpr std::array<SBurst, 5> skBurstsLanded{{
|
||||||
{30, {3, 4, 5, 11, 12, 4, -1, 0}, 0.1f, 0.05f},
|
{30, {3, 4, 5, 11, 12, 4, -1, 0}, 0.1f, 0.05f},
|
||||||
{20, {2, 3, 4, 5, 4, 3, -1, 0}, 0.1f, 0.05f},
|
{20, {2, 3, 4, 5, 4, 3, -1, 0}, 0.1f, 0.05f},
|
||||||
{20, {5, 4, 3, 13, 12, 11, -1, 0}, 0.1f, 0.05f},
|
{20, {5, 4, 3, 13, 12, 11, -1, 0}, 0.1f, 0.05f},
|
||||||
@ -47,7 +47,7 @@ constexpr std::array<SBurst, 5> skBurst3{{
|
|||||||
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
{0, {0, 0, 0, 0, 0, 0, 0, 0}, 0.000000, 0.000000},
|
||||||
}};
|
}};
|
||||||
|
|
||||||
constexpr std::array<SBurst, 5> skBurst4{{
|
constexpr std::array<SBurst, 5> skBurstsLandedOutOfView{{
|
||||||
{10, {6, 5, 4, 14, 13, 12, -1, 0}, 0.1f, 0.05f},
|
{10, {6, 5, 4, 14, 13, 12, -1, 0}, 0.1f, 0.05f},
|
||||||
{20, {14, 13, 12, 11, 10, 9, -1, 0}, 0.1f, 0.05f},
|
{20, {14, 13, 12, 11, 10, 9, -1, 0}, 0.1f, 0.05f},
|
||||||
{20, {14, 15, 16, 11, 10, 9, -1, 0}, 0.1f, 0.05f},
|
{20, {14, 15, 16, 11, 10, 9, -1, 0}, 0.1f, 0.05f},
|
||||||
@ -56,7 +56,11 @@ constexpr std::array<SBurst, 5> skBurst4{{
|
|||||||
}};
|
}};
|
||||||
|
|
||||||
constexpr std::array<const SBurst*, 5> skBursts{
|
constexpr std::array<const SBurst*, 5> skBursts{
|
||||||
skBurst1.data(), skBurst2.data(), skBurst3.data(), skBurst4.data(), nullptr,
|
skBurstsFlying.data(),
|
||||||
|
skBurstsFlyingOutOfView.data(),
|
||||||
|
skBurstsLanded.data(),
|
||||||
|
skBurstsLandedOutOfView.data(),
|
||||||
|
nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<std::string_view, 15> skParts{
|
constexpr std::array<std::string_view, 15> skParts{
|
||||||
|
335
Runtime/MP1/World/CGrenadeLauncher.cpp
Normal file
335
Runtime/MP1/World/CGrenadeLauncher.cpp
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
#include "Runtime/MP1/World/CGrenadeLauncher.hpp"
|
||||||
|
|
||||||
|
#include "Runtime/Character/CPASAnimParm.hpp"
|
||||||
|
#include "Runtime/Character/CPASAnimParmData.hpp"
|
||||||
|
#include "Runtime/CSimplePool.hpp"
|
||||||
|
#include "Runtime/CStateManager.hpp"
|
||||||
|
#include "Runtime/GameGlobalObjects.hpp"
|
||||||
|
#include "Runtime/Weapon/CGameProjectile.hpp"
|
||||||
|
#include "Runtime/World/CExplosion.hpp"
|
||||||
|
#include "Runtime/World/CPatterned.hpp"
|
||||||
|
#include "Runtime/World/CPlayer.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
CGrenadeLauncher::CGrenadeLauncher(TUniqueId uid, std::string_view name, const CEntityInfo& info,
|
||||||
|
const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& bounds,
|
||||||
|
const CHealthInfo& healthInfo, const CDamageVulnerability& vulnerability,
|
||||||
|
const CActorParameters& actParams, TUniqueId parentId,
|
||||||
|
const SGrenadeLauncherData& data, float f1)
|
||||||
|
: CPhysicsActor(uid, true, name, info, xf, std::move(mData), {EMaterialTypes::Character, EMaterialTypes::Solid}, bounds,
|
||||||
|
SMoverData{1000.f}, actParams, 0.3f, 0.1f)
|
||||||
|
, x25c_healthInfo(healthInfo)
|
||||||
|
, x264_vulnerability(vulnerability)
|
||||||
|
, x2cc_parentId(parentId)
|
||||||
|
, x2d0_data(data)
|
||||||
|
, x328_cSphere({{}, mData.GetScale().z()}, {EMaterialTypes::Character, EMaterialTypes::Solid})
|
||||||
|
, x350_grenadeActorParams(actParams)
|
||||||
|
, x3e8_thermalMag(actParams.GetThermalMag())
|
||||||
|
, x3f8_explodePlayerDistance(f1) {
|
||||||
|
if (data.GetExplosionGenDescId().IsValid()) {
|
||||||
|
x3b8_particleGenDesc = g_SimplePool->GetObj({SBIG('PART'), data.GetExplosionGenDescId()});
|
||||||
|
}
|
||||||
|
GetModelData()->EnableLooping(true);
|
||||||
|
const CPASDatabase& pasDatabase = GetModelData()->GetAnimationData()->GetCharacterInfo().GetPASDatabase();
|
||||||
|
for (int i = 0; i < x3c8_animIds.size(); ++i) {
|
||||||
|
const auto result = pasDatabase.FindBestAnimation(CPASAnimParmData{22, CPASAnimParm::FromEnum(i)}, -1);
|
||||||
|
x3c8_animIds[i] = result.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector3f CGrenadeLauncher::GrenadeTarget(const CStateManager& mgr) {
|
||||||
|
const zeus::CVector3f& aim = mgr.GetPlayer().GetAimPosition(mgr, 1.f);
|
||||||
|
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) {
|
||||||
|
return aim - zeus::CVector3f{0.f, 0.f, 0.5f * mgr.GetPlayer().GetEyeHeight()};
|
||||||
|
}
|
||||||
|
return aim;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::CalculateGrenadeTrajectory(const zeus::CVector3f& target, const zeus::CVector3f& origin,
|
||||||
|
const SGrenadeTrajectoryInfo& info, float& angleOut,
|
||||||
|
float& velocityOut) {
|
||||||
|
float angle = info.GetAngleMin();
|
||||||
|
float velocity = info.GetVelocityMin();
|
||||||
|
float delta = std::max(0.01f, 0.1f * (info.GetAngleMax() - info.GetAngleMin()));
|
||||||
|
zeus::CVector3f dist = target - origin;
|
||||||
|
float distXYMag = dist.toVec2f().magnitude();
|
||||||
|
float velocityMinSq = info.GetVelocityMin() * info.GetVelocityMin();
|
||||||
|
float velocityMaxSq = info.GetVelocityMax() * info.GetVelocityMax();
|
||||||
|
float gravAdj = distXYMag * ((0.5f * CPhysicsActor::GravityConstant()) * distXYMag);
|
||||||
|
float currAngle = info.GetAngleMin();
|
||||||
|
float leastResult = FLT_MAX;
|
||||||
|
while (info.GetAngleMax() >= currAngle) {
|
||||||
|
float cos = std::cos(currAngle);
|
||||||
|
float sin = std::sin(currAngle);
|
||||||
|
float result = (distXYMag * (cos * sin) - (dist.z() * (cos * cos)));
|
||||||
|
if (result > FLT_EPSILON) {
|
||||||
|
float div = gravAdj / result;
|
||||||
|
if (velocityMinSq <= result && result <= velocityMaxSq) {
|
||||||
|
angle = currAngle;
|
||||||
|
velocity = std::sqrt(div);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (result <= velocityMaxSq) {
|
||||||
|
result = velocityMinSq - result;
|
||||||
|
} else {
|
||||||
|
result = result - velocityMaxSq;
|
||||||
|
}
|
||||||
|
if (result < leastResult) {
|
||||||
|
angle = currAngle;
|
||||||
|
velocity = std::sqrt(div);
|
||||||
|
leastResult = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currAngle += delta;
|
||||||
|
}
|
||||||
|
angleOut = angle;
|
||||||
|
velocityOut = velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
|
||||||
|
CActor::AcceptScriptMsg(msg, uid, mgr);
|
||||||
|
switch (msg) {
|
||||||
|
case EScriptObjectMessage::Start:
|
||||||
|
if (x2cc_parentId == uid && x258_started != 1) {
|
||||||
|
x258_started = 1;
|
||||||
|
sub_80230438();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EScriptObjectMessage::Stop:
|
||||||
|
if (x2cc_parentId == uid && x258_started != 0) {
|
||||||
|
x258_started = 0;
|
||||||
|
sub_80230438();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EScriptObjectMessage::Action:
|
||||||
|
if (x2cc_parentId == uid && x258_started == 1) {
|
||||||
|
x3fc_launchGrenade = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case EScriptObjectMessage::Registered:
|
||||||
|
sub_80230438();
|
||||||
|
break;
|
||||||
|
case EScriptObjectMessage::Damage:
|
||||||
|
x3ec_damageTimer = 0.33f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
|
||||||
|
CActor::AddToRenderer(frustum, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<zeus::CAABox> CGrenadeLauncher::GetTouchBounds() const {
|
||||||
|
return x328_cSphere.CalculateAABox(GetTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) {
|
||||||
|
if (x3f4_color3.a() == 1.f) {
|
||||||
|
xb4_drawFlags = CModelFlags{2, 0, 3, zeus::skWhite};
|
||||||
|
// Original code redundantly sets a() = 1.f
|
||||||
|
xb4_drawFlags.addColor = x3f4_color3;
|
||||||
|
} else {
|
||||||
|
xb4_drawFlags = CModelFlags{5, 0, 3, zeus::skWhite};
|
||||||
|
xb4_drawFlags.addColor = x3f4_color3;
|
||||||
|
}
|
||||||
|
CActor::PreRender(mgr, frustum);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::Render(const CStateManager& mgr) const {
|
||||||
|
if (x3fd_visible) {
|
||||||
|
CPhysicsActor::Render(mgr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::Think(float dt, CStateManager& mgr) {
|
||||||
|
if (GetActive()) {
|
||||||
|
if (x3fc_launchGrenade) {
|
||||||
|
LaunchGrenade(mgr);
|
||||||
|
x3fc_launchGrenade = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateCollision();
|
||||||
|
UpdateColor(dt);
|
||||||
|
sub_8022f9e0(mgr, dt);
|
||||||
|
UpdateDamageTime(dt);
|
||||||
|
|
||||||
|
const SAdvancementDeltas& deltas = CActor::UpdateAnimation(dt, mgr, true);
|
||||||
|
MoveToOR(deltas.x0_posDelta, dt);
|
||||||
|
RotateToOR(deltas.xc_rotDelta, dt);
|
||||||
|
|
||||||
|
TCastToPtr<CPatterned> parent = mgr.ObjectById(x2cc_parentId);
|
||||||
|
if (parent == nullptr || !parent->IsAlive() || parent->HealthInfo(mgr)->GetHP() <= 0.f) {
|
||||||
|
mgr.SendScriptMsg(parent, GetUniqueId(), EScriptObjectMessage::Damage);
|
||||||
|
CreateExplosion(mgr);
|
||||||
|
mgr.FreeScriptObject(GetUniqueId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::Touch(CActor& act, CStateManager& mgr) {
|
||||||
|
if (TCastToPtr<CGameProjectile> projectile = act) {
|
||||||
|
if (projectile->GetOwnerId() == mgr.GetPlayer().GetUniqueId() &&
|
||||||
|
GetDamageVulnerability()->WeaponHurts(CWeaponMode{projectile->GetType()}, false)) {
|
||||||
|
x348_shotTimer = 0.5f;
|
||||||
|
CEntity* parent = mgr.ObjectById(x2cc_parentId);
|
||||||
|
if (parent != nullptr) {
|
||||||
|
mgr.SendScriptMsg(parent, GetUniqueId(), EScriptObjectMessage::Touched);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::UpdateCollision() {
|
||||||
|
x328_cSphere.SetSphereCenter(GetLocatorTransform("lockon_target_LCTR"sv).origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::UpdateColor(float arg) {
|
||||||
|
if (x348_shotTimer > 0.f) {
|
||||||
|
x348_shotTimer = std::max(0.f, x348_shotTimer - arg);
|
||||||
|
x34c_color1 = zeus::CColor::lerp(zeus::skWhite, zeus::skRed, x348_shotTimer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::UpdateDamageTime(float arg) {
|
||||||
|
if (x3ec_damageTimer <= 0.f) {
|
||||||
|
xd0_damageMag = x3e8_thermalMag;
|
||||||
|
} else {
|
||||||
|
x3ec_damageTimer = std::max(0.f, x3ec_damageTimer - arg);
|
||||||
|
x3f4_color3 = zeus::CColor::lerp(zeus::skBlack, x3f0_color2, std::clamp(x3ec_damageTimer / 0.33f, 0.f, 1.f));
|
||||||
|
xd0_damageMag = 5.f * x3ec_damageTimer + x3e8_thermalMag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::CreateExplosion(CStateManager& mgr) {
|
||||||
|
if (!x3b8_particleGenDesc) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mgr.AddObject(new CExplosion(*x3b8_particleGenDesc, mgr.AllocateUniqueId(), true,
|
||||||
|
{GetAreaIdAlways(), CEntity::NullConnectionList}, "Grenade Launcher Explode Fx"sv,
|
||||||
|
GetTransform(), 0, GetModelData()->GetScale(), zeus::skWhite));
|
||||||
|
CSfxManager::SfxStart(x2d0_data.GetExplosionSfx(), 1.f, 1.f, false, 0x7f, false, kInvalidAreaId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::sub_8022f9e0(CStateManager& mgr, float dt) {
|
||||||
|
CModelData* modelData = GetModelData();
|
||||||
|
CAnimData* animData = nullptr;
|
||||||
|
|
||||||
|
if (modelData != nullptr && (animData = modelData->GetAnimationData()) != nullptr && x258_started == 1 && x3fe_) {
|
||||||
|
const zeus::CVector3f& target = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetTranslation();
|
||||||
|
const zeus::CVector3f& rot = GetTransform().rotate({target.x(), target.y(), 0.f}); // TODO double check
|
||||||
|
|
||||||
|
if (rot.canBeNormalized()) {
|
||||||
|
constexpr float p36d = zeus::degToRad(36.476f);
|
||||||
|
constexpr float n45d = zeus::degToRad(-45.f);
|
||||||
|
constexpr float p45d = zeus::degToRad(45.f);
|
||||||
|
|
||||||
|
float l84 = p36d * std::clamp(std::atan2(rot.x(), rot.y()), n45d, p45d);
|
||||||
|
float l88 = std::clamp((0.25f * (l84 - x3d8_)) / dt, -3.f, 3.f);
|
||||||
|
float l8c = std::clamp((l88 - x3dc_) / dt, -10.f, 10.f);
|
||||||
|
x3dc_ += dt * l8c;
|
||||||
|
|
||||||
|
float l90 = p36d * std::clamp(std::atan2(rot.z(), rot.toVec2f().magnitude()), n45d, p45d);
|
||||||
|
l88 = std::clamp((0.25f * (l90 - x3e0_)) / dt, -3.f, 3.f);
|
||||||
|
l8c = std::clamp((l88 - x3e4_) / dt, -10.f, 10.f);
|
||||||
|
x3e4_ += dt * l8c;
|
||||||
|
|
||||||
|
float dVar7 = std::clamp(dt * x3dc_ + x3d8_, -0.5f, 0.5f);
|
||||||
|
float dVar8 = std::clamp(dt * x3e4_ + x3e0_, -0.5f, 0.5f);
|
||||||
|
|
||||||
|
if (dVar7 != x3d8_) {
|
||||||
|
if (std::abs(x3d8_) > 0.f && x3d8_ * dVar7 <= 0.f) {
|
||||||
|
animData->DelAdditiveAnimation(x3c8_animIds[x3d8_ >= 0.f ? 1 : 0]);
|
||||||
|
}
|
||||||
|
float weight = std::abs(dVar7);
|
||||||
|
if (weight > 0.f) {
|
||||||
|
animData->AddAdditiveAnimation(x3c8_animIds[dVar7 >= 0.f ? 1 : 0], weight, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dVar8 != x3e0_) {
|
||||||
|
if (std::abs(x3e0_) > 0.f && x3e0_ * dVar8 <= 0.f) {
|
||||||
|
animData->DelAdditiveAnimation(x3c8_animIds[x3e0_ <= 0.f ? 3 : 2]);
|
||||||
|
}
|
||||||
|
float weight = std::abs(dVar8);
|
||||||
|
if (weight > 0.f) {
|
||||||
|
animData->AddAdditiveAnimation(x3c8_animIds[dVar8 <= 0.f ? 3 : 2], weight, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x3d8_ = dVar7;
|
||||||
|
x3e0_ = dVar8;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (x3d8_ != 0.f) {
|
||||||
|
if (animData != nullptr) { // Original code does not check
|
||||||
|
animData->DelAdditiveAnimation(x3c8_animIds[x3d8_ >= 0.f ? 1 : 0]);
|
||||||
|
}
|
||||||
|
x3d8_ = 0.f;
|
||||||
|
}
|
||||||
|
if (x3e0_ != 0.f) {
|
||||||
|
if (animData != nullptr) { // Original code does not check
|
||||||
|
animData->DelAdditiveAnimation(x3c8_animIds[x3e0_ <= 0.f ? 3 : 2]);
|
||||||
|
}
|
||||||
|
x3e0_ = 0.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::sub_80230438() {
|
||||||
|
CModelData* modelData = GetModelData();
|
||||||
|
CAnimData* animData;
|
||||||
|
if (modelData == nullptr || (animData = modelData->GetAnimationData()) == nullptr || x258_started <= -1 ||
|
||||||
|
x258_started >= 2) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr std::array arr = {0, 3};
|
||||||
|
const auto& anim = animData->GetCharacterInfo().GetPASDatabase().FindBestAnimation(
|
||||||
|
CPASAnimParmData{5, CPASAnimParm::FromEnum(0), CPASAnimParm::FromEnum(arr[x258_started])}, -1);
|
||||||
|
if (anim.first > 0.f) {
|
||||||
|
animData->SetAnimation({anim.second, -1, 1.f, true}, false);
|
||||||
|
modelData->EnableLooping(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CGrenadeLauncher::LaunchGrenade(CStateManager& mgr) {
|
||||||
|
CModelData* modelData = GetModelData();
|
||||||
|
CAnimData* animData;
|
||||||
|
if (modelData == nullptr || (animData = modelData->GetAnimationData()) == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& anim = animData->GetCharacterInfo().GetPASDatabase().FindBestAnimation(CPASAnimParmData{23}, -1);
|
||||||
|
if (anim.first > 0.f) {
|
||||||
|
animData->AddAdditiveAnimation(anim.second, 1.f, false, true);
|
||||||
|
const zeus::CVector3f& origin =
|
||||||
|
GetTranslation() + GetTransform().rotate(GetLocatorTransform("grenade_LCTR"sv).origin);
|
||||||
|
const zeus::CVector3f& target = GrenadeTarget(mgr);
|
||||||
|
float angleOut = x2d0_data.GetGrenadeTrajectoryInfo().GetAngleMin();
|
||||||
|
float velocityOut = x2d0_data.GetGrenadeTrajectoryInfo().GetVelocityMin();
|
||||||
|
CalculateGrenadeTrajectory(target, origin, x2d0_data.GetGrenadeTrajectoryInfo(), angleOut, velocityOut);
|
||||||
|
|
||||||
|
zeus::CVector3f dist = target - origin;
|
||||||
|
dist.z() = 0.f;
|
||||||
|
const zeus::CVector3f& front = GetTransform().frontVector();
|
||||||
|
if (dist.canBeNormalized()) {
|
||||||
|
dist.normalize();
|
||||||
|
} else {
|
||||||
|
dist = front;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr float maxAngle = zeus::degToRad(45.f);
|
||||||
|
if (zeus::CVector3f::getAngleDiff(front, dist) > maxAngle) {
|
||||||
|
dist = zeus::CVector3f::slerp(front, dist, maxAngle);
|
||||||
|
}
|
||||||
|
|
||||||
|
const zeus::CVector3f& look = zeus::CVector3f::slerp(dist, zeus::skUp, angleOut);
|
||||||
|
const zeus::CTransform& xf = zeus::lookAt(origin, origin + look, zeus::skUp);
|
||||||
|
CModelData mData{CStaticRes{x2d0_data.GetGrenadeModelId(), GetModelData()->GetScale()}};
|
||||||
|
mgr.AddObject(new CBouncyGrenade(mgr.AllocateUniqueId(), "Bouncy Grenade"sv,
|
||||||
|
{GetAreaIdAlways(), CEntity::NullConnectionList}, xf, std::move(mData),
|
||||||
|
x350_grenadeActorParams, x2cc_parentId, x2d0_data.GetGrenadeData(), velocityOut,
|
||||||
|
x3f8_explodePlayerDistance));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace urde::MP1
|
124
Runtime/MP1/World/CGrenadeLauncher.hpp
Normal file
124
Runtime/MP1/World/CGrenadeLauncher.hpp
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Runtime/Character/CModelData.hpp"
|
||||||
|
#include "Runtime/Collision/CCollidableSphere.hpp"
|
||||||
|
#include "Runtime/MP1/World/CBouncyGrenade.hpp"
|
||||||
|
#include "Runtime/Particle/CGenDescription.hpp"
|
||||||
|
#include "Runtime/World/CActorParameters.hpp"
|
||||||
|
#include "Runtime/World/CDamageInfo.hpp"
|
||||||
|
#include "Runtime/World/CDamageVulnerability.hpp"
|
||||||
|
#include "Runtime/World/CEntityInfo.hpp"
|
||||||
|
#include "Runtime/World/CHealthInfo.hpp"
|
||||||
|
#include "Runtime/World/CPhysicsActor.hpp"
|
||||||
|
|
||||||
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
#include <string_view>
|
||||||
|
#include <zeus/CColor.hpp>
|
||||||
|
#include <zeus/CTransform.hpp>
|
||||||
|
#include <zeus/CQuaternion.hpp>
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
struct SGrenadeTrajectoryInfo {
|
||||||
|
private:
|
||||||
|
float x0_velocityMin;
|
||||||
|
float x4_velocityMax;
|
||||||
|
float x8_angleMin;
|
||||||
|
float xc_angleMax;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SGrenadeTrajectoryInfo(CInputStream& in)
|
||||||
|
: x0_velocityMin(in.readFloatBig())
|
||||||
|
, x4_velocityMax(in.readFloatBig())
|
||||||
|
, x8_angleMin(zeus::degToRad(in.readFloatBig()))
|
||||||
|
, xc_angleMax(zeus::degToRad(in.readFloatBig())) {}
|
||||||
|
|
||||||
|
[[nodiscard]] float GetVelocityMin() const { return x0_velocityMin; }
|
||||||
|
[[nodiscard]] float GetVelocityMax() const { return x4_velocityMax; }
|
||||||
|
[[nodiscard]] float GetAngleMin() const { return x8_angleMin; }
|
||||||
|
[[nodiscard]] float GetAngleMax() const { return xc_angleMax; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SGrenadeLauncherData {
|
||||||
|
private:
|
||||||
|
SBouncyGrenadeData x0_grenadeData;
|
||||||
|
CAssetId x3c_grenadeCmdl;
|
||||||
|
CAssetId x40_launcherExplodeGenDesc;
|
||||||
|
u16 x44_launcherExplodeSfx;
|
||||||
|
SGrenadeTrajectoryInfo x48_trajectoryInfo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SGrenadeLauncherData(const SBouncyGrenadeData& data, CAssetId w1, CAssetId w2, u16 sfx,
|
||||||
|
const SGrenadeTrajectoryInfo& trajectoryInfo)
|
||||||
|
: x0_grenadeData(data)
|
||||||
|
, x3c_grenadeCmdl(w1)
|
||||||
|
, x40_launcherExplodeGenDesc(w2)
|
||||||
|
, x44_launcherExplodeSfx(sfx)
|
||||||
|
, x48_trajectoryInfo(trajectoryInfo){};
|
||||||
|
|
||||||
|
[[nodiscard]] const SBouncyGrenadeData& GetGrenadeData() const { return x0_grenadeData; }
|
||||||
|
[[nodiscard]] CAssetId GetGrenadeModelId() const { return x3c_grenadeCmdl; }
|
||||||
|
[[nodiscard]] CAssetId GetExplosionGenDescId() const { return x40_launcherExplodeGenDesc; }
|
||||||
|
[[nodiscard]] u16 GetExplosionSfx() const { return x44_launcherExplodeSfx; }
|
||||||
|
[[nodiscard]] const SGrenadeTrajectoryInfo& GetGrenadeTrajectoryInfo() const { return x48_trajectoryInfo; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CGrenadeLauncher : public CPhysicsActor {
|
||||||
|
private:
|
||||||
|
int x258_started = 0;
|
||||||
|
CHealthInfo x25c_healthInfo;
|
||||||
|
CDamageVulnerability x264_vulnerability;
|
||||||
|
TUniqueId x2cc_parentId;
|
||||||
|
SGrenadeLauncherData x2d0_data;
|
||||||
|
CCollidableSphere x328_cSphere;
|
||||||
|
float x348_shotTimer = -1.f;
|
||||||
|
zeus::CColor x34c_color1{1.f};
|
||||||
|
CActorParameters x350_grenadeActorParams;
|
||||||
|
std::optional<TLockedToken<CGenDescription>> x3b8_particleGenDesc;
|
||||||
|
std::array<s32, 4> x3c8_animIds{};
|
||||||
|
float x3d8_ = 0.f;
|
||||||
|
float x3dc_ = 0.f;
|
||||||
|
float x3e0_ = 0.f;
|
||||||
|
float x3e4_ = 0.f;
|
||||||
|
float x3e8_thermalMag;
|
||||||
|
float x3ec_damageTimer = 0.f;
|
||||||
|
zeus::CColor x3f0_color2{0.5f, 0.f, 0.f};
|
||||||
|
zeus::CColor x3f4_color3{0.f};
|
||||||
|
float x3f8_explodePlayerDistance;
|
||||||
|
bool x3fc_launchGrenade = false;
|
||||||
|
bool x3fd_visible = true;
|
||||||
|
bool x3fe_ = true;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CGrenadeLauncher(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
CModelData&& mData, const zeus::CAABox& bounds, const CHealthInfo& healthInfo,
|
||||||
|
const CDamageVulnerability& vulnerability, const CActorParameters& actParams, TUniqueId parentId,
|
||||||
|
const SGrenadeLauncherData& data, float f1);
|
||||||
|
|
||||||
|
void Accept(IVisitor& visitor) override { visitor.Visit(this); }
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
|
||||||
|
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override;
|
||||||
|
[[nodiscard]] const CCollisionPrimitive* GetCollisionPrimitive() const override { return &x328_cSphere; }
|
||||||
|
[[nodiscard]] const CDamageVulnerability* GetDamageVulnerability() const override { return &x264_vulnerability; }
|
||||||
|
[[nodiscard]] std::optional<zeus::CAABox> GetTouchBounds() const override;
|
||||||
|
CHealthInfo* HealthInfo(CStateManager& mgr) override { return &x25c_healthInfo; }
|
||||||
|
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
|
||||||
|
void Render(const CStateManager& mgr) const override;
|
||||||
|
void Think(float dt, CStateManager& mgr) override;
|
||||||
|
void Touch(CActor& act, CStateManager& mgr) override;
|
||||||
|
|
||||||
|
static zeus::CVector3f GrenadeTarget(const CStateManager& mgr);
|
||||||
|
static void CalculateGrenadeTrajectory(const zeus::CVector3f& target, const zeus::CVector3f& origin,
|
||||||
|
const SGrenadeTrajectoryInfo& info, float& angleOut, float& velocityOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void UpdateCollision();
|
||||||
|
void UpdateColor(float arg);
|
||||||
|
void UpdateDamageTime(float arg);
|
||||||
|
void CreateExplosion(CStateManager& mgr);
|
||||||
|
void sub_8022f9e0(CStateManager& mgr, float dt);
|
||||||
|
void sub_80230438();
|
||||||
|
void LaunchGrenade(CStateManager& mgr);
|
||||||
|
};
|
||||||
|
} // namespace urde::MP1
|
@ -1,42 +1,47 @@
|
|||||||
set(MP1_WORLD_SOURCES
|
set(MP1_WORLD_SOURCES
|
||||||
CNewIntroBoss.hpp CNewIntroBoss.cpp
|
CActorContraption.hpp CActorContraption.cpp
|
||||||
CBeetle.hpp CBeetle.cpp
|
|
||||||
CWarWasp.hpp CWarWasp.cpp
|
|
||||||
CElitePirate.hpp CElitePirate.cpp
|
|
||||||
CBloodFlower.hpp CBloodFlower.cpp
|
|
||||||
CChozoGhost.hpp CChozoGhost.cpp
|
|
||||||
CSpacePirate.hpp CSpacePirate.cpp
|
|
||||||
CParasite.hpp CParasite.cpp
|
|
||||||
CBabygoth.hpp CBabygoth.cpp
|
|
||||||
CTryclops.hpp CTryclops.cpp
|
|
||||||
CFireFlea.hpp CFireFlea.cpp
|
|
||||||
CEnergyBall.hpp CEnergyBall.cpp
|
|
||||||
CEyeball.hpp CEyeball.cpp
|
|
||||||
CAtomicAlpha.hpp CAtomicAlpha.cpp
|
CAtomicAlpha.hpp CAtomicAlpha.cpp
|
||||||
CAtomicBeta.hpp CAtomicBeta.cpp
|
CAtomicBeta.hpp CAtomicBeta.cpp
|
||||||
|
CBabygoth.hpp CBabygoth.cpp
|
||||||
|
CBeetle.hpp CBeetle.cpp
|
||||||
|
CBloodFlower.hpp CBloodFlower.cpp
|
||||||
|
CBouncyGrenade.hpp CBouncyGrenade.cpp
|
||||||
|
CBurrower.hpp CBurrower.cpp
|
||||||
|
CChozoGhost.hpp CChozoGhost.cpp
|
||||||
|
CElitePirate.hpp CElitePirate.cpp
|
||||||
|
CEnergyBall.hpp CEnergyBall.cpp
|
||||||
|
CEyeball.hpp CEyeball.cpp
|
||||||
|
CFireFlea.hpp CFireFlea.cpp
|
||||||
|
CFlaahgra.hpp CFlaahgra.cpp
|
||||||
|
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp
|
||||||
|
CFlaahgraTentacle.hpp CFlaahgraTentacle.cpp
|
||||||
CFlickerBat.hpp CFlickerBat.cpp
|
CFlickerBat.hpp CFlickerBat.cpp
|
||||||
CJellyZap.hpp CJellyZap.cpp
|
|
||||||
CFlyingPirate.hpp CFlyingPirate.cpp
|
CFlyingPirate.hpp CFlyingPirate.cpp
|
||||||
CMetroidPrimeRelay.hpp CMetroidPrimeRelay.cpp
|
CGrenadeLauncher.hpp CGrenadeLauncher.cpp
|
||||||
|
CJellyZap.hpp CJellyZap.cpp
|
||||||
|
CMagdolite.hpp CMagdolite.cpp
|
||||||
|
CMetaree.hpp CMetaree.cpp
|
||||||
|
CMetroid.hpp CMetroid.cpp
|
||||||
|
CMetroidBeta.hpp CMetroidBeta.cpp
|
||||||
CMetroidPrimeExo.hpp CMetroidPrimeExo.cpp
|
CMetroidPrimeExo.hpp CMetroidPrimeExo.cpp
|
||||||
CMetroidPrimeProjectile.hpp CMetroidPrimeProjectile.cpp
|
CMetroidPrimeProjectile.hpp CMetroidPrimeProjectile.cpp
|
||||||
CActorContraption.hpp CActorContraption.cpp
|
CMetroidPrimeRelay.hpp CMetroidPrimeRelay.cpp
|
||||||
CThardusRockProjectile.hpp CThardusRockProjectile.cpp
|
CNewIntroBoss.hpp CNewIntroBoss.cpp
|
||||||
CMetroidBeta.hpp CMetroidBeta.cpp
|
COmegaPirate.hpp COmegaPirate.cpp
|
||||||
CMetroid.hpp CMetroid.cpp
|
CParasite.hpp CParasite.cpp
|
||||||
CMetaree.hpp CMetaree.cpp
|
|
||||||
CBurrower.hpp CBurrower.cpp
|
|
||||||
CPuffer.hpp CPuffer.cpp
|
|
||||||
CMagdolite.hpp CMagdolite.cpp
|
|
||||||
CSeedling.hpp CSeedling.cpp
|
|
||||||
CRidley.hpp CRidley.cpp
|
|
||||||
CPuddleToadGamma.hpp CPuddleToadGamma.cpp
|
|
||||||
CFlaahgra.hpp CFlaahgra.cpp
|
|
||||||
CFlaahgraTentacle.hpp CFlaahgraTentacle.cpp
|
|
||||||
CFlaahgraProjectile.hpp CFlaahgraProjectile.cpp
|
|
||||||
CSpankWeed.hpp CSpankWeed.cpp
|
|
||||||
CPuddleSpore.hpp CPuddleSpore.cpp
|
CPuddleSpore.hpp CPuddleSpore.cpp
|
||||||
|
CPuddleToadGamma.hpp CPuddleToadGamma.cpp
|
||||||
|
CPuffer.hpp CPuffer.cpp
|
||||||
|
CRidley.hpp CRidley.cpp
|
||||||
CRipper.hpp CRipper.cpp
|
CRipper.hpp CRipper.cpp
|
||||||
CThardus.hpp CThardus.cpp)
|
CSeedling.hpp CSeedling.cpp
|
||||||
|
CShockWave.hpp CShockWave.cpp
|
||||||
|
CSpacePirate.hpp CSpacePirate.cpp
|
||||||
|
CSpankWeed.hpp CSpankWeed.cpp
|
||||||
|
CThardus.hpp CThardus.cpp
|
||||||
|
CThardusRockProjectile.hpp CThardusRockProjectile.cpp
|
||||||
|
CTryclops.hpp CTryclops.cpp
|
||||||
|
CWarWasp.hpp CWarWasp.cpp
|
||||||
|
)
|
||||||
|
|
||||||
runtime_add_list(World MP1_WORLD_SOURCES)
|
runtime_add_list(World MP1_WORLD_SOURCES)
|
||||||
|
12
Runtime/MP1/World/COmegaPirate.cpp
Normal file
12
Runtime/MP1/World/COmegaPirate.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "Runtime/MP1/World/COmegaPirate.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
COmegaPirate::CFlash::CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, CToken& p4, float p5)
|
||||||
|
: CActor(uid, true, "Omega Pirate Flash", info, zeus::CTransform::Translate(pos), CModelData::CModelDataNull(), {},
|
||||||
|
CActorParameters::None(), kInvalidUniqueId) {}
|
||||||
|
|
||||||
|
COmegaPirate::COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
|
||||||
|
CElitePirateData data, CAssetId w1, CAssetId w2, CAssetId w3)
|
||||||
|
: CElitePirate(uid, name, info, xf, std::move(mData), pInfo, actParms, data) {}
|
||||||
|
} // namespace urde::MP1
|
24
Runtime/MP1/World/COmegaPirate.hpp
Normal file
24
Runtime/MP1/World/COmegaPirate.hpp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Runtime/MP1/World/CElitePirate.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
class COmegaPirate : public CElitePirate {
|
||||||
|
private:
|
||||||
|
class CFlash : public CActor {
|
||||||
|
private:
|
||||||
|
CToken xe8_;
|
||||||
|
int xf0_;
|
||||||
|
float xf4_;
|
||||||
|
float xf8_;
|
||||||
|
float xfc_;
|
||||||
|
|
||||||
|
CFlash(TUniqueId uid, const CEntityInfo& info, const zeus::CVector3f& pos, CToken& p4, float p5);
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
COmegaPirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CElitePirateData data,
|
||||||
|
CAssetId w1, CAssetId w2, CAssetId w3);
|
||||||
|
};
|
||||||
|
} // namespace urde::MP1
|
177
Runtime/MP1/World/CShockWave.cpp
Normal file
177
Runtime/MP1/World/CShockWave.cpp
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
#include "Runtime/MP1/World/CShockWave.hpp"
|
||||||
|
|
||||||
|
#include "Runtime/Collision/CCollisionActor.hpp"
|
||||||
|
#include "Runtime/CSimplePool.hpp"
|
||||||
|
#include "Runtime/CStateManager.hpp"
|
||||||
|
#include "Runtime/GameGlobalObjects.hpp"
|
||||||
|
#include "Runtime/Graphics/CBooRenderer.hpp"
|
||||||
|
#include "Runtime/World/CActorParameters.hpp"
|
||||||
|
#include "Runtime/World/CGameLight.hpp"
|
||||||
|
#include "Runtime/World/CHUDBillboardEffect.hpp"
|
||||||
|
#include "Runtime/World/CPlayer.hpp"
|
||||||
|
|
||||||
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
CShockWave::CShockWave(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
TUniqueId parent, const SShockWaveData& data, float minActiveTime, float knockback)
|
||||||
|
: CActor(uid, true, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::Projectile},
|
||||||
|
CActorParameters::None(), kInvalidUniqueId)
|
||||||
|
, xe8_id1(parent)
|
||||||
|
, xec_damageInfo(data.GetDamageInfo())
|
||||||
|
, x108_elementGenDesc(g_SimplePool->GetObj({SBIG('PART'), data.GetParticleDescId()}))
|
||||||
|
, x110_elementGen(std::make_unique<CElementGen>(x108_elementGenDesc))
|
||||||
|
, x114_data(data)
|
||||||
|
, x150_(data.GetX24())
|
||||||
|
, x154_(data.GetX2C())
|
||||||
|
, x15c_minActiveTime(minActiveTime)
|
||||||
|
, x160_knockback(knockback) {
|
||||||
|
if (data.GetWeaponDescId().IsValid()) {
|
||||||
|
x974_electricDesc = g_SimplePool->GetObj({SBIG('ELSC'), data.GetWeaponDescId()});
|
||||||
|
}
|
||||||
|
x110_elementGen->SetParticleEmission(true);
|
||||||
|
x110_elementGen->SetOrientation(GetTransform().getRotation());
|
||||||
|
x110_elementGen->SetGlobalTranslation(GetTranslation());
|
||||||
|
xe6_27_thermalVisorFlags = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShockWave::Accept(IVisitor& visitor) { visitor.Visit(this); }
|
||||||
|
|
||||||
|
void CShockWave::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
|
||||||
|
if (msg == EScriptObjectMessage::Registered) {
|
||||||
|
if (x110_elementGen->SystemHasLight()) {
|
||||||
|
x980_id2 = mgr.AllocateUniqueId();
|
||||||
|
mgr.AddObject(new CGameLight(x980_id2, GetAreaIdAlways(), GetActive(), "ShockWaveLight_" + x10_name,
|
||||||
|
GetTransform(), GetUniqueId(), x110_elementGen->GetLight(),
|
||||||
|
x114_data.GetParticleDescId().Value(), 1, 0.f));
|
||||||
|
}
|
||||||
|
} else if (msg == EScriptObjectMessage::Deleted) {
|
||||||
|
mgr.FreeScriptObject(x980_id2);
|
||||||
|
x980_id2 = kInvalidUniqueId;
|
||||||
|
}
|
||||||
|
CActor::AcceptScriptMsg(msg, uid, mgr);
|
||||||
|
mgr.SendScriptMsgAlways(x980_id2, uid, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShockWave::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
|
||||||
|
CActor::AddToRenderer(frustum, mgr);
|
||||||
|
g_Renderer->AddParticleGen(*x110_elementGen);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<zeus::CAABox> CShockWave::GetTouchBounds() const {
|
||||||
|
if (x150_ <= 0.f) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return zeus::CAABox({-x150_, -x150_, 0.f}, {x150_, x150_, 1.f}).getTransformedAABox(GetTransform());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShockWave::Render(const CStateManager& mgr) const {
|
||||||
|
CActor::Render(mgr);
|
||||||
|
x110_elementGen->Render();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShockWave::Think(float dt, CStateManager& mgr) {
|
||||||
|
if (GetActive()) {
|
||||||
|
x110_elementGen->Update(dt);
|
||||||
|
x158_activeTime += dt;
|
||||||
|
x150_ += x154_ * dt;
|
||||||
|
x154_ += dt * x114_data.GetX30();
|
||||||
|
x110_elementGen->SetExternalVar(0, x150_);
|
||||||
|
for (int i = 0; i < x110_elementGen->GetNumActiveChildParticles(); ++i) {
|
||||||
|
auto& particle = static_cast<CElementGen&>(x110_elementGen->GetActiveChildParticle(i));
|
||||||
|
if (particle.Get4CharId() == SBIG('PART')) {
|
||||||
|
particle.SetExternalVar(0, x150_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x16c_hitPlayerInAir) {
|
||||||
|
x164_timeSinceHitPlayerInAir += dt;
|
||||||
|
x16c_hitPlayerInAir = false;
|
||||||
|
}
|
||||||
|
if (x16d_hitPlayer) {
|
||||||
|
x168_timeSinceHitPlayer += dt;
|
||||||
|
x16d_hitPlayer = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x110_elementGen->IsSystemDeletable() && x15c_minActiveTime > 0.f && x158_activeTime >= x15c_minActiveTime) {
|
||||||
|
mgr.FreeScriptObject(GetUniqueId());
|
||||||
|
} else if (x980_id2 != kInvalidUniqueId) {
|
||||||
|
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x980_id2)) {
|
||||||
|
if (light->GetActive()) {
|
||||||
|
light->SetLight(x110_elementGen->GetLight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CShockWave::Touch(CActor& actor, CStateManager& mgr) {
|
||||||
|
if (x158_activeTime >= x15c_minActiveTime) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isParent = xe8_id1 == actor.GetUniqueId();
|
||||||
|
if (TCastToConstPtr<CCollisionActor> cactor = mgr.GetObjectById(actor.GetUniqueId())) {
|
||||||
|
isParent = xe8_id1 == cactor->GetOwnerId();
|
||||||
|
}
|
||||||
|
if (isParent) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float mmax = x150_ * x150_;
|
||||||
|
float mmin = mmax * x114_data.GetX28() * x114_data.GetX28();
|
||||||
|
zeus::CVector3f dist = actor.GetTranslation() - GetTranslation();
|
||||||
|
CDamageInfo damageInfo = xec_damageInfo;
|
||||||
|
float knockBackScale = std::max(0.f, 1.f - x160_knockback * x158_activeTime);
|
||||||
|
bool isPlayer = mgr.GetPlayer().GetUniqueId() == actor.GetUniqueId();
|
||||||
|
bool isPlayerInAir = isPlayer && mgr.GetPlayer().GetPlayerMovementState() != CPlayer::EPlayerMovementState::OnGround;
|
||||||
|
float distXYMag = dist.toVec2f().magSquared();
|
||||||
|
if (distXYMag < mmin || distXYMag > mmax) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlayer) {
|
||||||
|
if (mgr.GetPlayer().GetPlayerMovementState() == CPlayer::EPlayerMovementState::OnGround) {
|
||||||
|
const zeus::CTransform& playerTransform = mgr.GetPlayer().GetTransform();
|
||||||
|
zeus::CVector3f playerDir = GetTranslation() - playerTransform.origin;
|
||||||
|
if (playerDir.canBeNormalized()) {
|
||||||
|
playerDir.normalize();
|
||||||
|
float dot = std::abs(playerDir.dot(playerTransform.frontVector()));
|
||||||
|
knockBackScale = std::max(0.12f, 0.88f * dot * dot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mgr.GetPlayer().GetVelocity().magnitude() > 40.f) {
|
||||||
|
x168_timeSinceHitPlayer = 0.2666f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
damageInfo.SetKnockBackPower(knockBackScale * damageInfo.GetKnockBackPower());
|
||||||
|
|
||||||
|
if (isPlayer && (x164_timeSinceHitPlayerInAir >= 0.1333f || x168_timeSinceHitPlayer >= 0.2666f)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!IsHit(actor.GetUniqueId())) {
|
||||||
|
mgr.ApplyDamage(GetUniqueId(), actor.GetUniqueId(), GetUniqueId(), damageInfo,
|
||||||
|
CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), zeus::skZero3f);
|
||||||
|
if (isPlayer && x974_electricDesc) {
|
||||||
|
mgr.AddObject(new CHUDBillboardEffect(std::nullopt, x974_electricDesc, mgr.AllocateUniqueId(), true,
|
||||||
|
"VisorElectricFx", CHUDBillboardEffect::GetNearClipDistance(mgr),
|
||||||
|
CHUDBillboardEffect::GetScaleForPOV(mgr), zeus::skWhite, zeus::skOne3f,
|
||||||
|
zeus::skZero3f));
|
||||||
|
CSfxManager::SfxStart(x114_data.GetElectrocuteSfx(), 1.f, 1.f, false, 0x7f, false, kInvalidAreaId);
|
||||||
|
}
|
||||||
|
x170_hitIds.push_back(actor.GetUniqueId());
|
||||||
|
} else {
|
||||||
|
damageInfo.SetDamage(0.f);
|
||||||
|
mgr.ApplyDamage(GetUniqueId(), actor.GetUniqueId(), GetUniqueId(), damageInfo,
|
||||||
|
CMaterialFilter::MakeInclude({EMaterialTypes::Solid}), zeus::skZero3f);
|
||||||
|
}
|
||||||
|
if (isPlayerInAir) {
|
||||||
|
x16c_hitPlayerInAir = true;
|
||||||
|
}
|
||||||
|
if (isPlayer) {
|
||||||
|
x16d_hitPlayer = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CShockWave::IsHit(TUniqueId id) const {
|
||||||
|
return std::find(x170_hitIds.begin(), x170_hitIds.end(), id) != x170_hitIds.end();
|
||||||
|
}
|
||||||
|
} // namespace urde::MP1
|
69
Runtime/MP1/World/CShockWave.hpp
Normal file
69
Runtime/MP1/World/CShockWave.hpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Runtime/World/CActor.hpp"
|
||||||
|
#include "Runtime/World/CDamageInfo.hpp"
|
||||||
|
#include "Runtime/Particle/CElementGen.hpp"
|
||||||
|
|
||||||
|
namespace urde::MP1 {
|
||||||
|
struct SShockWaveData {
|
||||||
|
private:
|
||||||
|
u32 x0_ = 8;
|
||||||
|
CAssetId x4_particleDesc;
|
||||||
|
CDamageInfo x8_damageInfo;
|
||||||
|
float x24_ = 0.f;
|
||||||
|
float x28_ = 0.5f;
|
||||||
|
float x2c_ = 16.5217f;
|
||||||
|
float x30_ = 0.f;
|
||||||
|
CAssetId x34_weaponDesc;
|
||||||
|
u16 x38_electrocuteSfx;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SShockWaveData(CAssetId part, const CDamageInfo& dInfo, CAssetId weapon, u16 sfx)
|
||||||
|
: x4_particleDesc(part), x8_damageInfo(dInfo), x34_weaponDesc(weapon), x38_electrocuteSfx(sfx) {}
|
||||||
|
|
||||||
|
[[nodiscard]] CAssetId GetParticleDescId() const { return x4_particleDesc; }
|
||||||
|
[[nodiscard]] const CDamageInfo& GetDamageInfo() const { return x8_damageInfo; }
|
||||||
|
[[nodiscard]] float GetX24() const { return x24_; }
|
||||||
|
[[nodiscard]] float GetX28() const { return x28_; }
|
||||||
|
[[nodiscard]] float GetX2C() const { return x2c_; }
|
||||||
|
[[nodiscard]] float GetX30() const { return x30_; }
|
||||||
|
[[nodiscard]] CAssetId GetWeaponDescId() const { return x34_weaponDesc; }
|
||||||
|
[[nodiscard]] u16 GetElectrocuteSfx() const { return x38_electrocuteSfx; }
|
||||||
|
};
|
||||||
|
|
||||||
|
class CShockWave : public CActor {
|
||||||
|
private:
|
||||||
|
TUniqueId xe8_id1;
|
||||||
|
CDamageInfo xec_damageInfo;
|
||||||
|
TToken<CGenDescription> x108_elementGenDesc;
|
||||||
|
std::unique_ptr<CElementGen> x110_elementGen;
|
||||||
|
SShockWaveData x114_data;
|
||||||
|
float x150_;
|
||||||
|
float x154_;
|
||||||
|
float x158_activeTime = 0.f;
|
||||||
|
float x15c_minActiveTime;
|
||||||
|
float x160_knockback;
|
||||||
|
float x164_timeSinceHitPlayerInAir = 0.f;
|
||||||
|
float x168_timeSinceHitPlayer = 0.f;
|
||||||
|
bool x16c_hitPlayerInAir = false;
|
||||||
|
bool x16d_hitPlayer = false;
|
||||||
|
rstl::reserved_vector<TUniqueId, 1024> x170_hitIds;
|
||||||
|
std::optional<TToken<CElectricDescription>> x974_electricDesc;
|
||||||
|
TUniqueId x980_id2 = kInvalidUniqueId;
|
||||||
|
|
||||||
|
public:
|
||||||
|
CShockWave(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
|
||||||
|
TUniqueId parent, const SShockWaveData& data, float minActiveTime, float knockback);
|
||||||
|
|
||||||
|
void Accept(IVisitor& visitor) override;
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
|
||||||
|
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override;
|
||||||
|
[[nodiscard]] std::optional<zeus::CAABox> GetTouchBounds() const override;
|
||||||
|
void Render(const CStateManager& mgr) const override;
|
||||||
|
void Think(float dt, CStateManager& mgr) override;
|
||||||
|
void Touch(CActor& actor, CStateManager& mgr) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
[[nodiscard]] bool IsHit(TUniqueId id) const;
|
||||||
|
};
|
||||||
|
} // namespace urde::MP1
|
@ -25,7 +25,8 @@ CGameProjectile::CGameProjectile(bool active, const TToken<CWeaponDescription>&
|
|||||||
CMaterialFilter::MakeIncludeExclude(
|
CMaterialFilter::MakeIncludeExclude(
|
||||||
{EMaterialTypes::Solid, EMaterialTypes::NonSolidDamageable},
|
{EMaterialTypes::Solid, EMaterialTypes::NonSolidDamageable},
|
||||||
{EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, excludeMat}),
|
{EMaterialTypes::Projectile, EMaterialTypes::ProjectilePassthrough, excludeMat}),
|
||||||
CMaterialList(), dInfo, attribs | GetBeamAttribType(wType), CModelData::CModelDataNull())
|
CMaterialList(EMaterialTypes::Projectile), dInfo, attribs | GetBeamAttribType(wType),
|
||||||
|
CModelData::CModelDataNull())
|
||||||
, x158_visorParticle(visorParticle)
|
, x158_visorParticle(visorParticle)
|
||||||
, x168_visorSfx(visorSfx)
|
, x168_visorSfx(visorSfx)
|
||||||
, x170_projectile(wDesc, xf.origin, xf.basis, scale,
|
, x170_projectile(wDesc, xf.origin, xf.basis, scale,
|
||||||
|
@ -17,14 +17,14 @@ const CDamageVulnerability CDamageVulnerability::sImmuneVulnerability(
|
|||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
|
||||||
/* LOL, thanks retro */
|
|
||||||
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
|
const CDamageVulnerability CDamageVulnerability::sReflectVulnerability(
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect,
|
||||||
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::None);
|
EVulnerability::Deflect, EVulnerability::Deflect, EVulnerability::Deflect, EDeflectType::One);
|
||||||
|
|
||||||
const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
|
const CDamageVulnerability CDamageVulnerability::sPassThroughVulnerability(
|
||||||
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
|
EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough, EVulnerability::PassThrough,
|
||||||
|
@ -14,6 +14,7 @@ class CPathFindSearch;
|
|||||||
|
|
||||||
class CPathFindVisualizer {
|
class CPathFindVisualizer {
|
||||||
CLineRenderer m_spline = {CLineRenderer::EPrimitiveMode::LineStrip, 16, {}, true};
|
CLineRenderer m_spline = {CLineRenderer::EPrimitiveMode::LineStrip, 16, {}, true};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Draw(const CPathFindSearch& path);
|
void Draw(const CPathFindSearch& path);
|
||||||
};
|
};
|
||||||
@ -56,6 +57,8 @@ public:
|
|||||||
void SetArea(CPFArea* area) { x0_area = area; }
|
void SetArea(CPFArea* area) { x0_area = area; }
|
||||||
float GetCharacterHeight() const { return xd0_chHeight; }
|
float GetCharacterHeight() const { return xd0_chHeight; }
|
||||||
void SetCharacterHeight(float h) { xd0_chHeight = h; }
|
void SetCharacterHeight(float h) { xd0_chHeight = h; }
|
||||||
|
float GetCharacterRadius() const { return xd4_chRadius; }
|
||||||
|
void SetCharacterRadius(float r) { xd4_chRadius = r; }
|
||||||
void SetPadding(float padding) { xd8_padding = padding; }
|
void SetPadding(float padding) { xd8_padding = padding; }
|
||||||
float RemainingPathDistance(const zeus::CVector3f& pos) const;
|
float RemainingPathDistance(const zeus::CVector3f& pos) const;
|
||||||
void DebugDraw() const;
|
void DebugDraw() const;
|
||||||
|
@ -134,7 +134,7 @@ protected:
|
|||||||
bool x328_28_prevOnGround : 1;
|
bool x328_28_prevOnGround : 1;
|
||||||
bool x328_29_noPatternShagging : 1;
|
bool x328_29_noPatternShagging : 1;
|
||||||
bool x328_30_lookAtDeathDir : 1;
|
bool x328_30_lookAtDeathDir : 1;
|
||||||
bool x328_31_ : 1;
|
bool x328_31_energyAttractor : 1;
|
||||||
bool x329_24_ : 1;
|
bool x329_24_ : 1;
|
||||||
};
|
};
|
||||||
u32 _dummy = 0;
|
u32 _dummy = 0;
|
||||||
@ -367,6 +367,7 @@ public:
|
|||||||
}
|
}
|
||||||
float GetDamageDuration() const { return x504_damageDur; }
|
float GetDamageDuration() const { return x504_damageDur; }
|
||||||
zeus::CVector3f GetGunEyePos() const;
|
zeus::CVector3f GetGunEyePos() const;
|
||||||
|
bool IsEnergyAttractor() const { return x328_31_energyAttractor; }
|
||||||
bool IsAlive() const { return x400_25_alive; }
|
bool IsAlive() const { return x400_25_alive; }
|
||||||
|
|
||||||
void BuildBodyController(EBodyType);
|
void BuildBodyController(EBodyType);
|
||||||
|
@ -161,6 +161,7 @@ public:
|
|||||||
void SetMomentumWR(const zeus::CVector3f& momentum) { x150_momentum = momentum; }
|
void SetMomentumWR(const zeus::CVector3f& momentum) { x150_momentum = momentum; }
|
||||||
const zeus::CVector3f& GetConstantForce() const { return xfc_constantForce; }
|
const zeus::CVector3f& GetConstantForce() const { return xfc_constantForce; }
|
||||||
void SetConstantForce(const zeus::CVector3f& force) { xfc_constantForce = force; }
|
void SetConstantForce(const zeus::CVector3f& force) { xfc_constantForce = force; }
|
||||||
|
const zeus::CVector3f& GetAngularMomentum() const { return x108_angularMomentum; }
|
||||||
void SetAngularMomentum(const zeus::CAxisAngle& momentum) { x108_angularMomentum = momentum; }
|
void SetAngularMomentum(const zeus::CAxisAngle& momentum) { x108_angularMomentum = momentum; }
|
||||||
const zeus::CVector3f& GetMomentum() const { return x150_momentum; }
|
const zeus::CVector3f& GetMomentum() const { return x150_momentum; }
|
||||||
const zeus::CVector3f& GetVelocity() const { return x138_velocity; }
|
const zeus::CVector3f& GetVelocity() const { return x138_velocity; }
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "Runtime/MP1/World/CMetroidBeta.hpp"
|
#include "Runtime/MP1/World/CMetroidBeta.hpp"
|
||||||
#include "Runtime/MP1/World/CMetroidPrimeRelay.hpp"
|
#include "Runtime/MP1/World/CMetroidPrimeRelay.hpp"
|
||||||
#include "Runtime/MP1/World/CNewIntroBoss.hpp"
|
#include "Runtime/MP1/World/CNewIntroBoss.hpp"
|
||||||
|
#include "Runtime/MP1/World/COmegaPirate.hpp"
|
||||||
#include "Runtime/MP1/World/CParasite.hpp"
|
#include "Runtime/MP1/World/CParasite.hpp"
|
||||||
#include "Runtime/MP1/World/CPuddleSpore.hpp"
|
#include "Runtime/MP1/World/CPuddleSpore.hpp"
|
||||||
#include "Runtime/MP1/World/CPuddleToadGamma.hpp"
|
#include "Runtime/MP1/World/CPuddleToadGamma.hpp"
|
||||||
@ -127,6 +128,8 @@ static logvisor::Module Log("urde::ScriptLoader");
|
|||||||
|
|
||||||
constexpr SObjectTag MorphballDoorANCS = {FOURCC('ANCS'), 0x1F9DA858};
|
constexpr SObjectTag MorphballDoorANCS = {FOURCC('ANCS'), 0x1F9DA858};
|
||||||
|
|
||||||
|
constexpr int skElitePiratePropCount = 41;
|
||||||
|
|
||||||
static bool EnsurePropertyCount(int count, int expected, const char* structName) {
|
static bool EnsurePropertyCount(int count, int expected, const char* structName) {
|
||||||
if (count < expected) {
|
if (count < expected) {
|
||||||
Log.report(logvisor::Warning, fmt("Insufficient number of props ({}/{}) for {} entity"), count, expected,
|
Log.report(logvisor::Warning, fmt("Insufficient number of props ({}/{}) for {} entity"), count, expected,
|
||||||
@ -1394,7 +1397,7 @@ CEntity* ScriptLoader::LoadFlyingPirate(CStateManager& mgr, CInputStream& in, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
CEntity* ScriptLoader::LoadElitePirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
||||||
if (!EnsurePropertyCount(propCount, 41, "ElitePirate"))
|
if (!EnsurePropertyCount(propCount, skElitePiratePropCount, "ElitePirate"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
|
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
|
||||||
@ -3638,7 +3641,33 @@ CEntity* ScriptLoader::LoadMazeNode(CStateManager& mgr, CInputStream& in, int pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
CEntity* ScriptLoader::LoadOmegaPirate(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
||||||
|
if (!EnsurePropertyCount(propCount, skElitePiratePropCount + 1, "OmegaPirate")) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
SScaledActorHead actHead = LoadScaledActorHead(in, mgr);
|
||||||
|
auto pair = CPatternedInfo::HasCorrectParameterCount(in);
|
||||||
|
if (!pair.first) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPatternedInfo pInfo(in, pair.second);
|
||||||
|
CActorParameters actParms = LoadActorParameters(in);
|
||||||
|
MP1::CElitePirateData elitePirateData(in, propCount);
|
||||||
|
|
||||||
|
if (!pInfo.GetAnimationParameters().GetACSFile().IsValid()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
CModelData mData(CAnimRes(pInfo.GetAnimationParameters().GetACSFile(), pInfo.GetAnimationParameters().GetCharacter(),
|
||||||
|
actHead.x40_scale, pInfo.GetAnimationParameters().GetInitialAnimation(), true));
|
||||||
|
|
||||||
|
return new MP1::COmegaPirate(mgr.AllocateUniqueId(), actHead.x0_name, info, actHead.x10_transform, std::move(mData),
|
||||||
|
pInfo, actParms, elitePirateData, CAssetId(in), CAssetId(in), CAssetId(in));
|
||||||
|
#else
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
CEntity* ScriptLoader::LoadPhazonPool(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user