#include "Runtime/World/CScriptDamageableTrigger.hpp" #include "Runtime/CStateManager.hpp" #include "Runtime/World/CActorParameters.hpp" #include "Runtime/World/CScriptActor.hpp" #include "Runtime/World/CWorld.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path namespace metaforce { static CActorParameters MakeDamageableTriggerActorParms(const CActorParameters& aParams, const CVisorParameters& vParams) { CActorParameters ret = aParams; ret.SetVisorParameters(vParams); return ret; } static constexpr CMaterialList MakeDamageableTriggerMaterial(CScriptDamageableTrigger::ECanOrbit canOrbit) { if (canOrbit == CScriptDamageableTrigger::ECanOrbit::Orbit) { return CMaterialList(EMaterialTypes::Orbit, EMaterialTypes::Trigger, EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable, EMaterialTypes::ExcludeFromLineOfSightTest); } return CMaterialList(EMaterialTypes::Trigger, EMaterialTypes::Immovable, EMaterialTypes::NonSolidDamageable, EMaterialTypes::ExcludeFromLineOfSightTest); } CScriptDamageableTrigger::CScriptDamageableTrigger(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CVector3f& position, const zeus::CVector3f& extent, const CHealthInfo& hInfo, const CDamageVulnerability& dVuln, u32 faceFlag, CAssetId patternTex1, CAssetId patternTex2, CAssetId colorTex, ECanOrbit canOrbit, bool active, const CVisorParameters& vParams) : CActor(uid, active, name, info, zeus::CTransform::Translate(position), CModelData::CModelDataNull(), MakeDamageableTriggerMaterial(canOrbit), MakeDamageableTriggerActorParms(CActorParameters::None(), vParams), kInvalidUniqueId) , x14c_bounds(-extent * 0.5f, extent * 0.5f) , x164_origHInfo(hInfo) , x16c_hInfo(hInfo) , x174_dVuln(dVuln) , x1dc_faceFlag(faceFlag) , x254_fluidPlane(patternTex1, patternTex2, colorTex, 1.f, 2, EFluidType::NormalWater, 1.f, CFluidUVMotion(6.f, 0.f)) , x300_28_canOrbit(canOrbit == ECanOrbit::Orbit) { if (x1dc_faceFlag & 0x1) { x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.max.y(), 0.f); x1e4_faceDir = zeus::CTransform::RotateX(-M_PIF / 2.f); } else if (x1dc_faceFlag & 0x2) { x244_faceTranslate = zeus::CVector3f(0.f, x14c_bounds.min.y(), 0.f); x1e4_faceDir = zeus::CTransform::RotateX(M_PIF / 2.f); } else if (x1dc_faceFlag & 0x4) { x244_faceTranslate = zeus::CVector3f(x14c_bounds.min.x(), 0.f, 0.f); x1e4_faceDir = zeus::CTransform::RotateY(-M_PIF / 2.f); } else if (x1dc_faceFlag & 0x8) { x244_faceTranslate = zeus::CVector3f(x14c_bounds.max.x(), 0.f, 0.f); x1e4_faceDir = zeus::CTransform::RotateY(M_PIF / 2.f); } else if (x1dc_faceFlag & 0x10) { x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.max.z()); x1e4_faceDir = zeus::CTransform(); } else if (x1dc_faceFlag & 0x20) { x244_faceTranslate = zeus::CVector3f(0.f, 0.f, x14c_bounds.min.z()); x1e4_faceDir = zeus::CTransform::RotateY(M_PIF); } x214_faceDirInv = x1e4_faceDir.inverse(); } void CScriptDamageableTrigger::Accept(IVisitor& visitor) { visitor.Visit(this); } void CScriptDamageableTrigger::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr) { switch (msg) { case EScriptObjectMessage::Deactivate: if (x30_24_active && x300_25_alphaOut) { return; } [[fallthrough]]; case EScriptObjectMessage::Activate: if (!x30_24_active || x300_25_alphaOut) { x250_alphaTimer = 0.f; x16c_hInfo = x164_origHInfo; x300_25_alphaOut = false; if (x300_28_canOrbit) { AddMaterial(EMaterialTypes::Orbit, mgr); } SetLinkedObjectAlpha(0.f, mgr); x1e0_alpha = 0.f; } break; case EScriptObjectMessage::Damage: if (x300_27_invulnerable) { x16c_hInfo = x164_origHInfo; } break; case EScriptObjectMessage::Increment: x300_27_invulnerable = true; break; case EScriptObjectMessage::Decrement: x300_27_invulnerable = false; break; default: break; } CActor::AcceptScriptMsg(msg, sender, mgr); } EWeaponCollisionResponseTypes CScriptDamageableTrigger::GetCollisionResponseType(const zeus::CVector3f&, const zeus::CVector3f&, const CWeaponMode& weapMode, EProjectileAttrib) const { return x174_dVuln.WeaponHurts(weapMode, false) ? EWeaponCollisionResponseTypes::OtherProjectile : EWeaponCollisionResponseTypes::Unknown15; } void CScriptDamageableTrigger::Render(CStateManager& mgr) { if (x30_24_active && x1dc_faceFlag != 0 && std::fabs(x1e0_alpha) >= 0.00001f) { const zeus::CAABox aabb = x14c_bounds.getTransformedAABox(x214_faceDirInv); const zeus::CTransform xf = x34_transform * zeus::CTransform::Translate(x244_faceTranslate) * x1e4_faceDir; x254_fluidPlane.Render(mgr, x1e0_alpha, aabb, xf, zeus::CTransform(), false, xe8_frustum, {}, kInvalidUniqueId, nullptr, 0, 0, zeus::skZero3f); } CActor::Render(mgr); } void CScriptDamageableTrigger::AddToRenderer(const zeus::CFrustum& /*frustum*/, CStateManager& mgr) { if (x300_26_outOfFrustum) { return; } EnsureRendered(mgr, GetTranslation() - x244_faceTranslate, GetSortingBounds(mgr)); } void CScriptDamageableTrigger::PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) { x300_26_outOfFrustum = !frustum.aabbFrustumTest(x14c_bounds.getTransformedAABox(x34_transform)); if (x300_26_outOfFrustum) { return; } xe8_frustum = frustum; CActor::PreRender(mgr, frustum); } void CScriptDamageableTrigger::SetLinkedObjectAlpha(float a, CStateManager& mgr) { for (const SConnection& conn : x20_conns) { if (conn.x0_state != EScriptObjectState::MaxReached || conn.x4_msg != EScriptObjectMessage::Activate) { continue; } if (const TCastToPtr<CScriptActor> act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { if (!act->GetActive()) { act->SetActive(true); } act->SetDrawFlags(CModelFlags(5, 0, 3, zeus::CColor(1.f, a))); } } } float CScriptDamageableTrigger::GetPuddleAlphaScale() const { if (x250_alphaTimer <= 0.75f) { if (x300_25_alphaOut) { return 1.f - x250_alphaTimer / 0.75f; } return x250_alphaTimer / 0.75f; } if (x300_25_alphaOut) { return 0.f; } return 1.f; } void CScriptDamageableTrigger::Think(float dt, CStateManager& mgr) { if (!GetActive()) { return; } const CGameArea* area = mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways()); const auto occState = area->IsPostConstructed() ? area->GetOcclusionState() : CGameArea::EOcclusionState::Occluded; x300_24_notOccluded = occState == CGameArea::EOcclusionState::Visible; if (x300_25_alphaOut) { if (x250_alphaTimer >= 0.75f) { SetActive(false); for (const SConnection& conn : x20_conns) { if (conn.x0_state != EScriptObjectState::MaxReached || conn.x4_msg != EScriptObjectMessage::Activate) { continue; } if (const TCastToPtr<CScriptActor> act = mgr.ObjectById(mgr.GetIdForScript(conn.x8_objId))) { act->SetActive(false); } } SetLinkedObjectAlpha(0.f, mgr); x300_25_alphaOut = false; return; } } else if (x16c_hInfo.GetHP() <= 0.f && x30_24_active) { SendScriptMsgs(EScriptObjectState::Dead, mgr, EScriptObjectMessage::None); RemoveMaterial(EMaterialTypes::Orbit, mgr); x300_25_alphaOut = true; x250_alphaTimer = 0.f; } if (x250_alphaTimer <= 0.75f) { x250_alphaTimer += dt; } const float objAlpha = GetPuddleAlphaScale(); x1e0_alpha = 0.2f * objAlpha; SetLinkedObjectAlpha(objAlpha, mgr); } std::optional<zeus::CAABox> CScriptDamageableTrigger::GetTouchBounds() const { if (x30_24_active && x300_24_notOccluded) { return zeus::CAABox(x14c_bounds.min + GetTranslation(), x14c_bounds.max + GetTranslation()); } return std::nullopt; } } // namespace metaforce