Merge branch 'liyunfan1223:master' into master

This commit is contained in:
fuzzdeveloper
2024-07-05 00:06:24 +10:00
committed by GitHub
25 changed files with 215 additions and 72 deletions

View File

@@ -144,7 +144,7 @@ bool Engine::DoNextAction(Unit* unit, uint32 depth, bool minimal)
ActionBasket* basket = nullptr;
time_t currentTime = time(nullptr);
aiObjectContext->Update();
// aiObjectContext->Update();
ProcessTriggers(minimal);
PushDefaultActions();
@@ -469,7 +469,7 @@ bool Engine::HasStrategy(std::string const name)
void Engine::ProcessTriggers(bool minimal)
{
std::unordered_map<Trigger*, Event> fires;
// std::unordered_map<Trigger*, Event> fires;
for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
{
TriggerNode* node = *i;
@@ -499,21 +499,22 @@ void Engine::ProcessTriggers(bool minimal)
if (!event)
continue;
fires[trigger] = event;
// fires[trigger] = event;
LogAction("T:%s", trigger->getName().c_str());
MultiplyAndPush(node->getHandlers(), 0.0f, false, event, "trigger");
}
}
for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
{
TriggerNode* node = *i;
Trigger* trigger = node->getTrigger();
Event event = fires[trigger];
if (!event)
continue;
// for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
// {
// TriggerNode* node = *i;
// Trigger* trigger = node->getTrigger();
// if (fires.find(trigger) == fires.end())
// continue;
MultiplyAndPush(node->getHandlers(), 0.0f, false, event, "trigger");
}
// Event event = fires[trigger];
// }
for (std::vector<TriggerNode*>::iterator i = triggers.begin(); i != triggers.end(); i++)
{

View File

@@ -23,10 +23,15 @@ bool ChangeTalentsAction::Execute(Event event)
if (param.find("help") != std::string::npos) {
out << TalentsHelp();
} else if (param.find("switch") != std::string::npos) {
if (param.find("switch 1")) {
if (param.find("switch 1") != std::string::npos) {
bot->ActivateSpec(0);
out << "Active first talent";
} else if (param.find("switch 2")) {
} else if (param.find("switch 2") != std::string::npos) {
if (bot->GetSpecsCount() == 1 && bot->GetLevel() >= sWorld->getIntConfig(CONFIG_MIN_DUALSPEC_LEVEL))
{
bot->CastSpell(bot, 63680, true, nullptr, nullptr, bot->GetGUID());
bot->CastSpell(bot, 63624, true, nullptr, nullptr, bot->GetGUID());
}
bot->ActivateSpec(1);
out << "Active second talent";
}

View File

@@ -115,6 +115,7 @@ class ChatActionContext : public NamedObjectContext<Action>
creators["de"] = &ChatActionContext::dead;
creators["trainer"] = &ChatActionContext::trainer;
creators["maintenance"] = &ChatActionContext::maintenance;
creators["remove glyph"] = &ChatActionContext::remove_glyph;
creators["autogear"] = &ChatActionContext::autogear;
creators["equip upgrade"] = &ChatActionContext::equip_upgrade;
creators["attack my target"] = &ChatActionContext::attack_my_target;
@@ -215,6 +216,7 @@ class ChatActionContext : public NamedObjectContext<Action>
static Action* attack_my_target(PlayerbotAI* botAI) { return new AttackMyTargetAction(botAI); }
static Action* trainer(PlayerbotAI* botAI) { return new TrainerAction(botAI); }
static Action* maintenance(PlayerbotAI* botAI) { return new MaintenanceAction(botAI); }
static Action* remove_glyph(PlayerbotAI* botAI) { return new RemoveGlyphAction(botAI); }
static Action* autogear(PlayerbotAI* botAI) { return new AutoGearAction(botAI); }
static Action* equip_upgrade(PlayerbotAI* botAI) { return new EquipUpgradeAction(botAI); }
static Action* co(PlayerbotAI* botAI) { return new ChangeCombatStrategyAction(botAI); }

View File

@@ -33,6 +33,7 @@ bool FollowChatShortcutAction::Execute(Event event)
botAI->Reset();
botAI->ChangeStrategy("+follow,-passive,-grind", BOT_STATE_NON_COMBAT);
botAI->ChangeStrategy("-follow,-passive,-grind", BOT_STATE_COMBAT);
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({});
PositionMap& posMap = context->GetValue<PositionMap&>("position")->Get();
PositionInfo pos = posMap["return"];

View File

@@ -1645,34 +1645,107 @@ bool AvoidAoeAction::AvoidUnitWithDamageAura()
return false;
}
bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name)
Position AvoidAoeAction::BestPositionForMelee(Position pos, float radius)
{
Unit* currentTarget = AI_VALUE(Unit*, "current target");
std::vector<float> possibleAngles;
std::vector<CheckAngle> possibleAngles;
if (currentTarget) {
// Normally, move to left or right is the best position
float angleLeft = bot->GetAngle(currentTarget) + M_PI / 2;
float angleRight = bot->GetAngle(currentTarget) - M_PI / 2;
possibleAngles.push_back(angleLeft);
possibleAngles.push_back(angleRight);
bool isTanking = (currentTarget->CanFreeMove()) && (currentTarget->GetVictim() == bot);
float angle = bot->GetAngle(currentTarget);
float angleLeft = angle + (float)M_PI / 2;
float angleRight = angle - (float)M_PI / 2;
possibleAngles.push_back({angleLeft, false});
possibleAngles.push_back({angleRight, false});
possibleAngles.push_back({angle, true});
if (isTanking) {
possibleAngles.push_back({angle + (float)M_PI, false});
possibleAngles.push_back({bot->GetAngle(&pos) - (float)M_PI, false});
}
} else {
float angleTo = bot->GetAngle(&pos) - M_PI;
possibleAngles.push_back(angleTo);
float angleTo = bot->GetAngle(&pos) - (float)M_PI;
possibleAngles.push_back({angleTo, false});
}
float farestDis = 0.0f;
Position bestPos;
for (float &angle : possibleAngles) {
for (CheckAngle &checkAngle : possibleAngles) {
float angle = checkAngle.angle;
bool strict = checkAngle.strict;
float fleeDis = sPlayerbotAIConfig->fleeDistance;
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis,
bot->GetPositionY() + sin(angle) * fleeDis,
bot->GetPositionZ()};
// todo (Yunfan): check carefully
if (strict && currentTarget
&& fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->tooCloseDistance) {
continue;
}
if (pos.GetExactDist(fleePos) > farestDis) {
farestDis = pos.GetExactDist(fleePos);
bestPos = fleePos;
}
}
if (farestDis > 0.0f) {
return bestPos;
}
return Position();
}
Position AvoidAoeAction::BestPositionForRanged(Position pos, float radius)
{
Unit* currentTarget = AI_VALUE(Unit*, "current target");
std::vector<CheckAngle> possibleAngles;
float angleToTarget = 0.0f;
float angleFleeFromCenter = bot->GetAngle(&pos) - (float)M_PI;
if (currentTarget) {
// Normally, move to left or right is the best position
angleToTarget = bot->GetAngle(currentTarget);
float angleLeft = angleToTarget + (float)M_PI / 2;
float angleRight = angleToTarget - (float)M_PI / 2;
possibleAngles.push_back({angleLeft, false});
possibleAngles.push_back({angleRight, false});
possibleAngles.push_back({angleToTarget + (float)M_PI, true});
possibleAngles.push_back({angleToTarget, true});
possibleAngles.push_back({angleFleeFromCenter, true});
} else {
possibleAngles.push_back({angleFleeFromCenter, false});
}
float farestDis = 0.0f;
Position bestPos;
for (CheckAngle &checkAngle : possibleAngles) {
float angle = checkAngle.angle;
bool strict = checkAngle.strict;
float fleeDis = sPlayerbotAIConfig->fleeDistance;
Position fleePos{bot->GetPositionX() + cos(angle) * fleeDis,
bot->GetPositionY() + sin(angle) * fleeDis,
bot->GetPositionZ()};
if (strict && currentTarget
&& fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() > sPlayerbotAIConfig->spellDistance) {
continue;
}
if (strict && currentTarget
&& fleePos.GetExactDist(currentTarget) - currentTarget->GetCombatReach() < (sPlayerbotAIConfig->tooCloseDistance)) {
continue;
}
if (pos.GetExactDist(fleePos) > farestDis) {
farestDis = pos.GetExactDist(fleePos);
bestPos = fleePos;
}
}
if (farestDis > 0.0f) {
return bestPos;
}
return Position();
}
bool AvoidAoeAction::FleePosition(Position pos, float radius, std::string name)
{
Position bestPos;
if (botAI->IsMelee(bot)) {
bestPos = BestPositionForMelee(pos, radius);
} else {
bestPos = BestPositionForRanged(pos, radius);
}
if (bestPos != Position()) {
if (MoveTo(bot->GetMapId(), bestPos.GetPositionX(), bestPos.GetPositionY(), bestPos.GetPositionZ(), false, false, true)) {
if (sPlayerbotAIConfig->tellWhenAvoidAoe && lastTellTimer < time(NULL) - 10) {
lastTellTimer = time(NULL);

View File

@@ -78,11 +78,14 @@ class AvoidAoeAction : public MovementAction
bool AvoidAuraWithDynamicObj();
bool AvoidGameObjectWithDamage();
bool AvoidUnitWithDamageAura();
// Position PositionForTank(Position pos, float radius);
// Position PositionForMelee(Position pos, float radius);
// Position PositionForRanged(Position pos, float radius);
Position BestPositionForMelee(Position pos, float radius);
Position BestPositionForRanged(Position pos, float radius);
bool FleePosition(Position pos, float radius, std::string name);
time_t lastTellTimer = 0;
struct CheckAngle {
float angle;
bool strict;
};
};
class RunAwayAction : public MovementAction

View File

@@ -175,6 +175,15 @@ bool MaintenanceAction::Execute(Event event)
return true;
}
bool RemoveGlyphAction::Execute(Event event)
{
for (uint32 slotIndex = 0; slotIndex < MAX_GLYPH_SLOT_INDEX; ++slotIndex)
{
bot->SetGlyph(slotIndex, 0, true);
}
return true;
}
bool AutoGearAction::Execute(Event event)
{
if (!sPlayerbotAIConfig->autoGearCommand) {

View File

@@ -35,6 +35,13 @@ class MaintenanceAction : public Action
bool Execute(Event event) override;
};
class RemoveGlyphAction : public Action
{
public:
RemoveGlyphAction(PlayerbotAI* botAI) : Action(botAI, "remove glyph") { }
bool Execute(Event event) override;
};
class AutoGearAction : public Action
{
public:

View File

@@ -81,8 +81,10 @@ bool SummonAction::Execute(Event event)
pet->GetCharmInfo()->IsReturning();
}
if (master->GetSession()->GetSecurity() >= SEC_PLAYER)
if (master->GetSession()->GetSecurity() >= SEC_PLAYER) {
botAI->GetAiObjectContext()->GetValue<GuidVector>("prioritized targets")->Set({});
return Teleport(master, bot);
}
if (SummonUsingGos(master, bot) || SummonUsingNpcs(master, bot))
{

View File

@@ -4,6 +4,7 @@
#include "XpGainAction.h"
#include "Event.h"
#include "PlayerbotAIConfig.h"
#include "Playerbots.h"
bool XpGainAction::Execute(Event event)

View File

@@ -89,6 +89,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
supported.push_back("de");
supported.push_back("trainer");
supported.push_back("maintenance");
supported.push_back("remove glyph");
supported.push_back("autogear");
supported.push_back("equip upgrade");
supported.push_back("chat");

View File

@@ -55,6 +55,7 @@ class ChatTriggerContext : public NamedObjectContext<Trigger>
creators["de"] = &ChatTriggerContext::dead;
creators["trainer"] = &ChatTriggerContext::trainer;
creators["maintenance"] = &ChatTriggerContext::maintenance;
creators["remove glyph"] = &ChatTriggerContext::remove_glyph;
creators["autogear"] = &ChatTriggerContext::autogear;
creators["equip upgrade"] = &ChatTriggerContext::equip_upgrade;
creators["attack"] = &ChatTriggerContext::attack;
@@ -168,6 +169,7 @@ class ChatTriggerContext : public NamedObjectContext<Trigger>
static Trigger* attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attack"); }
static Trigger* trainer(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "trainer"); }
static Trigger* maintenance(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "maintenance"); }
static Trigger* remove_glyph(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "remove glyph"); }
static Trigger* autogear(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "autogear"); }
static Trigger* equip_upgrade(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "equip upgrade"); }
static Trigger* co(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "co"); }

View File

@@ -125,7 +125,8 @@ Aura* AreaDebuffValue::Calculate()
Unit::AuraEffectList const& aurasPeriodicDamagePercent = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_DAMAGE_PERCENT);
Unit::AuraEffectList const& aurasPeriodicTriggerSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL);
Unit::AuraEffectList const& aurasPeriodicTriggerWithValueSpell = bot->GetAuraEffectsByType(SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE);
for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicDamagePercent, aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell}) {
Unit::AuraEffectList const& aurasDummy = bot->GetAuraEffectsByType(SPELL_AURA_DUMMY);
for (const Unit::AuraEffectList& list : {aurasPeriodicDamage, aurasPeriodicDamagePercent, aurasPeriodicTriggerSpell, aurasPeriodicTriggerWithValueSpell, aurasDummy}) {
for (auto i = list.begin(); i != list.end(); ++i)
{
AuraEffect* aurEff = *i;

View File

@@ -104,7 +104,7 @@ void AttackersValue::RemoveNonThreating(std::unordered_set<Unit*>& targets)
for(std::unordered_set<Unit *>::iterator tIter = targets.begin(); tIter != targets.end();)
{
Unit* unit = *tIter;
if(bot->GetMapId() != unit->GetMapId() || !hasRealThreat(unit) || !IsValidTarget(unit, bot) || !bot->IsWithinLOSInMap(unit))
if(bot->GetMapId() != unit->GetMapId() || !hasRealThreat(unit) || !IsValidTarget(unit, bot))
{
std::unordered_set<Unit *>::iterator tIter2 = tIter;
++tIter;
@@ -113,15 +113,6 @@ void AttackersValue::RemoveNonThreating(std::unordered_set<Unit*>& targets)
else
++tIter;
}
// Unit* unit = *tIter;
// if (!IsValidTarget(unit, bot) || !bot->IsWithinLOSInMap(unit))
// {
// std::unordered_set<Unit*>::iterator tIter2 = tIter;
// ++tIter;
// targets.erase(tIter2);
// }
// else
// ++tIter;
}
bool AttackersValue::hasRealThreat(Unit *attacker)
@@ -160,7 +151,7 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range)
// bool inCannon = botAI->IsInVehicle(false, true);
// bool enemy = botAI->GetAiObjectContext()->GetValue<Unit*>("enemy player target")->Get();
return attacker &&
return attacker && attacker->IsVisible() &&
attacker->IsInWorld() &&
attacker->GetMapId() == bot->GetMapId() &&
!attacker->isDead() &&
@@ -183,10 +174,9 @@ bool AttackersValue::IsPossibleTarget(Unit* attacker, Player* bot, float range)
bool AttackersValue::IsValidTarget(Unit *attacker, Player *bot)
{
return attacker->IsVisible() &&
IsPossibleTarget(attacker, bot) &&
(attacker->GetThreatMgr().getCurrentVictim() || attacker->GetGuidValue(UNIT_FIELD_TARGET) ||
attacker->GetGUID().IsPlayer() || attacker->GetGUID() == GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<ObjectGuid>("pull target")->Get());
return IsPossibleTarget(attacker, bot) && bot->IsWithinLOSInMap(attacker);
// (attacker->GetThreatMgr().getCurrentVictim() || attacker->GetGuidValue(UNIT_FIELD_TARGET) ||
// attacker->GetGUID().IsPlayer() || attacker->GetGUID() == GET_PLAYERBOT_AI(bot)->GetAiObjectContext()->GetValue<ObjectGuid>("pull target")->Get());
}
bool PossibleAddsValue::Calculate()

View File

@@ -71,6 +71,12 @@ class CasterFindTargetSmartStrategy : public FindTargetStrategy
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
{
if (Group* group = botAI->GetBot()->GetGroup())
{
ObjectGuid guid = group->GetTargetIcon(4);
if (guid && attacker->GetGUID() == guid)
return;
}
if (!attacker->IsAlive()) {
return;
}
@@ -138,6 +144,12 @@ class NonCasterFindTargetSmartStrategy : public FindTargetStrategy
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
{
if (Group* group = botAI->GetBot()->GetGroup())
{
ObjectGuid guid = group->GetTargetIcon(4);
if (guid && attacker->GetGUID() == guid)
return;
}
if (!attacker->IsAlive()) {
return;
}
@@ -193,6 +205,12 @@ class ComboFindTargetSmartStrategy : public FindTargetStrategy
void CheckAttacker(Unit* attacker, ThreatMgr* threatMgr) override
{
if (Group* group = botAI->GetBot()->GetGroup())
{
ObjectGuid guid = group->GetTargetIcon(4);
if (guid && attacker->GetGUID() == guid)
return;
}
if (!attacker->IsAlive()) {
return;
}

View File

@@ -27,9 +27,7 @@ bool InvalidTargetValue::Calculate()
target->isFeared() ||
target->HasUnitState(UNIT_STATE_ISOLATED) ||
target->IsFriendlyTo(bot) ||
!AttackersValue::IsValidTarget(target, bot) ||
// !bot->IsWithinDistInMap(target, sPlayerbotAIConfig->sightDistance) ||
!bot->IsWithinLOSInMap(target);
!AttackersValue::IsValidTarget(target, bot);
}
return !target;