diff --git a/Runtime/MP1/World/CFlaahgra.cpp b/Runtime/MP1/World/CFlaahgra.cpp index 473ba5dc0..243b8b0bd 100644 --- a/Runtime/MP1/World/CFlaahgra.cpp +++ b/Runtime/MP1/World/CFlaahgra.cpp @@ -280,12 +280,49 @@ void CFlaahgra::Death(CStateManager& mgr, const zeus::CVector3f& dir, EScriptObj void CFlaahgra::DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) { switch (type) { case EUserEventType::Projectile: { + const auto lctrXf = GetLctrTransform(node.GetLocatorName()); + const auto attackTargetPos = GetAttackTargetPos(mgr); + if (x7b4_ == 0 || x7b4_ == 1) { + if (x72c_ == 0) { + x730_.clear(); + auto& player = mgr.GetPlayer(); + const auto interceptPos = + GetProjectileInfo()->PredictInterceptPos(lctrXf.origin, attackTargetPos, player, false, dt); + x730_.push_back(interceptPos); + const auto& xf = GetTransform(); + auto basis = xf.basis; + const auto rot = zeus::CMatrix3f::RotateZ(zeus::degToRad(x7b4_ == 1 ? -4.f : 4.f)); + for (int i = 1; i < x730_.capacity(); ++i) { + basis = basis * rot; + const auto vec = basis * xf.transposeRotate(interceptPos - xf.origin); + x730_.push_back(zeus::CVector3f{xf.origin.x() + vec.x(), xf.origin.y() + vec.y(), interceptPos.z()}); + } + if (x72c_ > -1 && x730_.size() > x72c_) { + CreateProjectile(zeus::lookAt(lctrXf.origin, x730_[x72c_]), mgr); + x72c_++; + } + } + } else { + CPlayer& player = mgr.GetPlayer(); + const auto interceptPos = + GetProjectileInfo()->PredictInterceptPos(lctrXf.origin, attackTargetPos, player, false, dt); + auto target = interceptPos; + auto dir = interceptPos - lctrXf.origin; + dir.z() = 0.f; + const auto frontVec = GetTransform().frontVector(); + if (zeus::CVector3f::getAngleDiff(frontVec, dir) > zeus::degToRad(45.f)) { + if (dir.canBeNormalized()) { + target = lctrXf.origin + + (dir.magnitude() * zeus::CVector3f::slerp(frontVec, dir.normalized(), zeus::degToRad(45.f))); + } else { + target = lctrXf.origin + dir.magnitude() * lctrXf.frontVector(); + } + } + CreateProjectile(zeus::lookAt(lctrXf.origin, target), mgr); + } return; } case EUserEventType::BeginAction: { -//#ifndef NDEBUG -// printf("BeginAction\n"); -//#endif x8e4_26_ = true; x7c4_ = GetEndActionTime(); break; @@ -844,7 +881,8 @@ void CFlaahgra::Generate(CStateManager& mgr, EStateMsg msg, float) { x7c0_ = 11.f; } } -zeus::CVector3f CFlaahgra::GetAttacktargetPos(const CStateManager& mgr) const { + +zeus::CVector3f CFlaahgra::GetAttackTargetPos(const CStateManager& mgr) const { if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphed) return mgr.GetPlayer().GetMorphBall()->GetBallToWorld().origin; @@ -1224,6 +1262,21 @@ void CFlaahgra::Enraged(CStateManager&, EStateMsg msg, float) { } } +CFlaahgraProjectile* CFlaahgra::CreateProjectile(const zeus::CTransform& xf, CStateManager& mgr) { + CProjectileInfo* projectileInfo = GetProjectileInfo(); + if (!projectileInfo->Token() || !mgr.CanCreateProjectile(GetUniqueId(), EWeaponType::AI, 6)) { + return nullptr; + } + CDamageInfo damageInfo = projectileInfo->GetDamage(); + if (x788_ > 1) { + damageInfo.SetDamage(damageInfo.GetDamage() * 1.33f); + } + auto* projectile = new CFlaahgraProjectile(x8e4_30_, projectileInfo->Token(), xf, damageInfo, mgr.AllocateUniqueId(), + GetAreaIdAlways(), GetUniqueId()); + mgr.AddObject(projectile); + return projectile; +} + CFlaahgraPlants::CFlaahgraPlants(const TToken& genDesc, const CActorParameters& actParms, TUniqueId uid, TAreaId aId, TUniqueId owner, const zeus::CTransform& xf, const CDamageInfo& dInfo, const zeus::CVector3f& extents) diff --git a/Runtime/MP1/World/CFlaahgra.hpp b/Runtime/MP1/World/CFlaahgra.hpp index 1a23dfdcd..9fd2c7eac 100644 --- a/Runtime/MP1/World/CFlaahgra.hpp +++ b/Runtime/MP1/World/CFlaahgra.hpp @@ -7,6 +7,7 @@ #include "Runtime/CDependencyGroup.hpp" #include "Runtime/rstl.hpp" #include "Runtime/Collision/CJointCollisionDescription.hpp" +#include "Runtime/MP1/World/CFlaahgraProjectile.hpp" #include "Runtime/Weapon/CProjectileInfo.hpp" #include "Runtime/World/CActorParameters.hpp" #include "Runtime/World/CAnimationParameters.hpp" @@ -88,13 +89,13 @@ public: class CFlaahgra : public CPatterned { s32 x568_ = -1; CFlaahgraData x56c_; - std::unique_ptr x6cc_boneTracking; // Used to be an rstl::pair + std::unique_ptr x6cc_boneTracking; // Used to be an rstl::optional_object TUniqueId x6d0_rendererId = kInvalidUniqueId; TToken x6d4_; CProjectileInfo x6dc_; CProjectileInfo x704_; s32 x72c_ = -1; - u32 x730_ = 0; + rstl::reserved_vector x730_; rstl::reserved_vector x770_mirrorWaypoints; TUniqueId x77c_ = kInvalidUniqueId; u32 x780_ = 1; @@ -174,7 +175,7 @@ class CFlaahgra : public CPatterned { void UpdateScale(float, float, float); float GetEndActionTime() const; void SetupHealthInfo(CStateManager&); - zeus::CVector3f GetAttacktargetPos(const CStateManager&) const; + zeus::CVector3f GetAttackTargetPos(const CStateManager& mgr) const; void RattlePlayer(CStateManager& mgr, const zeus::CVector3f& vec); bool sub801e4f8() const { return x7a8_ == 0 || x7a8_ == 1; } void sub801ade80(); @@ -182,6 +183,7 @@ class CFlaahgra : public CPatterned { u32 sub801ae828(const CStateManager&) const; zeus::CVector3f sub801ae754(const CStateManager&) const; + CFlaahgraProjectile* CreateProjectile(const zeus::CTransform& xf, CStateManager& mgr); TUniqueId GetMirrorNearestPlayer(const CStateManager&) const; @@ -229,4 +231,4 @@ public: void SpecialAttack(CStateManager&, EStateMsg, float) override; void Enraged(CStateManager&, EStateMsg, float) override; }; -} // namespace urde::MP1 \ No newline at end of file +} // namespace urde::MP1