mirror of https://github.com/AxioDL/metaforce.git
CBouncyGrenade implementation
This commit is contained in:
parent
fbbd73db48
commit
bc08792523
|
@ -0,0 +1,203 @@
|
||||||
|
#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}, {},
|
||||||
|
{data.x0_.x0_mass}, actParams, 0.3f, 0.1f)
|
||||||
|
, x258_data(data)
|
||||||
|
, x294_numBounces(data.x34_numBounces)
|
||||||
|
, x298_parentId(parentId)
|
||||||
|
, x2a0_elementGen1(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.x24_elementGenId1})))
|
||||||
|
, x2a4_elementGen2(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.x28_elementGenId2})))
|
||||||
|
, x2a8_elementGen3(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.x2c_elementGenId3})))
|
||||||
|
, x2ac_elementGen4(std::make_unique<CElementGen>(g_SimplePool->GetObj({'PART', data.x30_elementGenId4})))
|
||||||
|
, 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.x0_.x4_ * GetConstantForce().magnitude()) * *normal;
|
||||||
|
const zeus::CVector3f angle = -x258_data.x0_.x4_ * GetAngularMomentum();
|
||||||
|
ApplyImpulseWR(impulse, angle);
|
||||||
|
CSfxManager::AddEmitter(x258_data.x38_bounceSfx, 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.x3a_explodeSfx, 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.x8_damageInfo;
|
||||||
|
{
|
||||||
|
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 CActor* 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
|
|
@ -0,0 +1,73 @@
|
||||||
|
#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 {
|
||||||
|
float x0_mass;
|
||||||
|
float x4_; // speed?
|
||||||
|
|
||||||
|
SGrenadeUnknownStruct(CInputStream& in) : x0_mass(in.readFloatBig()), x4_(in.readFloatBig()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SBouncyGrenadeData {
|
||||||
|
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;
|
||||||
|
|
||||||
|
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){};
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
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
|
|
@ -64,7 +64,7 @@ CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount)
|
||||||
, xd4_(in)
|
, xd4_(in)
|
||||||
, xd8_(in)
|
, xd8_(in)
|
||||||
, xe0_trajectoryInfo(in)
|
, xe0_trajectoryInfo(in)
|
||||||
, xf0_(in)
|
, xf0_grenadeNumBounces(in.readUint32Big())
|
||||||
, xf4_(CSfxManager::TranslateSFXID(in.readUint32Big()))
|
, xf4_(CSfxManager::TranslateSFXID(in.readUint32Big()))
|
||||||
, xf6_(CSfxManager::TranslateSFXID(in.readUint32Big()))
|
, xf6_(CSfxManager::TranslateSFXID(in.readUint32Big()))
|
||||||
, xf8_(in)
|
, xf8_(in)
|
||||||
|
@ -892,7 +892,7 @@ void CElitePirate::CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid) {
|
||||||
CModelData mData(CAnimRes(params.GetACSFile(), params.GetCharacter(), GetModelData()->GetScale(),
|
CModelData mData(CAnimRes(params.GetACSFile(), params.GetCharacter(), GetModelData()->GetScale(),
|
||||||
params.GetInitialAnimation(), true));
|
params.GetInitialAnimation(), true));
|
||||||
SBouncyGrenadeData grenadeData{x5d8_data.xd8_, x5d8_data.xa8_, x5d8_data.xc8_, x5d8_data.xcc_, x5d8_data.xd0_,
|
SBouncyGrenadeData grenadeData{x5d8_data.xd8_, x5d8_data.xa8_, x5d8_data.xc8_, x5d8_data.xcc_, x5d8_data.xd0_,
|
||||||
x5d8_data.xd4_, x5d8_data.xf0_, x5d8_data.xf4_, x5d8_data.xf6_};
|
x5d8_data.xd4_, x5d8_data.xf0_grenadeNumBounces, x5d8_data.xf4_, x5d8_data.xf6_};
|
||||||
CGrenadeLauncherData launcherData{grenadeData, x5d8_data.xa4_, x5d8_data.x9c_, x5d8_data.xa0_,
|
CGrenadeLauncherData launcherData{grenadeData, x5d8_data.xa4_, x5d8_data.x9c_, x5d8_data.xa0_,
|
||||||
x5d8_data.xe0_trajectoryInfo};
|
x5d8_data.xe0_trajectoryInfo};
|
||||||
mgr.AddObject(new CGrenadeLauncher(uid, "Grenade Launcher", {GetAreaIdAlways(), CEntity::NullConnectionList},
|
mgr.AddObject(new CGrenadeLauncher(uid, "Grenade Launcher", {GetAreaIdAlways(), CEntity::NullConnectionList},
|
||||||
|
|
|
@ -38,7 +38,7 @@ public:
|
||||||
CAssetId xd4_;
|
CAssetId xd4_;
|
||||||
SGrenadeUnknownStruct xd8_;
|
SGrenadeUnknownStruct xd8_;
|
||||||
SGrenadeTrajectoryInfo xe0_trajectoryInfo;
|
SGrenadeTrajectoryInfo xe0_trajectoryInfo;
|
||||||
CAssetId xf0_;
|
u32 xf0_grenadeNumBounces;
|
||||||
u16 xf4_;
|
u16 xf4_;
|
||||||
u16 xf6_;
|
u16 xf6_;
|
||||||
CAssetId xf8_;
|
CAssetId xf8_;
|
||||||
|
|
|
@ -10,8 +10,7 @@
|
||||||
#include "Runtime/World/CPatterned.hpp"
|
#include "Runtime/World/CPatterned.hpp"
|
||||||
#include "Runtime/World/CPlayer.hpp"
|
#include "Runtime/World/CPlayer.hpp"
|
||||||
|
|
||||||
namespace urde {
|
namespace urde::MP1 {
|
||||||
namespace MP1 {
|
|
||||||
CGrenadeLauncher::CGrenadeLauncher(TUniqueId uid, std::string_view name, const CEntityInfo& info,
|
CGrenadeLauncher::CGrenadeLauncher(TUniqueId uid, std::string_view name, const CEntityInfo& info,
|
||||||
const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& bounds,
|
const zeus::CTransform& xf, CModelData&& mData, const zeus::CAABox& bounds,
|
||||||
const CHealthInfo& healthInfo, const CDamageVulnerability& vulnerability,
|
const CHealthInfo& healthInfo, const CDamageVulnerability& vulnerability,
|
||||||
|
@ -24,9 +23,9 @@ CGrenadeLauncher::CGrenadeLauncher(TUniqueId uid, std::string_view name, const C
|
||||||
, x2cc_parentId(parentId)
|
, x2cc_parentId(parentId)
|
||||||
, x2d0_data(data)
|
, x2d0_data(data)
|
||||||
, x328_cSphere({{}, mData.GetScale().z()}, {EMaterialTypes::Character, EMaterialTypes::Solid})
|
, x328_cSphere({{}, mData.GetScale().z()}, {EMaterialTypes::Character, EMaterialTypes::Solid})
|
||||||
, x350_actParms(actParams)
|
, x350_grenadeActorParams(actParams)
|
||||||
, x3e8_thermalMag(actParams.GetThermalMag())
|
, x3e8_thermalMag(actParams.GetThermalMag())
|
||||||
, x3f8_(f1) {
|
, x3f8_explodePlayerDistance(f1) {
|
||||||
if (data.x40_.IsValid()) {
|
if (data.x40_.IsValid()) {
|
||||||
x3b8_particleGenDesc = g_SimplePool->GetObj({SBIG('PART'), data.x40_});
|
x3b8_particleGenDesc = g_SimplePool->GetObj({SBIG('PART'), data.x40_});
|
||||||
}
|
}
|
||||||
|
@ -293,8 +292,33 @@ void CGrenadeLauncher::LaunchGrenade(CStateManager& mgr) {
|
||||||
const auto& anim = animData->GetCharacterInfo().GetPASDatabase().FindBestAnimation({24}, -1);
|
const auto& anim = animData->GetCharacterInfo().GetPASDatabase().FindBestAnimation({24}, -1);
|
||||||
if (anim.first > 0.f) {
|
if (anim.first > 0.f) {
|
||||||
animData->AddAdditiveAnimation(anim.second, 1.f, false, true);
|
animData->AddAdditiveAnimation(anim.second, 1.f, false, true);
|
||||||
// TODO
|
const zeus::CVector3f& origin =
|
||||||
|
GetTranslation() + GetTransform().rotate(GetLocatorTransform("grenade_LCTR"sv).origin);
|
||||||
|
const zeus::CVector3f& target = GrenadeTarget(mgr);
|
||||||
|
float angleOut = x2d0_data.x48_trajectoryInfo.x8_angleMin, velocityOut = x2d0_data.x48_trajectoryInfo.x0_;
|
||||||
|
CalculateGrenadeTrajectory(target, origin, x2d0_data.x48_trajectoryInfo, 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.x3c_grenadeCmdl, GetModelData()->GetScale()}};
|
||||||
|
mgr.AddObject(new CBouncyGrenade(mgr.AllocateUniqueId(), "Bouncy Grenade"sv,
|
||||||
|
{GetAreaIdAlways(), CEntity::NullConnectionList}, xf, std::move(mData),
|
||||||
|
x350_grenadeActorParams, x2cc_parentId, x2d0_data.x0_grenadeData, velocityOut,
|
||||||
|
x3f8_explodePlayerDistance));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // namespace MP1
|
} // namespace urde::MP1
|
||||||
} // namespace urde
|
|
||||||
|
|
|
@ -2,15 +2,14 @@
|
||||||
|
|
||||||
#include "Runtime/Character/CModelData.hpp"
|
#include "Runtime/Character/CModelData.hpp"
|
||||||
#include "Runtime/Collision/CCollidableSphere.hpp"
|
#include "Runtime/Collision/CCollidableSphere.hpp"
|
||||||
|
#include "Runtime/MP1/World/CBouncyGrenade.hpp"
|
||||||
#include "Runtime/Particle/CGenDescription.hpp"
|
#include "Runtime/Particle/CGenDescription.hpp"
|
||||||
#include "Runtime/RetroTypes.hpp"
|
|
||||||
#include "Runtime/World/CActorParameters.hpp"
|
#include "Runtime/World/CActorParameters.hpp"
|
||||||
#include "Runtime/World/CDamageInfo.hpp"
|
#include "Runtime/World/CDamageInfo.hpp"
|
||||||
#include "Runtime/World/CDamageVulnerability.hpp"
|
#include "Runtime/World/CDamageVulnerability.hpp"
|
||||||
#include "Runtime/World/CEntityInfo.hpp"
|
#include "Runtime/World/CEntityInfo.hpp"
|
||||||
#include "Runtime/World/CHealthInfo.hpp"
|
#include "Runtime/World/CHealthInfo.hpp"
|
||||||
#include "Runtime/World/CPhysicsActor.hpp"
|
#include "Runtime/World/CPhysicsActor.hpp"
|
||||||
#include "Runtime/World/CPhysicsActor.hpp"
|
|
||||||
|
|
||||||
#include "TCastTo.hpp" // Generated file, do not modify include path
|
#include "TCastTo.hpp" // Generated file, do not modify include path
|
||||||
|
|
||||||
|
@ -20,8 +19,7 @@
|
||||||
#include <zeus/CTransform.hpp>
|
#include <zeus/CTransform.hpp>
|
||||||
#include <zeus/CQuaternion.hpp>
|
#include <zeus/CQuaternion.hpp>
|
||||||
|
|
||||||
namespace urde {
|
namespace urde::MP1 {
|
||||||
namespace MP1 {
|
|
||||||
struct SGrenadeTrajectoryInfo {
|
struct SGrenadeTrajectoryInfo {
|
||||||
float x0_;
|
float x0_;
|
||||||
float x4_;
|
float x4_;
|
||||||
|
@ -35,40 +33,21 @@ struct SGrenadeTrajectoryInfo {
|
||||||
, xc_angleMax(zeus::degToRad(in.readFloatBig())) {}
|
, xc_angleMax(zeus::degToRad(in.readFloatBig())) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SGrenadeUnknownStruct {
|
|
||||||
float x0_mass;
|
|
||||||
float x4_;
|
|
||||||
|
|
||||||
SGrenadeUnknownStruct(CInputStream& in) : x0_mass(in.readFloatBig()), x4_(in.readFloatBig()) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SBouncyGrenadeData {
|
|
||||||
SGrenadeUnknownStruct x0_;
|
|
||||||
CDamageInfo x8_damageInfo;
|
|
||||||
CAssetId x24_;
|
|
||||||
CAssetId x28_;
|
|
||||||
CAssetId x2c_;
|
|
||||||
CAssetId x30_;
|
|
||||||
CAssetId x34_;
|
|
||||||
u16 x38_;
|
|
||||||
u16 x3a_;
|
|
||||||
|
|
||||||
SBouncyGrenadeData(const SGrenadeUnknownStruct& unkStruct, const CDamageInfo& damageInfo, CAssetId w1, CAssetId w2,
|
|
||||||
CAssetId w3, CAssetId w4, CAssetId w5, u16 s1, u16 s2)
|
|
||||||
: x0_(unkStruct), x8_damageInfo(damageInfo), x24_(w1), x28_(w2), x2c_(w3), x30_(w4), x34_(w5), x38_(s1), x3a_(s2){};
|
|
||||||
};
|
|
||||||
|
|
||||||
class CGrenadeLauncherData {
|
class CGrenadeLauncherData {
|
||||||
public:
|
public:
|
||||||
SBouncyGrenadeData x0_;
|
SBouncyGrenadeData x0_grenadeData;
|
||||||
CAssetId x3c_;
|
CAssetId x3c_grenadeCmdl;
|
||||||
CAssetId x40_;
|
CAssetId x40_;
|
||||||
u16 x44_launcherExplodeSfx;
|
u16 x44_launcherExplodeSfx;
|
||||||
SGrenadeTrajectoryInfo x48_trajectoryInfo;
|
SGrenadeTrajectoryInfo x48_trajectoryInfo;
|
||||||
|
|
||||||
CGrenadeLauncherData(const SBouncyGrenadeData& data, CAssetId w1, CAssetId w2, u16 sfx,
|
CGrenadeLauncherData(const SBouncyGrenadeData& data, CAssetId w1, CAssetId w2, u16 sfx,
|
||||||
const SGrenadeTrajectoryInfo& trajectoryInfo)
|
const SGrenadeTrajectoryInfo& trajectoryInfo)
|
||||||
: x0_(data), x3c_(w1), x40_(w2), x44_launcherExplodeSfx(sfx), x48_trajectoryInfo(trajectoryInfo){};
|
: x0_grenadeData(data)
|
||||||
|
, x3c_grenadeCmdl(w1)
|
||||||
|
, x40_(w2)
|
||||||
|
, x44_launcherExplodeSfx(sfx)
|
||||||
|
, x48_trajectoryInfo(trajectoryInfo){};
|
||||||
};
|
};
|
||||||
|
|
||||||
class CGrenadeLauncher : public CPhysicsActor {
|
class CGrenadeLauncher : public CPhysicsActor {
|
||||||
|
@ -81,7 +60,7 @@ public:
|
||||||
CCollidableSphere x328_cSphere;
|
CCollidableSphere x328_cSphere;
|
||||||
float x348_shotTimer = -1.f;
|
float x348_shotTimer = -1.f;
|
||||||
zeus::CColor x34c_color1{1.f};
|
zeus::CColor x34c_color1{1.f};
|
||||||
CActorParameters x350_actParms;
|
CActorParameters x350_grenadeActorParams;
|
||||||
std::optional<TLockedToken<CGenDescription>> x3b8_particleGenDesc;
|
std::optional<TLockedToken<CGenDescription>> x3b8_particleGenDesc;
|
||||||
std::array<s32, 4> x3c8_animIds;
|
std::array<s32, 4> x3c8_animIds;
|
||||||
float x3d8_ = 0.f;
|
float x3d8_ = 0.f;
|
||||||
|
@ -92,7 +71,7 @@ public:
|
||||||
float x3ec_damageTimer = 0.f;
|
float x3ec_damageTimer = 0.f;
|
||||||
zeus::CColor x3f0_color2{0.5f, 0.f, 0.f};
|
zeus::CColor x3f0_color2{0.5f, 0.f, 0.f};
|
||||||
zeus::CColor x3f4_color3{0.f};
|
zeus::CColor x3f4_color3{0.f};
|
||||||
float x3f8_;
|
float x3f8_explodePlayerDistance;
|
||||||
bool x3fc_launchGrenade = false;
|
bool x3fc_launchGrenade = false;
|
||||||
bool x3fd_visible = true;
|
bool x3fd_visible = true;
|
||||||
bool x3fe_ = true;
|
bool x3fe_ = true;
|
||||||
|
@ -127,5 +106,4 @@ protected:
|
||||||
void sub_80230438();
|
void sub_80230438();
|
||||||
void LaunchGrenade(CStateManager& mgr);
|
void LaunchGrenade(CStateManager& mgr);
|
||||||
};
|
};
|
||||||
} // namespace MP1
|
} // namespace urde::MP1
|
||||||
} // namespace urde
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ set(MP1_WORLD_SOURCES
|
||||||
CBabygoth.hpp CBabygoth.cpp
|
CBabygoth.hpp CBabygoth.cpp
|
||||||
CBeetle.hpp CBeetle.cpp
|
CBeetle.hpp CBeetle.cpp
|
||||||
CBloodFlower.hpp CBloodFlower.cpp
|
CBloodFlower.hpp CBloodFlower.cpp
|
||||||
|
CBouncyGrenade.hpp CBouncyGrenade.cpp
|
||||||
CBurrower.hpp CBurrower.cpp
|
CBurrower.hpp CBurrower.cpp
|
||||||
CChozoGhost.hpp CChozoGhost.cpp
|
CChozoGhost.hpp CChozoGhost.cpp
|
||||||
CElitePirate.hpp CElitePirate.cpp
|
CElitePirate.hpp CElitePirate.cpp
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
Loading…
Reference in New Issue