mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-30 08:53:47 +00:00
Avoie aoe strategy
This commit is contained in:
@@ -155,22 +155,25 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
!bot->IsFlying() && !bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) && !bot->IsInWater();
|
!bot->IsFlying() && !bot->HasUnitMovementFlag(MOVEMENTFLAG_SWIMMING) && !bot->IsInWater();
|
||||||
if (!generatePath) {
|
if (!generatePath) {
|
||||||
float distance = bot->GetExactDist(x, y, z);
|
float distance = bot->GetExactDist(x, y, z);
|
||||||
WaitForReach(distance);
|
if (distance > sPlayerbotAIConfig->contactDistance)
|
||||||
|
|
||||||
if (bot->IsSitState())
|
|
||||||
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
|
||||||
|
|
||||||
if (bot->IsNonMeleeSpellCast(true))
|
|
||||||
{
|
{
|
||||||
bot->CastStop();
|
WaitForReach(distance);
|
||||||
botAI->InterruptSpell();
|
|
||||||
}
|
|
||||||
MotionMaster &mm = *bot->GetMotionMaster();
|
|
||||||
|
|
||||||
mm.Clear();
|
if (bot->IsSitState())
|
||||||
mm.MovePoint(mapId, x, y, z, generatePath);
|
bot->SetStandState(UNIT_STAND_STATE_STAND);
|
||||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation());
|
|
||||||
return true;
|
if (bot->IsNonMeleeSpellCast(true))
|
||||||
|
{
|
||||||
|
bot->CastStop();
|
||||||
|
botAI->InterruptSpell();
|
||||||
|
}
|
||||||
|
MotionMaster &mm = *bot->GetMotionMaster();
|
||||||
|
|
||||||
|
mm.Clear();
|
||||||
|
mm.MovePoint(mapId, x, y, z, generatePath);
|
||||||
|
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
float modifiedZ;
|
float modifiedZ;
|
||||||
Movement::PointsArray path = SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime);
|
Movement::PointsArray path = SearchForBestPath(x, y, z, modifiedZ, sPlayerbotAIConfig->maxMovementSearchTime);
|
||||||
@@ -197,7 +200,6 @@ bool MovementAction::MoveTo(uint32 mapId, float x, float y, float z, bool idle,
|
|||||||
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation());
|
AI_VALUE(LastMovement&, "last movement").Set(mapId, x, y, z, bot->GetOrientation());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -1484,11 +1486,62 @@ bool FleeWithPetAction::Execute(Event event)
|
|||||||
|
|
||||||
bool AvoidAoeAction::isUseful()
|
bool AvoidAoeAction::isUseful()
|
||||||
{
|
{
|
||||||
return false;
|
return AI_VALUE(Aura*, "area debuff");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AvoidAoeAction::Execute(Event event)
|
bool AvoidAoeAction::Execute(Event event)
|
||||||
{
|
{
|
||||||
|
// Case #1: Aura with dynamic object
|
||||||
|
Aura* aura = AI_VALUE(Aura*, "area debuff");
|
||||||
|
if (!aura) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!aura->GetSpellInfo()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!bot->HasAura(aura->GetSpellInfo()->Id)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
DynamicObject* dynOwner = aura->GetDynobjOwner();
|
||||||
|
if (!dynOwner || !dynOwner->IsInWorld()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
float radius = dynOwner->GetRadius();
|
||||||
|
if (bot->GetExactDist(dynOwner) > radius) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Unit* currentTarget = AI_VALUE(Unit*, "current target");
|
||||||
|
std::vector<float> possibleAngles;
|
||||||
|
if (currentTarget) {
|
||||||
|
float angleLeft = bot->GetAngle(currentTarget) + M_PI / 2;
|
||||||
|
float angleRight = bot->GetAngle(currentTarget) - M_PI / 2;
|
||||||
|
possibleAngles.push_back(angleLeft);
|
||||||
|
possibleAngles.push_back(angleRight);
|
||||||
|
} else {
|
||||||
|
float angleTo = bot->GetAngle(dynOwner) - M_PI;
|
||||||
|
possibleAngles.push_back(angleTo);
|
||||||
|
}
|
||||||
|
float farestDis = 0.0f;
|
||||||
|
Position bestPos;
|
||||||
|
// float disToDyn = bot->GetExactDist(dynOwner);
|
||||||
|
// float maxDisToGo = radius > disToDyn ? std::sqrt(radius * radius - disToDyn * disToDyn) + 0.5f : 0.5f;
|
||||||
|
for (float &angle : possibleAngles) {
|
||||||
|
float fleeDis = sPlayerbotAIConfig->fleeDistance;
|
||||||
|
Position pos{bot->GetPositionX() + cos(angle) * fleeDis,
|
||||||
|
bot->GetPositionY() + sin(angle) * fleeDis,
|
||||||
|
bot->GetPositionZ()};
|
||||||
|
// todo(Yunfan): check carefully
|
||||||
|
if (dynOwner->GetExactDist(pos) > farestDis) {
|
||||||
|
farestDis = dynOwner->GetExactDist(pos);
|
||||||
|
bestPos = pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (farestDis > 0.0f) {
|
||||||
|
std::ostringstream out;
|
||||||
|
out << "I'm avoiding aoe spell [" << aura->GetSpellInfo()->SpellName[0] << "]...";
|
||||||
|
bot->Say(out.str(), LANG_UNIVERSAL);
|
||||||
|
return MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true);
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,11 @@ bool TellLosAction::Execute(Event event)
|
|||||||
ListUnits("--- Friendly players ---", *context->GetValue<GuidVector>("nearest friendly players"));
|
ListUnits("--- Friendly players ---", *context->GetValue<GuidVector>("nearest friendly players"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (param.empty() || param == "triggers")
|
||||||
|
{
|
||||||
|
ListUnits("--- Triggers ---", *context->GetValue<GuidVector>("possible triggers"));
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,8 +51,9 @@ void TellLosAction::ListUnits(std::string const title, GuidVector units)
|
|||||||
|
|
||||||
for (ObjectGuid const guid : units)
|
for (ObjectGuid const guid : units)
|
||||||
{
|
{
|
||||||
if (Unit* unit = botAI->GetUnit(guid))
|
if (Unit* unit = botAI->GetUnit(guid)) {
|
||||||
botAI->TellMaster(unit->GetName());
|
botAI->TellMaster(unit->GetName());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -117,3 +117,26 @@ bool HasAreaDebuffValue::Calculate()
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Aura* AreaDebuffValue::Calculate()
|
||||||
|
{
|
||||||
|
Unit::AuraApplicationMap& map = bot->GetAppliedAuras();
|
||||||
|
for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i)
|
||||||
|
{
|
||||||
|
Aura *aura = i->second->GetBase();
|
||||||
|
if (!aura)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
AuraObjectType type = aura->GetType();
|
||||||
|
// bool is_area = aura->IsArea();
|
||||||
|
bool isPositive = aura->GetSpellInfo()->IsPositive();
|
||||||
|
if (type == DYNOBJ_AURA_TYPE && !isPositive) {
|
||||||
|
DynamicObject* dynOwner = aura->GetDynobjOwner();
|
||||||
|
if (!dynOwner) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
return aura;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
@@ -41,4 +41,13 @@ class HasAreaDebuffValue : public BoolCalculatedValue, public Qualified
|
|||||||
virtual bool Calculate();
|
virtual bool Calculate();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AreaDebuffValue : public CalculatedValue<Aura*>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AreaDebuffValue(PlayerbotAI* botAI) :
|
||||||
|
CalculatedValue<Aura*>(botAI, "area debuff", 1 * 1000) { }
|
||||||
|
|
||||||
|
Aura* Calculate() override;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,13 +34,4 @@ class ExpectedGroupDpsValue : public FloatCalculatedValue
|
|||||||
float Calculate() override;
|
float Calculate() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AreaDebuffValue : public CalculatedValue<Aura*>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AreaDebuffValue(PlayerbotAI* botAI) :
|
|
||||||
CalculatedValue<Aura*>(botAI, "area debuff", 20 * 1000) { }
|
|
||||||
|
|
||||||
Aura* Calculate() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "GridNotifiers.h"
|
#include "GridNotifiers.h"
|
||||||
#include "GridNotifiersImpl.h"
|
#include "GridNotifiersImpl.h"
|
||||||
#include "Playerbots.h"
|
#include "Playerbots.h"
|
||||||
|
#include "Unit.h"
|
||||||
|
|
||||||
void PossibleTargetsValue::FindUnits(std::list<Unit*>& targets)
|
void PossibleTargetsValue::FindUnits(std::list<Unit*>& targets)
|
||||||
{
|
{
|
||||||
@@ -20,3 +21,17 @@ bool PossibleTargetsValue::AcceptUnit(Unit* unit)
|
|||||||
{
|
{
|
||||||
return AttackersValue::IsPossibleTarget(unit, bot, range);
|
return AttackersValue::IsPossibleTarget(unit, bot, range);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PossibleTriggersValue::FindUnits(std::list<Unit*>& targets)
|
||||||
|
{
|
||||||
|
Acore::AnyUnfriendlyUnitInObjectRangeCheck u_check(bot, bot, range);
|
||||||
|
Acore::UnitListSearcher<Acore::AnyUnfriendlyUnitInObjectRangeCheck> searcher(bot, targets, u_check);
|
||||||
|
Cell::VisitAllObjects(bot, searcher, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PossibleTriggersValue::AcceptUnit(Unit* unit)
|
||||||
|
{
|
||||||
|
return unit->HasUnitFlag(UNIT_FLAG_NON_ATTACKABLE) && unit->HasUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||||
|
return true; // AttackersValue::IsPossibleTarget(unit, bot, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,4 +27,14 @@ class AllTargetsValue : public PossibleTargetsValue
|
|||||||
AllTargetsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) : PossibleTargetsValue(botAI, "all targets", range, true) { }
|
AllTargetsValue(PlayerbotAI* botAI, float range = sPlayerbotAIConfig->sightDistance) : PossibleTargetsValue(botAI, "all targets", range, true) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PossibleTriggersValue : public NearestUnitsValue
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PossibleTriggersValue(PlayerbotAI* botAI, std::string const name = "possible targets", float range = sPlayerbotAIConfig->sightDistance, bool ignoreLos = true):
|
||||||
|
NearestUnitsValue(botAI, name, range, ignoreLos) { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void FindUnits(std::list<Unit*>& targets) override;
|
||||||
|
bool AcceptUnit(Unit* unit) override;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
|
|||||||
creators["nearest enemy players"] = &ValueContext::nearest_enemy_players;
|
creators["nearest enemy players"] = &ValueContext::nearest_enemy_players;
|
||||||
creators["possible targets"] = &ValueContext::possible_targets;
|
creators["possible targets"] = &ValueContext::possible_targets;
|
||||||
creators["possible targets no los"] = &ValueContext::possible_targets_no_los;
|
creators["possible targets no los"] = &ValueContext::possible_targets_no_los;
|
||||||
|
creators["possible triggers"] = &ValueContext::possible_triggers;
|
||||||
creators["possible adds"] = &ValueContext::possible_adds;
|
creators["possible adds"] = &ValueContext::possible_adds;
|
||||||
creators["all targets"] = &ValueContext::all_targets;
|
creators["all targets"] = &ValueContext::all_targets;
|
||||||
creators["possible rpg targets"] = &ValueContext::possible_rpg_targets;
|
creators["possible rpg targets"] = &ValueContext::possible_rpg_targets;
|
||||||
@@ -377,6 +378,7 @@ class ValueContext : public NamedObjectContext<UntypedValue>
|
|||||||
static UntypedValue* nearest_corpses(PlayerbotAI* botAI) { return new NearestCorpsesValue(botAI); }
|
static UntypedValue* nearest_corpses(PlayerbotAI* botAI) { return new NearestCorpsesValue(botAI); }
|
||||||
static UntypedValue* possible_rpg_targets(PlayerbotAI* botAI) { return new PossibleRpgTargetsValue(botAI); }
|
static UntypedValue* possible_rpg_targets(PlayerbotAI* botAI) { return new PossibleRpgTargetsValue(botAI); }
|
||||||
static UntypedValue* possible_targets(PlayerbotAI* botAI) { return new PossibleTargetsValue(botAI); }
|
static UntypedValue* possible_targets(PlayerbotAI* botAI) { return new PossibleTargetsValue(botAI); }
|
||||||
|
static UntypedValue* possible_triggers(PlayerbotAI* botAI) { return new PossibleTriggersValue(botAI); }
|
||||||
static UntypedValue* possible_targets_no_los(PlayerbotAI* botAI) { return new PossibleTargetsValue(botAI, "possible targets", sPlayerbotAIConfig->sightDistance, true); }
|
static UntypedValue* possible_targets_no_los(PlayerbotAI* botAI) { return new PossibleTargetsValue(botAI, "possible targets", sPlayerbotAIConfig->sightDistance, true); }
|
||||||
static UntypedValue* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsValue(botAI); }
|
static UntypedValue* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsValue(botAI); }
|
||||||
static UntypedValue* all_targets(PlayerbotAI* botAI) { return new AllTargetsValue(botAI); }
|
static UntypedValue* all_targets(PlayerbotAI* botAI) { return new AllTargetsValue(botAI); }
|
||||||
|
|||||||
Reference in New Issue
Block a user