mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-13 09:07:19 +00:00
[Combat formation] Last flee angle check
This commit is contained in:
@@ -329,7 +329,22 @@ class UnitManualSetValue : public ManualSetValue<Unit*>
|
||||
class DisperseDistanceValue : public ManualSetValue<float>
|
||||
{
|
||||
public:
|
||||
DisperseDistanceValue(PlayerbotAI* botAI, float defaultValue = -1.0f, std::string const name = "disperse value") :
|
||||
DisperseDistanceValue(PlayerbotAI* botAI, float defaultValue = -1.0f, std::string const name = "disperse distance") :
|
||||
ManualSetValue<float>(botAI, defaultValue, name) { }
|
||||
};
|
||||
|
||||
class LastFleeAngleValue : public ManualSetValue<float>
|
||||
{
|
||||
public:
|
||||
LastFleeAngleValue(PlayerbotAI* botAI, float defaultValue = 0.0f, std::string const name = "last flee angle") :
|
||||
ManualSetValue<float>(botAI, defaultValue, name) { }
|
||||
};
|
||||
|
||||
class LastFleeTimestampValue : public ManualSetValue<uint32>
|
||||
{
|
||||
public:
|
||||
LastFleeTimestampValue(PlayerbotAI* botAI, uint32 defaultValue = 0, std::string const name = "last flee timestamp") :
|
||||
ManualSetValue<uint32>(botAI, defaultValue, name) { }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "MovementActions.h"
|
||||
#include "GameObject.h"
|
||||
#include "Geometry.h"
|
||||
#include "Map.h"
|
||||
#include "MotionMaster.h"
|
||||
#include "MoveSplineInitArgs.h"
|
||||
@@ -31,6 +32,8 @@
|
||||
#include "Unit.h"
|
||||
#include "Vehicle.h"
|
||||
#include "WaypointMovementGenerator.h"
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <string>
|
||||
|
||||
@@ -1511,17 +1514,14 @@ bool AvoidAoeAction::Execute(Event event)
|
||||
{
|
||||
// Case #1: Aura with dynamic object (e.g. rain of fire)
|
||||
if (AvoidAuraWithDynamicObj()) {
|
||||
lastMoveTimer = getMSTime();
|
||||
return true;
|
||||
}
|
||||
// Case #2: Trap game object with spell (e.g. lava bomb)
|
||||
if (AvoidGameObjectWithDamage()) {
|
||||
lastMoveTimer = getMSTime();
|
||||
return true;
|
||||
}
|
||||
// Case #3: Trigger npc (e.g. Lesser shadow fissure)
|
||||
if (AvoidUnitWithDamageAura()) {
|
||||
lastMoveTimer = getMSTime();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1550,10 +1550,11 @@ bool AvoidAoeAction::AvoidAuraWithDynamicObj()
|
||||
return false;
|
||||
}
|
||||
std::ostringstream name;
|
||||
name << spellInfo->SpellName[0]; // << "] (aura)";
|
||||
name << spellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; // << "] (aura)";
|
||||
if (FleePosition(dynOwner->GetPosition(), radius)) {
|
||||
if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) {
|
||||
lastTellTimer = time(NULL);
|
||||
lastMoveTimer = getMSTime();
|
||||
std::ostringstream out;
|
||||
out << "I'm avoiding " << name.str() << "...";
|
||||
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||
@@ -1607,10 +1608,11 @@ bool AvoidAoeAction::AvoidGameObjectWithDamage()
|
||||
continue;
|
||||
}
|
||||
std::ostringstream name;
|
||||
name << spellInfo->SpellName[0]; // << "] (object)";
|
||||
name << spellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; // << "] (object)";
|
||||
if (FleePosition(go->GetPosition(), radius)) {
|
||||
if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) {
|
||||
lastTellTimer = time(NULL);
|
||||
lastMoveTimer = getMSTime();
|
||||
std::ostringstream out;
|
||||
out << "I'm avoiding " << name.str() << "...";
|
||||
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||
@@ -1655,10 +1657,11 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
|
||||
break;
|
||||
}
|
||||
std::ostringstream name;
|
||||
name << triggerSpellInfo->SpellName[0]; //<< "] (unit)";
|
||||
name << triggerSpellInfo->SpellName[sWorld->GetDefaultDbcLocale()]; //<< "] (unit)";
|
||||
if (FleePosition(unit->GetPosition(), radius)) {
|
||||
if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) {
|
||||
lastTellTimer = time(NULL);
|
||||
lastMoveTimer = getMSTime();
|
||||
std::ostringstream out;
|
||||
out << "I'm avoiding " << name.str() << "...";
|
||||
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||
@@ -1697,6 +1700,11 @@ 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)) {
|
||||
continue;
|
||||
}
|
||||
bool strict = checkAngle.strict;
|
||||
float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance);
|
||||
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis,
|
||||
@@ -1740,6 +1748,11 @@ 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)) {
|
||||
continue;
|
||||
}
|
||||
bool strict = checkAngle.strict;
|
||||
float fleeDis = std::min(radius + 1.0f, sPlayerbotAIConfig->fleeDistance);
|
||||
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis,
|
||||
@@ -1774,12 +1787,29 @@ 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());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MovementAction::CheckLastFlee(float curAngle, float lastAngle, uint32 lastTS)
|
||||
{
|
||||
// more than 5 sec
|
||||
if (lastTS + 5000 < getMSTime()) {
|
||||
return true;
|
||||
}
|
||||
float revAngle = fmod(lastAngle + M_PI, 2 * M_PI);
|
||||
curAngle = fmod(curAngle, 2 * M_PI);
|
||||
// angle too close
|
||||
if (fabs(revAngle - curAngle) < M_PI / 8) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CombatFormationMoveAction::isUseful()
|
||||
{
|
||||
if (getMSTime() - moveInterval < lastMoveTimer) {
|
||||
|
||||
@@ -44,6 +44,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);
|
||||
protected:
|
||||
struct CheckAngle {
|
||||
float angle;
|
||||
|
||||
@@ -302,6 +302,8 @@ class ValueContext : public NamedObjectContext<UntypedValue>
|
||||
creators["area debuff"] = &ValueContext::area_debuff;
|
||||
creators["nearest trap with damage"] = &ValueContext::nearest_trap_with_damange;
|
||||
creators["disperse distance"] = &ValueContext::disperse_distance;
|
||||
creators["last flee angle"] = &ValueContext::last_flee_angle;
|
||||
creators["last flee timestamp"] = &ValueContext::last_flee_timestamp;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -507,6 +509,8 @@ class ValueContext : public NamedObjectContext<UntypedValue>
|
||||
static UntypedValue* area_debuff(PlayerbotAI* ai) { return new AreaDebuffValue(ai); }
|
||||
static UntypedValue* nearest_trap_with_damange(PlayerbotAI* ai) { return new NearestTrapWithDamageValue(ai); }
|
||||
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); }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user