From fe64d9ce005a9857a6b97ff59b31215c874bb94c Mon Sep 17 00:00:00 2001 From: Yunfan Li Date: Tue, 9 Jul 2024 16:39:50 +0800 Subject: [PATCH] [Combat formation] Avoid flee repeatly --- src/Playerbots.h | 2 + src/strategy/Value.h | 40 ++++++++++++++- src/strategy/actions/MovementActions.cpp | 50 ++++++++++++------- src/strategy/actions/MovementActions.h | 3 +- .../actions/UseMeetingStoneAction.cpp | 1 + src/strategy/values/ValueContext.h | 2 + 6 files changed, 79 insertions(+), 19 deletions(-) diff --git a/src/Playerbots.h b/src/Playerbots.h index 66ec850c..7e678af3 100644 --- a/src/Playerbots.h +++ b/src/Playerbots.h @@ -34,6 +34,8 @@ int strcmpi(char const* s1, char const* s2); #define AI_VALUE_LAZY(type, name) context->GetValue(name)->LazyGet() #define AI_VALUE2_LAZY(type, name, param) context->GetValue(name, param)->LazyGet() +#define AI_VALUE_REF(type, name) context->GetValue(name)->RefGet() + #define SET_AI_VALUE(type, name, value) context->GetValue(name)->Set(value) #define SET_AI_VALUE2(type, name, param, value) context->GetValue(name, param)->Set(value) #define RESET_AI_VALUE(type, name) context->GetValue(name)->Reset() diff --git a/src/strategy/Value.h b/src/strategy/Value.h index 1a7e05ef..4d4196a3 100644 --- a/src/strategy/Value.h +++ b/src/strategy/Value.h @@ -16,6 +16,16 @@ class PlayerbotAI; class Unit; +class FleeInfo +{ + public: + Position fromPos; + float radius; + float angle; + uint32 timestamp; + int GetAngleRangeIndex() { return (angle + 2 * M_PI) / (M_PI / 2); } // [0, 7) +}; + struct CreatureData; class UntypedValue : public AiNamedObject @@ -37,6 +47,7 @@ class Value virtual ~Value() { } virtual T Get() = 0; virtual T LazyGet() = 0; + virtual T& RefGet() = 0; virtual void Reset() { } virtual void Set(T value) = 0; operator T() { return Get(); } @@ -79,7 +90,26 @@ class CalculatedValue : public UntypedValue, public Value return value; } - + T& RefGet() override + { + if (checkInterval < 2) { + // PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); + value = Calculate(); + // if (pmo) + // pmo->finish(); + } else { + time_t now = getMSTime(); + if (!lastCheckTime || now - lastCheckTime >= checkInterval) + { + lastCheckTime = now; + // PerformanceMonitorOperation* pmo = sPerformanceMonitor->start(PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); + value = Calculate(); + // if (pmo) + // pmo->finish(); + } + } + return value; + } void Set(T val) override { value = val; } void Update() override {} void Reset() override { lastCheckTime = 0; } @@ -304,6 +334,7 @@ class ManualSetValue : public UntypedValue, public Value T Get() override { return value; } T LazyGet() override { return value; } + T& RefGet() override { return value; } void Set(T val) override { value = val; } void Update() override {} void Reset() override @@ -347,4 +378,11 @@ class LastFleeTimestampValue : public ManualSetValue ManualSetValue(botAI, defaultValue, name) { } }; +class RecentlyFleeInfo : public ManualSetValue> +{ + public: + RecentlyFleeInfo(PlayerbotAI* botAI, std::list defaultValue = {}, std::string const name = "recently flee info") : + ManualSetValue>(botAI, defaultValue, name) { } +}; + #endif diff --git a/src/strategy/actions/MovementActions.cpp b/src/strategy/actions/MovementActions.cpp index 06bc7d74..b1a1fbe3 100644 --- a/src/strategy/actions/MovementActions.cpp +++ b/src/strategy/actions/MovementActions.cpp @@ -1700,9 +1700,8 @@ Position MovementAction::BestPositionForMeleeToFlee(Position pos, float radius) Position bestPos; for (CheckAngle &checkAngle : possibleAngles) { float angle = checkAngle.angle; - float lastFleeAngle = AI_VALUE(float, "last flee angle"); - uint32 lastFleeTimestamp = AI_VALUE(uint32, "last flee timestamp"); - if (!CheckLastFlee(angle, lastFleeAngle, lastFleeTimestamp)) { + auto& infoList = AI_VALUE_REF(std::list, "recently flee info"); + if (!CheckLastFlee(angle, infoList)) { continue; } bool strict = checkAngle.strict; @@ -1748,9 +1747,8 @@ Position MovementAction::BestPositionForRangedToFlee(Position pos, float radius) Position bestPos; for (CheckAngle &checkAngle : possibleAngles) { float angle = checkAngle.angle; - float lastFleeAngle = AI_VALUE(float, "last flee angle"); - uint32 lastFleeTimestamp = AI_VALUE(uint32, "last flee timestamp"); - if (!CheckLastFlee(angle, lastFleeAngle, lastFleeTimestamp)) { + auto& infoList = AI_VALUE_REF(std::list, "recently flee info"); + if (!CheckLastFlee(angle, infoList)) { continue; } bool strict = checkAngle.strict; @@ -1787,25 +1785,43 @@ bool MovementAction::FleePosition(Position pos, float radius) } if (bestPos != Position()) { if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true)) { - SET_AI_VALUE(float, "last flee angle", bot->GetAngle(&bestPos)); - SET_AI_VALUE(uint32, "last flee timestamp", getMSTime()); + auto& infoList = AI_VALUE_REF(std::list, "recently flee info"); + uint32 curTS = getMSTime(); + while (!infoList.empty()) { + if (infoList.size() > 10 || infoList.front().timestamp + 5000 < curTS) { + infoList.pop_front(); + } else { + break; + } + } + infoList.push_back({pos, radius, bot->GetAngle(&bestPos), curTS}); return true; } } return false; } -bool MovementAction::CheckLastFlee(float curAngle, float lastAngle, uint32 lastTS) +bool MovementAction::CheckLastFlee(float curAngle, std::list& infoList) { - // more than 5 sec - if (lastTS + 5000 < getMSTime()) { - return true; - } - float revAngle = fmod(lastAngle + M_PI, 2 * M_PI); + uint32 curTS = getMSTime(); curAngle = fmod(curAngle, 2 * M_PI); - // angle too close - if (fabs(revAngle - curAngle) < M_PI / 8) { - return false; + while (!infoList.empty()) { + if (infoList.size() > 10 || infoList.front().timestamp + 5000 < curTS) { + infoList.pop_front(); + } else { + break; + } + } + for (FleeInfo& info : infoList) { + // more than 5 sec + if (info.timestamp + 5000 < curTS) { + continue; + } + float revAngle = fmod(info.angle + M_PI, 2 * M_PI); + // angle too close + if (fabs(revAngle - curAngle) < M_PI / 8) { + return false; + } } return true; } diff --git a/src/strategy/actions/MovementActions.h b/src/strategy/actions/MovementActions.h index 0db8e7cd..c00ee5c8 100644 --- a/src/strategy/actions/MovementActions.h +++ b/src/strategy/actions/MovementActions.h @@ -13,6 +13,7 @@ class Player; class PlayerbotAI; class Unit; class WorldObject; +class Position; class MovementAction : public Action { @@ -44,7 +45,7 @@ class MovementAction : public Action Position BestPositionForMeleeToFlee(Position pos, float radius); Position BestPositionForRangedToFlee(Position pos, float radius); bool FleePosition(Position pos, float radius); - bool CheckLastFlee(float curAngle, float lastAngle, uint32 lastTS); + bool CheckLastFlee(float curAngle, std::list& infoList); protected: struct CheckAngle { float angle; diff --git a/src/strategy/actions/UseMeetingStoneAction.cpp b/src/strategy/actions/UseMeetingStoneAction.cpp index b0a68990..0d4be53e 100644 --- a/src/strategy/actions/UseMeetingStoneAction.cpp +++ b/src/strategy/actions/UseMeetingStoneAction.cpp @@ -83,6 +83,7 @@ bool SummonAction::Execute(Event event) if (master->GetSession()->GetSecurity() >= SEC_PLAYER) { // botAI->GetAiObjectContext()->GetValue("prioritized targets")->Set({}); + SET_AI_VALUE(std::list, "recently flee info", {}); return Teleport(master, bot); } diff --git a/src/strategy/values/ValueContext.h b/src/strategy/values/ValueContext.h index e202ff8d..2888b246 100644 --- a/src/strategy/values/ValueContext.h +++ b/src/strategy/values/ValueContext.h @@ -304,6 +304,7 @@ class ValueContext : public NamedObjectContext creators["disperse distance"] = &ValueContext::disperse_distance; creators["last flee angle"] = &ValueContext::last_flee_angle; creators["last flee timestamp"] = &ValueContext::last_flee_timestamp; + creators["recently flee info"] = &ValueContext::recently_flee_info; } private: @@ -511,6 +512,7 @@ class ValueContext : public NamedObjectContext static UntypedValue* disperse_distance(PlayerbotAI* ai) { return new DisperseDistanceValue(ai); } static UntypedValue* last_flee_angle(PlayerbotAI* ai) { return new LastFleeAngleValue(ai); } static UntypedValue* last_flee_timestamp(PlayerbotAI* ai) { return new LastFleeTimestampValue(ai); } + static UntypedValue* recently_flee_info(PlayerbotAI* ai) { return new RecentlyFleeInfo(ai); } }; #endif