2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-08-08 12:19:07 +00:00

Pathfinding and generator fixes

This commit is contained in:
Jack Andersen 2019-01-29 22:38:16 -10:00
parent c9a38c567f
commit c3d8afa852
7 changed files with 69 additions and 71 deletions

View File

@ -486,7 +486,7 @@ bool CSpacePirate::ShouldFrenzy(CStateManager& mgr) {
} }
void CSpacePirate::SquadReset(CStateManager& mgr) { void CSpacePirate::SquadReset(CStateManager& mgr) {
CTeamAiMgr::ResetTeamAiRole(!x634_27_melee ? CTeamAiMgr::EAttackType::Projectile : CTeamAiMgr::EAttackType::Melee, CTeamAiMgr::ResetTeamAiRole(!x634_27_melee ? CTeamAiMgr::EAttackType::Ranged : CTeamAiMgr::EAttackType::Melee,
mgr, x8c8_teamAiMgrId, GetUniqueId(), true); mgr, x8c8_teamAiMgrId, GetUniqueId(), true);
} }
@ -496,7 +496,7 @@ void CSpacePirate::SquadAdd(CStateManager& mgr) {
if (x8c8_teamAiMgrId != kInvalidUniqueId) { if (x8c8_teamAiMgrId != kInvalidUniqueId) {
if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) { if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x8c8_teamAiMgrId)) {
aimgr->AssignTeamAiRole(*this, aimgr->AssignTeamAiRole(*this,
x634_27_melee ? CTeamAiRole::ETeamAiRole::Melee : CTeamAiRole::ETeamAiRole::Projectile, x634_27_melee ? CTeamAiRole::ETeamAiRole::Melee : CTeamAiRole::ETeamAiRole::Ranged,
CTeamAiRole::ETeamAiRole::Unknown, CTeamAiRole::ETeamAiRole::Invalid); CTeamAiRole::ETeamAiRole::Unknown, CTeamAiRole::ETeamAiRole::Invalid);
} }
} }
@ -565,9 +565,9 @@ void CSpacePirate::UpdateAttacks(float dt, CStateManager& mgr) {
x7bc_attackRemTime -= dt; x7bc_attackRemTime -= dt;
if (x7bc_attackRemTime < 0.f) { if (x7bc_attackRemTime < 0.f) {
const CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x8c8_teamAiMgrId, GetUniqueId()); const CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x8c8_teamAiMgrId, GetUniqueId());
if (!role || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Projectile) { if (!role || role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged) {
if (x8c8_teamAiMgrId == kInvalidUniqueId || if (x8c8_teamAiMgrId == kInvalidUniqueId ||
CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Projectile, mgr, x8c8_teamAiMgrId, GetUniqueId())) { CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Ranged, mgr, x8c8_teamAiMgrId, GetUniqueId())) {
if (ShouldFrenzy(mgr)) if (ShouldFrenzy(mgr))
x7c4_burstFire.SetBurstType(2); x7c4_burstFire.SetBurstType(2);
if (x635_26_seated) if (x635_26_seated)

View File

@ -41,7 +41,7 @@ void CWarWasp::SwarmAdd(CStateManager& mgr) {
if (x674_aiMgr != kInvalidUniqueId) { if (x674_aiMgr != kInvalidUniqueId) {
if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x674_aiMgr)) { if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x674_aiMgr)) {
CTeamAiRole::ETeamAiRole role = x3fc_flavor == EFlavorType::Two ? CTeamAiRole::ETeamAiRole role = x3fc_flavor == EFlavorType::Two ?
CTeamAiRole::ETeamAiRole::Projectile : CTeamAiRole::ETeamAiRole::Melee; CTeamAiRole::ETeamAiRole::Ranged : CTeamAiRole::ETeamAiRole::Melee;
if (!aimgr->IsPartOfTeam(GetUniqueId())) { if (!aimgr->IsPartOfTeam(GetUniqueId())) {
aimgr->AssignTeamAiRole(*this, role, CTeamAiRole::ETeamAiRole::Invalid, CTeamAiRole::ETeamAiRole::Invalid); aimgr->AssignTeamAiRole(*this, role, CTeamAiRole::ETeamAiRole::Invalid, CTeamAiRole::ETeamAiRole::Invalid);
} }
@ -343,7 +343,7 @@ void CWarWasp::ApplySeparationBehavior(CStateManager& mgr, float sep) {
float useSep = sep; float useSep = sep;
if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x674_aiMgr, ai->GetUniqueId())) { if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x674_aiMgr, ai->GetUniqueId())) {
if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Melee || if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Melee ||
role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Projectile) role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged)
useSep *= 2.f; useSep *= 2.f;
} }
zeus::CVector3f separation = x45c_steeringBehaviors.Separation(*this, ai->GetTranslation(), useSep); zeus::CVector3f separation = x45c_steeringBehaviors.Separation(*this, ai->GetTranslation(), useSep);
@ -724,7 +724,7 @@ void CWarWasp::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) {
case EStateMsg::Activate: case EStateMsg::Activate:
x72e_28_inProjectileAttack = true; x72e_28_inProjectileAttack = true;
if (x674_aiMgr != kInvalidUniqueId) { if (x674_aiMgr != kInvalidUniqueId) {
x568_stateProg = CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Projectile, x568_stateProg = CTeamAiMgr::AddAttacker(CTeamAiMgr::EAttackType::Ranged,
mgr, x674_aiMgr, GetUniqueId()) ? 0 : 3; mgr, x674_aiMgr, GetUniqueId()) ? 0 : 3;
} else { } else {
x568_stateProg = 0; x568_stateProg = 0;
@ -752,7 +752,7 @@ void CWarWasp::ProjectileAttack(CStateManager& mgr, EStateMsg msg, float dt) {
} }
break; break;
case EStateMsg::Deactivate: case EStateMsg::Deactivate:
CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Projectile, mgr, x674_aiMgr, GetUniqueId(), false); CTeamAiMgr::ResetTeamAiRole(CTeamAiMgr::EAttackType::Ranged, mgr, x674_aiMgr, GetUniqueId(), false);
x700_attackRemTime = CalcTimeToNextAttack(mgr); x700_attackRemTime = CalcTimeToNextAttack(mgr);
x72e_28_inProjectileAttack = false; x72e_28_inProjectileAttack = false;
break; break;
@ -778,9 +778,9 @@ float CWarWasp::CalcTimeToNextAttack(CStateManager& mgr) {
float mul = 1.f; float mul = 1.f;
if (TCastToConstPtr<CTeamAiMgr> aimgr = mgr.GetObjectById(x674_aiMgr)) { if (TCastToConstPtr<CTeamAiMgr> aimgr = mgr.GetObjectById(x674_aiMgr)) {
s32 maxCount = (x3fc_flavor == EFlavorType::Two) ? s32 maxCount = (x3fc_flavor == EFlavorType::Two) ?
aimgr->GetMaxProjectileAttackerCount() : aimgr->GetMaxMeleeAttackerCount(); aimgr->GetMaxRangedAttackerCount() : aimgr->GetMaxMeleeAttackerCount();
s32 count = (x3fc_flavor == EFlavorType::Two) ? s32 count = (x3fc_flavor == EFlavorType::Two) ?
aimgr->GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole::Projectile) : aimgr->GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole::Ranged) :
aimgr->GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole::Melee); aimgr->GetNumAssignedOfRole(CTeamAiRole::ETeamAiRole::Melee);
if (count <= maxCount) if (count <= maxCount)
mul *= 0.5f; mul *= 0.5f;
@ -1122,11 +1122,11 @@ bool CWarWasp::HearShot(CStateManager& mgr, float arg) {
bool CWarWasp::ShouldFire(CStateManager& mgr, float arg) { bool CWarWasp::ShouldFire(CStateManager& mgr, float arg) {
if (x700_attackRemTime <= 0.f) { if (x700_attackRemTime <= 0.f) {
if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x674_aiMgr, GetUniqueId())) { if (CTeamAiRole* role = CTeamAiMgr::GetTeamAiRole(mgr, x674_aiMgr, GetUniqueId())) {
if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Projectile) { if (role->GetTeamAiRole() == CTeamAiRole::ETeamAiRole::Ranged) {
zeus::CVector3f delta = GetProjectileAimPos(mgr, -1.25f) - GetTranslation(); zeus::CVector3f delta = GetProjectileAimPos(mgr, -1.25f) - GetTranslation();
if (delta.canBeNormalized() && GetTransform().basis[1].dot(delta.normalized()) >= 0.906f) { if (delta.canBeNormalized() && GetTransform().basis[1].dot(delta.normalized()) >= 0.906f) {
if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x674_aiMgr)) { if (TCastToPtr<CTeamAiMgr> aimgr = mgr.ObjectById(x674_aiMgr)) {
return !aimgr->HasProjectileAttackers(); return !aimgr->HasRangedAttackers();
} }
} }
} }

View File

@ -188,14 +188,14 @@ zeus::CVector3f CPFRegion::FitThroughLink2d(const zeus::CVector3f& p1, const CPF
zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos(); zeus::CVector3f nodeDelta = nextNode.GetPos() - node.GetPos();
float t = 0.5f; float t = 0.5f;
if (chRadius < 0.5f * link.Get2dWidth()) { if (chRadius < 0.5f * link.Get2dWidth()) {
zeus::CVector2f delta2d(nodeDelta.x(), nodeDelta.y()); zeus::CVector2f delta2d = nodeDelta.toVec2f();
delta2d *= link.GetOO2dWidth(); delta2d *= link.GetOO2dWidth();
zeus::CVector3f nodeToP1 = p1 - node.GetPos(); zeus::CVector3f nodeToP1 = p1 - node.GetPos();
float f27 = nodeToP1.dot(node.GetNormal()); float f27 = nodeToP1.dot(node.GetNormal());
float f31 = delta2d.dot(zeus::CVector2f(nodeToP1.y(), nodeToP1.y())); float f31 = delta2d.dot(nodeToP1.toVec2f());
zeus::CVector3f nodeToP2 = p2 - node.GetPos(); zeus::CVector3f nodeToP2 = p2 - node.GetPos();
float f26 = -nodeToP2.dot(node.GetNormal()); float f26 = -nodeToP2.dot(node.GetNormal());
float f1b = delta2d.dot(zeus::CVector2f(nodeToP2.y(), nodeToP2.y())); float f1b = delta2d.dot(nodeToP2.toVec2f());
float f3 = f27 + f26; float f3 = f27 + f26;
if (f3 > FLT_EPSILON) if (f3 > FLT_EPSILON)
t = zeus::clamp(chRadius, 1.f / f3 * (f26 * f31 + f27 * f1b), link.Get2dWidth() - chRadius) * link.GetOO2dWidth(); t = zeus::clamp(chRadius, 1.f / f3 * (f26 * f31 + f27 * f1b), link.Get2dWidth() - chRadius) * link.GetOO2dWidth();

View File

@ -688,17 +688,15 @@ bool CPatterned::OffLine(CStateManager&, float arg) {
void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt) { void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
if (CPathFindSearch* search = GetSearchPath()) { if (CPathFindSearch* search = GetSearchPath()) {
u32 curWp = search->GetCurrentWaypoint();
const auto& waypoints = search->GetWaypoints();
switch (msg) { switch (msg) {
case EStateMsg::Activate: { case EStateMsg::Activate: {
if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) { if (search->Search(GetTranslation(), x2e0_destPos) == CPathFindSearch::EResult::Success) {
x2ec_reflectedDestPos = GetTranslation(); x2ec_reflectedDestPos = GetTranslation();
zeus::CVector3f destPos; zeus::CVector3f destPos;
if (curWp + 1 < waypoints.size()) if (search->GetCurrentWaypoint() + 1 < search->GetWaypoints().size())
destPos = waypoints[curWp + 1]; destPos = search->GetWaypoints()[search->GetCurrentWaypoint() + 1];
else else
destPos = waypoints[curWp]; destPos = search->GetWaypoints()[search->GetCurrentWaypoint()];
SetDestPos(destPos); SetDestPos(destPos);
x328_24_inPosition = false; x328_24_inPosition = false;
ApproachDest(mgr); ApproachDest(mgr);
@ -706,7 +704,7 @@ void CPatterned::PathFind(CStateManager& mgr, EStateMsg msg, float dt) {
break; break;
} }
case EStateMsg::Update: { case EStateMsg::Update: {
if (curWp < waypoints.size() - 1) { if (search->GetCurrentWaypoint() < search->GetWaypoints().size() - 1) {
if (x328_24_inPosition || x328_27_onGround) if (x328_24_inPosition || x328_27_onGround)
x401_24_pathOverCount += 1; x401_24_pathOverCount += 1;
zeus::CVector3f biasedPos = GetTranslation() + 0.3f * zeus::CVector3f::skUp; zeus::CVector3f biasedPos = GetTranslation() + 0.3f * zeus::CVector3f::skUp;

View File

@ -53,9 +53,9 @@ void CScriptGenerator::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sende
if (!stateMgr.GetObjectById(uid)) if (!stateMgr.GetObjectById(uid))
continue; continue;
activates.emplace_back(uid, conn.x8_objId); activates.emplace_back(uid, conn.x8_objId);
} else {
stateMgr.SendScriptMsgAlways(uid, GetUniqueId(), conn.x4_msg);
} }
stateMgr.SendScriptMsgAlways(uid, GetUniqueId(), conn.x4_msg);
} }
if (activates.empty()) if (activates.empty())

View File

@ -29,13 +29,13 @@ struct TeamAiRoleSorter {
CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount) CTeamAiData::CTeamAiData(CInputStream& in, s32 propCount)
: x0_aiCount(in.readUint32Big()) : x0_aiCount(in.readUint32Big())
, x4_meleeCount(in.readUint32Big()) , x4_meleeCount(in.readUint32Big())
, x8_projectileCount(in.readUint32Big()) , x8_rangedCount(in.readUint32Big())
, xc_unknownCount(in.readUint32Big()) , xc_unknownCount(in.readUint32Big())
, x10_maxMeleeAttackerCount(in.readUint32Big()) , x10_maxMeleeAttackerCount(in.readUint32Big())
, x14_maxProjectileAttackerCount(in.readUint32Big()) , x14_maxRangedAttackerCount(in.readUint32Big())
, x18_positionMode(in.readUint32Big()) , x18_positionMode(in.readUint32Big())
, x1c_meleeTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) , x1c_meleeTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f)
, x20_projectileTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) {} , x20_rangedTimeInterval(propCount > 8 ? in.readFloatBig() : 0.f) {}
CTeamAiMgr::CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data) CTeamAiMgr::CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo& info, const CTeamAiData& data)
: CEntity(uid, info, true, name), x34_data(data) { : CEntity(uid, info, true, name), x34_data(data) {
@ -43,8 +43,8 @@ CTeamAiMgr::CTeamAiMgr(TUniqueId uid, std::string_view name, const CEntityInfo&
x58_roles.reserve(x34_data.x0_aiCount); x58_roles.reserve(x34_data.x0_aiCount);
if (x34_data.x4_meleeCount) if (x34_data.x4_meleeCount)
x68_meleeAttackers.reserve(x34_data.x4_meleeCount); x68_meleeAttackers.reserve(x34_data.x4_meleeCount);
if (x34_data.x8_projectileCount) if (x34_data.x8_rangedCount)
x78_projectileAttackers.reserve(x34_data.x8_projectileCount); x78_rangedAttackers.reserve(x34_data.x8_rangedCount);
} }
void CTeamAiMgr::Accept(IVisitor& visitor) { visitor.Visit(this); } void CTeamAiMgr::Accept(IVisitor& visitor) { visitor.Visit(this); }
@ -158,7 +158,7 @@ void CTeamAiMgr::UpdateRoles(CStateManager& mgr) {
TeamAiRoleSorter sorter(aimPos, 1); TeamAiRoleSorter sorter(aimPos, 1);
std::sort(x58_roles.begin(), x58_roles.end(), sorter); std::sort(x58_roles.begin(), x58_roles.end(), sorter);
AssignRoles(CTeamAiRole::ETeamAiRole::Melee, x34_data.x4_meleeCount); AssignRoles(CTeamAiRole::ETeamAiRole::Melee, x34_data.x4_meleeCount);
AssignRoles(CTeamAiRole::ETeamAiRole::Projectile, x34_data.x8_projectileCount); AssignRoles(CTeamAiRole::ETeamAiRole::Ranged, x34_data.x8_rangedCount);
AssignRoles(CTeamAiRole::ETeamAiRole::Unknown, x34_data.xc_unknownCount); AssignRoles(CTeamAiRole::ETeamAiRole::Unknown, x34_data.xc_unknownCount);
for (auto& role : x58_roles) { for (auto& role : x58_roles) {
if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial || if (role.GetTeamAiRole() <= CTeamAiRole::ETeamAiRole::Initial ||
@ -176,7 +176,7 @@ void CTeamAiMgr::Think(float dt, CStateManager& mgr) {
UpdateRoles(mgr); UpdateRoles(mgr);
PositionTeam(mgr); PositionTeam(mgr);
x90_timeSinceMelee += dt; x90_timeSinceMelee += dt;
x94_timeSinceProjectile += dt; x94_timeSinceRanged += dt;
} }
void CTeamAiMgr::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) { void CTeamAiMgr::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& mgr) {
@ -233,36 +233,36 @@ void CTeamAiMgr::RemoveMeleeAttacker(TUniqueId aiId) {
x68_meleeAttackers.erase(search); x68_meleeAttackers.erase(search);
} }
bool CTeamAiMgr::IsProjectileAttacker(TUniqueId aiId) const { bool CTeamAiMgr::IsRangedAttacker(TUniqueId aiId) const {
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); auto search = rstl::binary_find(x78_rangedAttackers.begin(), x78_rangedAttackers.end(), aiId);
return search != x78_projectileAttackers.end(); return search != x78_rangedAttackers.end();
} }
bool CTeamAiMgr::CanAcceptProjectileAttacker(TUniqueId aiId) const { bool CTeamAiMgr::CanAcceptRangedAttacker(TUniqueId aiId) const {
if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && if (x94_timeSinceRanged >= x34_data.x20_rangedTimeInterval &&
x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount) x78_rangedAttackers.size() < x34_data.x14_maxRangedAttackerCount)
return true; return true;
return IsProjectileAttacker(aiId); return IsRangedAttacker(aiId);
} }
bool CTeamAiMgr::AddProjectileAttacker(TUniqueId aiId) { bool CTeamAiMgr::AddRangedAttacker(TUniqueId aiId) {
if (x94_timeSinceProjectile >= x34_data.x20_projectileTimeInterval && if (x94_timeSinceRanged >= x34_data.x20_rangedTimeInterval &&
x78_projectileAttackers.size() < x34_data.x14_maxProjectileAttackerCount && HasTeamAiRole(aiId)) { x78_rangedAttackers.size() < x34_data.x14_maxRangedAttackerCount && HasTeamAiRole(aiId)) {
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); auto search = rstl::binary_find(x78_rangedAttackers.begin(), x78_rangedAttackers.end(), aiId);
if (search == x78_projectileAttackers.end()) { if (search == x78_rangedAttackers.end()) {
x78_projectileAttackers.insert( x78_rangedAttackers.insert(
std::lower_bound(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId), aiId); std::lower_bound(x78_rangedAttackers.begin(), x78_rangedAttackers.end(), aiId), aiId);
x94_timeSinceProjectile = 0.f; x94_timeSinceRanged = 0.f;
} }
return true; return true;
} }
return false; return false;
} }
void CTeamAiMgr::RemoveProjectileAttacker(TUniqueId aiId) { void CTeamAiMgr::RemoveRangedAttacker(TUniqueId aiId) {
auto search = rstl::binary_find(x78_projectileAttackers.begin(), x78_projectileAttackers.end(), aiId); auto search = rstl::binary_find(x78_rangedAttackers.begin(), x78_rangedAttackers.end(), aiId);
if (search != x78_projectileAttackers.end()) if (search != x78_rangedAttackers.end())
x78_projectileAttackers.erase(search); x78_rangedAttackers.erase(search);
} }
bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, CTeamAiRole::ETeamAiRole roleB, bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA, CTeamAiRole::ETeamAiRole roleB,
@ -283,8 +283,8 @@ bool CTeamAiMgr::AssignTeamAiRole(const CAi& ai, CTeamAiRole::ETeamAiRole roleA,
void CTeamAiMgr::RemoveTeamAiRole(TUniqueId aiId) { void CTeamAiMgr::RemoveTeamAiRole(TUniqueId aiId) {
if (IsMeleeAttacker(aiId)) if (IsMeleeAttacker(aiId))
RemoveMeleeAttacker(aiId); RemoveMeleeAttacker(aiId);
if (IsProjectileAttacker(aiId)) if (IsRangedAttacker(aiId))
RemoveProjectileAttacker(aiId); RemoveRangedAttacker(aiId);
auto search = auto search =
rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); }); rstl::binary_find(x58_roles.begin(), x58_roles.end(), aiId, [](const auto& obj) { return obj.GetOwnerId(); });
x58_roles.erase(search); x58_roles.erase(search);
@ -328,9 +328,9 @@ void CTeamAiMgr::ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId
if (type == EAttackType::Melee) { if (type == EAttackType::Melee) {
if (tmgr->IsMeleeAttacker(aiId)) if (tmgr->IsMeleeAttacker(aiId))
tmgr->RemoveMeleeAttacker(aiId); tmgr->RemoveMeleeAttacker(aiId);
} else if (type == EAttackType::Projectile) { } else if (type == EAttackType::Ranged) {
if (tmgr->IsProjectileAttacker(aiId)) if (tmgr->IsRangedAttacker(aiId))
tmgr->RemoveProjectileAttacker(aiId); tmgr->RemoveRangedAttacker(aiId);
} }
if (clearRole) if (clearRole)
tmgr->ClearTeamAiRole(aiId); tmgr->ClearTeamAiRole(aiId);
@ -343,8 +343,8 @@ bool CTeamAiMgr::CanAcceptAttacker(EAttackType type, CStateManager& mgr, TUnique
if (tmgr->HasTeamAiRole(aiId)) { if (tmgr->HasTeamAiRole(aiId)) {
if (type == EAttackType::Melee) if (type == EAttackType::Melee)
return tmgr->CanAcceptMeleeAttacker(aiId); return tmgr->CanAcceptMeleeAttacker(aiId);
else if (type == EAttackType::Projectile) else if (type == EAttackType::Ranged)
return tmgr->CanAcceptProjectileAttacker(aiId); return tmgr->CanAcceptRangedAttacker(aiId);
} }
} }
return false; return false;
@ -355,8 +355,8 @@ bool CTeamAiMgr::AddAttacker(EAttackType type, CStateManager& mgr, TUniqueId mgr
if (tmgr->HasTeamAiRole(aiId)) { if (tmgr->HasTeamAiRole(aiId)) {
if (type == EAttackType::Melee) if (type == EAttackType::Melee)
return tmgr->AddMeleeAttacker(aiId); return tmgr->AddMeleeAttacker(aiId);
else if (type == EAttackType::Projectile) else if (type == EAttackType::Ranged)
return tmgr->AddProjectileAttacker(aiId); return tmgr->AddRangedAttacker(aiId);
} }
} }
return false; return false;

View File

@ -11,7 +11,7 @@ class CTeamAiRole {
friend class CTeamAiMgr; friend class CTeamAiMgr;
public: public:
enum class ETeamAiRole { Invalid = -1, Initial, Melee, Projectile, Unknown, Unassigned }; enum class ETeamAiRole { Invalid = -1, Initial, Melee, Ranged, Unknown, Unassigned };
private: private:
TUniqueId x0_ownerId; TUniqueId x0_ownerId;
@ -41,13 +41,13 @@ class CTeamAiData {
friend class CTeamAiMgr; friend class CTeamAiMgr;
u32 x0_aiCount; u32 x0_aiCount;
u32 x4_meleeCount; u32 x4_meleeCount;
u32 x8_projectileCount; u32 x8_rangedCount;
u32 xc_unknownCount; u32 xc_unknownCount;
u32 x10_maxMeleeAttackerCount; u32 x10_maxMeleeAttackerCount;
u32 x14_maxProjectileAttackerCount; u32 x14_maxRangedAttackerCount;
u32 x18_positionMode; u32 x18_positionMode;
float x1c_meleeTimeInterval; float x1c_meleeTimeInterval;
float x20_projectileTimeInterval; float x20_rangedTimeInterval;
public: public:
CTeamAiData(CInputStream& in, s32 propCount); CTeamAiData(CInputStream& in, s32 propCount);
@ -55,17 +55,17 @@ public:
class CTeamAiMgr : public CEntity { class CTeamAiMgr : public CEntity {
public: public:
enum class EAttackType { Melee, Projectile }; enum class EAttackType { Melee, Ranged };
private: private:
CTeamAiData x34_data; CTeamAiData x34_data;
std::vector<CTeamAiRole> x58_roles; std::vector<CTeamAiRole> x58_roles;
std::vector<TUniqueId> x68_meleeAttackers; std::vector<TUniqueId> x68_meleeAttackers;
std::vector<TUniqueId> x78_projectileAttackers; std::vector<TUniqueId> x78_rangedAttackers;
float x88_timeDirty = 0.f; float x88_timeDirty = 0.f;
TUniqueId x8c_teamCaptainId = kInvalidUniqueId; TUniqueId x8c_teamCaptainId = kInvalidUniqueId;
float x90_timeSinceMelee; float x90_timeSinceMelee;
float x94_timeSinceProjectile; float x94_timeSinceRanged;
void UpdateTeamCaptain(); void UpdateTeamCaptain();
bool ShouldUpdateRoles(float dt); bool ShouldUpdateRoles(float dt);
@ -95,17 +95,17 @@ public:
bool CanAcceptMeleeAttacker(TUniqueId aiId) const; bool CanAcceptMeleeAttacker(TUniqueId aiId) const;
bool AddMeleeAttacker(TUniqueId aiId); bool AddMeleeAttacker(TUniqueId aiId);
void RemoveMeleeAttacker(TUniqueId aiId); void RemoveMeleeAttacker(TUniqueId aiId);
bool IsProjectileAttacker(TUniqueId aiId) const; bool IsRangedAttacker(TUniqueId aiId) const;
bool CanAcceptProjectileAttacker(TUniqueId aiId) const; bool CanAcceptRangedAttacker(TUniqueId aiId) const;
bool AddProjectileAttacker(TUniqueId aiId); bool AddRangedAttacker(TUniqueId aiId);
void RemoveProjectileAttacker(TUniqueId aiId); void RemoveRangedAttacker(TUniqueId aiId);
bool HasMeleeAttackers() const { return !x68_meleeAttackers.empty(); } bool HasMeleeAttackers() const { return !x68_meleeAttackers.empty(); }
bool HasProjectileAttackers() const { return !x78_projectileAttackers.empty(); } bool HasRangedAttackers() const { return !x78_rangedAttackers.empty(); }
s32 GetNumRoles() const { return x58_roles.size(); } s32 GetNumRoles() const { return x58_roles.size(); }
const std::vector<CTeamAiRole>& GetRoles() const { return x58_roles; } const std::vector<CTeamAiRole>& GetRoles() const { return x58_roles; }
s32 GetMaxMeleeAttackerCount() const { return x34_data.x10_maxMeleeAttackerCount; } s32 GetMaxMeleeAttackerCount() const { return x34_data.x10_maxMeleeAttackerCount; }
s32 GetMaxProjectileAttackerCount() const { return x34_data.x14_maxProjectileAttackerCount; } s32 GetMaxRangedAttackerCount() const { return x34_data.x14_maxRangedAttackerCount; }
static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId); static CTeamAiRole* GetTeamAiRole(CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId);
static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole); static void ResetTeamAiRole(EAttackType type, CStateManager& mgr, TUniqueId mgrId, TUniqueId aiId, bool clearRole);