mirror of
				https://github.com/AxioDL/metaforce.git
				synced 2025-10-27 15:30:23 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			163 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			163 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include "Runtime/MP1/World/CAtomicAlpha.hpp"
 | |
| 
 | |
| #include <array>
 | |
| 
 | |
| #include "Runtime/CStateManager.hpp"
 | |
| #include "Runtime/Weapon/CPlayerGun.hpp"
 | |
| #include "Runtime/World/CGameArea.hpp"
 | |
| #include "Runtime/World/CPatternedInfo.hpp"
 | |
| #include "Runtime/World/CPlayer.hpp"
 | |
| #include "Runtime/World/CWorld.hpp"
 | |
| 
 | |
| namespace urde::MP1 {
 | |
| constexpr std::array skBombLocators{
 | |
|     "bomb1_LCTR"sv,
 | |
|     "bomb2_LCTR"sv,
 | |
|     "bomb3_LCTR"sv,
 | |
|     "bomb4_LCTR"sv,
 | |
| };
 | |
| 
 | |
| CAtomicAlpha::CAtomicAlpha(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
 | |
|                            CModelData&& mData, const CActorParameters& actParms, const CPatternedInfo& pInfo,
 | |
|                            CAssetId bombWeapon, const CDamageInfo& bombDamage, float bombDropDelay, float f2, float f3,
 | |
|                            CAssetId cmdl, bool invisible, bool b2)
 | |
| : CPatterned(ECharacter::AtomicAlpha, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
 | |
|              EMovementType::Flyer, EColliderType::One, EBodyType::Flyer, actParms, EKnockBackVariant::Medium)
 | |
| , x568_24_inRange(false)
 | |
| , x568_25_invisible(invisible)
 | |
| , x568_26_applyBeamAttraction(b2)
 | |
| , x56c_bomdDropDelay(bombDropDelay)
 | |
| , x570_bombReappearDelay(f2)
 | |
| , x574_bombRappearTime(f3)
 | |
| , x580_pathFind(nullptr, 3, pInfo.GetPathfindingIndex(), 1.f, 1.f)
 | |
| , x668_bombProjectile(bombWeapon, bombDamage)
 | |
| , x690_bombModel(CStaticRes(cmdl, GetModelData()->GetScale())) {
 | |
|   x668_bombProjectile.Token().Lock();
 | |
|   for (u32 i = 0; i < skBombCount; ++i) {
 | |
|     x6dc_bombLocators.emplace_back(skBombLocators[i], pas::ELocomotionType(u32(pas::ELocomotionType::Internal10) + i));
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
 | |
|   CPatterned::AcceptScriptMsg(msg, uid, mgr);
 | |
|   if (msg == EScriptObjectMessage::InitializedInArea) {
 | |
|     x580_pathFind.SetArea(mgr.GetWorld()->GetAreaAlways(GetAreaIdAlways())->GetPostConstructed()->x10bc_pathArea);
 | |
|   } else if (msg == EScriptObjectMessage::Registered) {
 | |
|     x450_bodyController->Activate(mgr);
 | |
|   } else if (msg == EScriptObjectMessage::AddSplashInhabitant) {
 | |
|     if (x400_25_alive)
 | |
|       x401_30_pendingDeath = true;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::Render(const CStateManager& mgr) const {
 | |
|   if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && x568_25_invisible)
 | |
|     return;
 | |
| 
 | |
|   CPatterned::Render(mgr);
 | |
|   for (const SBomb& bomb : x6dc_bombLocators) {
 | |
|     zeus::CTransform locatorXf =
 | |
|         GetTransform() * GetScaledLocatorTransform(bomb.x0_locatorName) *
 | |
|         zeus::CTransform::Scale(
 | |
|             std::min(1.f, std::max(0.f, bomb.x14_scaleTime - x570_bombReappearDelay) / x570_bombReappearDelay));
 | |
|     CModelFlags flags;
 | |
|     flags.x2_flags = 1 | 2;
 | |
|     flags.x4_color = zeus::skWhite;
 | |
|     x690_bombModel.Render(mgr, locatorXf, x90_actorLights.get(), flags);
 | |
|   }
 | |
| }
 | |
| void CAtomicAlpha::AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const {
 | |
|   if (mgr.GetPlayerState()->GetActiveVisor(mgr) != CPlayerState::EPlayerVisor::XRay && x568_25_invisible)
 | |
|     return;
 | |
|   CPatterned::AddToRenderer(frustum, mgr);
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::Think(float dt, CStateManager& mgr) {
 | |
|   CPatterned::Think(dt, mgr);
 | |
|   if (!GetActive())
 | |
|     return;
 | |
| 
 | |
|   x578_bombTime += dt;
 | |
| 
 | |
|   for (SBomb& bomb : x6dc_bombLocators) {
 | |
|     bomb.x14_scaleTime += dt;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) {
 | |
|   if (type == EUserEventType::Projectile) {
 | |
|     zeus::CVector3f origin = GetLctrTransform(node.GetLocatorName()).origin;
 | |
|     zeus::CTransform xf = zeus::lookAt(origin, origin + zeus::skDown, zeus::skUp);
 | |
|     LaunchProjectile(xf, mgr, 4, EProjectileAttrib::None, false, {}, 0xFFFF, false, zeus::CVector3f(1.f));
 | |
|     x578_bombTime = 0.f;
 | |
|     x57c_curBomb = (x57c_curBomb + 1) & (x6dc_bombLocators.size() - 1);
 | |
|   } else
 | |
|     CPatterned::DoUserAnimEvent(mgr, node, type, dt);
 | |
| }
 | |
| 
 | |
| bool CAtomicAlpha::Leash(CStateManager& mgr, float) {
 | |
|   if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() <=
 | |
|       x3cc_playerLeashRadius * x3cc_playerLeashRadius)
 | |
|     return false;
 | |
| 
 | |
|   return x3d4_curPlayerLeashTime > x3d0_playerLeashTime;
 | |
| }
 | |
| 
 | |
| bool CAtomicAlpha::AggressionCheck(CStateManager& mgr, float) {
 | |
|   const CPlayerGun* playerGun = mgr.GetPlayer().GetPlayerGun();
 | |
|   float factor = 0.f;
 | |
|   if (x568_26_applyBeamAttraction && playerGun->IsCharging())
 | |
|     factor = playerGun->GetChargeBeamFactor();
 | |
|   return factor > 0.1f;
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::CollidedWith(TUniqueId uid, const CCollisionInfoList& list, CStateManager& mgr) {
 | |
|   if (IsAlive()) {
 | |
|     if (TCastToConstPtr<CPlayer> pl = mgr.GetObjectById(uid)) {
 | |
|       if (x420_curDamageRemTime <= 0.f) {
 | |
|         mgr.GetPlayerState()->GetStaticInterference().AddSource(GetUniqueId(), 0.5f, 0.25f);
 | |
|         for (SBomb& bomb : x6dc_bombLocators) {
 | |
|           bomb.x14_scaleTime = 0.f;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   CPatterned::CollidedWith(uid, list, mgr);
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::Patrol(CStateManager& mgr, EStateMsg msg, float arg) {
 | |
|   CPatterned::Patrol(mgr, msg, arg);
 | |
|   if (msg == EStateMsg::Activate) {
 | |
|     x578_bombTime = 0.f;
 | |
|   } else if (msg == EStateMsg::Update) {
 | |
|     if (x568_24_inRange) {
 | |
|       if (x578_bombTime >= x56c_bomdDropDelay &&
 | |
|           x6dc_bombLocators[0].x14_scaleTime > (x570_bombReappearDelay + x574_bombRappearTime)) {
 | |
|         x450_bodyController->SetLocomotionType(x6dc_bombLocators[x57c_curBomb].x10_locomotionType);
 | |
|       } else {
 | |
|         x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
 | |
|       }
 | |
|       if (Leash(mgr, arg))
 | |
|         x568_24_inRange = false;
 | |
|     } else {
 | |
|       x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
 | |
|       if (InMaxRange(mgr, arg))
 | |
|         x568_24_inRange = true;
 | |
|     }
 | |
|   } else if (msg == EStateMsg::Deactivate) {
 | |
|     x568_24_inRange = false;
 | |
|   }
 | |
| }
 | |
| 
 | |
| void CAtomicAlpha::Attack(CStateManager& mgr, EStateMsg msg, float) {
 | |
|   if (msg == EStateMsg::Activate) {
 | |
|     x450_bodyController->SetLocomotionType(pas::ELocomotionType::Internal8);
 | |
|   } else if (msg == EStateMsg::Update) {
 | |
|     zeus::CVector3f seekVec = x664_steeringBehaviors.Seek(*this, mgr.GetPlayer().GetEyePosition());
 | |
|     x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(seekVec, {}, 1.f));
 | |
|   } else if (msg == EStateMsg::Deactivate) {
 | |
|     x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
 | |
|   }
 | |
| }
 | |
| } // namespace urde::MP1
 |