/* * Copyright (C) 2016+ AzerothCore , released under GNU GPL v2 license, you may redistribute it * and/or modify it under version 2 of the License, or (at your option), any later version. */ #ifndef _PLAYERBOT_VALUE_H #define _PLAYERBOT_VALUE_H #include #include "AiObject.h" #include "ObjectGuid.h" #include "PerformanceMonitor.h" #include "Timer.h" #include "Unit.h" 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 { public: UntypedValue(PlayerbotAI* botAI, std::string const name) : AiNamedObject(botAI, name) {} virtual ~UntypedValue() {} virtual void Update() {} virtual void Reset() {} virtual std::string const Format() { return "?"; } virtual std::string const Save() { return "?"; } virtual bool Load([[maybe_unused]] std::string const value) { return false; } }; template class Value { public: 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(); } }; template class CalculatedValue : public UntypedValue, public Value { public: CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1) : UntypedValue(botAI, name), checkInterval( checkInterval == 1 ? 1 : (checkInterval < 100 ? checkInterval * 1000 : checkInterval)) /*turn s -> ms?*/, lastCheckTime(0) { } virtual ~CalculatedValue() {} T Get() 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; } T LazyGet() override { if (!lastCheckTime) return Get(); 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; } protected: virtual T Calculate() = 0; uint32 checkInterval; uint32 lastCheckTime; T value; }; template class SingleCalculatedValue : public CalculatedValue { public: SingleCalculatedValue(PlayerbotAI* botAI, std::string const name = "value") : CalculatedValue(botAI, name) { this->Reset(); } T Get() override { time_t now = time(0); if (!this->lastCheckTime) { this->lastCheckTime = now; PerformanceMonitorOperation* pmo = sPerformanceMonitor->start( PERF_MON_VALUE, this->getName(), this->context ? &this->context->performanceStack : nullptr); this->value = this->Calculate(); if (pmo) pmo->finish(); } return this->value; } }; template class MemoryCalculatedValue : public CalculatedValue { public: MemoryCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1) : CalculatedValue(botAI, name, checkInterval) { lastChangeTime = time(0); } virtual bool EqualToLast(T value) = 0; virtual bool CanCheckChange() { return time(0) - lastChangeTime < minChangeInterval || EqualToLast(this->value); } virtual bool UpdateChange() { if (CanCheckChange()) return false; lastChangeTime = time(0); lastValue = this->value; return true; } void Set([[maybe_unused]] T value) override { CalculatedValue::Set(this->value); UpdateChange(); } T Get() override { this->value = CalculatedValue::Get(); UpdateChange(); return this->value; } T LazyGet() override { return this->value; } time_t LastChangeOn() { Get(); UpdateChange(); return lastChangeTime; } uint32 LastChangeDelay() { return time(0) - LastChangeOn(); } void Reset() override { CalculatedValue::Reset(); lastChangeTime = time(0); } protected: T lastValue; uint32 minChangeInterval = 0; time_t lastChangeTime; }; template class LogCalculatedValue : public MemoryCalculatedValue { public: LogCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1) : MemoryCalculatedValue(botAI, name, checkInterval) { } bool UpdateChange() override { if (MemoryCalculatedValue::UpdateChange()) return false; valueLog.push_back(std::make_pair(this->value, time(0))); if (valueLog.size() > logLength) valueLog.pop_front(); return true; } std::list> ValueLog() { return valueLog; } void Reset() override { MemoryCalculatedValue::Reset(); valueLog.clear(); } protected: std::list> valueLog; uint8 logLength = 10; }; class Uint8CalculatedValue : public CalculatedValue { public: Uint8CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", uint32 checkInterval = 1) : CalculatedValue(botAI, name, checkInterval) { } std::string const Format() override; }; class Uint32CalculatedValue : public CalculatedValue { public: Uint32CalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : CalculatedValue(botAI, name, checkInterval) { } std::string const Format() override; }; class FloatCalculatedValue : public CalculatedValue { public: FloatCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : CalculatedValue(botAI, name, checkInterval) { } std::string const Format() override; }; class BoolCalculatedValue : public CalculatedValue { public: BoolCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int checkInterval = 1) : CalculatedValue(botAI, name, checkInterval) { } std::string const Format() override { return Calculate() ? "true" : "false"; } }; class UnitCalculatedValue : public CalculatedValue { public: UnitCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); std::string const Format() override; Unit* Get() override; }; class CDPairCalculatedValue : public CalculatedValue { public: CDPairCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); std::string const Format() override; }; class CDPairListCalculatedValue : public CalculatedValue> { public: CDPairListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); std::string const Format() override; }; class ObjectGuidCalculatedValue : public CalculatedValue { public: ObjectGuidCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); std::string const Format() override; }; class ObjectGuidListCalculatedValue : public CalculatedValue { public: ObjectGuidListCalculatedValue(PlayerbotAI* botAI, std::string const name = "value", int32 checkInterval = 1); std::string const Format() override; }; template class ManualSetValue : public UntypedValue, public Value { public: ManualSetValue(PlayerbotAI* botAI, T defaultValue, std::string const name = "value") : UntypedValue(botAI, name), value(defaultValue), defaultValue(defaultValue) { } virtual ~ManualSetValue() {} 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 { value = defaultValue; } protected: T value; T defaultValue; }; class UnitManualSetValue : public ManualSetValue { public: UnitManualSetValue(PlayerbotAI* botAI, Unit* defaultValue, std::string const name = "value") : ManualSetValue(botAI, defaultValue, name) { } std::string const Format() override; Unit* Get() override; }; class DisperseDistanceValue : public ManualSetValue { public: DisperseDistanceValue(PlayerbotAI* botAI, float defaultValue = -1.0f, std::string const name = "disperse distance") : ManualSetValue(botAI, defaultValue, name) { } }; class LastFleeAngleValue : public ManualSetValue { public: LastFleeAngleValue(PlayerbotAI* botAI, float defaultValue = 0.0f, std::string const name = "last flee angle") : ManualSetValue(botAI, defaultValue, name) { } }; class LastFleeTimestampValue : public ManualSetValue { public: LastFleeTimestampValue(PlayerbotAI* botAI, uint32 defaultValue = 0, std::string const name = "last flee timestamp") : ManualSetValue(botAI, defaultValue, name) { } }; class RecentlyFleeInfo : public ManualSetValue&> { public: RecentlyFleeInfo(PlayerbotAI* botAI, std::string const name = "recently flee info") : ManualSetValue&>(botAI, data, name) { } private: std::list data = {}; }; #endif