Core/Spells: Added helper function to select random injured healing spell targets

This commit is contained in:
Shauren
2022-01-03 13:07:30 +01:00
parent 08b5a0586a
commit c0f976d23d
3 changed files with 72 additions and 6 deletions

View File

@@ -8613,6 +8613,75 @@ bool WorldObjectSpellLineTargetCheck::operator()(WorldObject* target) const
return WorldObjectSpellTargetCheck::operator ()(target);
}
void SelectRandomInjuredTargets(std::list<WorldObject*>& targets, size_t maxTargets, bool prioritizePlayers)
{
if (targets.size() <= maxTargets)
return;
std::vector<WorldObject*> tempTargets(targets.begin(), targets.end());
auto begin = tempTargets.begin();
auto end = tempTargets.end();
if (prioritizePlayers)
{
auto playersEnd = std::stable_partition(begin, end, [](WorldObject const* target)
{
return target->IsPlayer();
});
size_t playerCount = std::distance(begin, playersEnd);
if (playerCount < maxTargets)
{
// not enough players, add nonplayer targets
// prioritize injured nonplayers over full health nonplayers
auto injuredNonPlayersEnd = std::stable_partition(playersEnd, end, [](WorldObject const* target)
{
return target->IsUnit() && !target->ToUnit()->IsFullHealth();
});
size_t injuredNonPlayersCount = std::distance(playersEnd, injuredNonPlayersEnd);
if (playerCount + injuredNonPlayersCount < maxTargets)
{
// not enough players + injured nonplayers
// fill remainder with random full health nonplayers
Containers::RandomShuffle(injuredNonPlayersEnd, end);
}
else if (playerCount + injuredNonPlayersCount > maxTargets)
{
// randomize injured nonplayers order
// final list will contain all players + random injured nonplayers
Containers::RandomShuffle(playersEnd, injuredNonPlayersEnd);
}
targets.assign(tempTargets.begin(), tempTargets.begin() + maxTargets);
return;
}
// We have more players than we requested, proceed checking injured targets
end = playersEnd;
}
auto injuredUnitsEnd = std::stable_partition(begin, end, [](WorldObject const* target)
{
return target->IsUnit() && !target->ToUnit()->IsFullHealth();
});
size_t injuredUnitsCount = std::distance(begin, injuredUnitsEnd);
if (injuredUnitsCount < maxTargets)
{
// not enough injured units
// fill remainder with full health units
Containers::RandomShuffle(injuredUnitsEnd, end);
}
else if (injuredUnitsCount > maxTargets)
{
// select random injured units
Containers::RandomShuffle(begin, injuredUnitsEnd);
}
targets.assign(tempTargets.begin(), tempTargets.begin() + maxTargets);
}
} //namespace Trinity
CastSpellTargetArg::CastSpellTargetArg(WorldObject* target)

View File

@@ -933,6 +933,8 @@ namespace Trinity
bool operator()(WorldObject* target) const;
};
TC_GAME_API void SelectRandomInjuredTargets(std::list<WorldObject*>& targets, size_t maxTargets, bool prioritizePlayers);
}
using SpellEffectHandlerFn = void(Spell::*)();

View File

@@ -324,12 +324,7 @@ class spell_sha_downpour : public SpellScript
void FilterTargets(std::list<WorldObject*>& targets)
{
uint32 const maxTargets = 6;
if (targets.size() > maxTargets)
{
targets.sort(Trinity::HealthPctOrderPred());
targets.resize(maxTargets);
}
Trinity::SelectRandomInjuredTargets(targets, 6, true);
}
void CountEffectivelyHealedTarget()