fix party member dispel.

This commit is contained in:
Yunfan Li
2023-05-29 23:03:21 +08:00
parent aaa358bdbe
commit d45a7dc5b8
27 changed files with 316 additions and 89 deletions

View File

@@ -2568,7 +2568,7 @@ bool PlayerbotAI::HasAuraToDispel(Unit* target, uint32 dispelType)
continue;
if (sPlayerbotAIConfig->dispelAuraDuration && aura->GetDuration() && aura->GetDuration() < (int32)sPlayerbotAIConfig->dispelAuraDuration)
return false;
continue;
if (canDispel(spellInfo, dispelType))
return true;
@@ -2946,7 +2946,7 @@ void PlayerbotAI::RemoveShapeshift()
RemoveAura("swift flight form");
RemoveAura("aquatic form");
RemoveAura("ghost wolf");
RemoveAura("tree of life");
// RemoveAura("tree of life");
}
uint32 PlayerbotAI::GetEquipGearScore(Player* player, bool withBags, bool withBank)

View File

@@ -219,6 +219,8 @@ class ActionContext : public NamedObjectContext<Action>
creators["rpg trade useful"] = &ActionContext::rpg_trade_useful;
creators["rpg duel"] = &ActionContext::rpg_duel;
creators["rpg mount anim"] = &ActionContext::rpg_mount_anim;
creators["toggle pet spell"] = &ActionContext::toggle_pet_spell;
}
private:
@@ -378,6 +380,8 @@ class ActionContext : public NamedObjectContext<Action>
static Action* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulAction(botAI); }
static Action* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelAction(botAI); }
static Action* rpg_mount_anim(PlayerbotAI* botAI) { return new RpgMountAnimAction(botAI); }
static Action* toggle_pet_spell(PlayerbotAI* ai) { return new TogglePetSpellAutoCastAction(ai); }
};
#endif

View File

@@ -85,6 +85,7 @@ class ChatActionContext : public NamedObjectContext<Action>
creators["reputation"] = &ChatActionContext::reputation;
creators["log"] = &ChatActionContext::log;
creators["los"] = &ChatActionContext::los;
creators["aura"] = &ChatActionContext::aura;
creators["drop"] = &ChatActionContext::drop;
creators["clean quest log"] = &ChatActionContext::clean_quest_log;
creators["share"] = &ChatActionContext::share;
@@ -238,6 +239,7 @@ class ChatActionContext : public NamedObjectContext<Action>
static Action* reputation(PlayerbotAI* botAI) { return new TellReputationAction(botAI); }
static Action* log(PlayerbotAI* botAI) { return new LogLevelAction(botAI); }
static Action* los(PlayerbotAI* botAI) { return new TellLosAction(botAI); }
static Action* aura(PlayerbotAI* ai) { return new TellAuraAction(ai); }
static Action* ll(PlayerbotAI* botAI) { return new LootStrategyAction(botAI); }
static Action* ss(PlayerbotAI* botAI) { return new SkipSpellsListAction(botAI); }
static Action* add_all_loot(PlayerbotAI* botAI) { return new AddAllLootAction(botAI); }

View File

@@ -13,3 +13,30 @@ bool MeleeAction::isUseful()
return true;
}
bool TogglePetSpellAutoCastAction::Execute(Event event) {
Pet* pet = bot->GetPet();
if (!pet) {
return false;
}
for (PetSpellMap::const_iterator itr = pet->m_spells.begin(); itr != pet->m_spells.end(); ++itr)
{
if(itr->second.state == PETSPELL_REMOVED)
continue;
uint32 spellId = itr->first;
const SpellInfo* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (spellInfo->IsPassive())
continue;
// imp's spell, felhunte's intelligence, ghoul's leap
if (spellId == 4511 || spellId == 1742 ||
spellId == 54424 || spellId == 57564 || spellId == 57565 || spellId == 57566 || spellId == 57567 ||
spellId == 47482) {
pet->ToggleAutocast(spellInfo, false);
} else {
pet->ToggleAutocast(spellInfo, true);
}
}
return true;
}

View File

@@ -18,4 +18,11 @@ class MeleeAction : public AttackAction
bool isUseful() override;
};
class TogglePetSpellAutoCastAction: public Action
{
public:
TogglePetSpellAutoCastAction(PlayerbotAI* ai): Action(ai, "toggle pet spell") {}
virtual bool Execute(Event event) override;
};
#endif

View File

@@ -61,3 +61,68 @@ void TellLosAction::ListGameObjects(std::string const title, GuidVector gos)
botAI->TellMaster(chat->FormatGameobject(go));
}
}
bool TellAuraAction::Execute(Event event)
{
botAI->TellMaster("--- Auras ---");
sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "--- Auras ---");
Unit::AuraApplicationMap& map = bot->GetAppliedAuras();
for (Unit::AuraApplicationMap::iterator i = map.begin(); i != map.end(); ++i)
{
Aura * aura = i->second->GetBase();
if (!aura)
continue;
const std::string auraName = aura->GetSpellInfo()->SpellName[0];
sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "Info of Aura - name: " + auraName);
AuraObjectType type = aura->GetType();
WorldObject* owner = aura->GetOwner();
std::string owner_name = owner ? owner->GetName() : "unknown";
float distance = bot->GetDistance2d(owner);
Unit* caster = aura->GetCaster();
std::string caster_name = caster ? caster->GetName() : "unknown";
bool is_area = aura->IsArea();
int32 duration = aura->GetDuration();
const SpellInfo* spellInfo = aura->GetSpellInfo();
int32 spellId = aura->GetSpellInfo()->Id;
bool isPositive = aura->GetSpellInfo()->IsPositive();
sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, "Info of Aura - name: " + auraName +
" caster: " + caster_name +
" type: " + std::to_string(type) +
" owner: " + owner_name +
" distance: " + std::to_string(distance) +
" isArea: " + std::to_string(is_area) +
" duration: " + std::to_string(duration) +
" spellId: " + std::to_string(spellId) +
" isPositive: " + std::to_string(isPositive));
botAI->TellMaster("Info of Aura - name: " + auraName +
" caster: " + caster_name +
" type: " + std::to_string(type) +
" owner: " + owner_name +
" distance: " + std::to_string(distance) +
" isArea: " + std::to_string(is_area) +
" duration: " + std::to_string(duration) +
" spellId: " + std::to_string(spellId) +
" isPositive: " + std::to_string(isPositive));
if (type == DYNOBJ_AURA_TYPE) {
DynamicObject* dyn_owner = aura->GetDynobjOwner();
float radius = dyn_owner->GetRadius();
int32 spellId = dyn_owner->GetSpellId();
int32 duration = dyn_owner->GetDuration();
sLog->outMessage("playerbot", LOG_LEVEL_DEBUG, std::string("Info of DynamicObject -") +
" name: " + dyn_owner->GetName() +
" radius: " + std::to_string(radius) +
" spell id: " + std::to_string(spellId) +
" duration: " + std::to_string(duration));
botAI->TellMaster(std::string("Info of DynamicObject -") +
" name: " + dyn_owner->GetName() +
" radius: " + std::to_string(radius) +
" spell id: " + std::to_string(spellId) +
" duration: " + std::to_string(duration));
}
}
return true;
}

View File

@@ -21,4 +21,11 @@ class TellLosAction : public Action
void ListGameObjects(std::string const title, GuidVector gos);
};
class TellAuraAction : public Action
{
public:
TellAuraAction(PlayerbotAI* ai) : Action(ai, "aura") {}
virtual bool Execute(Event event);
};
#endif

View File

@@ -44,9 +44,10 @@ void GenericDKNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("raise dead", ACTION_NORMAL + 1), nullptr)));
triggers.push_back(new TriggerNode("horn of winter", NextAction::array(0, new NextAction("horn of winter", 21.0f), nullptr)));
triggers.push_back(new TriggerNode("bone shield", NextAction::array(0, new NextAction("bone shield", 21.0f), nullptr)));
triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 11.0f), NULL)));
}
void DKBuffDpsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode("improved icy talons", NextAction::array(0, new NextAction("improved icy talons", 19.0f), nullptr)));
// triggers.push_back(new TriggerNode("improved icy talons", NextAction::array(0, new NextAction("improved icy talons", 19.0f), nullptr)));
}

View File

@@ -236,4 +236,21 @@ class CastNaturesSwiftnessAction : public CastBuffSpellAction
CastNaturesSwiftnessAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "nature's swiftness") { }
};
class CastWildGrowthOnPartyAction : public HealPartyMemberAction
{
public:
CastWildGrowthOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "wild growth") {}
};
class CastPartySwiftmendAction : public HealPartyMemberAction
{
public:
CastPartySwiftmendAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "swiftmend") {}
};
class CastPartyNourishAction : public HealPartyMemberAction
{
public:
CastPartyNourishAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "nourish") {}
};
#endif

View File

@@ -199,6 +199,9 @@ class DruidAiObjectContextInternal : public NamedObjectContext<Action>
creators["shred"] = &DruidAiObjectContextInternal::shred;
creators["ravage"] = &DruidAiObjectContextInternal::ravage;
creators["pounce"] = &DruidAiObjectContextInternal::pounce;
creators["wild growth on party"] = &DruidAiObjectContextInternal::wild_growth_on_party;
creators["swiftmend on party"] = &DruidAiObjectContextInternal::swiftmend_on_party;
creators["nourish on party"] = &DruidAiObjectContextInternal::nourish_on_party;
}
private:
@@ -270,6 +273,9 @@ class DruidAiObjectContextInternal : public NamedObjectContext<Action>
static Action* prowl(PlayerbotAI* botAI) { return new CastProwlAction(botAI); }
static Action* dash(PlayerbotAI* botAI) { return new CastDashAction(botAI); }
static Action* shred(PlayerbotAI* botAI) { return new CastShredAction(botAI); }
static Action* wild_growth_on_party(PlayerbotAI* ai) { return new CastWildGrowthOnPartyAction(ai); }
static Action* swiftmend_on_party(PlayerbotAI *ai) { return new CastPartySwiftmendAction(ai); }
static Action* nourish_on_party(PlayerbotAI *ai) { return new CastPartyNourishAction(ai); }
};
DruidAiObjectContext::DruidAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)

View File

@@ -39,3 +39,8 @@ bool CastCasterFormAction::Execute(Event event)
botAI->RemoveShapeshift();
return true;
}
bool CastTreeFormAction::isUseful() {
return GetTarget() && (GetTarget() != nullptr) && (GetTarget() != nullptr) &&
CastSpellAction::isUseful() && !botAI->HasAura(33891, bot);
}

View File

@@ -36,6 +36,7 @@ class CastTreeFormAction : public CastBuffSpellAction
{
public:
CastTreeFormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "tree of life") { }
bool isUseful() override;
};
class CastMoonkinFormAction : public CastBuffSpellAction

View File

@@ -42,7 +42,7 @@ bool BearFormTrigger::IsActive()
bool TreeFormTrigger::IsActive()
{
return !botAI->HasAura("tree of life", bot);
return !botAI->HasAura(33891, bot);
}
bool CatFormTrigger::IsActive()

View File

@@ -14,7 +14,7 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory
creators["thorns on party"] = &thorns_on_party;
creators["mark of the wild"] = &mark_of_the_wild;
creators["mark of the wild on party"] = &mark_of_the_wild_on_party;
creators["innervate"] = &innervate;
// creators["innervate"] = &innervate;
}
private:
@@ -50,13 +50,13 @@ class GenericDruidNonCombatStrategyActionNodeFactory : public NamedObjectFactory
/*C*/ nullptr);
}
static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI)
{
return new ActionNode ("innervate",
/*P*/ nullptr,
/*A*/ NextAction::array(0, new NextAction("drink"), nullptr),
/*C*/ nullptr);
}
// static ActionNode* innervate([[maybe_unused]] PlayerbotAI* botAI)
// {
// return new ActionNode ("innervate",
// /*P*/ nullptr,
// /*A*/ NextAction::array(0, new NextAction("drink"), nullptr),
// /*C*/ nullptr);
// }
};
GenericDruidNonCombatStrategy::GenericDruidNonCombatStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)
@@ -70,12 +70,27 @@ void GenericDruidNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& trig
triggers.push_back(new TriggerNode("mark of the wild", NextAction::array(0, new NextAction("mark of the wild", 14.0f), nullptr)));
triggers.push_back(new TriggerNode("thorns", NextAction::array(0, new NextAction("thorns", 12.0f), nullptr)));
triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), nullptr)));
// triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", 21.0f), nullptr)));
triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", 20.0f), nullptr)));
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("revive", 22.0f), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr)));
triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic form", 1.0f), nullptr)));
// triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr)));
// triggers.push_back(new TriggerNode("swimming", NextAction::array(0, new NextAction("aquatic form", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("often", NextAction::array(0, new NextAction("apply oil", 1.0f), nullptr)));
triggers.push_back(new TriggerNode("party member critical health",
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 5),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 6), NULL)));
triggers.push_back(new TriggerNode("party member low health",
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 4), NULL)));
triggers.push_back(new TriggerNode("party member medium health",
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 1),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2), NULL)));
triggers.push_back(new TriggerNode("party member almost full health",
NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2), NULL)));
}
GenericDruidBuffStrategy::GenericDruidBuffStrategy(PlayerbotAI* botAI) : NonCombatStrategy(botAI)

View File

@@ -104,17 +104,17 @@ void GenericDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
CombatStrategy::InitTriggers(triggers);
triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("regrowth", ACTION_CRITICAL_HEAL + 2), new NextAction("healing touch", ACTION_CRITICAL_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 1), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr)));
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr)));
// triggers.push_back(new TriggerNode("party member low health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
// triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("regrowth", ACTION_CRITICAL_HEAL + 2), new NextAction("healing touch", ACTION_CRITICAL_HEAL + 2), nullptr)));
// triggers.push_back(new TriggerNode("party member critical health", NextAction::array(0, new NextAction("regrowth on party", ACTION_CRITICAL_HEAL + 1), new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 1), nullptr)));
// triggers.push_back(new TriggerNode("party member dead", NextAction::array(0, new NextAction("rebirth", ACTION_HIGH + 1), nullptr)));
// triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("innervate", ACTION_EMERGENCY + 5), nullptr)));
}
void DruidCureStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", ACTION_DISPEL + 2), nullptr)));
// triggers.push_back(new TriggerNode("cure poison", NextAction::array(0, new NextAction("abolish poison", ACTION_DISPEL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member cure poison", NextAction::array(0, new NextAction("abolish poison on party", ACTION_DISPEL + 1), nullptr)));
}

View File

@@ -22,10 +22,58 @@ void HealDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
triggers.push_back(new TriggerNode("enemy out of spell", NextAction::array(0, new NextAction("reach spell", ACTION_NORMAL + 9), nullptr)));
triggers.push_back(new TriggerNode("tree form", NextAction::array(0, new NextAction("tree form", ACTION_HIGH + 1), nullptr)));
triggers.push_back(new TriggerNode("medium health", NextAction::array(0, new NextAction("regrowth", ACTION_MEDIUM_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member medium health", NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("almost full health", NextAction::array(0, new NextAction("rejuvenation", ACTION_LIGHT_HEAL + 2), nullptr)));
triggers.push_back(new TriggerNode("party member almost full health", NextAction::array(0, new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("medium aoe heal", NextAction::array(0, new NextAction("tranquility", ACTION_MEDIUM_HEAL + 3), nullptr)));
triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 1), nullptr)));
triggers.push_back(new TriggerNode("party member to heal out of spell range", NextAction::array(0, new NextAction("reach party member to heal", ACTION_CRITICAL_HEAL + 9), nullptr)));
// CRITICAL
triggers.push_back(new TriggerNode(
"party member critical health",
NextAction::array(0,
new NextAction("swiftmend on party", ACTION_CRITICAL_HEAL + 3),
new NextAction("wild growth", ACTION_CRITICAL_HEAL + 2),
new NextAction("nourish on party", ACTION_CRITICAL_HEAL + 1),
// new NextAction("healing touch on party", ACTION_CRITICAL_HEAL + 0),
NULL)));
triggers.push_back(new TriggerNode(
"party member critical health",
NextAction::array(0, new NextAction("nature's swiftness", ACTION_CRITICAL_HEAL + 4), NULL)));
triggers.push_back(new TriggerNode(
"group heal occasion",
NextAction::array(0, new NextAction("tranquility", ACTION_CRITICAL_HEAL + 5), NULL)));
// LOW
triggers.push_back(new TriggerNode(
"party member low health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 9),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 8),
new NextAction("swiftmend on party", ACTION_MEDIUM_HEAL + 7),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 6),
// new NextAction("healing touch on party", ACTION_MEDIUM_HEAL + 5),
NULL)));
// MEDIUM
triggers.push_back(new TriggerNode(
"party member medium health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_MEDIUM_HEAL + 4),
new NextAction("rejuvenation on party", ACTION_MEDIUM_HEAL + 3),
new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 2),
new NextAction("nourish on party", ACTION_MEDIUM_HEAL + 1),
NULL)));
// almost full
triggers.push_back(new TriggerNode(
"party member almost full health",
NextAction::array(0, new NextAction("wild growth on party", ACTION_LIGHT_HEAL + 3),
new NextAction("rejuvenation on party", ACTION_LIGHT_HEAL + 2),
new NextAction("regrowth on party", ACTION_LIGHT_HEAL + 1),
NULL)));
triggers.push_back(new TriggerNode(
"medium mana",
NextAction::array(0, new NextAction("innervate", ACTION_HIGH + 5), NULL)));
triggers.push_back(new TriggerNode(
"enemy too close for spell",
NextAction::array(0, new NextAction("flee", 49.0f), NULL)));
}

View File

@@ -70,6 +70,7 @@ ChatCommandHandlerStrategy::ChatCommandHandlerStrategy(PlayerbotAI* botAI) : Pas
supported.push_back("reputation");
supported.push_back("log");
supported.push_back("los");
supported.push_back("aura");
supported.push_back("drop");
supported.push_back("share");
supported.push_back("ll");

View File

@@ -52,6 +52,7 @@ void GenericHunterNonCombatStrategy::InitTriggers(std::vector<TriggerNode*>& tri
void HunterPetStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
{
triggers.push_back(new TriggerNode("no pet", NextAction::array(0, new NextAction("call pet", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("has pet", NextAction::array(0, new NextAction("toggle pet spell", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("pet not happy", NextAction::array(0, new NextAction("feed pet", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("hunters pet low health", NextAction::array(0, new NextAction("mend pet", 60.0f), nullptr)));
triggers.push_back(new TriggerNode("hunters pet dead", NextAction::array(0, new NextAction("revive pet", 60.0f), nullptr)));

View File

@@ -22,6 +22,7 @@ class ChatTriggerContext : public NamedObjectContext<Trigger>
creators["reputation"] = &ChatTriggerContext::reputation;
creators["log"] = &ChatTriggerContext::log;
creators["los"] = &ChatTriggerContext::los;
creators["aura"] = &ChatTriggerContext::aura;
creators["drop"] = &ChatTriggerContext::drop;
creators["share"] = &ChatTriggerContext::share;
creators["q"] = &ChatTriggerContext::q;
@@ -187,6 +188,7 @@ class ChatTriggerContext : public NamedObjectContext<Trigger>
static Trigger* reputation(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reputation"); }
static Trigger* log(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "log"); }
static Trigger* los(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "los"); }
static Trigger* aura(PlayerbotAI* ai) { return new ChatCommandTrigger(ai, "aura"); }
static Trigger* loot_all(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "add all loot"); }
static Trigger* release(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "release"); }
static Trigger* reset_ai(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "reset botAI"); }

View File

@@ -13,7 +13,7 @@ class Unit;
class NeedCureTrigger : public SpellTrigger
{
public:
NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 5), dispelType(dispelType) { }
NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 1), dispelType(dispelType) { }
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;

View File

@@ -21,6 +21,10 @@ bool NoPetTrigger::IsActive()
return !AI_VALUE(Unit*, "pet target") && !AI_VALUE2(bool, "mounted", "self target");
}
bool HasPetTrigger::IsActive() {
return AI_VALUE(Unit*, "pet target") && !AI_VALUE2(bool, "mounted", "self target");;
}
bool HighManaTrigger::IsActive()
{
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < 65;

View File

@@ -418,6 +418,14 @@ class NoPetTrigger : public Trigger
bool IsActive() override;
};
class HasPetTrigger : public Trigger
{
public:
HasPetTrigger(PlayerbotAI* ai) : Trigger(ai, "no pet", 5) {}
virtual bool IsActive() override;
};
class ItemCountTrigger : public Trigger
{
public:

View File

@@ -30,3 +30,8 @@ bool AoeHealTrigger::IsActive()
return AI_VALUE2(uint8, "aoe heal", type) >= count;
}
bool AoeInGroupTrigger::IsActive()
{
Group *group = bot->GetGroup();
return group && AI_VALUE2(uint8, "aoe heal", type) >= (group->GetMembersCount() * ratio);
}

View File

@@ -132,4 +132,14 @@ class AoeHealTrigger : public Trigger
std::string const type;
};
class AoeInGroupTrigger : public Trigger {
public:
AoeInGroupTrigger(PlayerbotAI* ai, std::string name, std::string type, float ratio) :
Trigger(ai, name), ratio(ratio), type(type) {}
virtual bool IsActive();
protected:
float ratio;
std::string type;
};
#endif

View File

@@ -97,6 +97,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
creators["corpse near"] = &TriggerContext::corpse_near;
creators["party member dead"] = &TriggerContext::PartyMemberDead;
creators["no pet"] = &TriggerContext::no_pet;
creators["has pet"] = &TriggerContext::has_pet;
creators["has attackers"] = &TriggerContext::has_attackers;
creators["no possible targets"] = &TriggerContext::no_possible_targets;
creators["possible adds"] = &TriggerContext::possible_adds;
@@ -118,6 +119,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
creators["critical aoe heal"] = &TriggerContext::critical_aoe_heal;
creators["low aoe heal"] = &TriggerContext::low_aoe_heal;
creators["medium aoe heal"] = &TriggerContext::medium_aoe_heal;
creators["group heal occasion"] = &TriggerContext::group_heal_occasion;
creators["invalid target"] = &TriggerContext::invalid_target;
creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active;
@@ -210,6 +212,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
static Trigger* critical_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "critical aoe heal", "critical", 2); }
static Trigger* low_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "low aoe heal", "low", 2); }
static Trigger* medium_aoe_heal(PlayerbotAI* botAI) { return new AoeHealTrigger(botAI, "medium aoe heal", "medium", 2); }
static Trigger* group_heal_occasion(PlayerbotAI* ai) { return new AoeInGroupTrigger(ai, "group heal occasion", "almost full", 0.4); }
static Trigger* target_changed(PlayerbotAI* botAI) { return new TargetChangedTrigger(botAI); }
static Trigger* swimming(PlayerbotAI* botAI) { return new IsSwimmingTrigger(botAI); }
static Trigger* no_possible_targets(PlayerbotAI* botAI) { return new NoPossibleTargetsTrigger(botAI); }
@@ -277,6 +280,7 @@ class TriggerContext : public NamedObjectContext<Trigger>
static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI) { return new PartyMemberCriticalHealthTrigger(botAI); }
static Trigger* protect_party_member(PlayerbotAI* botAI) { return new ProtectPartyMemberTrigger(botAI); }
static Trigger* no_pet(PlayerbotAI* botAI) { return new NoPetTrigger(botAI); }
static Trigger* has_pet(PlayerbotAI* botAI) { return new HasPetTrigger(botAI); }
static Trigger* has_attackers(PlayerbotAI* botAI) { return new HasAttackersTrigger(botAI); }
static Trigger* random_bot_update_trigger(PlayerbotAI* botAI) { return new RandomBotUpdateTrigger(botAI); }
static Trigger* no_non_bot_players_around(PlayerbotAI* botAI) { return new NoNonBotPlayersAroundTrigger(botAI); }

View File

@@ -29,77 +29,54 @@ inline bool compareByHealth(Unit const* u1, Unit const* u2)
Unit* PartyMemberToHeal::Calculate()
{
IsTargetOfHealingSpell predicate;
std::vector<Unit*> needHeals;
std::vector<Unit*> tankTargets;
if (bot->GetTarget())
{
Unit* target = botAI->GetUnit(bot->GetTarget());
if (target && target->IsFriendlyTo(bot) && target->HealthBelowPct(100))
needHeals.push_back(target);
}
IsTargetOfHealingSpell predicate;
Group* group = bot->GetGroup();
if (!group && needHeals.empty())
return nullptr;
if (!group)
return bot;
if (group)
bool isRaid = bot->GetGroup()->isRaidGroup();
MinValueCalculator calc(100);
for (GroupReference *gref = group->GetFirstMember(); gref; gref = gref->next())
{
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
{
Player* player = gref->GetSource();
if (!Check(player) || !player->IsAlive())
continue;
// do not heal dueling members
if (player->duel && player->duel->Opponent)
continue;
Player* player = gref->GetSource();
if (player && Check(player) && player->IsAlive()) {
uint8 health = player->GetHealthPct();
if (health < sPlayerbotAIConfig->almostFullHealth || !IsTargetOfSpellCast(player, predicate))
needHeals.push_back(player);
if (botAI->IsTank(player) && bot->IsInSameRaidWith(player))
tankTargets.push_back(player);
}
}
if (needHeals.empty() && tankTargets.empty())
return nullptr;
if (needHeals.empty() && !tankTargets.empty())
needHeals = tankTargets;
std::sort(needHeals.begin(), needHeals.end(), compareByHealth);
uint32 healerIndex = 0;
if (group)
{
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
{
Player* player = gref->GetSource();
if (!player) continue;
if (player == bot) break;
if (botAI->IsHeal(player))
{
float percent = (float)player->GetPower(POWER_MANA) / (float)player->GetMaxPower(POWER_MANA) * 100.0;
if (percent > sPlayerbotAIConfig->lowMana)
healerIndex++;
if (isRaid || health < sPlayerbotAIConfig->mediumHealth || !IsTargetOfSpellCast(player, predicate)) {
if (player->GetDistance2d(bot) > sPlayerbotAIConfig->spellDistance) {
calc.probe(health + 30, player);
} else {
calc.probe(health + player->GetDistance2d(bot) / 10, player);
}
}
}
}
else
healerIndex = 1;
healerIndex = healerIndex % needHeals.size();
return needHeals[healerIndex];
Pet* pet = player->GetPet();
if (pet && Check(pet) && pet->IsAlive()) {
uint8 health = ((Unit*)pet)->GetHealthPct();
if (isRaid || health < sPlayerbotAIConfig->mediumHealth)
calc.probe(health + 30, pet);
}
Unit* charm = player->GetCharm();
if (charm && Check(charm) && charm->IsAlive()) {
uint8 health = charm->GetHealthPct();
if (isRaid || health < sPlayerbotAIConfig->mediumHealth)
calc.probe(health, charm);
}
}
return (Unit*)calc.param;
}
bool PartyMemberToHeal::Check(Unit* player)
{
return player && player != bot && player->GetMapId() == bot->GetMapId() && player->IsInWorld() &&
sServerFacade->GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f : 40.0f);
// return player && player != bot && player->GetMapId() == bot->GetMapId() && player->IsInWorld() &&
// sServerFacade->GetDistance2d(bot, player) < (player->IsPlayer() && botAI->IsTank((Player*)player) ? 50.0f : 40.0f);
return player && player->GetMapId() == bot->GetMapId() &&
bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 &&
bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
}
Unit* PartyMemberToProtect::Calculate()

View File

@@ -45,12 +45,19 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign
}
}
}
} else {
std::vector<Player*> vec;
vec.push_back(bot);
Unit* target = FindPartyMember(&vec, predicate);
if (target)
return target;
return NULL;
}
if (!ignoreOutOfGroup && !nearestPlayers.empty() && nearestPlayers.size() < 100)
nearestGroupPlayers.insert(nearestGroupPlayers.end(), nearestPlayers.begin(), nearestPlayers.end());
nearestPlayers.insert(nearestPlayers.end(), nearestGroupPlayers.begin(), nearestGroupPlayers.end());
// nearestPlayers.insert(nearestP layers.end(), nearestGroupPlayers.begin(), nearestGroupPlayers.end());
std::vector<Player*> healers;
std::vector<Player*> tanks;
@@ -93,7 +100,10 @@ Unit* PartyMemberValue::FindPartyMember(FindPlayerPredicate& predicate, bool ign
bool PartyMemberValue::Check(Unit* player)
{
return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, sPlayerbotAIConfig->sightDistance, false);
// return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player, sPlayerbotAIConfig->sightDistance, false);
return player && player->GetMapId() == bot->GetMapId() &&
bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 &&
bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
}
bool PartyMemberValue::IsTargetOfSpellCast(Player* target, SpellEntryPredicate &predicate)