metaforce/Runtime/Weapon/CBomb.cpp

164 lines
6.6 KiB
C++
Raw Normal View History

#include "Runtime/Weapon/CBomb.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Graphics/CCubeRenderer.hpp"
#include "Runtime/Particle/CElementGen.hpp"
#include "Runtime/World/CGameLight.hpp"
#include "Runtime/World/CMorphBall.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "Audio/SFX/Weapons.h"
#include "TCastTo.hpp" // Generated file, do not modify include path
2021-04-10 08:42:06 +00:00
namespace metaforce {
2018-09-09 01:13:56 +00:00
CBomb::CBomb(const TCachedToken<CGenDescription>& particle1, const TCachedToken<CGenDescription>& particle2,
2018-12-08 05:30:43 +00:00
TUniqueId uid, TAreaId aid, TUniqueId playerId, float f1, const zeus::CTransform& xf,
const CDamageInfo& dInfo)
: CWeapon(uid, aid, true, playerId, EWeaponType::Bomb, "Bomb", xf,
2018-12-08 05:30:43 +00:00
CMaterialFilter::MakeIncludeExclude(
{EMaterialTypes::Solid, EMaterialTypes::Trigger, EMaterialTypes::NonSolidDamageable},
{EMaterialTypes::Projectile, EMaterialTypes::Bomb}),
{EMaterialTypes::Projectile, EMaterialTypes::Bomb}, dInfo, EProjectileAttrib::Bombs,
CModelData::CModelDataNull())
, x170_prevLocation(xf.origin)
2018-09-09 01:13:56 +00:00
, x17c_fuseTime(f1)
, x180_particle1(std::make_unique<CElementGen>(particle1, CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One))
, x184_particle2(std::make_unique<CElementGen>(particle2, CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One))
, x18c_particle2Obj(particle2.GetObj()) {
2018-12-08 05:30:43 +00:00
x180_particle1->SetGlobalTranslation(xf.origin);
x184_particle2->SetGlobalTranslation(xf.origin);
2018-09-09 01:13:56 +00:00
}
2021-04-10 08:42:06 +00:00
void CBomb::Accept(metaforce::IVisitor& visitor) { visitor.Visit(this); }
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
void CBomb::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
if (msg == EScriptObjectMessage::Registered) {
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
x188_lightId = mgr.AllocateUniqueId();
2021-06-07 19:29:18 +00:00
CGameLight* gameLight = new CGameLight(
x188_lightId, GetAreaIdAlways(), false, std::string("Bomb_PLight") + GetName().data(), GetTransform(),
GetUniqueId(), x184_particle2->GetLight(), reinterpret_cast<size_t>(x18c_particle2Obj), 1, 0.f);
2018-12-08 05:30:43 +00:00
mgr.AddObject(gameLight);
mgr.AddWeaponId(xec_ownerId, xf0_weaponType);
CSfxManager::AddEmitter(SFXwpn_bomb_drop, GetTranslation(), {}, true, false, 0x7f, -1);
mgr.InformListeners(GetTranslation(), EListenNoiseType::BombExplode);
return;
} else if (msg == EScriptObjectMessage::Deleted) {
if (x188_lightId != kInvalidUniqueId)
mgr.FreeScriptObject(x188_lightId);
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
if (x190_24_isNotDetonated)
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
return;
}
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
CActor::AcceptScriptMsg(msg, uid, mgr);
}
2018-09-09 01:13:56 +00:00
constexpr CMaterialFilter kSolidFilter =
2018-12-08 05:30:43 +00:00
CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {EMaterialTypes::Character, EMaterialTypes::Player,
EMaterialTypes::ProjectilePassthrough});
2021-04-10 08:42:06 +00:00
void CBomb::Think(float dt, metaforce::CStateManager& mgr) {
2018-12-08 05:30:43 +00:00
CWeapon::Think(dt, mgr);
if (x190_24_isNotDetonated) {
if (x17c_fuseTime <= 0.f) {
Explode(GetTranslation(), mgr);
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x188_lightId))
light->SetActive(true);
2018-09-09 01:13:56 +00:00
}
2018-12-08 05:30:43 +00:00
if (x17c_fuseTime > 0.5f)
x180_particle1->Update(dt);
else
UpdateLight(dt, mgr);
if (!x190_26_disableFuse)
x17c_fuseTime -= dt;
} else {
UpdateLight(dt, mgr);
if (x184_particle2->IsSystemDeletable())
mgr.FreeScriptObject(GetUniqueId());
}
if (x190_24_isNotDetonated) {
if (x164_acceleration.magSquared() > 0.f)
x158_velocity += dt * x164_acceleration;
2018-12-08 05:30:43 +00:00
if (x158_velocity.magSquared() > 0.f) {
2018-12-08 05:30:43 +00:00
x170_prevLocation = GetTranslation();
CActor::SetTranslation((dt * x158_velocity) + GetTranslation());
2018-12-08 05:30:43 +00:00
zeus::CVector3f diffVec = (GetTranslation() - x170_prevLocation);
float diffMag = diffVec.magnitude();
if (diffMag == 0.f)
Explode(GetTranslation(), mgr);
else {
CRayCastResult res =
mgr.RayStaticIntersection(x170_prevLocation, (1.f / diffMag) * diffVec, diffMag, kSolidFilter);
if (res.IsValid())
Explode(GetTranslation(), mgr);
}
2018-09-09 01:13:56 +00:00
}
2018-12-08 05:30:43 +00:00
}
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
x180_particle1->SetGlobalTranslation(GetTranslation());
x184_particle2->SetGlobalTranslation(GetTranslation());
2018-09-09 01:13:56 +00:00
}
void CBomb::AddToRenderer(const zeus::CFrustum& frustum, CStateManager& mgr) {
2018-12-08 05:30:43 +00:00
zeus::CVector3f origin = GetTranslation();
float ballRadius = mgr.GetPlayer().GetMorphBall()->GetBallRadius();
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
zeus::CAABox aabox(origin - (0.9f * ballRadius), origin + (0.9f * ballRadius));
zeus::CVector3f closestPoint = aabox.closestPointAlongVector(CGraphics::g_ViewMatrix.frontVector());
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
if (x190_24_isNotDetonated && x17c_fuseTime > 0.5f)
g_Renderer->AddParticleGen(*x180_particle1, closestPoint, aabox);
else
g_Renderer->AddParticleGen(*x184_particle2, closestPoint, aabox);
2018-09-09 01:13:56 +00:00
}
2021-04-10 08:42:06 +00:00
void CBomb::Touch(CActor&, metaforce::CStateManager&) {
2018-09-09 01:13:56 +00:00
#if 0
x190_24_isNotDetonated; /* wat? */
#endif
}
std::optional<zeus::CAABox> CBomb::GetTouchBounds() const {
2018-12-08 05:30:43 +00:00
float radius = (x190_24_isNotDetonated ? 0.2f : x12c_curDamageInfo.GetRadius());
float minX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) - radius;
float minY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) - radius;
float minZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) - radius;
float maxX = (x170_prevLocation.x() >= GetTranslation().x() ? x170_prevLocation.x() : GetTranslation().x()) + radius;
float maxY = (x170_prevLocation.y() >= GetTranslation().y() ? x170_prevLocation.y() : GetTranslation().y()) + radius;
float maxZ = (x170_prevLocation.z() >= GetTranslation().z() ? x170_prevLocation.z() : GetTranslation().z()) + radius;
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
return {{minX, minY, minZ, maxX, maxY, maxZ}};
}
2018-09-09 01:13:56 +00:00
2018-12-08 05:30:43 +00:00
void CBomb::Explode(const zeus::CVector3f& pos, CStateManager& mgr) {
mgr.ApplyDamageToWorld(xec_ownerId, *this, pos, x12c_curDamageInfo, xf8_filter);
CSfxManager::AddEmitter(SFXwpn_bomb_explo, GetTranslation(), {}, true, false, 0x7f, -1);
mgr.InformListeners(pos, EListenNoiseType::BombExplode);
mgr.RemoveWeaponId(xec_ownerId, xf0_weaponType);
x190_24_isNotDetonated = false;
2018-09-09 01:13:56 +00:00
}
2018-12-08 05:30:43 +00:00
void CBomb::UpdateLight(float dt, CStateManager& mgr) {
x184_particle2->Update(dt);
if (x188_lightId == kInvalidUniqueId)
return;
if (TCastToPtr<CGameLight> light = mgr.ObjectById(x188_lightId))
if (light->GetActive())
light->SetLight(x184_particle2->GetLight());
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce