CElitePirate: Nearly complete implementation

This commit is contained in:
Luke Street 2020-03-29 03:28:14 -04:00
parent 4f7e0a85a3
commit 4ada5a00cb
5 changed files with 556 additions and 166 deletions

View File

@ -68,7 +68,7 @@ enum class EFallState { Invalid = -1, Zero, One , Two};
enum class EReactionType { Invalid = -1, Zero, One, Two, Three }; enum class EReactionType { Invalid = -1, Zero, One, Two, Three };
enum class EAdditiveReactionType { Invalid = -1, Electrocution, One, Two, IceBreakout }; enum class EAdditiveReactionType { Invalid = -1, Electrocution, One, Two, IceBreakout, Four, Five, Six, Seven };
enum class EJumpType { Normal, One, Ambush }; enum class EJumpType { Normal, One, Ambush };
@ -96,7 +96,7 @@ enum class ELoopState { Invalid = -1, Begin, Loop, End };
enum class ELoopAttackType { Invalid = -1 }; enum class ELoopAttackType { Invalid = -1 };
enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four }; enum class EGenerateType { Invalid = -1, Zero, One, Two, Three, Four, Five };
enum class ESlideType { Invalid = -1, Zero = 0 }; enum class ESlideType { Invalid = -1, Zero = 0 };

View File

@ -41,8 +41,8 @@ static constexpr std::array<SSphereJointInfo, 7> skSphereJointList{{
} // namespace } // namespace
CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount) CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount)
: x0_(in.readFloatBig()) : x0_tauntInterval(in.readFloatBig())
, x4_(in.readFloatBig()) , x4_tauntVariance(in.readFloatBig())
, x8_(in.readFloatBig()) , x8_(in.readFloatBig())
, xc_(in.readFloatBig()) , xc_(in.readFloatBig())
, x10_(in.readFloatBig()) , x10_(in.readFloatBig())
@ -57,13 +57,13 @@ CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount)
, xa0_(CSfxManager::TranslateSFXID(in.readUint32Big())) , xa0_(CSfxManager::TranslateSFXID(in.readUint32Big()))
, xa4_(in) , xa4_(in)
, xa8_(in) , xa8_(in)
, xc4_(in.readFloatBig()) , xc4_launcherHp(in.readFloatBig())
, xc8_(in) , xc8_(in)
, xcc_(in) , xcc_(in)
, xd0_(in) , xd0_(in)
, xd4_(in) , xd4_(in)
, xd8_(in) , xd8_(in)
, xe0_(in.readFloatBig(), in.readFloatBig(), zeus::degToRad(in.readFloatBig()), zeus::degToRad(in.readFloatBig())) , xe0_trajectoryInfo(in)
, xf0_(in) , xf0_(in)
, xf4_(CSfxManager::TranslateSFXID(in.readUint32Big())) , xf4_(CSfxManager::TranslateSFXID(in.readUint32Big()))
, xf6_(CSfxManager::TranslateSFXID(in.readUint32Big())) , xf6_(CSfxManager::TranslateSFXID(in.readUint32Big()))
@ -72,15 +72,15 @@ CElitePirateData::CElitePirateData(CInputStream& in, u32 propCount)
, x118_(in) , x118_(in)
, x11c_(CSfxManager::TranslateSFXID(in.readUint32Big())) , x11c_(CSfxManager::TranslateSFXID(in.readUint32Big()))
, x11e_(in.readBool()) , x11e_(in.readBool())
, x11f_(propCount < 24 ? true : in.readBool()) {} , x11f_(propCount < 42 ? true : in.readBool()) {}
CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf, CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityInfo& info, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms, CModelData&& mData, const CPatternedInfo& pInfo, const CActorParameters& actParms,
const CElitePirateData& eliteData) const CElitePirateData& data)
: CPatterned(ECharacter::ElitePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo, : CPatterned(ECharacter::ElitePirate, uid, name, EFlavorType::Zero, info, xf, std::move(mData), pInfo,
EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large) EMovementType::Ground, EColliderType::One, EBodyType::BiPedal, actParms, EKnockBackVariant::Large)
, x56c_vulnerability(pInfo.GetDamageVulnerability()) , x56c_vulnerability(pInfo.GetDamageVulnerability())
, x5d8_data(eliteData) , x5d8_data(data)
, x6f8_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f), , x6f8_boneTracking(*GetModelData()->GetAnimationData(), "Head_1", zeus::degToRad(80.f), zeus::degToRad(180.f),
EBoneTrackingFlags::None) EBoneTrackingFlags::None)
, x738_(GetBoundingBox(), GetMaterialList()) , x738_(GetBoundingBox(), GetMaterialList())
@ -96,7 +96,7 @@ CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityIn
, x988_31_(false) , x988_31_(false)
, x989_24_(false) { , x989_24_(false) {
if (x5d8_data.GetX20().IsValid()) { if (x5d8_data.GetX20().IsValid()) {
x760_ = g_SimplePool->GetObj({SBIG('PART'), x5d8_data.GetX20()}); x760_energyAbsorbDesc = g_SimplePool->GetObj({SBIG('PART'), x5d8_data.GetX20()});
} }
x460_knockBackController.SetEnableFreeze(false); x460_knockBackController.SetEnableFreeze(false);
@ -109,7 +109,26 @@ CElitePirate::CElitePirate(TUniqueId uid, std::string_view name, const CEntityIn
void CElitePirate::Accept(IVisitor& visitor) { visitor.Visit(this); } void CElitePirate::Accept(IVisitor& visitor) { visitor.Visit(this); }
void CElitePirate::Think(float dt, CStateManager& mgr) { CPatterned::Think(dt, mgr); } void CElitePirate::Think(float dt, CStateManager& mgr) {
if (GetActive()) {
CPatterned::Think(dt, mgr);
x6f8_boneTracking.Update(dt);
if (sub_802273a8()) {
x730_collisionActorMgr2->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
}
x5d4_collisionActorMgr1->Update(dt, mgr, CCollisionActorManager::EUpdateOptions::ObjectSpace);
if (sub_80229208() && x5d8_data.x11f_) {
x3b4_speed = 2.f * x7a0_;
} else {
x3b4_speed = x7a0_;
}
sub_80228e50(dt);
sub_80228798();
sub_802289dc(mgr, x772_launcherId, "grenadeLauncher_LCTR"sv);
sub_80228e84(mgr);
x328_31_ = sub_80229208();
}
}
void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) { void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
bool shouldPass = true; bool shouldPass = true;
@ -149,7 +168,7 @@ void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
} }
const TUniqueId& touchedUid = actor->GetLastTouchedObject(); const TUniqueId& touchedUid = actor->GetLastTouchedObject();
if (touchedUid != GetUniqueId()) { if (touchedUid != GetUniqueId()) {
if (TCastToPtr<CGameProjectile> projectile = mgr.ObjectById(touchedUid)) { if (TCastToPtr<CGameProjectile>(mgr.ObjectById(touchedUid))) {
sub_8022759c(true, mgr); sub_8022759c(true, mgr);
} }
break; break;
@ -207,8 +226,8 @@ void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
KnockBack(projectile->GetTranslation() - projectile->GetPreviousPos(), mgr, damageInfo, KnockBack(projectile->GetTranslation() - projectile->GetPreviousPos(), mgr, damageInfo,
EKnockBackType::Radius, false, damageInfo.GetKnockBackPower()); EKnockBackType::Radius, false, damageInfo.GetKnockBackPower());
CPatterned::AcceptScriptMsg(msg, uid, mgr); CPatterned::AcceptScriptMsg(msg, uid, mgr);
} else if (uid == x79c_ && x760_->IsLoaded()) { } else if (uid == x79c_ && x760_energyAbsorbDesc->IsLoaded()) {
sub_802281d8(mgr, projectile->GetTransform()); CreateEnergyAbsorb(mgr, projectile->GetTransform());
} }
sub_8022759c(true, mgr); sub_8022759c(true, mgr);
} }
@ -216,14 +235,13 @@ void CElitePirate::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CSta
x450_bodyController->GetCommandMgr().DeliverCmd( x450_bodyController->GetCommandMgr().DeliverCmd(
CBCKnockBackCmd(GetTransform().frontVector(), pas::ESeverity::Eight)); CBCKnockBackCmd(GetTransform().frontVector(), pas::ESeverity::Eight));
} else { } else {
sub_80227464(mgr, uid); ApplyDamageToHead(mgr, uid);
} }
break; break;
case EScriptObjectMessage::InvulnDamage: { case EScriptObjectMessage::InvulnDamage: {
sub_8022759c(true, mgr); sub_8022759c(true, mgr);
TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid); if (!TCastToPtr<CCollisionActor>(mgr.ObjectById(uid))) {
if (!actor) { ApplyDamageToHead(mgr, uid);
sub_80227464(mgr, uid);
} }
break; break;
} }
@ -269,7 +287,7 @@ zeus::CVector3f CElitePirate::GetOrbitPosition(const CStateManager& mgr) const {
return GetLctrTransform("lockon_target_LCTR").origin; return GetLctrTransform("lockon_target_LCTR").origin;
} }
zeus::CVector3f CElitePirate::GetAimPosition(const CStateManager& mgr, float dt) const { zeus::CVector3f CElitePirate::GetAimPosition(const CStateManager& mgr, float) const {
std::shared_ptr<CPlayerState> playerState = mgr.GetPlayerState(); std::shared_ptr<CPlayerState> playerState = mgr.GetPlayerState();
if (x5d4_collisionActorMgr1->GetActive() && playerState->IsFiringComboBeam() && if (x5d4_collisionActorMgr1->GetActive() && playerState->IsFiringComboBeam() &&
playerState->GetCurrentBeam() == CPlayerState::EBeamId::Wave) { playerState->GetCurrentBeam() == CPlayerState::EBeamId::Wave) {
@ -370,28 +388,28 @@ void CElitePirate::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
x6f8_boneTracking.SetActive(true); x6f8_boneTracking.SetActive(true);
sub_80228634(mgr); sub_80228634(mgr);
CPatterned::PathFind(mgr, msg, dt); CPatterned::PathFind(mgr, msg, dt);
x7bc_ = x5d8_data.x4_ * mgr.GetActiveRandom()->Float() + x5d8_data.x0_; x7bc_tauntTimer = x5d8_data.x4_tauntVariance * mgr.GetActiveRandom()->Float() + x5d8_data.x0_tauntInterval;
if (TooClose(mgr, 0.f)) { if (TooClose(mgr, 0.f)) {
x450_bodyController->GetCommandMgr().ClearLocomotionCmds(); x450_bodyController->GetCommandMgr().ClearLocomotionCmds();
} }
} else if (msg == EStateMsg::Update) { } else if (msg == EStateMsg::Update) {
if (x7bc_ > 0.f) { if (x7bc_tauntTimer > 0.f) {
x7bc_ -= dt; x7bc_tauntTimer -= dt;
} }
if (!TooClose(mgr, 0.f) && !PathShagged(mgr, 0.f)) { if (!TooClose(mgr, 0.f) && !PathShagged(mgr, 0.f)) {
CPatterned::PathFind(mgr, msg, dt); CPatterned::PathFind(mgr, msg, dt);
} else { } else {
if (PathShagged(mgr, 0.f)) { if (PathShagged(mgr, 0.f)) {
const zeus::CVector3f& move = x8c0_.sub_802a07f0(GetTranslation(), GetTransform().frontVector()); const zeus::CVector3f& move = x8c0_.GetValue(GetTranslation(), GetTransform().frontVector());
if (move != zeus::skZero3f) { if (move != zeus::skZero3f) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f));
} }
} else if (ShouldTurn(mgr, 0.f)) { } else if (ShouldTurn(mgr, 0.f)) {
const zeus::CVector3f& aim = const zeus::CVector3f& aim =
mgr.GetPlayer().GetAimPosition(mgr, 0.5f * GetModelData()->GetAnimationData()->GetSpeedScale()); mgr.GetPlayer().GetAimPosition(mgr, 0.5f * GetModelData()->GetAnimationData()->GetSpeedScale());
const zeus::CVector3f& move = aim - GetTranslation(); const zeus::CVector3f& face = aim - GetTranslation();
if (move.canBeNormalized()) { if (face.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, move.normalized(), 1.f)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, face.normalized(), 1.f));
} }
} }
} }
@ -400,9 +418,32 @@ void CElitePirate::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
} }
} }
void CElitePirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) { CPatterned::TargetPatrol(mgr, msg, dt); } void CElitePirate::TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
if (HasPatrolPath(mgr, 0.f)) {
CPatterned::Patrol(mgr, msg, dt);
UpdateDest(mgr);
} else {
SetDestPos(x3a0_latestLeashPosition);
}
x8b4_ = x2e0_destPos;
if (GetSearchPath() != nullptr) {
CPatterned::PathFind(mgr, msg, dt);
}
} else if (msg == EStateMsg::Update) {
if (PathShagged(mgr, 0.f)) {
const zeus::CVector3f& move = x45c_steeringBehaviors.Arrival(*this, x8b4_, 25.f);
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f));
} else {
CPatterned::PathFind(mgr, msg, dt);
}
} else if (msg == EStateMsg::Deactivate) {
x988_28_alert = false;
}
}
void CElitePirate::Halt(CStateManager& mgr, EStateMsg msg, float dt) { void CElitePirate::Halt(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) { if (msg == EStateMsg::Activate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk); x450_bodyController->SetLocomotionType(pas::ELocomotionType::Lurk);
x989_24_ = false; x989_24_ = false;
@ -429,15 +470,15 @@ void CElitePirate::Run(CStateManager& mgr, EStateMsg msg, float dt) {
CPatterned::PathFind(mgr, msg, dt); CPatterned::PathFind(mgr, msg, dt);
} else if (msg == EStateMsg::Update) { } else if (msg == EStateMsg::Update) {
if (PathShagged(mgr, 0.f)) { if (PathShagged(mgr, 0.f)) {
auto move = x8c0_.sub_802a07f0(GetTranslation(), GetTransform().frontVector()); auto move = x8c0_.GetValue(GetTranslation(), GetTransform().frontVector());
if (move != zeus::skZero3f) { if (move != zeus::skZero3f) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f));
} else if (ShouldTurn(mgr, 0.f)) { } else if (ShouldTurn(mgr, 0.f)) {
const zeus::CVector3f& aim = const zeus::CVector3f& aim =
mgr.GetPlayer().GetAimPosition(mgr, 0.5f * GetModelData()->GetAnimationData()->GetSpeedScale()); mgr.GetPlayer().GetAimPosition(mgr, 0.5f * GetModelData()->GetAnimationData()->GetSpeedScale());
move = aim - GetTranslation(); auto face = aim - GetTranslation();
if (move.canBeNormalized()) { if (face.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, move.normalized(), 1.f)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, face.normalized(), 1.f));
} }
} }
} else { } else {
@ -450,65 +491,104 @@ void CElitePirate::Run(CStateManager& mgr, EStateMsg msg, float dt) {
} }
} }
void CElitePirate::Generate(CStateManager& mgr, EStateMsg msg, float dt) { void CElitePirate::Generate(CStateManager& mgr, EStateMsg msg, float) {
switch (msg) { if (msg == EStateMsg::Activate) {
case EStateMsg::Activate: x568_ = EState::One;
x568_ = 1; } else if (msg == EStateMsg::Update) {
break; if (x568_ == EState::Zero) {
case EStateMsg::Update:
switch (x568_) {
case 0:
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) {
x568_ = 2; x568_ = EState::Two;
} else { } else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Zero));
} }
break; } else if (x568_ == EState::One) {
case 1:
if (ShouldTurn(mgr, 0.f)) { if (ShouldTurn(mgr, 0.f)) {
const auto& playerPos = mgr.GetPlayer().GetTranslation(); const auto& face = mgr.GetPlayer().GetTranslation() - GetTranslation();
if (playerPos.canBeNormalized()) { if (face.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd( x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, face.normalized(), 1.f));
CBCLocomotionCmd(zeus::skZero3f, playerPos.normalized(), 1.f));
} }
} else { } else {
x568_ = 0; x568_ = EState::Zero;
} }
break; } else if (x568_ == EState::Two && x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) {
case 2: x568_ = EState::Over;
if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) {
x568_ = 3;
}
break;
} }
break; } else if (msg == EStateMsg::Deactivate) {
case EStateMsg::Deactivate:
sub_8022759c(false, mgr); sub_8022759c(false, mgr);
sub_802289b0(mgr, true); sub_802289b0(mgr, true);
break;
} }
} }
void CElitePirate::Attack(CStateManager& mgr, EStateMsg msg, float dt) { CAi::Attack(mgr, msg, dt); } void CElitePirate::Attack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
x568_ = EState::Zero;
ExtendTouchBounds(mgr, x774_collisionRJointIds, zeus::CVector3f(2.f));
if (x64_modelData->GetNumMaterialSets() > 1) {
x7cc_ = 1;
}
} else if (msg == EStateMsg::Update) {
if (x568_ == EState::Zero) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
x568_ = EState::One;
x988_25_ = true;
x7c8_currAnimId = x450_bodyController->GetCurrentAnimId();
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::One));
}
} else if (x568_ == EState::One) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
if (x7c8_currAnimId == x450_bodyController->GetCurrentAnimId()) {
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
if (ShouldAttack(mgr, 0.f)) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCMeleeAttackCmd(pas::ESeverity::Two));
}
} else {
x568_ = EState::Two;
x988_25_ = false;
x988_26_ = true;
ExtendTouchBounds(mgr, x774_collisionRJointIds, zeus::skZero3f);
ExtendTouchBounds(mgr, x788_collisionLJointIds, zeus::CVector3f(2.f));
}
} else {
x568_ = EState::Over;
}
} else if (x568_ == EState::Two) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::MeleeAttack) {
x450_bodyController->GetCommandMgr().DeliverTargetVector(mgr.GetPlayer().GetTranslation() - GetTranslation());
} else {
x568_ = EState::Over;
}
}
} else if (msg == EStateMsg::Deactivate) {
sub_802285c4(mgr);
x988_24_ = false;
x988_26_ = false;
x988_25_ = false;
x7c8_currAnimId = -1;
ExtendTouchBounds(mgr, x774_collisionRJointIds, zeus::skZero3f);
ExtendTouchBounds(mgr, x788_collisionLJointIds, zeus::skZero3f);
x7cc_ = 0;
}
}
void CElitePirate::Taunt(CStateManager& mgr, EStateMsg msg, float dt) { CAi::Taunt(mgr, msg, dt); } void CElitePirate::Taunt(CStateManager& mgr, EStateMsg msg, float dt) { CAi::Taunt(mgr, msg, dt); }
void CElitePirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) { void CElitePirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) { if (msg == EStateMsg::Activate) {
x568_ = 0; x568_ = EState::Zero;
} else if (msg == EStateMsg::Update) { } else if (msg == EStateMsg::Update) {
const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation(); const zeus::CVector3f& playerPos = mgr.GetPlayer().GetTranslation();
if (x568_ == 0) { if (x568_ == EState::Zero) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
x568_ = 2; x568_ = EState::Two;
} else { } else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity::One, playerPos, false)); x450_bodyController->GetCommandMgr().DeliverCmd(CBCProjectileAttackCmd(pas::ESeverity::One, playerPos, false));
} }
} else if (x568_ == 2) { } else if (x568_ == EState::Two) {
if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::ProjectileAttack) {
x450_bodyController->GetCommandMgr().DeliverTargetVector(playerPos - GetTranslation()); x450_bodyController->GetCommandMgr().DeliverTargetVector(playerPos - GetTranslation());
} else { } else {
x568_ = 3; x568_ = EState::Over;
} }
} }
} else if (msg == EStateMsg::Deactivate) { } else if (msg == EStateMsg::Deactivate) {
@ -518,32 +598,105 @@ void CElitePirate::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt)
void CElitePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) { CAi::SpecialAttack(mgr, msg, dt); } void CElitePirate::SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) { CAi::SpecialAttack(mgr, msg, dt); }
void CElitePirate::CallForBackup(CStateManager& mgr, EStateMsg msg, float dt) { CAi::CallForBackup(mgr, msg, dt); } void CElitePirate::CallForBackup(CStateManager& mgr, EStateMsg msg, float) {
if (msg == EStateMsg::Activate) {
bool CElitePirate::TooClose(CStateManager& mgr, float arg) { return CPatterned::TooClose(mgr, arg); } x568_ = EState::Zero;
x988_30_ = true;
bool CElitePirate::InDetectionRange(CStateManager& mgr, float arg) { sub_8022759c(false, mgr);
if (x988_28_alert) { } else if (msg == EStateMsg::Update) {
return true; if (x568_ == EState::Zero) {
} else { if (x450_bodyController->GetCurrentStateId() == pas::EAnimationState::Generate) {
return CPatterned::InDetectionRange(mgr, arg); x568_ = EState::Two;
} else {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCGenerateCmd(pas::EGenerateType::Five, zeus::skZero3f));
}
} else if (x568_ == EState::Two) {
if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Generate) {
x568_ = EState::Over;
}
}
} else if (msg == EStateMsg::Deactivate) {
SendScriptMsgs(EScriptObjectState::Zero, mgr, EScriptObjectMessage::None);
} }
} }
bool CElitePirate::SpotPlayer(CStateManager& mgr, float arg) { return CPatterned::SpotPlayer(mgr, arg); } void CElitePirate::Cover(CStateManager& mgr, EStateMsg msg, float dt) {
if (msg == EStateMsg::Activate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Crouch);
if (sub_802273a8()) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(x770_collisionHeadId)) {
actor->SetDamageVulnerability(CDamageVulnerability::ImmuneVulnerabilty());
}
}
x5d4_collisionActorMgr1->SetActive(mgr, true);
x6f8_boneTracking.SetTarget(mgr.GetPlayer().GetUniqueId());
x6f8_boneTracking.SetActive(true);
sub_80228634(mgr);
CPatterned::PathFind(mgr, msg, dt);
if (TooClose(mgr, 0.f)) {
x450_bodyController->GetCommandMgr().ClearLocomotionCmds();
}
} else if (msg == EStateMsg::Update) {
if (x988_27_) {
x7c0_ -= dt;
if (x7c0_ <= 0.f) {
x988_27_ = false;
}
}
x7a8_ = PathShagged(mgr, 0.f) ? x7a8_ + dt : 0.f;
if (!TooClose(mgr, 0.f) && !PathShagged(mgr, 0.f)) {
CPatterned::PathFind(mgr, msg, dt);
} else if (PathShagged(mgr, 0.f)) {
const zeus::CVector3f& move = x8c0_.GetValue(GetTranslation(), GetTransform().frontVector());
if (move != zeus::skZero3f) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(move, zeus::skZero3f, 1.f));
}
} else if (ShouldTurn(mgr, 0.f)) {
const zeus::CVector3f& aim =
mgr.GetPlayer().GetAimPosition(mgr, 0.5f * GetModelData()->GetAnimationData()->GetSpeedScale());
const zeus::CVector3f& face = aim - GetTranslation();
if (face.canBeNormalized()) {
x450_bodyController->GetCommandMgr().DeliverCmd(CBCLocomotionCmd(zeus::skZero3f, face.normalized(), 1.f));
}
}
sub_80227a90(mgr);
sub_802277e0(mgr, dt);
} else if (msg == EStateMsg::Deactivate) {
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
x6f8_boneTracking.SetActive(false);
if (sub_802273a8()) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(x770_collisionHeadId)) {
actor->SetDamageVulnerability(x56c_vulnerability);
}
}
x5d4_collisionActorMgr1->SetActive(mgr, false);
}
}
bool CElitePirate::AnimOver(CStateManager& mgr, float arg) { return x568_ == 3; } bool CElitePirate::TooClose(CStateManager& mgr, float) {
return x2fc_minAttackRange * x2fc_minAttackRange > (GetTranslation() - mgr.GetPlayer().GetTranslation()).magSquared();
}
bool CElitePirate::ShouldAttack(CStateManager& mgr, float arg) { bool CElitePirate::InDetectionRange(CStateManager& mgr, float arg) {
return x988_28_alert ? true : CPatterned::InDetectionRange(mgr, arg);
}
bool CElitePirate::SpotPlayer(CStateManager& mgr, float arg) {
return x988_28_alert ? true : CPatterned::SpotPlayer(mgr, arg);
}
bool CElitePirate::AnimOver(CStateManager& mgr, float) { return x568_ == EState::Over; }
bool CElitePirate::ShouldAttack(CStateManager& mgr, float) {
if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange) { if ((mgr.GetPlayer().GetTranslation() - GetTranslation()).magSquared() > x2fc_minAttackRange * x2fc_minAttackRange) {
return false; return false;
} }
return !ShouldTurn(mgr, 0.f); return !ShouldTurn(mgr, 0.f);
} }
bool CElitePirate::InPosition(CStateManager& mgr, float arg) { return (x8b4_ - GetTranslation()).magSquared() < 25.f; } bool CElitePirate::InPosition(CStateManager& mgr, float) { return (x8b4_ - GetTranslation()).magSquared() < 25.f; }
bool CElitePirate::ShouldTurn(CStateManager& mgr, float arg) { bool CElitePirate::ShouldTurn(CStateManager& mgr, float) {
return zeus::CVector2f::getAngleDiff((mgr.GetPlayer().GetTranslation() - GetTranslation()).toVec2f(), return zeus::CVector2f::getAngleDiff((mgr.GetPlayer().GetTranslation() - GetTranslation()).toVec2f(),
GetTransform().frontVector().toVec2f()) > zeus::degToRad(15.f); GetTransform().frontVector().toVec2f()) > zeus::degToRad(15.f);
} }
@ -559,17 +712,29 @@ bool CElitePirate::AggressionCheck(CStateManager& mgr, float arg) {
return false; return false;
} }
bool CElitePirate::ShouldTaunt(CStateManager& mgr, float arg) { return CAi::ShouldTaunt(mgr, arg); } bool CElitePirate::ShouldTaunt(CStateManager& mgr, float) { return x7bc_tauntTimer <= 0.f; }
bool CElitePirate::ShouldFire(CStateManager& mgr, float arg) { return CAi::ShouldFire(mgr, arg); } bool CElitePirate::ShouldFire(CStateManager& mgr, float) { return ShouldFireFromLauncher(mgr, x772_launcherId); }
bool CElitePirate::ShotAt(CStateManager& mgr, float arg) { return x988_27_; } bool CElitePirate::ShotAt(CStateManager& mgr, float) { return x988_27_; }
bool CElitePirate::ShouldSpecialAttack(CStateManager& mgr, float arg) { return CAi::ShouldSpecialAttack(mgr, arg); } bool CElitePirate::ShouldSpecialAttack(CStateManager& mgr, float) {
if (x7b8_attackTimer <= 0.f && GetAreaIdAlways() == mgr.GetPlayer().GetAreaIdAlways()) {
const zeus::CVector3f& dist = mgr.GetPlayer().GetAimPosition(mgr, 0.f) - GetTranslation();
float magSquared = dist.magSquared();
if (x2fc_minAttackRange * x2fc_minAttackRange <= magSquared &&
magSquared <= x300_maxAttackRange * x300_maxAttackRange) {
return std::abs(dist.z()) < 3.f;
}
}
return false;
}
bool CElitePirate::ShouldCallForBackup(CStateManager& mgr, float arg) { return CAi::ShouldCallForBackup(mgr, arg); } bool CElitePirate::ShouldCallForBackup(CStateManager& mgr, float) {
return ShouldCallForBackupFromLauncher(mgr, x772_launcherId);
}
CPathFindSearch* CElitePirate::GetSearchPath() { return CPatterned::GetSearchPath(); } CPathFindSearch* CElitePirate::GetSearchPath() { return &x7d0_pathFindSearch; }
void CElitePirate::SetupHealthInfo(CStateManager& mgr) { void CElitePirate::SetupHealthInfo(CStateManager& mgr) {
const CHealthInfo* const health = HealthInfo(mgr); const CHealthInfo* const health = HealthInfo(mgr);
@ -732,16 +897,17 @@ void CElitePirate::CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid) {
} }
CModelData mData(CAnimRes(params.GetACSFile(), params.GetCharacter(), GetModelData()->GetScale(), CModelData mData(CAnimRes(params.GetACSFile(), params.GetCharacter(), GetModelData()->GetScale(),
params.GetInitialAnimation(), true)); params.GetInitialAnimation(), true));
SGrenadeLauncherData transfer{x5d8_data.xd8_, x5d8_data.xa8_, x5d8_data.xc8_, x5d8_data.xcc_, x5d8_data.xd0_, SBouncyGrenadeData grenadeData{x5d8_data.xd8_, x5d8_data.xa8_, x5d8_data.xc8_, x5d8_data.xcc_, x5d8_data.xd0_,
x5d8_data.xd4_, x5d8_data.xf0_, x5d8_data.xf4_, x5d8_data.xf6_}; x5d8_data.xd4_, x5d8_data.xf0_, x5d8_data.xf4_, x5d8_data.xf6_};
CGrenadeLauncherData launcherData{transfer, x5d8_data.xa4_, x5d8_data.x9c_, x5d8_data.xa0_, x5d8_data.xe0_}; CGrenadeLauncherData launcherData{grenadeData, x5d8_data.xa4_, x5d8_data.x9c_, x5d8_data.xa0_,
x5d8_data.xe0_trajectoryInfo};
mgr.AddObject(new CGrenadeLauncher(uid, "Grenade Launcher", {GetAreaIdAlways(), CEntity::NullConnectionList}, mgr.AddObject(new CGrenadeLauncher(uid, "Grenade Launcher", {GetAreaIdAlways(), CEntity::NullConnectionList},
GetTransform(), std::move(mData), mData.GetBounds(GetTransform().getRotation()), GetTransform(), std::move(mData), mData.GetBounds(GetTransform().getRotation()),
CHealthInfo(x5d8_data.xc4_, 10.f), x56c_vulnerability, CHealthInfo(x5d8_data.xc4_launcherHp, 10.f), x56c_vulnerability,
x5d8_data.x28_launcherActParams, GetUniqueId(), launcherData, 0.f)); x5d8_data.x28_launcherActParams, GetUniqueId(), launcherData, 0.f));
} }
void CElitePirate::sub_80227464(CStateManager& mgr, TUniqueId uid) { void CElitePirate::ApplyDamageToHead(CStateManager& mgr, TUniqueId uid) {
if (!sub_802273a8()) { if (!sub_802273a8()) {
return; return;
} }
@ -753,14 +919,15 @@ void CElitePirate::sub_80227464(CStateManager& mgr, TUniqueId uid) {
} }
} }
void CElitePirate::sub_802281d8(CStateManager& mgr, const zeus::CTransform& xf) { void CElitePirate::CreateEnergyAbsorb(CStateManager& mgr, const zeus::CTransform& xf) {
if (x7ac_ > 0.f) { if (x7ac_energyAbsorbCooldown > 0.f) {
return; return;
} }
mgr.AddObject(new CExplosion(*x760_, mgr.AllocateUniqueId(), true, {GetAreaIdAlways(), CEntity::NullConnectionList}, mgr.AddObject(new CExplosion(*x760_energyAbsorbDesc, mgr.AllocateUniqueId(), true,
"Absorb energy Fx", xf, 0, GetModelData()->GetScale(), zeus::skWhite)); {GetAreaIdAlways(), CEntity::NullConnectionList}, "Absorb energy Fx", xf, 0,
GetModelData()->GetScale(), zeus::skWhite));
CSfxManager::AddEmitter(x5d8_data.x24_sfxAbsorb, GetTranslation(), zeus::skUp, false, false, 0x7f, GetAreaIdAlways()); CSfxManager::AddEmitter(x5d8_data.x24_sfxAbsorb, GetTranslation(), zeus::skUp, false, false, 0x7f, GetAreaIdAlways());
x7ac_ = 0.25f; x7ac_energyAbsorbCooldown = 0.25f;
} }
void CElitePirate::UpdateHealthInfo(CStateManager& mgr, TUniqueId uid) { void CElitePirate::UpdateHealthInfo(CStateManager& mgr, TUniqueId uid) {
@ -768,7 +935,7 @@ void CElitePirate::UpdateHealthInfo(CStateManager& mgr, TUniqueId uid) {
if (uid != kInvalidUniqueId) { if (uid != kInvalidUniqueId) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid)) { if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid)) {
auto actHealth = actor->HealthInfo(mgr); auto actHealth = actor->HealthInfo(mgr);
actHealth->SetHP(x5d8_data.xc4_); actHealth->SetHP(x5d8_data.xc4_launcherHp);
actHealth->SetKnockbackResistance(health->GetKnockbackResistance()); actHealth->SetKnockbackResistance(health->GetKnockbackResistance());
actor->SetDamageVulnerability(x56c_vulnerability); actor->SetDamageVulnerability(x56c_vulnerability);
} }
@ -804,11 +971,131 @@ void CElitePirate::sub_80228634(CStateManager& mgr) {
void CElitePirate::sub_802285c4(CStateManager& mgr) { void CElitePirate::sub_802285c4(CStateManager& mgr) {
if (mgr.GetActiveRandom()->Float() > x5d8_data.x10_) { if (mgr.GetActiveRandom()->Float() > x5d8_data.x10_) {
x7b8_ = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime; x7b8_attackTimer = x308_attackTimeVariation * mgr.GetActiveRandom()->Float() + x304_averageAttackTime;
} }
} }
zeus::CVector3f CElitePirate::SUnknownStruct::sub_802a07f0(const zeus::CVector3f& v1, const zeus::CVector3f& v2) { void CElitePirate::sub_80227a90(CStateManager& mgr) {
// TODO
}
void CElitePirate::sub_802277e0(CStateManager& mgr, float dt) {
if (!x988_27_ || x450_bodyController->IsFrozen()) {
return;
}
x7c4_ += dt;
if (x7c4_ < 3.f) {
return;
}
if (x450_bodyController->GetCurrentStateId() != pas::EAnimationState::Turn &&
x450_bodyController->GetBodyStateInfo().GetCurrentState()->IsMoving()) {
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCAdditiveReactionCmd(pas::EAdditiveReactionType::Six, 1.f, false));
} else {
bool b = false;
if (sub_802273a8()) {
if (TCastToConstPtr<CCollisionActor> actor = mgr.GetObjectById(x770_collisionHeadId)) {
float z = actor->GetTranslation().z();
b = z - 0.5f * (z - GetTranslation().z()) <= mgr.GetPlayer().GetTranslation().z();
}
}
b = b || TooClose(mgr, 0.f);
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCAdditiveReactionCmd(b ? pas::EAdditiveReactionType::Seven : pas::EAdditiveReactionType::Five, 1.f, false));
}
x7c4_ = 0.f;
}
bool CElitePirate::sub_80229208() {
if (x450_bodyController->GetLocomotionType() != pas::ELocomotionType::Crouch) {
return false;
}
const pas::EAnimationState state = x450_bodyController->GetCurrentStateId();
return state == pas::EAnimationState::Locomotion || state == pas::EAnimationState::Turn;
}
void CElitePirate::sub_80228e50(float dt) {
if (x7b8_attackTimer > 0.f) {
x7b8_attackTimer -= dt;
}
if (x7ac_energyAbsorbCooldown > 0.f) {
x7ac_energyAbsorbCooldown -= dt;
}
}
void CElitePirate::sub_80228798() {
const zeus::CVector3f& pos = GetTranslation();
if (x7d0_pathFindSearch.OnPath(pos) == CPathFindSearch::EResult::Success) {
x8c0_.Clear();
}
x8c0_.AddValue(pos);
}
void CElitePirate::sub_802289dc(CStateManager& mgr, TUniqueId& uid, std::string_view name) {
if (uid == kInvalidUniqueId) {
return;
}
CActor* actor = static_cast<CActor*>(mgr.ObjectById(uid));
if (actor == nullptr) {
uid = kInvalidUniqueId;
return;
}
actor->SetTransform(GetLctrTransform(name));
}
void CElitePirate::sub_80228e84(CStateManager& mgr) {
float hp = HealthInfo(mgr)->GetHP();
if (sub_802273a8()) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(x770_collisionHeadId)) {
float headHp = actor->HealthInfo(mgr)->GetHP();
HealthInfo(mgr)->SetHP(hp - (hp - headHp));
*actor->HealthInfo(mgr) = *HealthInfo(mgr); // TODO does this work?
}
}
if (HealthInfo(mgr)->GetHP() <= 0.f) {
Death(mgr, zeus::skZero3f, EScriptObjectState::DeathRattle);
RemoveMaterial(EMaterialTypes::Orbit, EMaterialTypes::Target, mgr);
}
}
void CElitePirate::ExtendTouchBounds(CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 7>& uids,
const zeus::CVector3f& vec) {
for (const TUniqueId uid : uids) {
if (TCastToPtr<CCollisionActor> actor = mgr.ObjectById(uid)) {
actor->SetExtendedTouchBounds(vec);
}
}
}
bool CElitePirate::ShouldFireFromLauncher(CStateManager& mgr, TUniqueId launcherId) {
if (x7b8_attackTimer <= 0.f && launcherId != kInvalidUniqueId) {
const CActor* launcher = static_cast<const CActor*>(mgr.GetObjectById(launcherId));
if (launcher != nullptr) {
const zeus::CVector3f& aim = mgr.GetPlayer().GetAimPosition(mgr, 0.f);
if (x300_maxAttackRange * x300_maxAttackRange <= (aim - GetTranslation()).magSquared() && !ShouldTurn(mgr, 0.f)) {
const zeus::CVector3f& origin = sub_80228864(launcher);
if (!IsPatternObstructed(mgr, origin, aim)) {
const zeus::CVector3f& target = CGrenadeLauncher::GrenadeTarget(mgr);
float angleOut = x5d8_data.xe0_trajectoryInfo.x8_angleMin, velocityOut = x5d8_data.xe0_trajectoryInfo.x0_;
CGrenadeLauncher::CalculateGrenadeTrajectory(target, origin, x5d8_data.xe0_trajectoryInfo, angleOut,
velocityOut);
const zeus::CVector3f& rot = GetTransform().rotate({0.f, std::cos(angleOut), std::sin(angleOut)});
return !CPatterned::IsPatternObstructed(mgr, target, target + (7.5f * rot));
}
}
}
}
return false;
}
bool CElitePirate::ShouldCallForBackupFromLauncher(CStateManager& mgr, TUniqueId uid) {
if (!x988_30_ && uid == kInvalidUniqueId && x5d8_data.x11e_) {
return x7a8_ >= 3.f;
}
return false;
}
zeus::CVector3f CElitePirate::SUnknownStruct::GetValue(const zeus::CVector3f& v1, const zeus::CVector3f& v2) {
while (x4_.size()) { while (x4_.size()) {
const zeus::CVector3f v = x4_[x4_.size() - 1] - v1; const zeus::CVector3f v = x4_[x4_.size() - 1] - v1;
if (v.dot(v2) > 0.f && v.isMagnitudeSafe()) { if (v.dot(v2) > 0.f && v.isMagnitudeSafe()) {
@ -818,4 +1105,17 @@ zeus::CVector3f CElitePirate::SUnknownStruct::sub_802a07f0(const zeus::CVector3f
} }
return zeus::skZero3f; return zeus::skZero3f;
} }
void CElitePirate::SUnknownStruct::AddValue(const zeus::CVector3f& vec) {
if (x4_.size() > 15) {
return;
}
if (x4_.empty()) {
x4_.emplace_back(vec);
return;
}
if (x4_[x4_.size() - 1].magSquared() > x0_) {
x4_.emplace_back(vec);
}
}
} // namespace urde::MP1 } // namespace urde::MP1

View File

@ -2,6 +2,7 @@
#include "Runtime/Character/CBoneTracking.hpp" #include "Runtime/Character/CBoneTracking.hpp"
#include "Runtime/Collision/CJointCollisionDescription.hpp" #include "Runtime/Collision/CJointCollisionDescription.hpp"
#include "Runtime/MP1/World/CGrenadeLauncher.hpp"
#include "Runtime/MP1/World/CShockWave.hpp" #include "Runtime/MP1/World/CShockWave.hpp"
#include "Runtime/World/CActorParameters.hpp" #include "Runtime/World/CActorParameters.hpp"
#include "Runtime/World/CAnimationParameters.hpp" #include "Runtime/World/CAnimationParameters.hpp"
@ -14,8 +15,8 @@ class CGenDescription;
namespace MP1 { namespace MP1 {
class CElitePirateData { class CElitePirateData {
public: public:
float x0_; float x0_tauntInterval;
float x4_; float x4_tauntVariance;
float x8_; float x8_;
float xc_; float xc_;
float x10_; float x10_;
@ -23,20 +24,20 @@ public:
float x18_; float x18_;
float x1c_; float x1c_;
CAssetId x20_; CAssetId x20_;
s16 x24_sfxAbsorb; u16 x24_sfxAbsorb;
CActorParameters x28_launcherActParams; CActorParameters x28_launcherActParams;
CAnimationParameters x90_launcherAnimParams; CAnimationParameters x90_launcherAnimParams;
CAssetId x9c_; CAssetId x9c_;
u16 xa0_; u16 xa0_;
CAssetId xa4_; CAssetId xa4_;
CDamageInfo xa8_; CDamageInfo xa8_;
float xc4_; float xc4_launcherHp;
CAssetId xc8_; CAssetId xc8_;
CAssetId xcc_; CAssetId xcc_;
CAssetId xd0_; CAssetId xd0_;
CAssetId xd4_; CAssetId xd4_;
CHealthInfo xd8_; // FIXME probably wrong type SGrenadeUnknownStruct xd8_;
zeus::CQuaternion xe0_; // FIXME probably wrong type SGrenadeTrajectoryInfo xe0_trajectoryInfo;
CAssetId xf0_; CAssetId xf0_;
u16 xf4_; u16 xf4_;
u16 xf6_; u16 xf6_;
@ -61,10 +62,20 @@ class CElitePirate : public CPatterned {
float x0_; float x0_;
rstl::reserved_vector<zeus::CVector3f, 16> x4_; rstl::reserved_vector<zeus::CVector3f, 16> x4_;
SUnknownStruct(float f) : x0_(f * f) {} SUnknownStruct(float f) : x0_(f * f) {}
zeus::CVector3f sub_802a07f0(const zeus::CVector3f& v1, const zeus::CVector3f& v2); zeus::CVector3f GetValue(const zeus::CVector3f& v1, const zeus::CVector3f& v2);
void AddValue(const zeus::CVector3f& vec);
void Clear() { x4_.clear(); }
}; };
s32 x568_ = -1; enum class EState {
Invalid = -1,
Zero = 0,
One = 1,
Two = 2,
Over = 3,
};
EState x568_ = EState::Invalid;
CDamageVulnerability x56c_vulnerability; CDamageVulnerability x56c_vulnerability;
std::unique_ptr<CCollisionActorManager> x5d4_collisionActorMgr1; std::unique_ptr<CCollisionActorManager> x5d4_collisionActorMgr1;
CElitePirateData x5d8_data; CElitePirateData x5d8_data;
@ -72,7 +83,7 @@ class CElitePirate : public CPatterned {
std::unique_ptr<CCollisionActorManager> x730_collisionActorMgr2; std::unique_ptr<CCollisionActorManager> x730_collisionActorMgr2;
s32 x734_; s32 x734_;
CCollidableAABox x738_; CCollidableAABox x738_;
std::optional<TLockedToken<CGenDescription>> x760_; std::optional<TLockedToken<CGenDescription>> x760_energyAbsorbDesc;
TUniqueId x770_collisionHeadId = kInvalidUniqueId; TUniqueId x770_collisionHeadId = kInvalidUniqueId;
TUniqueId x772_launcherId = kInvalidUniqueId; TUniqueId x772_launcherId = kInvalidUniqueId;
rstl::reserved_vector<TUniqueId, 7> x774_collisionRJointIds; rstl::reserved_vector<TUniqueId, 7> x774_collisionRJointIds;
@ -81,14 +92,14 @@ class CElitePirate : public CPatterned {
float x7a0_; float x7a0_;
float x7a4_ = 1.f; float x7a4_ = 1.f;
float x7a8_ = 0.f; float x7a8_ = 0.f;
float x7ac_ = 0.f; float x7ac_energyAbsorbCooldown = 0.f;
float x7b0_ = 1.f; float x7b0_ = 1.f;
float x7b4_hp = 0.f; float x7b4_hp = 0.f;
float x7b8_ = 0.f; float x7b8_attackTimer = 0.f;
float x7bc_ = 0.f; float x7bc_tauntTimer = 0.f;
float x7c0_ = 0.f; float x7c0_ = 0.f;
float x7c4_ = 0.f; float x7c4_ = 0.f;
s32 x7c8_ = -1; s32 x7c8_currAnimId = -1;
s32 x7cc_ = 0; s32 x7cc_ = 0;
CPathFindSearch x7d0_pathFindSearch; CPathFindSearch x7d0_pathFindSearch;
zeus::CVector3f x8b4_; zeus::CVector3f x8b4_;
@ -121,33 +132,34 @@ public:
zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const override; zeus::CVector3f GetAimPosition(const CStateManager& mgr, float) const override;
void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override; void DoUserAnimEvent(CStateManager& mgr, const CInt32POINode& node, EUserEventType type, float dt) override;
const CCollisionPrimitive* GetCollisionPrimitive() const override; const CCollisionPrimitive* GetCollisionPrimitive() const override;
void KnockBack(const zeus::CVector3f&, CStateManager&, const CDamageInfo& info, EKnockBackType type, bool inDeferred, void KnockBack(const zeus::CVector3f&, CStateManager& mgr, const CDamageInfo& info, EKnockBackType type,
float magnitude) override; bool inDeferred, float magnitude) override;
void TakeDamage(const zeus::CVector3f&, float arg) override; void TakeDamage(const zeus::CVector3f&, float arg) override;
void Patrol(CStateManager&, EStateMsg msg, float dt) override; void Patrol(CStateManager& mgr, EStateMsg msg, float dt) override;
void PathFind(CStateManager&, EStateMsg msg, float dt) override; void PathFind(CStateManager& mgr, EStateMsg msg, float dt) override;
void TargetPatrol(CStateManager&, EStateMsg msg, float dt) override; void TargetPatrol(CStateManager& mgr, EStateMsg msg, float dt) override;
void Halt(CStateManager&, EStateMsg msg, float dt) override; void Halt(CStateManager& mgr, EStateMsg msg, float dt) override;
void Run(CStateManager&, EStateMsg msg, float dt) override; void Run(CStateManager& mgr, EStateMsg msg, float dt) override;
void Generate(CStateManager&, EStateMsg msg, float dt) override; void Generate(CStateManager& mgr, EStateMsg msg, float dt) override;
void Attack(CStateManager&, EStateMsg msg, float dt) override; void Attack(CStateManager& mgr, EStateMsg msg, float dt) override;
void Taunt(CStateManager&, EStateMsg msg, float dt) override; void Taunt(CStateManager& mgr, EStateMsg msg, float dt) override;
void ProjectileAttack(CStateManager&, EStateMsg msg, float dt) override; void ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) override;
void SpecialAttack(CStateManager&, EStateMsg msg, float dt) override; void SpecialAttack(CStateManager& mgr, EStateMsg msg, float dt) override;
void CallForBackup(CStateManager&, EStateMsg msg, float dt) override; void CallForBackup(CStateManager& mgr, EStateMsg msg, float dt) override;
bool TooClose(CStateManager&, float arg) override; void Cover(CStateManager& mgr, EStateMsg msg, float dt) override;
bool InDetectionRange(CStateManager&, float arg) override; bool TooClose(CStateManager& mgr, float arg) override;
bool SpotPlayer(CStateManager&, float arg) override; bool InDetectionRange(CStateManager& mgr, float arg) override;
bool AnimOver(CStateManager&, float arg) override; bool SpotPlayer(CStateManager& mgr, float arg) override;
bool ShouldAttack(CStateManager&, float arg) override; bool AnimOver(CStateManager& mgr, float arg) override;
bool InPosition(CStateManager&, float arg) override; bool ShouldAttack(CStateManager& mgr, float arg) override;
bool ShouldTurn(CStateManager&, float arg) override; bool InPosition(CStateManager& mgr, float arg) override;
bool AggressionCheck(CStateManager&, float arg) override; bool ShouldTurn(CStateManager& mgr, float arg) override;
bool ShouldTaunt(CStateManager&, float arg) override; bool AggressionCheck(CStateManager& mgr, float arg) override;
bool ShouldFire(CStateManager&, float arg) override; bool ShouldTaunt(CStateManager& mgr, float arg) override;
bool ShotAt(CStateManager&, float arg) override; bool ShouldFire(CStateManager& mgr, float arg) override;
bool ShouldSpecialAttack(CStateManager&, float arg) override; bool ShotAt(CStateManager& mgr, float arg) override;
bool ShouldCallForBackup(CStateManager&, float arg) override; bool ShouldSpecialAttack(CStateManager& mgr, float arg) override;
bool ShouldCallForBackup(CStateManager& mgr, float arg) override;
CPathFindSearch* GetSearchPath() override; CPathFindSearch* GetSearchPath() override;
virtual bool sub_802273a8() const { return true; } virtual bool sub_802273a8() const { return true; }
virtual bool sub_802273b0() const { return true; } virtual bool sub_802273b0() const { return true; }
@ -169,14 +181,25 @@ private:
void SetupCollisionActorInfo(CStateManager& mgr); void SetupCollisionActorInfo(CStateManager& mgr);
bool IsArmClawCollider(std::string_view name, std::string_view locator, const SJointInfo* info, size_t infoCount); bool IsArmClawCollider(std::string_view name, std::string_view locator, const SJointInfo* info, size_t infoCount);
void CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid); void CreateGrenadeLauncher(CStateManager& mgr, TUniqueId uid);
void sub_80227464(CStateManager& mgr, TUniqueId uid); void ApplyDamageToHead(CStateManager& mgr, TUniqueId uid);
void sub_802281d8(CStateManager& mgr, const zeus::CTransform& xf); void CreateEnergyAbsorb(CStateManager& mgr, const zeus::CTransform& xf);
void UpdateHealthInfo(CStateManager& mgr, TUniqueId uid); void UpdateHealthInfo(CStateManager& mgr, TUniqueId uid);
void sub_80228920(CStateManager& mgr, bool b, TUniqueId uid); void sub_80228920(CStateManager& mgr, bool b, TUniqueId uid);
zeus::CVector3f sub_80228864(const CActor* actor) const; zeus::CVector3f sub_80228864(const CActor* actor) const;
bool sub_80227430(const CDamageInfo& info) const; bool sub_80227430(const CDamageInfo& info) const;
void sub_80228634(CStateManager& mgr); void sub_80228634(CStateManager& mgr);
void sub_802285c4(CStateManager& mgr); void sub_802285c4(CStateManager& mgr);
void sub_80227a90(CStateManager& mgr);
void sub_802277e0(CStateManager& mgr, float dt);
bool sub_80229208();
void sub_80228e50(float dt);
void sub_80228798();
void sub_802289dc(CStateManager& mgr, TUniqueId& uid, std::string_view name);
void sub_80228e84(CStateManager& mgr);
void ExtendTouchBounds(CStateManager& mgr, const rstl::reserved_vector<TUniqueId, 7>& uids,
const zeus::CVector3f& vec);
bool ShouldFireFromLauncher(CStateManager& mgr, TUniqueId launcherId);
bool ShouldCallForBackupFromLauncher(CStateManager& mgr, TUniqueId uid);
}; };
} // namespace MP1 } // namespace MP1
} // namespace urde } // namespace urde

View File

@ -1,9 +1,11 @@
#include "Runtime/MP1/World/CGrenadeLauncher.hpp" #include "Runtime/MP1/World/CGrenadeLauncher.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Character/CPASAnimParm.hpp" #include "Runtime/Character/CPASAnimParm.hpp"
#include "Runtime/Character/CPASAnimParmData.hpp" #include "Runtime/Character/CPASAnimParmData.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/World/CPlayer.hpp"
namespace urde { namespace urde {
namespace MP1 { namespace MP1 {
@ -30,5 +32,54 @@ CGrenadeLauncher::CGrenadeLauncher(TUniqueId uid, std::string_view name, const C
x3c8_animIds[i] = result.second; x3c8_animIds[i] = result.second;
} }
} }
zeus::CVector3f CGrenadeLauncher::GrenadeTarget(const CStateManager& mgr) {
const zeus::CVector3f& aim = mgr.GetPlayer().GetAimPosition(mgr, 1.f);
if (mgr.GetPlayer().GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphed) {
return aim - zeus::CVector3f{0.f, 0.f, 0.5f * mgr.GetPlayer().GetEyeHeight()};
}
return aim;
}
void CGrenadeLauncher::CalculateGrenadeTrajectory(const zeus::CVector3f& target, const zeus::CVector3f& origin,
const SGrenadeTrajectoryInfo& info, float& angleOut,
float& velocityOut) {
float angle = info.x8_angleMin;
float velocity = info.x0_;
float delta = std::max(0.01f, 0.1f * (info.xc_angleMax - info.x8_angleMin));
zeus::CVector3f dist = target - origin;
float distXYMag = dist.toVec2f().magnitude();
float qwSq = info.x0_ * info.x0_;
float qxSq = info.x4_ * info.x4_;
float gravAdj = distXYMag * ((0.5f * CPhysicsActor::GravityConstant()) * distXYMag);
float currAngle = info.x8_angleMin;
float leastResult = FLT_MAX;
while (info.xc_angleMax >= currAngle) {
float cos = std::cos(currAngle);
float sin = std::sin(currAngle);
float result = (distXYMag * (cos * sin) - (dist.z() * (cos * cos)));
if (result > FLT_EPSILON) {
float div = gravAdj / result;
if (qwSq <= result && result <= qxSq) {
angle = currAngle;
velocity = std::sqrt(div);
break;
}
if (result <= qxSq) {
result = qwSq - result;
} else {
result = result - qxSq;
}
if (result < leastResult) {
angle = currAngle;
velocity = std::sqrt(div);
leastResult = result;
}
}
currAngle += delta;
}
angleOut = angle;
velocityOut = velocity;
}
} // namespace MP1 } // namespace MP1
} // namespace urde } // namespace urde

View File

@ -22,8 +22,28 @@
namespace urde { namespace urde {
namespace MP1 { namespace MP1 {
struct SGrenadeLauncherData { struct SGrenadeTrajectoryInfo {
CHealthInfo x0_healthInfo; float x0_;
float x4_;
float x8_angleMin;
float xc_angleMax;
SGrenadeTrajectoryInfo(CInputStream& in)
: x0_(in.readFloatBig())
, x4_(in.readFloatBig())
, x8_angleMin(zeus::degToRad(in.readFloatBig()))
, xc_angleMax(zeus::degToRad(in.readFloatBig())) {}
};
struct SGrenadeUnknownStruct {
float x0_mass;
float x4_;
SGrenadeUnknownStruct(CInputStream& in) : x0_mass(in.readFloatBig()), x4_(in.readFloatBig()) {}
};
struct SBouncyGrenadeData {
SGrenadeUnknownStruct x0_;
CDamageInfo x8_damageInfo; CDamageInfo x8_damageInfo;
CAssetId x24_; CAssetId x24_;
CAssetId x28_; CAssetId x28_;
@ -33,30 +53,22 @@ struct SGrenadeLauncherData {
u16 x38_; u16 x38_;
u16 x3a_; u16 x3a_;
SGrenadeLauncherData(const CHealthInfo& healthInfo, const CDamageInfo& damageInfo, CAssetId w1, CAssetId w2, SBouncyGrenadeData(const SGrenadeUnknownStruct& unkStruct, const CDamageInfo& damageInfo, CAssetId w1, CAssetId w2,
CAssetId w3, CAssetId w4, CAssetId w5, u16 s1, u16 s2) CAssetId w3, CAssetId w4, CAssetId w5, u16 s1, u16 s2)
: x0_healthInfo(healthInfo) : x0_(unkStruct), x8_damageInfo(damageInfo), x24_(w1), x28_(w2), x2c_(w3), x30_(w4), x34_(w5), x38_(s1), x3a_(s2){};
, x8_damageInfo(damageInfo)
, x24_(w1)
, x28_(w2)
, x2c_(w3)
, x30_(w4)
, x34_(w5)
, x38_(s1)
, x3a_(s2){};
}; };
class CGrenadeLauncherData { class CGrenadeLauncherData {
public: public:
SGrenadeLauncherData x0_; SBouncyGrenadeData x0_;
CAssetId x3c_; CAssetId x3c_;
CAssetId x40_; CAssetId x40_;
u16 x44_sfx; u16 x44_sfx;
zeus::CQuaternion x48_quat; SGrenadeTrajectoryInfo x48_trajectoryInfo;
CGrenadeLauncherData(const SGrenadeLauncherData& data, CAssetId w1, CAssetId w2, u16 sfx, CGrenadeLauncherData(const SBouncyGrenadeData& data, CAssetId w1, CAssetId w2, u16 sfx,
const zeus::CQuaternion& quat) const SGrenadeTrajectoryInfo& trajectoryInfo)
: x0_(data), x3c_(w1), x40_(w2), x44_sfx(sfx), x48_quat(quat){}; : x0_(data), x3c_(w1), x40_(w2), x44_sfx(sfx), x48_trajectoryInfo(trajectoryInfo){};
}; };
class CGrenadeLauncher : public CPhysicsActor { class CGrenadeLauncher : public CPhysicsActor {
@ -92,16 +104,20 @@ public:
const CGrenadeLauncherData& data, float f1); const CGrenadeLauncherData& data, float f1);
void Accept(IVisitor& visitor) override { visitor.Visit(this); } void Accept(IVisitor& visitor) override { visitor.Visit(this); }
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override; // void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) override;
void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override; // void AddToRenderer(const zeus::CFrustum& frustum, const CStateManager& mgr) const override;
const CCollisionPrimitive* GetCollisionPrimitive() const override { return &x328_cSphere; } const CCollisionPrimitive* GetCollisionPrimitive() const override { return &x328_cSphere; }
const CDamageVulnerability* GetDamageVulnerability() const override { return &x264_vulnerability; } const CDamageVulnerability* GetDamageVulnerability() const override { return &x264_vulnerability; }
std::optional<zeus::CAABox> GetTouchBounds() const override; // std::optional<zeus::CAABox> GetTouchBounds() const override;
CHealthInfo* HealthInfo(CStateManager& mgr) override; // CHealthInfo* HealthInfo(CStateManager& mgr) override;
void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override; // void PreRender(CStateManager& mgr, const zeus::CFrustum& frustum) override;
void Render(const CStateManager& mgr) const override; // void Render(const CStateManager& mgr) const override;
void Think(float dt, CStateManager& mgr) override; // void Think(float dt, CStateManager& mgr) override;
void Touch(CActor& act, CStateManager& mgr) override; // void Touch(CActor& act, CStateManager& mgr) override;
static zeus::CVector3f GrenadeTarget(const CStateManager& mgr);
static void CalculateGrenadeTrajectory(const zeus::CVector3f& target, const zeus::CVector3f& origin,
const SGrenadeTrajectoryInfo& info, float& angleOut, float& velocityOut);
protected: protected:
void UpdateCollision(); void UpdateCollision();