mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-10-02 02:43:44 +00:00
fix(combat): area attacks handle each target once, in the client's order (issues 917, 1189)
The client's AreaOfEffectBehavior::Cast (0x004ec590) writes every target id, then runs and writes the action once per unique target in ascending id order. The server ran it for every listed target in list order, so a target listed twice (the caster with a magnet, Everlasting items' refill) was handled twice, and later targets' data was read against the wrong target. Handle and the server's own Calculate now go through the unique ids in ascending order. Check: Thumpin' Bass / Flowin' MC refill once; Shinobi charge with a magnet gives imagination once; area attacks on several enemies still hit each of them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,7 @@
|
|||||||
#include "AreaOfEffectBehavior.h"
|
#include "AreaOfEffectBehavior.h"
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "EntityManager.h"
|
#include "EntityManager.h"
|
||||||
@@ -47,7 +49,10 @@ void AreaOfEffectBehavior::Handle(BehaviorContext* context, RakNet::BitStream& b
|
|||||||
targets.push_back(target);
|
targets.push_back(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto target : targets) {
|
// The client writes the action once per unique target, in ascending id order (AreaOfEffectBehavior::Cast,
|
||||||
|
// 0x004ec590, runs it over a set of the ids), so a target listed twice is handled once
|
||||||
|
const std::set<LWOOBJID> uniqueTargets(targets.begin(), targets.end());
|
||||||
|
for (auto target : uniqueTargets) {
|
||||||
branch.target = target;
|
branch.target = target;
|
||||||
this->m_action->Handle(context, bitStream, branch);
|
this->m_action->Handle(context, bitStream, branch);
|
||||||
}
|
}
|
||||||
@@ -96,9 +101,11 @@ void AreaOfEffectBehavior::Calculate(BehaviorContext* context, RakNet::BitStream
|
|||||||
bitStream.Write(target->GetObjectID());
|
bitStream.Write(target->GetObjectID());
|
||||||
}
|
}
|
||||||
|
|
||||||
// then cast all the actions
|
// then cast the action once per unique target in ascending id order, the order clients read them in
|
||||||
for (auto* target : targets) {
|
std::set<LWOOBJID> uniqueTargets;
|
||||||
branch.target = target->GetObjectID();
|
for (auto* target : targets) uniqueTargets.insert(target->GetObjectID());
|
||||||
|
for (const auto target : uniqueTargets) {
|
||||||
|
branch.target = target;
|
||||||
this->m_action->Calculate(context, bitStream, branch);
|
this->m_action->Calculate(context, bitStream, branch);
|
||||||
}
|
}
|
||||||
PlayFx(u"cast", context->originator);
|
PlayFx(u"cast", context->originator);
|
||||||
|
|||||||
Reference in New Issue
Block a user