mirror of https://github.com/PrimeDecomp/prime.git
157 lines
5.6 KiB
C++
157 lines
5.6 KiB
C++
#include "MetroidPrime/CExplosion.hpp"
|
|
|
|
#include "MetroidPrime/CGameLight.hpp"
|
|
#include "MetroidPrime/CStateManager.hpp"
|
|
#include "MetroidPrime/Player/CPlayerState.hpp"
|
|
|
|
#include "Kyoto/Graphics/CCubeModel.hpp"
|
|
#include "Kyoto/Graphics/CGraphics.hpp"
|
|
#include "Kyoto/Math/CFrustumPlanes.hpp"
|
|
#include "Kyoto/Particles/CElementGen.hpp"
|
|
#include "Kyoto/Particles/CGenDescription.hpp"
|
|
#include "Kyoto/Particles/CParticleElectric.hpp"
|
|
#include "MetaRender/CCubeRenderer.hpp"
|
|
|
|
CExplosion::CExplosion(const TLockedToken< CGenDescription >& particle, TUniqueId uid, bool active,
|
|
const CEntityInfo& info, const rstl::string& name, const CTransform4f& xf,
|
|
uint flags, const CVector3f& scale, const CColor& color)
|
|
: CEffect(uid, info, active, name, xf)
|
|
, xe8_particleGen(rs_new CElementGen(TToken< CGenDescription >(particle), CElementGen::kMOT_Normal,
|
|
flags & 0x2 ? CElementGen::kOSF_Two : CElementGen::kOSF_One))
|
|
, xec_explosionLight(kInvalidUniqueId)
|
|
, xf0_sourceId(CToken(particle).GetTag().GetId())
|
|
, xf4_24_renderThermalHot(flags & 0x4)
|
|
, xf4_25_hasRenderBounds(true)
|
|
, xf4_26_renderXray(flags & 0x8)
|
|
, xf8_time(0.0f) {
|
|
SetThermalFlags(flags & 0x1 ? kTF_Cold : kTF_Hot);
|
|
xe8_particleGen->SetGlobalTranslation(xf.GetTranslation());
|
|
xe8_particleGen->SetOrientation(xf.GetRotation());
|
|
xe8_particleGen->SetGlobalScale(scale);
|
|
xe8_particleGen->SetModulationColor(color);
|
|
}
|
|
|
|
CExplosion::CExplosion(const TLockedToken< CElectricDescription >& electric, TUniqueId uid,
|
|
bool active, const CEntityInfo& info, const rstl::string& name,
|
|
const CTransform4f& xf, uint flags, const CVector3f& scale,
|
|
const CColor& color)
|
|
: CEffect(uid, info, active, name, xf)
|
|
, xe8_particleGen(rs_new CParticleElectric(electric))
|
|
, xec_explosionLight(kInvalidUniqueId)
|
|
, xf0_sourceId(CToken(electric).GetTag().GetId())
|
|
, xf4_24_renderThermalHot(flags & 0x4)
|
|
, xf4_25_hasRenderBounds(true)
|
|
, xf4_26_renderXray(flags & 0x8)
|
|
#if NONMATCHING
|
|
, xf8_time(0.0f)
|
|
#endif
|
|
{
|
|
SetThermalFlags(flags & 0x1 ? kTF_Cold : kTF_Hot);
|
|
xe8_particleGen->SetGlobalTranslation(xf.GetTranslation());
|
|
xe8_particleGen->SetOrientation(xf.GetRotation());
|
|
xe8_particleGen->SetGlobalScale(scale);
|
|
xe8_particleGen->SetModulationColor(color);
|
|
}
|
|
|
|
CExplosion::~CExplosion() {}
|
|
|
|
void CExplosion::AddToRenderer(const CFrustumPlanes& frustum, const CStateManager& mgr) const {
|
|
if (GetPreRenderClipped()) {
|
|
return;
|
|
}
|
|
|
|
if ((xf4_24_renderThermalHot && mgr.GetThermalDrawFlag() == kTD_Hot) ||
|
|
(xf4_26_renderXray && mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::kPV_XRay)) {
|
|
EnsureRendered(mgr);
|
|
} else {
|
|
gpRender->AddParticleGen(*xe8_particleGen);
|
|
}
|
|
}
|
|
|
|
void CExplosion::PreRender(CStateManager& mgr, const CFrustumPlanes& frustum) {
|
|
CActor::PreRender(mgr, frustum);
|
|
SetPreRenderClipped(!xf4_25_hasRenderBounds || !frustum.BoxInFrustumPlanes(GetRenderBoundsCached()));
|
|
}
|
|
|
|
void CExplosion::Think(float dt, CStateManager& mgr) {
|
|
if (GetTransformDirtySpare()) {
|
|
xe8_particleGen->SetGlobalTranslation(GetTranslation());
|
|
xe8_particleGen->SetOrientation(GetTransform().GetRotation());
|
|
SetTransformDirtySpare(false);
|
|
}
|
|
xe8_particleGen->Update(dt);
|
|
|
|
if (xec_explosionLight != kInvalidUniqueId) {
|
|
CGameLight* light = TCastToPtr< CGameLight >(mgr.ObjectById(xec_explosionLight));
|
|
if (light && GetActive())
|
|
light->SetLight(xe8_particleGen->GetLight());
|
|
}
|
|
|
|
xf8_time += dt;
|
|
|
|
if (xf8_time > 15.f) {
|
|
mgr.DeleteObjectRequest(GetUniqueId());
|
|
} else if (xe8_particleGen->IsSystemDeletable()) {
|
|
mgr.DeleteObjectRequest(GetUniqueId());
|
|
}
|
|
}
|
|
|
|
void CExplosion::Accept(IVisitor& visitor) { visitor.Visit(*this); }
|
|
|
|
void CExplosion::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) {
|
|
switch (msg) {
|
|
case kSM_Registered:
|
|
if (xe8_particleGen->SystemHasLight()) {
|
|
xec_explosionLight = mgr.AllocateUniqueId();
|
|
uint sourceId = xf0_sourceId;
|
|
mgr.AddObject(rs_new CGameLight(xec_explosionLight, GetCurrentAreaId(), GetActive(),
|
|
rstl::string_l("ExplodePLight_") + GetDebugName(),
|
|
GetTransform(), GetUniqueId(), xe8_particleGen->GetLight(),
|
|
sourceId, 1, 0.f));
|
|
}
|
|
break;
|
|
case kSM_Deleted:
|
|
if (xec_explosionLight != kInvalidUniqueId) {
|
|
mgr.DeleteObjectRequest(xec_explosionLight);
|
|
xec_explosionLight = kInvalidUniqueId;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
CActor::AcceptScriptMsg(msg, sender, mgr);
|
|
|
|
if (xec_explosionLight != kInvalidUniqueId)
|
|
mgr.SendScriptMsgAlways(xec_explosionLight, sender, msg);
|
|
}
|
|
|
|
void CExplosion::CalculateRenderBounds() {
|
|
rstl::optional_object< CAABox > bounds = xe8_particleGen->GetBounds();
|
|
if (bounds) {
|
|
SetRenderBounds(*bounds);
|
|
xf4_25_hasRenderBounds = true;
|
|
} else {
|
|
xf4_25_hasRenderBounds = false;
|
|
CVector3f pos = GetTransform().GetTranslation();
|
|
SetRenderBounds(CAABox(pos, pos));
|
|
}
|
|
}
|
|
|
|
void CExplosion::Render(const CStateManager& mgr) const {
|
|
if (mgr.GetThermalDrawFlag() == kTD_Hot && xf4_24_renderThermalHot) {
|
|
CElementGen::SetSubtractBlend(true);
|
|
CCubeModel::SetRenderModelBlack(true);
|
|
xe8_particleGen->Render();
|
|
CCubeModel::SetRenderModelBlack(false);
|
|
CElementGen::SetSubtractBlend(false);
|
|
return;
|
|
}
|
|
|
|
CElementGen::SetSubtractBlend(!xf4_24_renderThermalHot);
|
|
CGraphics::SetFog(kRFM_PerspLin, 0.f, 75.f, CColor::Black());
|
|
xe8_particleGen->Render();
|
|
mgr.SetupFogForArea(GetCurrentAreaId());
|
|
CElementGen::SetSubtractBlend(false);
|
|
}
|