diff options
author | Shauren <shauren.trinity@gmail.com> | 2025-09-06 12:28:12 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2025-09-06 13:19:38 +0200 |
commit | 03d072da463769ff02090e08d12b4da3f6a49222 (patch) | |
tree | 3b67edcd4c0e7df18de425489f688eb621a32235 /src/server/game/Spells/Spell.cpp | |
parent | 2e3f3fda3fc533daa4064739b633dbb28f5115d3 (diff) |
Core/Spells: Simplify SortTargetsWithPriorityRules
* Remove manul weight assignment
* Removed std::vector alloc
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 58 |
1 files changed, 16 insertions, 42 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bce4b676490..111d2914c57 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -9633,67 +9633,41 @@ void SelectRandomInjuredTargets(std::list<WorldObject*>& targets, size_t maxTarg std::ranges::transform(tempTargets.begin(), tempTargets.begin() + maxTargets, targets.begin(), Trinity::TupleElement<0>); } -void SortTargetsWithPriorityRules(std::list<WorldObject*>& targets, size_t maxTargets, std::vector<PriorityRules> const& rules) +void SortTargetsWithPriorityRules(std::list<WorldObject*>& targets, size_t maxTargets, std::span<TargetPriorityRule const> rules) { if (targets.size() <= maxTargets) return; - std::vector<std::pair<WorldObject*, int32>> prioritizedTargets; + std::vector<std::pair<WorldObject*, int32>> prioritizedTargets(targets.size()); // score each target based on how many rules they satisfy. - for (WorldObject* object : targets) + std::ranges::transform(targets, prioritizedTargets.begin(), [&](WorldObject* target) { - Unit* unit = object ? object->ToUnit() : nullptr; - if (!unit) - continue; - int32 score = 0; + for (std::size_t i = 0; i < rules.size(); ++i) + if (rules[i].Rule(target)) + score |= 1 << (rules.size() - 1 - i); - for (PriorityRules const& rule : rules) - { - if (rule.condition(unit)) - score += rule.weight; - } - - prioritizedTargets.emplace_back(object, score); - } + return std::make_pair(target, score); + }); // the higher the value, the higher the priority is. - std::ranges::sort(prioritizedTargets, [](const std::pair<WorldObject*, int32>& left, const std::pair<WorldObject*, int32>& right) - { - return left.second > right.second; - }); + std::ranges::sort(prioritizedTargets, std::ranges::greater(), Trinity::TupleElement<1>); - size_t cutOff = std::min(maxTargets, prioritizedTargets.size()); + int32 tieScore = prioritizedTargets[maxTargets - 1].second; // if there are ties at the cutoff, shuffle them to avoid selection bias. - if (cutOff < prioritizedTargets.size()) + if (prioritizedTargets[maxTargets].second == tieScore) { - int32 tieScore = prioritizedTargets[cutOff - 1].second; - - auto const isTieScore = [tieScore](const std::pair<WorldObject*, int32>& entry) - { return entry.second == tieScore; }; - - // scan backwards to include tied entries before the cutoff. - std::ptrdiff_t tieStart = static_cast<std::ptrdiff_t>(cutOff - 1); - while (tieStart > 0 && isTieScore(prioritizedTargets[tieStart - 1])) - --tieStart; - - // scan forward to include tied entries after the cutoff. - std::ptrdiff_t tieEnd = static_cast<std::ptrdiff_t>(cutOff); - while (tieEnd < static_cast<std::ptrdiff_t>(prioritizedTargets.size()) && isTieScore(prioritizedTargets[tieEnd])) - ++tieEnd; + auto toShuffle = std::equal_range(prioritizedTargets.begin(), prioritizedTargets.end(), std::pair<WorldObject*, int32>(nullptr, tieScore), + [](std::pair<WorldObject*, int32> const& target1, std::pair<WorldObject*, int32> const& target2) { return target1.second > target2.second; }); // shuffle only the tied range to randomize final selection. - Containers::RandomShuffle( - std::ranges::next(prioritizedTargets.begin(), tieStart), - std::ranges::next(prioritizedTargets.begin(), tieEnd)); + Containers::RandomShuffle(toShuffle.first, toShuffle.second); } - targets.clear(); - - for (size_t i = 0; i < cutOff; ++i) - targets.push_back(prioritizedTargets[i].first); + targets.resize(maxTargets); + std::ranges::transform(prioritizedTargets.begin(), prioritizedTargets.begin() + maxTargets, targets.begin(), Trinity::TupleElement<0>); } } //namespace Trinity |