diff --git a/Runtime/MP1/World/CChozoGhost.cpp b/Runtime/MP1/World/CChozoGhost.cpp index b458af192..8ad615c90 100644 --- a/Runtime/MP1/World/CChozoGhost.cpp +++ b/Runtime/MP1/World/CChozoGhost.cpp @@ -5,7 +5,10 @@ #include "Runtime/CSimplePool.hpp" #include "Runtime/CRandom16.hpp" #include "Runtime/Character/CPASAnimParmData.hpp" +#include "Runtime/Weapon/CGameProjectile.hpp" #include "Runtime/World/CPlayer.hpp" +#include "Runtime/World/CScriptCoverPoint.hpp" +#include "Runtime/World/CScriptWaypoint.hpp" #include "Runtime/World/CTeamAiMgr.hpp" #include "TCastTo.hpp" // Generated file, do not modify include path @@ -225,7 +228,19 @@ void CChozoGhost::Render(const CStateManager& mgr) const { } } -void CChozoGhost::Touch(CActor& act, CStateManager& mgr) { CPatterned::Touch(act, mgr); } +void CChozoGhost::Touch(CActor& act, CStateManager& mgr) { + + if (IsVisibleEnough(mgr)) { + if (TCastToPtr pl = act) { + if (x420_curDamageRemTime <= 0.f) { + mgr.ApplyDamage(GetUniqueId(), pl->GetUniqueId(), GetUniqueId(), GetContactDamage(), + CMaterialFilter::MakeIncludeExclude({EMaterialTypes::Solid}, {}), {}); + x420_curDamageRemTime = x424_damageWaitTime; + } + } + } + CPatterned::Touch(act, mgr); +} EWeaponCollisionResponseTypes CChozoGhost::GetCollisionResponseType(const zeus::CVector3f& pos, const zeus::CVector3f& dir, const CWeaponMode& mode, @@ -234,7 +249,59 @@ EWeaponCollisionResponseTypes CChozoGhost::GetCollisionResponseType(const zeus:: } void CChozoGhost::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { + + if (type == EUserEventType::FadeIn) { + if (x664_30_) { + x3e8_alphaDelta = 2.f; + CSfxManager::AddEmitter(x630_, GetTranslation(), {}, false, false, 127, -1); + } + AddMaterial(EMaterialTypes::Target, mgr); + x664_30_ = false; + x664_29_ = true; + return; + } else if (type == EUserEventType::Projectile) { + zeus::CTransform xf = + zeus::lookAt(GetLctrTransform(node.GetLocatorName()).origin, mgr.GetPlayer().GetAimPosition(mgr, 0.f)); + if (x67c_ == 2) { + CGameProjectile* proj = + LaunchProjectile(xf, mgr, 2, EProjectileAttrib::BigStrike | EProjectileAttrib::StaticInterference, true, + {x640_}, x650_sound_ProjectileVisor, false, zeus::skOne3f); + if (proj) { + proj->AddAttrib(EProjectileAttrib::BigStrike); + proj->SetDamageDuration(x62c_); + proj->AddAttrib(EProjectileAttrib::StaticInterference); + proj->SetInterferenceDuration(x62c_); + proj->SetMinHomingDistance(x634_); + } + } else { + CGameProjectile* proj = + LaunchProjectile(xf, mgr, 5, EProjectileAttrib::DamageFalloff | EProjectileAttrib::StaticInterference, true, + {x640_}, x650_sound_ProjectileVisor, false, zeus::skOne3f); + if (proj) { + proj->AddAttrib(EProjectileAttrib::BigStrike); + proj->SetDamageDuration(x62c_); + proj->AddAttrib(EProjectileAttrib::StaticInterference); + proj->SetInterferenceDuration(x62c_); + proj->SetMinHomingDistance(x634_); + } + } + return; + } else if (type == EUserEventType::FadeOut) { + if (x664_29_) { + x3e8_alphaDelta = -2.f; + CSfxManager::AddEmitter(x632_, GetTranslation(), {}, false, false, 127, -1); + } + RemoveMaterial(EMaterialTypes::Target, mgr); + x664_29_ = false; + x664_30_ = true; + x665_26_ = true; + return; + } + CPatterned::DoUserAnimEvent(mgr, node, type, dt); + + if (type == EUserEventType::Delete) + x3e8_alphaDelta = -1.f; } void CChozoGhost::KnockBack(const zeus::CVector3f& dir, CStateManager& mgr, const CDamageInfo& info, @@ -473,7 +540,33 @@ void CChozoGhost::Hurled(CStateManager& mgr, EStateMsg msg, float arg) { } } -void CChozoGhost::WallDetach(CStateManager& mgr, EStateMsg msg, float arg) { CAi::WallDetach(mgr, msg, arg); } +void CChozoGhost::WallDetach(CStateManager& mgr, EStateMsg msg, float arg) { + if (msg == EStateMsg::Activate) { + x330_stateMachineState.SetDelay(x56c_fadeOutDelay); + x3e8_alphaDelta = 0.f; + x664_29_ = false; + if (x56c_fadeOutDelay > 0.f) { + x6c8_ = x56c_fadeOutDelay; + FindNearestSolid(mgr, GetTransform().basis[1]); + } + TUniqueId wpId = GetWaypointForState(mgr, EScriptObjectState::Attack, EScriptObjectMessage::Follow); + TCastToConstPtr wp; + if (wpId != kInvalidUniqueId) { + wp = TCastToConstPtr(mgr.GetObjectById(wpId)); + } + if (wp) + SetDestPos(wp->GetTranslation()); + else + SetDestPos(GetTranslation() + (2.f * x66c_) * GetTranslation()); + + SendScriptMsgs(EScriptObjectState::Attack, mgr, EScriptObjectMessage::Follow); + } else if (msg == EStateMsg::Deactivate) { + x68c_boneTracking.SetActive(true); + x68c_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId()); + x665_24_ = false; + x680_behaveType = EBehaveType::Move; + } +} void CChozoGhost::Growth(CStateManager& mgr, EStateMsg msg, float arg) { if (msg == EStateMsg::Activate) { @@ -586,6 +679,89 @@ void CChozoGhost::FindNearestSolid(CStateManager& mgr, const zeus::CVector3f& di x6cc_ = res.GetPoint(); } -void CChozoGhost::FindBestAnchor(urde::CStateManager& mgr) {} +void CChozoGhost::FindBestAnchor(urde::CStateManager& mgr) { + x665_27_playerInLeashRange = false; + u32 chance = mgr.GetActiveRandom()->Next() % 100; + chance = chance < x65c_nearChance ? 0 : (chance < (x65c_nearChance + x660_midChance)) + 2; + float dVar10 = 10.f; + float dVar15 = dVar10 * x658_; + float dVar14 = dVar15; + float dVar13 = dVar15; + if (chance == 0) { + dVar13 = dVar15 * dVar10; + dVar15 *= 5.f; + } else if (chance == 1) { + dVar13 = dVar15 * 5.f; + dVar15 *= dVar10; + } else if (chance == 2) { + dVar14 = dVar15 * 5.f; + dVar15 *= dVar10; + } + float prevDist = FLT_MAX; + CScriptCoverPoint* target = nullptr; + for (CEntity* ent : mgr.GetAiWaypointObjectList()) { + if (TCastToPtr cover = ent) { + if (cover->GetActive() && !cover->GetInUse(kInvalidUniqueId) && cover->GetAreaIdAlways() == GetAreaId()) { + float fVar17 = (cover->GetTranslation() - GetTranslation()).magnitude(); + if (2.f * x66c_ <= fVar17) { + float dist = std::max(0.f, x654_ - fVar17); + zeus::CVector3f diff = (cover->GetTranslation() - mgr.GetPlayer().GetTranslation()); + fVar17 = diff.magnitude(); + if (x2fc_minAttackRange <= fVar17) { + if (std::fabs(diff.z()) / fVar17 < 0.2f) { + dist = (20.f * x658_) * ((std::fabs(diff.z()) / fVar17) - 0.2f) + dist; + } + if (x654_ <= dVar10) { + if (x658_ <= dVar10) { + dist = (dist + dVar13); + } else { + dist = (dist + dVar14); + if (dist < prevDist) { + fVar17 = 1.f / dVar10; + diff = diff * fVar17; + dist += (10.f * x658_) * (1.f * mgr.GetPlayer().GetTransform().basis[1].dot(diff)); + } + } + } else { + dist += dVar15; + if (dist < prevDist) { + fVar17 = 1.f / dVar10; + diff = diff * fVar17; + dist += (10.f * x658_) * (1.f * mgr.GetPlayer().GetTransform().basis[1].dot(diff)); + } + } + if (dist < prevDist) { + dist += x658_ * mgr.GetActiveRandom()->Float(); + if (dist < prevDist) { + x665_27_playerInLeashRange = false; + target = cover; + prevDist = dist; + } + } + } + } + } + } + } + + if (target) { + x2dc_destObj = target->GetUniqueId(); + SetDestPos(target->GetTranslation()); + ReleaseCoverPoint(mgr, x674_coverPoint); + SetCoverPoint(target, x674_coverPoint); + } else if (mgr.GetPlayer().GetAreaIdAlways() == GetAreaIdAlways()) { + x2dc_destObj = mgr.GetPlayer().GetUniqueId(); + zeus::CVector3f destPos = + mgr.GetPlayer().GetTranslation() - x654_ * (mgr.GetPlayer().GetTranslation() - GetTranslation()).normalized(); + CRayCastResult res = + mgr.RayStaticIntersection(destPos, zeus::skDown, 8.f, CMaterialFilter::MakeInclude(EMaterialTypes::Floor)); + if (res.IsValid()) + destPos = res.GetPoint(); + SetDestPos(destPos); + } else { + x2dc_destObj = kInvalidUniqueId; + x2e0_destPos = GetTranslation(); + } +} } // namespace urde::MP1 \ No newline at end of file diff --git a/Runtime/Weapon/CGameProjectile.hpp b/Runtime/Weapon/CGameProjectile.hpp index 31f482089..752b097cf 100644 --- a/Runtime/Weapon/CGameProjectile.hpp +++ b/Runtime/Weapon/CGameProjectile.hpp @@ -92,5 +92,6 @@ public: const CProjectileWeapon& GetProjectileWeapon() const { return x170_projectile; } TUniqueId GetHomingTargetId() const { return x2c0_homingTargetId; } zeus::CVector3f GetPreviousPos() const { return x298_previousPos; } + void SetMinHomingDistance(float dist) { x2e0_minHomingDist = dist; } }; } // namespace urde diff --git a/Runtime/Weapon/CWeapon.hpp b/Runtime/Weapon/CWeapon.hpp index 672ee2002..025e89ab6 100644 --- a/Runtime/Weapon/CWeapon.hpp +++ b/Runtime/Weapon/CWeapon.hpp @@ -30,6 +30,7 @@ public: void Accept(IVisitor& visitor) override; bool HasAttrib(EProjectileAttrib attrib) const { return (int(xe8_projectileAttribs) & int(attrib)) == int(attrib); } EProjectileAttrib GetAttribField() const { return xe8_projectileAttribs; } + void AddAttrib(EProjectileAttrib attrib) { xe8_projectileAttribs |= attrib; } const CMaterialFilter& GetFilter() const { return xf8_filter; } void SetFilter(const CMaterialFilter& filter) { xf8_filter = filter; } TUniqueId GetOwnerId() const { return xec_ownerId; } @@ -39,7 +40,9 @@ public: CDamageInfo& DamageInfo() { return x12c_curDamageInfo; } void SetDamageInfo(const CDamageInfo& dInfo) { x12c_curDamageInfo = dInfo; } float GetDamageDuration() const { return x150_damageDuration; } + void SetDamageDuration(float dur) { x150_damageDuration = dur; } float GetInterferenceDuration() const { return x154_interferenceDuration; } + void SetInterferenceDuration(float dur) { x154_interferenceDuration = dur; } void Think(float, CStateManager&) override; void Render(const CStateManager&) const override; diff --git a/Runtime/World/CPatterned.cpp b/Runtime/World/CPatterned.cpp index 88fcb6a28..100fc1b27 100644 --- a/Runtime/World/CPatterned.cpp +++ b/Runtime/World/CPatterned.cpp @@ -1081,7 +1081,7 @@ void CPatterned::SetupPlayerCollision(bool v) { SetMaterialFilter(CMaterialFilter::MakeIncludeExclude(include, exclude)); } -void CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, +CGameProjectile* CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, bool playerHoming, const std::optional>& visorParticle, u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale) { @@ -1094,8 +1094,10 @@ void CPatterned::LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& pInfo->GetDamage(), mgr.AllocateUniqueId(), GetAreaIdAlways(), GetUniqueId(), homingId, attrib, false, scale, visorParticle, visorSfx, sendCollideMsg); mgr.AddObject(newProjectile); + return newProjectile; } } + return nullptr; } void CPatterned::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { diff --git a/Runtime/World/CPatterned.hpp b/Runtime/World/CPatterned.hpp index e8a6bb9a4..612eec1be 100644 --- a/Runtime/World/CPatterned.hpp +++ b/Runtime/World/CPatterned.hpp @@ -373,9 +373,10 @@ public: CBodyController* GetBodyController() { return x450_bodyController.get(); } const CKnockBackController& GetKnockBackController() const { return x460_knockBackController; } void SetupPlayerCollision(bool); - void LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, EProjectileAttrib attrib, - bool playerHoming, const std::optional>& visorParticle, - u16 visorSfx, bool sendCollideMsg, const zeus::CVector3f& scale); + CGameProjectile* LaunchProjectile(const zeus::CTransform& gunXf, CStateManager& mgr, int maxAllowed, + EProjectileAttrib attrib, bool playerHoming, + const std::optional>& visorParticle, u16 visorSfx, + bool sendCollideMsg, const zeus::CVector3f& scale); void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; void SetDestPos(const zeus::CVector3f& pos) { x2e0_destPos = pos; } diff --git a/Runtime/World/CScriptCoverPoint.cpp b/Runtime/World/CScriptCoverPoint.cpp index 20bbf4eb9..44af6ac16 100644 --- a/Runtime/World/CScriptCoverPoint.cpp +++ b/Runtime/World/CScriptCoverPoint.cpp @@ -45,10 +45,7 @@ bool CScriptCoverPoint::GetInUse(TUniqueId uid) const { if (xf8_25_inUse || x11c_timeLeft > 0.f) return true; - if (xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid) - return false; - - return true; + return !(xfa_occupant == kInvalidUniqueId || uid == kInvalidUniqueId || xfa_occupant == uid); } bool CScriptCoverPoint::Blown(const zeus::CVector3f& point) const { diff --git a/Runtime/World/CStateMachine.cpp b/Runtime/World/CStateMachine.cpp index 74c261f7f..c45e53bcf 100644 --- a/Runtime/World/CStateMachine.cpp +++ b/Runtime/World/CStateMachine.cpp @@ -111,7 +111,7 @@ void CStateMachineState::SetState(CStateManager& mgr, CAi& ai, const CStateMachi return; if (!x0_machine) - x0_machine = machine; + Setup(machine); s32 idx = machine->GetStateIndex(state); SetState(mgr, ai, idx); diff --git a/Runtime/World/CStateMachine.hpp b/Runtime/World/CStateMachine.hpp index 51470b73b..1c2ee71a5 100644 --- a/Runtime/World/CStateMachine.hpp +++ b/Runtime/World/CStateMachine.hpp @@ -27,7 +27,7 @@ public: bool CallFunc(CStateManager& mgr, CAi& ai) const { if (x0_func) { bool ret = (ai.*x0_func)(mgr, xc_arg); - return x18_lNot ? !ret : ret; + return x18_lNot == !ret; } return true; }