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