mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-18 11:15:43 +00:00
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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"];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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))
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "XpGainAction.h"
|
||||
#include "Event.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "Playerbots.h"
|
||||
|
||||
bool XpGainAction::Execute(Event event)
|
||||
|
||||
Reference in New Issue
Block a user