Big update.

This commit is contained in:
UltraNix
2022-03-12 22:27:09 +01:00
parent b3d00ccb26
commit b952636f0d
843 changed files with 1534330 additions and 99 deletions

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "ChatCommandTrigger.h"
#include "Playerbots.h"
ChatCommandTrigger::ChatCommandTrigger(PlayerbotAI* botAI, std::string const command) : Trigger(botAI, command), triggered(false), owner(nullptr)
{
}
void ChatCommandTrigger::ExternalEvent(std::string const paramName, Player* eventPlayer)
{
param = paramName;
owner = eventPlayer;
triggered = true;
}
Event ChatCommandTrigger::Check()
{
if (!triggered)
return Event();
return Event(getName(), param, owner);
}
void ChatCommandTrigger::Reset()
{
triggered = false;
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_CHATCOMMANDTRIGGER_H
#define _PLAYERBOT_CHATCOMMANDTRIGGER_H
#include "Trigger.h"
class Event;
class Player;
class PlayerbotAI;
class ChatCommandTrigger : public Trigger
{
public:
ChatCommandTrigger(PlayerbotAI* botAI, std::string const command);
void ExternalEvent(std::string const param, Player* owner = nullptr) override;
Event Check() override;
void Reset() override;
private:
std::string param;
bool triggered;
Player* owner;
};
#endif

View File

@@ -0,0 +1,203 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_CHATTRIGGERCONTEXT_H
#define _PLAYERBOT_CHATTRIGGERCONTEXT_H
#include "ChatCommandTrigger.h"
#include "NamedObjectContext.h"
class PlayerbotAI;
class ChatTriggerContext : public NamedObjectContext<Trigger>
{
public:
ChatTriggerContext()
{
creators["quests"] = &ChatTriggerContext::quests;
creators["stats"] = &ChatTriggerContext::stats;
creators["leave"] = &ChatTriggerContext::leave;
creators["rep"] = &ChatTriggerContext::reputation;
creators["reputation"] = &ChatTriggerContext::reputation;
creators["log"] = &ChatTriggerContext::log;
creators["los"] = &ChatTriggerContext::los;
creators["drop"] = &ChatTriggerContext::drop;
creators["share"] = &ChatTriggerContext::share;
creators["q"] = &ChatTriggerContext::q;
creators["ll"] = &ChatTriggerContext::ll;
creators["ss"] = &ChatTriggerContext::ss;
creators["loot all"] = &ChatTriggerContext::loot_all;
creators["add all loot"] = &ChatTriggerContext::loot_all;
creators["release"] = &ChatTriggerContext::release;
creators["teleport"] = &ChatTriggerContext::teleport;
creators["taxi"] = &ChatTriggerContext::taxi;
creators["repair"] = &ChatTriggerContext::repair;
creators["u"] = &ChatTriggerContext::use;
creators["use"] = &ChatTriggerContext::use;
creators["c"] = &ChatTriggerContext::item_count;
creators["items"] = &ChatTriggerContext::item_count;
creators["inventory"] = &ChatTriggerContext::item_count;
creators["inv"] = &ChatTriggerContext::item_count;
creators["e"] = &ChatTriggerContext::equip;
creators["equip"] = &ChatTriggerContext::equip;
creators["ue"] = &ChatTriggerContext::uneqip;
creators["s"] = &ChatTriggerContext::sell;
creators["b"] = &ChatTriggerContext::buy;
creators["r"] = &ChatTriggerContext::reward;
creators["t"] = &ChatTriggerContext::trade;
creators["nt"] = &ChatTriggerContext::nontrade;
creators["talents"] = &ChatTriggerContext::talents;
creators["spells"] = &ChatTriggerContext::spells;
creators["co"] = &ChatTriggerContext::co;
creators["nc"] = &ChatTriggerContext::nc;
creators["de"] = &ChatTriggerContext::dead;
creators["trainer"] = &ChatTriggerContext::trainer;
creators["attack"] = &ChatTriggerContext::attack;
creators["chat"] = &ChatTriggerContext::chat;
creators["accept"] = &ChatTriggerContext::accept;
creators["home"] = &ChatTriggerContext::home;
creators["reset botAI"] = &ChatTriggerContext::reset_ai;
creators["destroy"] = &ChatTriggerContext::destroy;
creators["emote"] = &ChatTriggerContext::emote;
creators["buff"] = &ChatTriggerContext::buff;
creators["help"] = &ChatTriggerContext::help;
creators["gb"] = &ChatTriggerContext::gb;
creators["gbank"] = &ChatTriggerContext::gb;
creators["bank"] = &ChatTriggerContext::bank;
creators["follow"] = &ChatTriggerContext::follow;
creators["stay"] = &ChatTriggerContext::stay;
creators["flee"] = &ChatTriggerContext::flee;
creators["grind"] = &ChatTriggerContext::grind;
creators["tank attack"] = &ChatTriggerContext::tank_attack;
creators["talk"] = &ChatTriggerContext::talk;
creators["cast"] = &ChatTriggerContext::cast;
creators["castnc"] = &ChatTriggerContext::castnc;
creators["invite"] = &ChatTriggerContext::invite;
creators["spell"] = &ChatTriggerContext::spell;
creators["rti"] = &ChatTriggerContext::rti;
creators["revive"] = &ChatTriggerContext::revive;
creators["runaway"] = &ChatTriggerContext::runaway;
creators["warning"] = &ChatTriggerContext::warning;
creators["position"] = &ChatTriggerContext::position;
creators["summon"] = &ChatTriggerContext::summon;
creators["who"] = &ChatTriggerContext::who;
creators["save mana"] = &ChatTriggerContext::save_mana;
creators["max dps"] = &ChatTriggerContext::max_dps;
creators["attackers"] = &ChatTriggerContext::attackers;
creators["formation"] = &ChatTriggerContext::formation;
creators["stance"] = &ChatTriggerContext::stance;
creators["sendmail"] = &ChatTriggerContext::sendmail;
creators["mail"] = &ChatTriggerContext::mail;
creators["outfit"] = &ChatTriggerContext::outfit;
creators["go"] = &ChatTriggerContext::go;
creators["ready"] = &ChatTriggerContext::ready_check;
creators["debug"] = &ChatTriggerContext::debug;
creators["cdebug"] = &ChatTriggerContext::cdebug;
creators["cs"] = &ChatTriggerContext::cs;
creators["wts"] = &ChatTriggerContext::wts;
creators["hire"] = &ChatTriggerContext::hire;
creators["craft"] = &ChatTriggerContext::craft;
creators["flag"] = &ChatTriggerContext::craft;
creators["range"] = &ChatTriggerContext::range;
creators["ra"] = &ChatTriggerContext::ra;
creators["give leader"] = &ChatTriggerContext::give_leader;
creators["cheat"] = &ChatTriggerContext::cheat;
creators["ginvite"] = &ChatTriggerContext::ginvite;
creators["guild promote"] = &ChatTriggerContext::guild_promote;
creators["guild demote"] = &ChatTriggerContext::guild_demote;
creators["guild remove"] = &ChatTriggerContext::guild_remove;
creators["guild leave"] = &ChatTriggerContext::guild_leave;
creators["rtsc"] = &ChatTriggerContext::rtsc;
}
private:
static Trigger* ra(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ra"); }
static Trigger* range(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "range"); }
static Trigger* flag(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "flag"); }
static Trigger* craft(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "craft"); }
static Trigger* hire(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "hire"); }
static Trigger* wts(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "wts"); }
static Trigger* cs(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "cs"); }
static Trigger* debug(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "debug"); }
static Trigger* cdebug(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "cdebug"); }
static Trigger* go(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "go"); }
static Trigger* outfit(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "outfit"); }
static Trigger* mail(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "mail"); }
static Trigger* sendmail(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "sendmail"); }
static Trigger* formation(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "formation"); }
static Trigger* stance(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stance"); }
static Trigger* attackers(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attackers"); }
static Trigger* max_dps(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "max dps"); }
static Trigger* save_mana(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "save mana"); }
static Trigger* who(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "who"); }
static Trigger* summon(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "summon"); }
static Trigger* position(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "position"); }
static Trigger* runaway(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "runaway"); }
static Trigger* warning(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "warning"); }
static Trigger* revive(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "revive"); }
static Trigger* rti(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rti"); }
static Trigger* invite(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "invite"); }
static Trigger* cast(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "cast"); }
static Trigger* castnc(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "castnc"); }
static Trigger* talk(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "talk"); }
static Trigger* flee(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "flee"); }
static Trigger* grind(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "grind"); }
static Trigger* tank_attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "tank attack"); }
static Trigger* stay(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stay"); }
static Trigger* follow(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "follow"); }
static Trigger* gb(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "gb"); }
static Trigger* bank(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "bank"); }
static Trigger* help(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "help"); }
static Trigger* buff(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "buff"); }
static Trigger* emote(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "emote"); }
static Trigger* destroy(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "destroy"); }
static Trigger* home(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "home"); }
static Trigger* accept(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "accept"); }
static Trigger* chat(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "chat"); }
static Trigger* attack(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "attack"); }
static Trigger* trainer(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "trainer"); }
static Trigger* co(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "co"); }
static Trigger* nc(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "nc"); }
static Trigger* dead(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "de"); }
static Trigger* spells(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "spells"); }
static Trigger* talents(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "talents"); }
static Trigger* equip(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "e"); }
static Trigger* uneqip(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ue"); }
static Trigger* sell(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "s"); }
static Trigger* buy(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "b"); }
static Trigger* reward(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "r"); }
static Trigger* trade(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "t"); }
static Trigger* nontrade(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "nt"); }
static Trigger* item_count(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "c"); }
static Trigger* use(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "use"); }
static Trigger* repair(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "repair"); }
static Trigger* taxi(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "taxi"); }
static Trigger* teleport(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "teleport"); }
static Trigger* q(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "q"); }
static Trigger* ll(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ll"); }
static Trigger* ss(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ss"); }
static Trigger* drop(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "drop"); }
static Trigger* share(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "share"); }
static Trigger* quests(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "quests"); }
static Trigger* stats(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "stats"); }
static Trigger* leave(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "leave"); }
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* 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"); }
static Trigger* spell(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "spell"); }
static Trigger* ready_check(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ready check"); }
static Trigger* give_leader(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "give leader"); }
static Trigger* cheat(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "cheat"); }
static Trigger* ginvite(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "ginvite"); }
static Trigger* guild_promote(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild promote"); }
static Trigger* guild_demote(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild demote"); }
static Trigger* guild_remove(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild remove"); }
static Trigger* guild_leave(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "guild leave"); }
static Trigger* rtsc(PlayerbotAI* botAI) { return new ChatCommandTrigger(botAI, "rtsc"); }
};
#endif

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "CureTriggers.h"
#include "Playerbots.h"
#include "WorldBuffAction.h"
bool NeedCureTrigger::IsActive()
{
Unit* target = GetTarget();
return target && botAI->HasAuraToDispel(target, dispelType);
}
Value<Unit*>* PartyMemberNeedCureTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("party member to dispel", dispelType);
}
bool NeedWorldBuffTrigger::IsActive()
{
return !WorldBuffAction::NeedWorldBuffs(bot).empty();
}

View File

@@ -0,0 +1,49 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_CURETRIGGERS_H
#define _PLAYERBOT_CURETRIGGERS_H
#include "GenericTriggers.h"
class PlayerbotAI;
class Unit;
class NeedCureTrigger : public SpellTrigger
{
public:
NeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : SpellTrigger(botAI, spell, 5), dispelType(dispelType) { }
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;
protected:
uint32 dispelType;
};
class TargetAuraDispelTrigger : public NeedCureTrigger
{
public:
TargetAuraDispelTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : NeedCureTrigger(botAI, spell, dispelType) { }
std::string const GetTargetName() override { return "current target"; }
};
class PartyMemberNeedCureTrigger : public NeedCureTrigger
{
public:
PartyMemberNeedCureTrigger(PlayerbotAI* botAI, std::string const spell, uint32 dispelType) : NeedCureTrigger(botAI, spell, dispelType) { }
Value<Unit*>* GetTargetValue() override;
};
class NeedWorldBuffTrigger : public Trigger
{
public:
NeedWorldBuffTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,469 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "GenericTriggers.h"
#include "BattlegroundWS.h"
#include "Playerbots.h"
bool LowManaTrigger::IsActive()
{
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana;
}
bool MediumManaTrigger::IsActive()
{
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->mediumMana;
}
bool NoPetTrigger::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;
}
bool AlmostFullManaTrigger::IsActive()
{
return AI_VALUE2(bool, "has mana", "self target") && AI_VALUE2(uint8, "mana", "self target") > 85;
}
bool RageAvailable::IsActive()
{
return AI_VALUE2(uint8, "rage", "self target") >= amount;
}
bool EnergyAvailable::IsActive()
{
return AI_VALUE2(uint8, "energy", "self target") >= amount;
}
bool ComboPointsAvailableTrigger::IsActive()
{
return AI_VALUE2(uint8, "combo", "current target") >= amount;
}
bool LoseAggroTrigger::IsActive()
{
return !AI_VALUE2(bool, "has aggro", "current target");
}
bool HasAggroTrigger::IsActive()
{
return AI_VALUE2(bool, "has aggro", "current target");
}
bool PanicTrigger::IsActive()
{
return AI_VALUE2(uint8, "health", "self target") < sPlayerbotAIConfig->criticalHealth &&
(!AI_VALUE2(bool, "has mana", "self target") || AI_VALUE2(uint8, "mana", "self target") < sPlayerbotAIConfig->lowMana);
}
bool OutNumberedTrigger::IsActive()
{
int32 botLevel = bot->getLevel();
uint32 friendPower = 200;
uint32 foePower = 0;
for (auto& attacker : botAI->GetAiObjectContext()->GetValue<GuidVector>("attackers")->Get())
{
Creature* creature = botAI->GetCreature(attacker);
if (!creature)
continue;
int32 dLevel = creature->getLevel() - botLevel;
if (dLevel > -10)
foePower = std::max(100 + 10 * dLevel, dLevel * 200);
}
if (!foePower)
return false;
for (auto& helper : botAI->GetAiObjectContext()->GetValue<GuidVector>("nearest friendly players")->Get())
{
Unit* player = botAI->GetUnit(helper);
if (!player || player == bot)
continue;
int32 dLevel = player->getLevel() - botLevel;
if (dLevel > -10 && bot->GetDistance(player) < 10.0f)
friendPower += std::max(200 + 20 * dLevel, dLevel * 200);
}
return friendPower < foePower;
}
bool BuffTrigger::IsActive()
{
Unit* target = GetTarget();
return SpellTrigger::IsActive() && !botAI->HasAura(spell, target, true);
}
Value<Unit*>* BuffOnPartyTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("party member without aura", spell);
}
bool ProtectPartyMemberTrigger::IsActive()
{
return AI_VALUE(Unit*, "party member to protect");
}
Value<Unit*>* DebuffOnAttackerTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("attacker without aura", spell);
}
bool NoAttackersTrigger::IsActive()
{
return !AI_VALUE(Unit*, "current target") && AI_VALUE(uint8, "my attacker count") > 0;
}
bool InvalidTargetTrigger::IsActive()
{
return AI_VALUE2(bool, "invalid target", "current target");
}
bool NoTargetTrigger::IsActive()
{
return !AI_VALUE(Unit*, "current target");
}
bool MyAttackerCountTrigger::IsActive()
{
return AI_VALUE2(bool, "combat", "self target") && AI_VALUE(uint8, "my attacker count") >= amount;
}
bool AoeTrigger::IsActive()
{
return AI_VALUE2(bool, "combat", "self target") && AI_VALUE(uint8, "aoe count") >= amount && AI_VALUE(uint8, "attacker count") >= amount;
}
bool NoFoodTrigger::IsActive()
{
return AI_VALUE2(std::vector<Item*>, "inventory items", "conjured food").empty();
}
bool NoDrinkTrigger::IsActive()
{
return AI_VALUE2(std::vector<Item*>, "inventory items", "conjured water").empty();
}
bool TargetInSightTrigger::IsActive()
{
return AI_VALUE(Unit*, "grind target");
}
bool DebuffTrigger::IsActive()
{
return BuffTrigger::IsActive() && AI_VALUE2(uint8, "health", GetTargetName()) > 15;
}
bool SpellTrigger::IsActive()
{
return GetTarget();
}
bool SpellCanBeCastTrigger::IsActive()
{
Unit* target = GetTarget();
return target && botAI->CanCastSpell(spell, target);
}
RandomTrigger::RandomTrigger(PlayerbotAI* botAI, std::string const name, int32 probability) : Trigger(botAI, name), probability(probability), lastCheck(time(nullptr))
{
}
bool RandomTrigger::IsActive()
{
if (time(nullptr) - lastCheck < sPlayerbotAIConfig->repeatDelay / 1000)
return false;
lastCheck = time(nullptr);
int32 k = (int32)(probability / sPlayerbotAIConfig->randomChangeMultiplier);
if (k < 1)
k = 1;
return (rand() % k) == 0;
}
bool AndTrigger::IsActive()
{
return ls->IsActive() && rs->IsActive();
}
std::string const AndTrigger::getName()
{
std::string name(ls->getName());
name = name + " and ";
name = name + rs->getName();
return name;
}
bool BoostTrigger::IsActive()
{
return BuffTrigger::IsActive() && AI_VALUE(uint8, "balance") <= balance;
}
bool ItemCountTrigger::IsActive()
{
return AI_VALUE2(uint32, "item count", item) < count;
}
bool InterruptSpellTrigger::IsActive()
{
return SpellTrigger::IsActive() && botAI->IsInterruptableSpellCasting(GetTarget(), getName());
}
bool DeflectSpellTrigger::IsActive()
{
Unit* target = GetTarget();
if (!target)
return false;
if (!target->IsNonMeleeSpellCast(true))
return false;
if (target->GetTarget() != bot->GetGUID())
return false;
uint32 spellid = context->GetValue<uint32>("spell id", spell)->Get();
if (!spellid)
return false;
SpellInfo const* deflectSpell = sSpellMgr->GetSpellInfo(spellid);
if (!deflectSpell)
return false;
// warrior deflects all
if (spell == "spell reflection")
return true;
// human priest feedback
if (spell == "feedback")
return true;
SpellSchoolMask deflectSchool = SpellSchoolMask(deflectSpell->Effects[EFFECT_0].MiscValue);
SpellSchoolMask attackSchool = SPELL_SCHOOL_MASK_NONE;
if (Spell* spell = target->GetCurrentSpell(CURRENT_GENERIC_SPELL))
{
if (SpellInfo const* tarSpellInfo = spell->GetSpellInfo())
{
attackSchool = tarSpellInfo->GetSchoolMask();
if (deflectSchool == attackSchool)
return true;
}
}
return false;
}
bool AttackerCountTrigger::IsActive()
{
return AI_VALUE(uint8, "attacker count") >= amount;
}
bool HasAuraTrigger::IsActive()
{
return botAI->HasAura(getName(), GetTarget());
}
bool TimerTrigger::IsActive()
{
if (time(nullptr) != lastCheck)
{
lastCheck = time(nullptr);
return true;
}
return false;
}
bool HasNoAuraTrigger::IsActive()
{
return !botAI->HasAura(getName(), GetTarget());
}
bool TankAssistTrigger::IsActive()
{
if (!AI_VALUE(uint8, "attacker count"))
return false;
Unit* currentTarget = AI_VALUE(Unit*, "current target");
if (!currentTarget)
return true;
Unit* tankTarget = AI_VALUE(Unit*, "tank target");
if (!tankTarget || currentTarget == tankTarget)
return false;
return currentTarget->GetVictim() == AI_VALUE(Unit*, "self target");
}
bool IsBehindTargetTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
return target && AI_VALUE2(bool, "behind", "current target");
}
bool IsNotBehindTargetTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
return target && !AI_VALUE2(bool, "behind", "current target");
}
bool IsNotFacingTargetTrigger::IsActive()
{
return !AI_VALUE2(bool, "facing", "current target");
}
bool HasCcTargetTrigger::IsActive()
{
return AI_VALUE2(Unit*, "cc target", getName()) && !AI_VALUE2(Unit*, "current cc target", getName());
}
bool NoMovementTrigger::IsActive()
{
return !AI_VALUE2(bool, "moving", "self target");
}
bool NoPossibleTargetsTrigger::IsActive()
{
GuidVector targets = AI_VALUE(GuidVector, "possible targets");
return !targets.size();
}
bool PossibleAddsTrigger::IsActive()
{
return AI_VALUE(bool, "possible adds") && !AI_VALUE(ObjectGuid, "pull target");
}
bool NotDpsTargetActiveTrigger::IsActive()
{
Unit* dps = AI_VALUE(Unit*, "dps target");
Unit* target = AI_VALUE(Unit*, "current target");
Unit* enemy = AI_VALUE(Unit*, "enemy player target");
// do not switch if enemy target
if (target && target == enemy && target->IsAlive())
return false;
return dps && target != dps;
}
bool NotDpsAoeTargetActiveTrigger::IsActive()
{
Unit* dps = AI_VALUE(Unit*, "dps aoe target");
Unit* target = AI_VALUE(Unit*, "current target");
Unit* enemy = AI_VALUE(Unit*, "enemy player target");
// do not switch if enemy target
if (target && target == enemy && target->IsAlive())
return false;
return dps && target != dps;
}
bool IsSwimmingTrigger::IsActive()
{
return AI_VALUE2(bool, "swimming", "self target");
}
bool HasNearestAddsTrigger::IsActive()
{
GuidVector targets = AI_VALUE(GuidVector, "nearest adds");
return targets.size();
}
bool HasItemForSpellTrigger::IsActive()
{
std::string const spell = getName();
uint32 spellId = AI_VALUE2(uint32, "spell id", spell);
return spellId && AI_VALUE2(Item*, "item for spell", spellId);
}
bool TargetChangedTrigger::IsActive()
{
Unit* oldTarget = context->GetValue<Unit*>("old target")->Get();
Unit* target = context->GetValue<Unit*>("current target")->Get();
return target && oldTarget != target;
}
Value<Unit*>* InterruptEnemyHealerTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("enemy healer target", spell);
}
bool RandomBotUpdateTrigger::IsActive()
{
return RandomTrigger::IsActive() && AI_VALUE(bool, "random bot update");
}
bool NoNonBotPlayersAroundTrigger::IsActive()
{
return !botAI->HasPlayerNearby();
/*if (!bot->InBattleground())
return AI_VALUE(GuidVector, "nearest non bot players").empty();
return false;
*/
}
bool NewPlayerNearbyTrigger::IsActive()
{
return AI_VALUE(ObjectGuid, "new player nearby");
}
bool CollisionTrigger::IsActive()
{
return AI_VALUE2(bool, "collision", "self target");
}
bool GiveItemTrigger::IsActive()
{
return AI_VALUE2(Unit*, "party member without item", item) && AI_VALUE2(uint32, "item count", item);
}
bool GiveFoodTrigger::IsActive()
{
return AI_VALUE(Unit*, "party member without food") && AI_VALUE2(uint32, "item count", item);
}
bool GiveWaterTrigger::IsActive()
{
return AI_VALUE(Unit*, "party member without water") && AI_VALUE2(uint32, "item count", item);
}
Value<Unit*>* SnareTargetTrigger::GetTargetValue()
{
return context->GetValue<Unit*>("snare target", spell);
}
bool StayTimeTrigger::IsActive()
{
time_t stayTime = AI_VALUE(time_t, "stay time");
time_t now = time(nullptr);
return delay && stayTime && now > stayTime + 2 * delay / 1000;
}
bool IsMountedTrigger::IsActive()
{
return AI_VALUE2(bool, "mounted", "self target");
}
bool CorpseNearTrigger::IsActive()
{
return bot->GetCorpse() && bot->GetCorpse()->IsWithinDistInMap(bot, CORPSE_RECLAIM_RADIUS, true);
}
bool IsFallingTrigger::IsActive()
{
return bot->HasUnitMovementFlag(MOVEMENTFLAG_FALLING);
}
bool IsFallingFarTrigger::IsActive()
{
return bot->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR);
}

View File

@@ -0,0 +1,677 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_GENERICTRIGGERS_H
#define _PLAYERBOT_GENERICTRIGGERS_H
#include "RangeTriggers.h"
#include "HealthTriggers.h"
class PlayerbotAI;
class Unit;
class StatAvailable : public Trigger
{
public:
StatAvailable(PlayerbotAI* botAI, int32 amount, std::string const name = "stat available") : Trigger(botAI, name), amount(amount) { }
protected:
int32 amount;
};
class HighManaTrigger : public Trigger
{
public:
HighManaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "high mana") { }
bool IsActive() override;
};
class AlmostFullManaTrigger : public Trigger
{
public:
AlmostFullManaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "almost full mana") { }
bool IsActive() override;
};
class RageAvailable : public StatAvailable
{
public:
RageAvailable(PlayerbotAI* botAI, int32 amount) : StatAvailable(botAI, amount, "rage available") { }
bool IsActive() override;
};
class LightRageAvailableTrigger : public RageAvailable
{
public:
LightRageAvailableTrigger(PlayerbotAI* botAI) : RageAvailable(botAI, 20) { }
};
class MediumRageAvailableTrigger : public RageAvailable
{
public:
MediumRageAvailableTrigger(PlayerbotAI* botAI) : RageAvailable(botAI, 40) { }
};
class HighRageAvailableTrigger : public RageAvailable
{
public:
HighRageAvailableTrigger(PlayerbotAI* botAI) : RageAvailable(botAI, 60) { }
};
class EnergyAvailable : public StatAvailable
{
public:
EnergyAvailable(PlayerbotAI* botAI, int32 amount) : StatAvailable(botAI, amount, "energy available") { }
bool IsActive() override;
};
class LightEnergyAvailableTrigger : public EnergyAvailable
{
public:
LightEnergyAvailableTrigger(PlayerbotAI* botAI) : EnergyAvailable(botAI, 20) { }
};
class MediumEnergyAvailableTrigger : public EnergyAvailable
{
public:
MediumEnergyAvailableTrigger(PlayerbotAI* botAI) : EnergyAvailable(botAI, 40) { }
};
class HighEnergyAvailableTrigger : public EnergyAvailable
{
public:
HighEnergyAvailableTrigger(PlayerbotAI* botAI) : EnergyAvailable(botAI, 60) { }
};
class ComboPointsAvailableTrigger : public StatAvailable
{
public:
ComboPointsAvailableTrigger(PlayerbotAI* botAI, int32 amount = 5) : StatAvailable(botAI, amount, "combo points available") { }
bool IsActive() override;
};
class LoseAggroTrigger : public Trigger
{
public:
LoseAggroTrigger(PlayerbotAI* botAI) : Trigger(botAI, "lose aggro") { }
bool IsActive() override;
};
class HasAggroTrigger : public Trigger
{
public:
HasAggroTrigger(PlayerbotAI* botAI) : Trigger(botAI, "have aggro") { }
bool IsActive() override;
};
class SpellTrigger : public Trigger
{
public:
SpellTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1) : Trigger(botAI, spell, checkInterval), spell(spell) { }
std::string const GetTargetName() override { return "current target"; }
std::string const getName() override { return spell; }
bool IsActive() override;
protected:
std::string spell;
};
class SpellCanBeCastTrigger : public SpellTrigger
{
public:
SpellCanBeCastTrigger(PlayerbotAI* botAI, std::string const spell) : SpellTrigger(botAI, spell) { }
bool IsActive() override;
};
// TODO: check other targets
class InterruptSpellTrigger : public SpellTrigger
{
public:
InterruptSpellTrigger(PlayerbotAI* botAI, std::string const spell) : SpellTrigger(botAI, spell) { }
bool IsActive() override;
};
class DeflectSpellTrigger : public SpellTrigger
{
public:
DeflectSpellTrigger(PlayerbotAI* botAI, std::string const spell) : SpellTrigger(botAI, spell) { }
bool IsActive() override;
};
class AttackerCountTrigger : public Trigger
{
public:
AttackerCountTrigger(PlayerbotAI* botAI, int32 amount, float distance = sPlayerbotAIConfig->sightDistance) : Trigger(botAI), amount(amount), distance(distance) { }
bool IsActive() override;
std::string const getName() override { return "attacker count"; }
protected:
int32 amount;
float distance;
};
class HasAttackersTrigger : public AttackerCountTrigger
{
public:
HasAttackersTrigger(PlayerbotAI* botAI) : AttackerCountTrigger(botAI, 1) { }
};
class MyAttackerCountTrigger : public AttackerCountTrigger
{
public:
MyAttackerCountTrigger(PlayerbotAI* botAI, int32 amount) : AttackerCountTrigger(botAI, amount) { }
bool IsActive() override;
std::string const getName() override { return "my attacker count"; }
};
class MediumThreatTrigger : public MyAttackerCountTrigger
{
public:
MediumThreatTrigger(PlayerbotAI* botAI) : MyAttackerCountTrigger(botAI, 2) { }
};
class AoeTrigger : public AttackerCountTrigger
{
public:
AoeTrigger(PlayerbotAI* botAI, int32 amount = 3, float range = 15.0f) : AttackerCountTrigger(botAI, amount), range(range) { }
bool IsActive() override;
std::string const getName() override { return "aoe"; }
private:
float range;
};
class NoFoodTrigger : public Trigger
{
public:
NoFoodTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no food trigger") { }
bool IsActive() override;
};
class NoDrinkTrigger : public Trigger
{
public:
NoDrinkTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no drink trigger") { }
bool IsActive() override;
};
class LightAoeTrigger : public AoeTrigger
{
public:
LightAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 2, 15.0f) { }
};
class MediumAoeTrigger : public AoeTrigger
{
public:
MediumAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 3, 17.0f) { }
};
class HighAoeTrigger : public AoeTrigger
{
public:
HighAoeTrigger(PlayerbotAI* botAI) : AoeTrigger(botAI, 4, 20.0f) { }
};
class BuffTrigger : public SpellTrigger
{
public:
BuffTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1) : SpellTrigger(botAI, spell, checkInterval) { }
public:
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;
};
class BuffOnPartyTrigger : public BuffTrigger
{
public:
BuffOnPartyTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1) : BuffTrigger(botAI, spell, checkInterval) { }
Value<Unit*>* GetTargetValue() override;
std::string const getName() override { return spell + " on party"; }
};
class ProtectPartyMemberTrigger : public Trigger
{
public:
ProtectPartyMemberTrigger(PlayerbotAI* botAI) : Trigger(botAI, "protect party member") { }
std::string const GetTargetName() override { return "party member to protect"; }
bool IsActive() override;
};
class NoAttackersTrigger : public Trigger
{
public:
NoAttackersTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no attackers") { }
bool IsActive() override;
};
class NoTargetTrigger : public Trigger
{
public:
NoTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no target") { }
bool IsActive() override;
};
class InvalidTargetTrigger : public Trigger
{
public:
InvalidTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "invalid target") { }
bool IsActive() override;
};
class TargetInSightTrigger : public Trigger
{
public:
TargetInSightTrigger(PlayerbotAI* botAI) : Trigger(botAI, "target in sight") { }
bool IsActive() override;
};
class DebuffTrigger : public BuffTrigger
{
public:
DebuffTrigger(PlayerbotAI* botAI, std::string const spell, int32 checkInterval = 1) : BuffTrigger(botAI, spell, checkInterval) { }
std::string const GetTargetName() override { return "current target"; }
bool IsActive() override;
};
class DebuffOnAttackerTrigger : public DebuffTrigger
{
public:
DebuffOnAttackerTrigger(PlayerbotAI* botAI, std::string const spell) : DebuffTrigger(botAI, spell) { }
Value<Unit*>* GetTargetValue() override;
std::string const getName() override { return spell + " on attacker"; }
};
class BoostTrigger : public BuffTrigger
{
public:
BoostTrigger(PlayerbotAI* botAI, std::string const spell, float balance = 50.f) : BuffTrigger(botAI, spell, 1), balance(balance) { }
bool IsActive() override;
protected:
float balance;
};
class RandomTrigger : public Trigger
{
public:
RandomTrigger(PlayerbotAI* botAI, std::string const name, int32 probability = 7);
bool IsActive() override;
protected:
int32 probability;
time_t lastCheck;
};
class AndTrigger : public Trigger
{
public:
AndTrigger(PlayerbotAI* botAI, Trigger* ls, Trigger* rs) : Trigger(botAI), ls(ls), rs(rs) { }
virtual ~AndTrigger()
{
delete ls;
delete rs;
}
bool IsActive() override;
std::string const getName() override;
protected:
Trigger* ls;
Trigger* rs;
};
class SnareTargetTrigger : public DebuffTrigger
{
public:
SnareTargetTrigger(PlayerbotAI* botAI, std::string const spell) : DebuffTrigger(botAI, spell) { }
Value<Unit*>* GetTargetValue() override;
std::string const getName() override { return spell + " on snare target"; }
};
class LowManaTrigger : public Trigger
{
public:
LowManaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "low mana") { }
bool IsActive() override;
};
class MediumManaTrigger : public Trigger
{
public:
MediumManaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "medium mana") { }
bool IsActive() override;
};
BEGIN_TRIGGER(PanicTrigger, Trigger)
std::string const getName() override { return "panic"; }
END_TRIGGER()
BEGIN_TRIGGER(OutNumberedTrigger, Trigger)
std::string const getName() override { return "outnumbered"; }
END_TRIGGER()
class NoPetTrigger : public Trigger
{
public:
NoPetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no pet", 30) { }
bool IsActive() override;
};
class ItemCountTrigger : public Trigger
{
public:
ItemCountTrigger(PlayerbotAI* botAI, std::string const item, int32 count, int32 interval = 30) : Trigger(botAI, item, interval), item(item), count(count) { }
bool IsActive() override;
std::string const getName() override { return "item count"; }
protected:
std::string const item;
int32 count;
};
class AmmoCountTrigger : public ItemCountTrigger
{
public:
AmmoCountTrigger(PlayerbotAI* botAI, std::string const item, uint32 count = 1, int32 interval = 30) : ItemCountTrigger(botAI, item, count, interval) { }
};
class HasAuraTrigger : public Trigger
{
public:
HasAuraTrigger(PlayerbotAI* botAI, std::string const spell) : Trigger(botAI, spell) { }
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;
};
class HasNoAuraTrigger : public Trigger
{
public:
HasNoAuraTrigger(PlayerbotAI* botAI, std::string const spell) : Trigger(botAI, spell) { }
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;
};
class TimerTrigger : public Trigger
{
public:
TimerTrigger(PlayerbotAI* botAI) : Trigger(botAI, "timer"), lastCheck(0) { }
bool IsActive() override;
private:
time_t lastCheck;
};
class TankAssistTrigger : public NoAttackersTrigger
{
public:
TankAssistTrigger(PlayerbotAI* botAI) : NoAttackersTrigger(botAI) { }
bool IsActive() override;
};
class IsBehindTargetTrigger : public Trigger
{
public:
IsBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
class IsNotBehindTargetTrigger : public Trigger
{
public:
IsNotBehindTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
class IsNotFacingTargetTrigger : public Trigger
{
public:
IsNotFacingTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
class HasCcTargetTrigger : public Trigger
{
public:
HasCcTargetTrigger(PlayerbotAI* botAI, std::string const name) : Trigger(botAI, name) { }
bool IsActive() override;
};
class NoMovementTrigger : public Trigger
{
public:
NoMovementTrigger(PlayerbotAI* botAI, std::string const name) : Trigger(botAI, name) { }
bool IsActive() override;
};
class NoPossibleTargetsTrigger : public Trigger
{
public:
NoPossibleTargetsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no possible targets") { }
bool IsActive() override;
};
class NotDpsTargetActiveTrigger : public Trigger
{
public:
NotDpsTargetActiveTrigger(PlayerbotAI* botAI) : Trigger(botAI, "not dps target active") { }
bool IsActive() override;
};
class NotDpsAoeTargetActiveTrigger : public Trigger
{
public:
NotDpsAoeTargetActiveTrigger(PlayerbotAI* botAI) : Trigger(botAI, "not dps aoe target active") { }
bool IsActive() override;
};
class PossibleAddsTrigger : public Trigger
{
public:
PossibleAddsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "possible adds") { }
bool IsActive() override;
};
class IsSwimmingTrigger : public Trigger
{
public:
IsSwimmingTrigger(PlayerbotAI* botAI) : Trigger(botAI, "swimming") { }
bool IsActive() override;
};
class HasNearestAddsTrigger : public Trigger
{
public:
HasNearestAddsTrigger(PlayerbotAI* botAI) : Trigger(botAI, "has nearest adds") { }
bool IsActive() override;
};
class HasItemForSpellTrigger : public Trigger
{
public:
HasItemForSpellTrigger(PlayerbotAI* botAI, std::string const spell) : Trigger(botAI, spell) { }
bool IsActive() override;
};
class TargetChangedTrigger : public Trigger
{
public:
TargetChangedTrigger(PlayerbotAI* botAI) : Trigger(botAI, "target changed") { }
bool IsActive() override;
};
class InterruptEnemyHealerTrigger : public SpellTrigger
{
public:
InterruptEnemyHealerTrigger(PlayerbotAI* botAI, std::string const spell) : SpellTrigger(botAI, spell) { }
Value<Unit*>* GetTargetValue() override;
std::string const getName() override { return spell + " on enemy healer"; }
};
class RandomBotUpdateTrigger : public RandomTrigger
{
public:
RandomBotUpdateTrigger(PlayerbotAI* botAI) : RandomTrigger(botAI, "random bot update", 30) { }
bool IsActive() override;
};
class NoNonBotPlayersAroundTrigger : public Trigger
{
public:
NoNonBotPlayersAroundTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no non bot players around", 10) { }
bool IsActive() override;
};
class NewPlayerNearbyTrigger : public Trigger
{
public:
NewPlayerNearbyTrigger(PlayerbotAI* botAI) : Trigger(botAI, "new player nearby", 10) { }
bool IsActive() override;
};
class CollisionTrigger : public Trigger
{
public:
CollisionTrigger(PlayerbotAI* botAI) : Trigger(botAI, "collision", 5) { }
bool IsActive() override;
};
class StayTimeTrigger : public Trigger
{
public:
StayTimeTrigger(PlayerbotAI* botAI, uint32 delay, std::string const name) : Trigger(botAI, name, 5), delay(delay) { }
bool IsActive() override;
private:
uint32 delay;
};
class SitTrigger : public StayTimeTrigger
{
public:
SitTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig->sitDelay, "sit") { }
};
class ReturnTrigger : public StayTimeTrigger
{
public:
ReturnTrigger(PlayerbotAI* botAI) : StayTimeTrigger(botAI, sPlayerbotAIConfig->returnDelay, "return") { }
};
class GiveItemTrigger : public Trigger
{
public:
GiveItemTrigger(PlayerbotAI* botAI, std::string const name, std::string const item) : Trigger(botAI, name, 2), item(item) { }
bool IsActive() override;
protected:
std::string const item;
};
class GiveFoodTrigger : public GiveItemTrigger
{
public:
GiveFoodTrigger(PlayerbotAI* botAI) : GiveItemTrigger(botAI, "give food", "conjured food") { }
bool IsActive() override;
};
class GiveWaterTrigger : public GiveItemTrigger
{
public:
GiveWaterTrigger(PlayerbotAI* botAI) : GiveItemTrigger(botAI, "give water", "conjured water") { }
bool IsActive() override;
};
class IsMountedTrigger : public Trigger
{
public:
IsMountedTrigger(PlayerbotAI* botAI) : Trigger(botAI, "mounted", 1) { }
bool IsActive() override;
};
class CorpseNearTrigger : public Trigger
{
public:
CorpseNearTrigger(PlayerbotAI* botAI) : Trigger(botAI, "corpse near", 10) { }
bool IsActive() override;
};
class IsFallingTrigger : public Trigger
{
public:
IsFallingTrigger(PlayerbotAI* botAI) : Trigger(botAI, "falling", 10) { }
bool IsActive() override;
};
class IsFallingFarTrigger : public Trigger
{
public:
IsFallingFarTrigger(PlayerbotAI* botAI) : Trigger(botAI, "falling far", 10) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,51 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "GuildTriggers.h"
#include "GuildMgr.h"
#include "Playerbots.h"
bool PetitionTurnInTrigger::IsActive()
{
return !bot->GetGuildId() && AI_VALUE2(uint32, "item count", chat->FormatQItem(5863)) && AI_VALUE(uint8, "petition signs") >= sWorld->getIntConfig(CONFIG_MIN_PETITION_SIGNS);
}
bool BuyTabardTrigger::IsActive()
{
return bot->GetGuildId() && !AI_VALUE2(uint32, "item count", chat->FormatQItem(5976));
}
bool LeaveLargeGuildTrigger::IsActive()
{
if (!bot->GetGuildId())
return false;
if (botAI->IsRealPlayer())
return false;
if (botAI->IsAlt())
return false;
GuilderType type = botAI->GetGuilderType();
Guild* guild = sGuildMgr->GetGuildById(bot->GetGuildId());
Player* leader = ObjectAccessor::FindPlayer(guild->GetLeaderGUID());
//Only leave the guild if we know the leader is not a real player.
if (!leader)
return false;
PlayerbotAI* leaderBotAI = GET_PLAYERBOT_AI(leader);
if (!leaderBotAI || leaderBotAI->IsRealPlayer())
return false;
if (type == GuilderType::SOLO && guild->GetLeaderGUID() != bot->GetGUID())
return true;
uint32 members = guild->GetMemberSize();
uint32 maxMembers = uint8(type);
return members > maxMembers;
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_GUILDTRIGGER_H
#define _PLAYERBOT_GUILDTRIGGER_H
#include "Trigger.h"
class PlayerbotAI;
class PetitionTurnInTrigger : public Trigger
{
public:
PetitionTurnInTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
class BuyTabardTrigger : public Trigger
{
public:
BuyTabardTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive() override;
};
class LeaveLargeGuildTrigger : public Trigger
{
public:
LeaveLargeGuildTrigger(PlayerbotAI* botAI) : Trigger(botAI) { }
bool IsActive();
};
#endif

View File

@@ -0,0 +1,32 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "HealthTriggers.h"
#include "Playerbots.h"
bool HealthInRangeTrigger::IsActive()
{
return ValueInRangeTrigger::IsActive() && !AI_VALUE2(bool, "dead", GetTargetName());
}
float HealthInRangeTrigger::GetValue()
{
return AI_VALUE2(uint8, "health", GetTargetName());
}
bool PartyMemberDeadTrigger::IsActive()
{
return GetTarget();
}
bool DeadTrigger::IsActive()
{
return AI_VALUE2(bool, "dead", GetTargetName());
}
bool AoeHealTrigger::IsActive()
{
return AI_VALUE2(uint8, "aoe heal", type) >= count;
}

View File

@@ -0,0 +1,135 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_HEALTHTRIGGERS_H
#define _PLAYERBOT_HEALTHTRIGGERS_H
#include "Trigger.h"
#include "PlayerbotAIConfig.h"
class PlayerbotAI;
class ValueInRangeTrigger : public Trigger
{
public:
ValueInRangeTrigger(PlayerbotAI* botAI, std::string const name, float maxValue, float minValue) : Trigger(botAI, name), maxValue(maxValue), minValue(minValue) { }
virtual float GetValue() = 0;
bool IsActive() override
{
float value = GetValue();
return value < maxValue && value >= minValue;
}
protected:
float maxValue, minValue;
};
class HealthInRangeTrigger : public ValueInRangeTrigger
{
public:
HealthInRangeTrigger(PlayerbotAI* botAI, std::string const name, float maxValue, float minValue = 0) : ValueInRangeTrigger(botAI, name, maxValue, minValue) { }
bool IsActive() override;
float GetValue() override;
};
class LowHealthTrigger : public HealthInRangeTrigger
{
public:
LowHealthTrigger(PlayerbotAI* botAI, std::string const name = "low health", float value = sPlayerbotAIConfig->lowHealth, float minValue = sPlayerbotAIConfig->criticalHealth) :
HealthInRangeTrigger(botAI, name, value, minValue) { }
std::string const GetTargetName() override { return "self target"; }
};
class CriticalHealthTrigger : public LowHealthTrigger
{
public:
CriticalHealthTrigger(PlayerbotAI* botAI) : LowHealthTrigger(botAI, "critical health", sPlayerbotAIConfig->criticalHealth, 0) { }
};
class MediumHealthTrigger : public LowHealthTrigger
{
public:
MediumHealthTrigger(PlayerbotAI* botAI) : LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, sPlayerbotAIConfig->lowHealth) { }
};
class AlmostFullHealthTrigger : public LowHealthTrigger
{
public:
AlmostFullHealthTrigger(PlayerbotAI* botAI) : LowHealthTrigger(botAI, "almost full health", sPlayerbotAIConfig->almostFullHealth, sPlayerbotAIConfig->mediumHealth) { }
};
class PartyMemberLowHealthTrigger : public HealthInRangeTrigger
{
public:
PartyMemberLowHealthTrigger(PlayerbotAI* botAI, std::string const name = "party member low health", float value = sPlayerbotAIConfig->lowHealth, float minValue = sPlayerbotAIConfig->criticalHealth) :
HealthInRangeTrigger(botAI, name, value, minValue) { }
std::string const GetTargetName() override { return "party member to heal"; }
};
class PartyMemberCriticalHealthTrigger : public PartyMemberLowHealthTrigger
{
public:
PartyMemberCriticalHealthTrigger(PlayerbotAI* botAI) : PartyMemberLowHealthTrigger(botAI, "party member critical health", sPlayerbotAIConfig->criticalHealth, 0) { }
};
class PartyMemberMediumHealthTrigger : public PartyMemberLowHealthTrigger
{
public:
PartyMemberMediumHealthTrigger(PlayerbotAI* botAI) : PartyMemberLowHealthTrigger(botAI, "party member medium health", sPlayerbotAIConfig->mediumHealth,sPlayerbotAIConfig->lowHealth) { }
};
class PartyMemberAlmostFullHealthTrigger : public PartyMemberLowHealthTrigger
{
public:
PartyMemberAlmostFullHealthTrigger(PlayerbotAI* botAI) : PartyMemberLowHealthTrigger(botAI, "party member almost full health", sPlayerbotAIConfig->almostFullHealth,sPlayerbotAIConfig->mediumHealth) { }
};
class TargetLowHealthTrigger : public HealthInRangeTrigger
{
public:
TargetLowHealthTrigger(PlayerbotAI* botAI, float value, float minValue = 0) : HealthInRangeTrigger(botAI, "target low health", value, minValue) { }
std::string const GetTargetName() override { return "current target"; }
};
class TargetCriticalHealthTrigger : public TargetLowHealthTrigger
{
public:
TargetCriticalHealthTrigger(PlayerbotAI* botAI) : TargetLowHealthTrigger(botAI, 20) { }
};
class PartyMemberDeadTrigger : public Trigger
{
public:
PartyMemberDeadTrigger(PlayerbotAI* botAI) : Trigger(botAI, "resurrect", 3) { }
std::string const GetTargetName() override { return "party member to resurrect"; }
bool IsActive() override;
};
class DeadTrigger : public Trigger
{
public:
DeadTrigger(PlayerbotAI* botAI) : Trigger(botAI, "dead") { }
std::string const GetTargetName() override { return "self target"; }
bool IsActive() override;
};
class AoeHealTrigger : public Trigger
{
public:
AoeHealTrigger(PlayerbotAI* botAI, std::string const name, std::string const type, int32 count) : Trigger(botAI, name), type(type), count(count) { }
bool IsActive() override;
protected:
int32 count;
std::string const type;
};
#endif

View File

@@ -0,0 +1,16 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "LfgTriggers.h"
#include "Playerbots.h"
bool LfgProposalActiveTrigger::IsActive()
{
return AI_VALUE(uint32, "lfg proposal");
}
bool UnknownDungeonTrigger::IsActive()
{
return botAI->HasActivePlayerMaster() && botAI->GetMaster() && botAI->GetMaster()->IsInWorld() && botAI->GetMaster()->GetMap()->IsDungeon() && bot->GetMapId() == botAI->GetMaster()->GetMapId();
}

View File

@@ -0,0 +1,28 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_LFGTRIGGERS_H
#define _PLAYERBOT_LFGTRIGGERS_H
#include "Trigger.h"
class PlayerbotAI;
class LfgProposalActiveTrigger : public Trigger
{
public:
LfgProposalActiveTrigger(PlayerbotAI* botAI) : Trigger(botAI, "lfg proposal active", 20) { }
bool IsActive() override;
};
class UnknownDungeonTrigger : public Trigger
{
public:
UnknownDungeonTrigger(PlayerbotAI* botAI) : Trigger(botAI, "unknown dungeon", 20) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,29 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "LootTriggers.h"
#include "LootObjectStack.h"
#include "Playerbots.h"
#include "ServerFacade.h"
bool LootAvailableTrigger::IsActive()
{
return AI_VALUE(bool, "has available loot") &&
(sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "loot target"), INTERACTION_DISTANCE) || AI_VALUE(GuidVector, "all targets").empty()) &&
!AI_VALUE2(bool, "combat", "self target") && !AI_VALUE2(bool, "mounted", "self target");
}
bool FarFromCurrentLootTrigger::IsActive()
{
LootObject loot = AI_VALUE(LootObject, "loot target");
if (!loot.IsLootPossible(bot))
return false;
return AI_VALUE2(float, "distance", "loot target") > INTERACTION_DISTANCE;
}
bool CanLootTrigger::IsActive()
{
return AI_VALUE(bool, "can loot");
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_LOOTTRIGGERS_H
#define _PLAYERBOT_LOOTTRIGGERS_H
#include "Trigger.h"
class PlayerbotAI;
class LootAvailableTrigger : public Trigger
{
public:
LootAvailableTrigger(PlayerbotAI* botAI) : Trigger(botAI, "loot available") { }
bool IsActive() override;
};
class FarFromCurrentLootTrigger : public Trigger
{
public:
FarFromCurrentLootTrigger(PlayerbotAI* botAI) : Trigger(botAI, "far from current loot") { }
bool IsActive() override;
};
class CanLootTrigger : public Trigger
{
public:
CanLootTrigger(PlayerbotAI* botAI) : Trigger(botAI, "can loot") { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,231 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "PvpTriggers.h"
#include "BattlegroundMgr.h"
#include "BattlegroundEY.h"
#include "BattlegroundWS.h"
#include "Playerbots.h"
#include "ServerFacade.h"
bool EnemyPlayerNear::IsActive()
{
return AI_VALUE(Unit*, "enemy player target");
}
bool PlayerHasNoFlag::IsActive()
{
if (botAI->GetBot()->InBattleground())
{
if (botAI->GetBot()->GetBattlegroundTypeId() == BattlegroundTypeId::BATTLEGROUND_WS)
{
BattlegroundWS *bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (!(bg->GetFlagState(bg->GetOtherTeamId(bot->GetTeamId())) == BG_WS_FLAG_STATE_ON_PLAYER))
return true;
if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE) || bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_HORDE))
{
return false;
}
return true;
}
return false;
}
return false;
}
bool PlayerIsInBattleground::IsActive()
{
return botAI->GetBot()->InBattleground();
}
bool BgWaitingTrigger::IsActive()
{
if (bot->InBattleground())
{
if (bot->GetBattleground() && bot->GetBattleground()->GetStatus() == STATUS_WAIT_JOIN)
return true;
}
return false;
}
bool BgActiveTrigger::IsActive()
{
if (bot->InBattleground())
{
if (bot->GetBattleground() && bot->GetBattleground()->GetStatus() == STATUS_IN_PROGRESS)
return true;
}
return false;
}
bool BgInviteActiveTrigger::IsActive()
{
if (bot->InBattleground() || !bot->InBattlegroundQueue())
{
return false;
}
for (uint8 i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
{
BattlegroundQueueTypeId queueTypeId = bot->GetBattlegroundQueueTypeId(i);
if (queueTypeId == BATTLEGROUND_QUEUE_NONE)
continue;
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(queueTypeId);
GroupQueueInfo ginfo;
if (bgQueue.GetPlayerGroupInfoData(bot->GetGUID(), &ginfo))
{
if (ginfo.IsInvitedToBGInstanceGUID && ginfo.RemoveInviteTime)
{
LOG_INFO("playerbots", "Bot {} <{}> ({} {}) : Invited to BG but not in BG",
bot->GetGUID().ToString().c_str(), bot->GetName(), bot->getLevel(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H");
return true;
}
}
}
return false;
}
bool PlayerIsInBattlegroundWithoutFlag::IsActive()
{
if (botAI->GetBot()->InBattleground())
{
if (botAI->GetBot()->GetBattlegroundTypeId() == BattlegroundTypeId::BATTLEGROUND_WS)
{
BattlegroundWS *bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (!(bg->GetFlagState(bg->GetOtherTeamId(bot->GetTeamId())) == BG_WS_FLAG_STATE_ON_PLAYER))
return true;
if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE) || bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE))
{
return false;
}
}
return true;
}
return false;
}
bool PlayerHasFlag::IsActive()
{
if (bot->InBattleground())
{
if (bot->GetBattlegroundTypeId() == BATTLEGROUND_WS)
{
BattlegroundWS *bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE) || bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_HORDE))
{
return true;
}
}
if (bot->GetBattlegroundTypeId() == BATTLEGROUND_EY)
{
BattlegroundEY* bg = (BattlegroundEY*) botAI->GetBot()->GetBattleground();
return bot->GetGUID() == bg->GetFlagPickerGUID();
}
return false;
}
return false;
}
bool TeamHasFlag::IsActive()
{
if (botAI->GetBot()->InBattleground())
{
if (botAI->GetBot()->GetBattlegroundTypeId() == BattlegroundTypeId::BATTLEGROUND_WS)
{
BattlegroundWS *bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_ALLIANCE) || bot->GetGUID() == bg->GetFlagPickerGUID(TEAM_HORDE))
{
return false;
}
if (bg->GetFlagState(bg->GetOtherTeamId(bot->GetTeamId())) == BG_WS_FLAG_STATE_ON_PLAYER)
return true;
}
return false;
}
return false;
}
bool EnemyTeamHasFlag::IsActive()
{
if (botAI->GetBot()->InBattleground())
{
if (botAI->GetBot()->GetBattlegroundTypeId() == BattlegroundTypeId::BATTLEGROUND_WS)
{
BattlegroundWS *bg = (BattlegroundWS*)botAI->GetBot()->GetBattleground();
if (bot->GetTeamId() == TEAM_HORDE)
{
if (!bg->GetFlagPickerGUID(TEAM_HORDE).IsEmpty())
return true;
}
else
{
if (!bg->GetFlagPickerGUID(TEAM_ALLIANCE).IsEmpty())
return true;
}
}
return false;
}
return false;
}
bool EnemyFlagCarrierNear::IsActive()
{
Unit* carrier = AI_VALUE(Unit*, "enemy flag carrier");
return carrier && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, carrier), 200.f);
}
bool TeamFlagCarrierNear::IsActive()
{
Unit* carrier = AI_VALUE(Unit*, "team flag carrier");
return carrier && sServerFacade->IsDistanceLessOrEqualThan(sServerFacade->GetDistance2d(bot, carrier), 200.f);
}
bool PlayerWantsInBattlegroundTrigger::IsActive()
{
if (bot->InBattleground())
return false;
if (bot->GetBattleground() && bot->GetBattleground()->GetStatus() == STATUS_WAIT_JOIN)
return false;
if (bot->GetBattleground() && bot->GetBattleground()->GetStatus() == STATUS_IN_PROGRESS)
return false;
if (!bot->CanJoinToBattleground())
return false;
return true;
}
bool VehicleNearTrigger::IsActive()
{
GuidVector npcs = AI_VALUE(GuidVector, "nearest vehicles");
return npcs.size();
}
bool InVehicleTrigger::IsActive()
{
return botAI->IsInVehicle();
}

View File

@@ -0,0 +1,132 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_PVPTRIGGERS_H
#define _PLAYERBOT_PVPTRIGGERS_H
#include "Trigger.h"
class PlayerbotAI;
class EnemyPlayerNear : public Trigger
{
public:
EnemyPlayerNear(PlayerbotAI* botAI) : Trigger(botAI, "enemy player near", 3) { }
bool IsActive() override;
};
class PlayerHasNoFlag : public Trigger
{
public:
PlayerHasNoFlag(PlayerbotAI* botAI) : Trigger(botAI, "player has no flag") { }
bool IsActive() override;
};
class PlayerHasFlag : public Trigger
{
public:
PlayerHasFlag(PlayerbotAI* botAI) : Trigger(botAI, "player has flag") { }
bool IsActive() override;
};
class EnemyFlagCarrierNear : public Trigger
{
public:
EnemyFlagCarrierNear(PlayerbotAI* botAI) : Trigger(botAI, "enemy flagcarrier near") { }
bool IsActive() override;
};
class TeamFlagCarrierNear : public Trigger
{
public:
TeamFlagCarrierNear(PlayerbotAI* botAI) : Trigger(botAI, "team flagcarrier near") { }
bool IsActive() override;
};
class TeamHasFlag : public Trigger
{
public:
TeamHasFlag(PlayerbotAI* botAI) : Trigger(botAI, "team has flag") { }
bool IsActive() override;
};
class EnemyTeamHasFlag : public Trigger
{
public:
EnemyTeamHasFlag(PlayerbotAI* botAI) : Trigger(botAI, "enemy team has flag") { }
bool IsActive() override;
};
class PlayerIsInBattleground : public Trigger
{
public:
PlayerIsInBattleground(PlayerbotAI* botAI) : Trigger(botAI, "in Battleground") { }
bool IsActive() override;
};
class BgWaitingTrigger : public Trigger
{
public:
BgWaitingTrigger(PlayerbotAI* botAI) : Trigger(botAI, "bg waiting", 30) { }
bool IsActive() override;
};
class BgActiveTrigger : public Trigger
{
public:
BgActiveTrigger(PlayerbotAI* botAI) : Trigger(botAI, "bg active", 1) { }
bool IsActive() override;
};
class BgInviteActiveTrigger : public Trigger
{
public:
BgInviteActiveTrigger(PlayerbotAI* botAI) : Trigger(botAI, "bg invite active", 10) { }
bool IsActive() override;
};
class PlayerIsInBattlegroundWithoutFlag : public Trigger
{
public:
PlayerIsInBattlegroundWithoutFlag(PlayerbotAI* botAI) : Trigger(botAI, "in Battleground without flag") { }
bool IsActive() override;
};
class PlayerWantsInBattlegroundTrigger : public Trigger
{
public:
PlayerWantsInBattlegroundTrigger(PlayerbotAI* botAI) : Trigger(botAI, "wants in bg") { }
bool IsActive() override;
};
class VehicleNearTrigger : public Trigger
{
public:
VehicleNearTrigger(PlayerbotAI* botAI) : Trigger(botAI, "vehicle near", 10) { }
bool IsActive() override;
};
class InVehicleTrigger : public Trigger
{
public:
InVehicleTrigger(PlayerbotAI* botAI) : Trigger(botAI, "in vehicle") { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,131 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "RangeTriggers.h"
#include "MoveSplineInit.h"
#include "Playerbots.h"
#include "ServerFacade.h"
static float GetSpeedInMotion(Unit* target)
{
return target->GetSpeed(Movement::SelectSpeedType(target->GetUnitMovementFlags()));
}
bool EnemyTooCloseForSpellTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (target)
{
if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f)
return false;
bool isBoss = false;
bool isRaid = false;
float targetDistance = sServerFacade->GetDistance2d(bot, target) + bot->GetCombatReach() + target->GetCombatReach();
if (target->GetTypeId() == TYPEID_UNIT)
{
Creature* creature = botAI->GetCreature(target->GetGUID());
if (creature)
{
isBoss = creature->isWorldBoss();
}
}
if (bot->GetMap() && bot->GetMap()->IsRaid())
isRaid = true;
if (isBoss || isRaid)
return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("spell"));
return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("spell") / 2));
}
return false;
}
bool EnemyTooCloseForShootTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (!target)
return false;
if (target->GetTarget() == bot->GetGUID() && !bot->GetGroup() && !target->HasUnitState(UNIT_STATE_ROOT) && GetSpeedInMotion(target) > GetSpeedInMotion(bot) * 0.65f)
return false;
bool isBoss = false;
float targetDistance = sServerFacade->GetDistance2d(bot, target) + bot->GetCombatReach() + target->GetCombatReach();
if (target->GetTypeId() == TYPEID_UNIT)
{
Creature* creature = botAI->GetCreature(target->GetGUID());
if (creature)
{
isBoss = creature->isWorldBoss();
}
}
if (isBoss)
return sServerFacade->IsDistanceLessThan(targetDistance, botAI->GetRange("shoot"));
return sServerFacade->IsDistanceLessOrEqualThan(targetDistance, (botAI->GetRange("shoot") / 2));
}
bool EnemyTooCloseForMeleeTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
if (target && target->IsPlayer())
return false;
return target && AI_VALUE2(bool, "inside target", "current target");
}
bool EnemyIsCloseTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, "current target");
return target && sServerFacade->IsDistanceLessOrEqualThan(AI_VALUE2(float, "distance", "current target"), sPlayerbotAIConfig->tooCloseDistance);
}
bool OutOfRangeTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, GetTargetName());
return target && sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", GetTargetName()), distance);
}
EnemyOutOfSpellRangeTrigger::EnemyOutOfSpellRangeTrigger(PlayerbotAI* botAI) : OutOfRangeTrigger(botAI, "enemy out of spell range", botAI->GetRange("spell"))
{
}
bool EnemyOutOfSpellRangeTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, GetTargetName());
return target && (sServerFacade->GetDistance2d(bot, target) > distance || !bot->IsWithinLOSInMap(target));
}
bool EnemyOutOfMeleeTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, GetTargetName());
if (!target)
return false;
float targetDistance = sServerFacade->GetDistance2d(bot, target);
return target && (targetDistance > std::max(5.0f, bot->GetCombatReach() + target->GetCombatReach()) || (!bot->IsWithinLOSInMap(target) && targetDistance > 5.0f));
}
bool PartyMemberToHealOutOfSpellRangeTrigger::IsActive()
{
Unit* target = AI_VALUE(Unit*, GetTargetName());
if (!target)
return false;
float combatReach = bot->GetCombatReach() + target->GetCombatReach();
return target && (sServerFacade->GetDistance2d(bot, target) > (distance + combatReach) || !bot->IsWithinLOSInMap(target));
}
PartyMemberToHealOutOfSpellRangeTrigger::PartyMemberToHealOutOfSpellRangeTrigger(PlayerbotAI* botAI) :
OutOfRangeTrigger(botAI, "party member to heal out of spell range", botAI->GetRange("heal"))
{
}
bool FarFromMasterTrigger::IsActive()
{
return sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float, "distance", "master target"), distance);
}

View File

@@ -0,0 +1,100 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RANGETRIGGERS_H
#define _PLAYERBOT_RANGETRIGGERS_H
#include "PlayerbotAIConfig.h"
#include "Trigger.h"
class PlayerbotAI;
class EnemyTooCloseForSpellTrigger : public Trigger
{
public:
EnemyTooCloseForSpellTrigger(PlayerbotAI* botAI) : Trigger(botAI, "enemy too close for spell") { }
bool IsActive() override;
};
class EnemyTooCloseForShootTrigger : public Trigger
{
public:
EnemyTooCloseForShootTrigger(PlayerbotAI* botAI) : Trigger(botAI, "enemy too close for shoot") { }
bool IsActive() override;
};
class EnemyTooCloseForMeleeTrigger : public Trigger
{
public:
EnemyTooCloseForMeleeTrigger(PlayerbotAI* botAI) : Trigger(botAI, "enemy too close for melee", 5) { }
bool IsActive() override;
};
class EnemyIsCloseTrigger : public Trigger
{
public:
EnemyIsCloseTrigger(PlayerbotAI* botAI) : Trigger(botAI, "enemy is close") { }
bool IsActive() override;
};
class OutOfRangeTrigger : public Trigger
{
public:
OutOfRangeTrigger(PlayerbotAI* botAI, std::string const name, float distance) : Trigger(botAI, name), distance(distance) { }
bool IsActive() override;
std::string const GetTargetName() override { return "current target"; }
protected:
float distance;
};
class EnemyOutOfMeleeTrigger : public OutOfRangeTrigger
{
public:
EnemyOutOfMeleeTrigger(PlayerbotAI* botAI) : OutOfRangeTrigger(botAI, "enemy out of melee range", sPlayerbotAIConfig->meleeDistance) { }
bool IsActive() override;
};
class EnemyOutOfSpellRangeTrigger : public OutOfRangeTrigger
{
public:
EnemyOutOfSpellRangeTrigger(PlayerbotAI* botAI);
bool IsActive() override;
};
class PartyMemberToHealOutOfSpellRangeTrigger : public OutOfRangeTrigger
{
public:
PartyMemberToHealOutOfSpellRangeTrigger(PlayerbotAI* botAI);
bool IsActive() override;
std::string const GetTargetName() override { return "party member to heal"; }
};
class FarFromMasterTrigger : public Trigger
{
public:
FarFromMasterTrigger(PlayerbotAI* botAI, std::string const name = "far from master", float distance = 12.0f, int32 checkInterval = 50) :
Trigger(botAI, name, checkInterval), distance(distance) { }
bool IsActive() override;
private:
float distance;
};
class OutOfReactRangeTrigger : public FarFromMasterTrigger
{
public:
OutOfReactRangeTrigger(PlayerbotAI* botAI) : FarFromMasterTrigger(botAI, "out of react range", 50.0f, 5) { }
};
#endif

View File

@@ -0,0 +1,454 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "RpgTriggers.h"
#include "BudgetValues.h"
#include "GuildCreateActions.h"
#include "Playerbots.h"
#include "ServerFacade.h"
#include "SocialMgr.h"
bool NoRpgTargetTrigger::IsActive()
{
return !AI_VALUE(GuidPosition, "rpg target");
}
bool HasRpgTargetTrigger::IsActive()
{
return !NoRpgTargetTrigger::IsActive();
}
bool FarFromRpgTargetTrigger::IsActive()
{
return !NoRpgTargetTrigger::IsActive() && AI_VALUE2(float, "distance", "rpg target") > INTERACTION_DISTANCE;
}
bool NearRpgTargetTrigger::IsActive()
{
return !NoRpgTargetTrigger::IsActive() && !FarFromRpgTargetTrigger::IsActive();
}
GuidPosition RpgTrigger::getGuidP()
{
return AI_VALUE(GuidPosition, "rpg target");
}
bool RpgTrigger::IsActive()
{
return true;
}
Event RpgTrigger::Check()
{
if (!NoRpgTargetTrigger::IsActive() && (AI_VALUE(std::string, "next rpg action") == "choose rpg target") || !FarFromRpgTargetTrigger::IsActive())
return Trigger::Check();
return Event();
}
bool RpgTaxiTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
return false;
uint32 node = sObjectMgr->GetNearestTaxiNode(guidP.getX(), guidP.getY(), guidP.getZ(), guidP.getMapId(), bot->GetTeamId());
if (!node)
return false;
if (!bot->m_taxi.IsTaximaskNodeKnown(node))
return false;
return true;
}
bool RpgDiscoverTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_FLIGHTMASTER))
return false;
if (bot->isTaxiCheater())
return false;
uint32 node = sObjectMgr->GetNearestTaxiNode(guidP.getX(), guidP.getY(), guidP.getZ(), guidP.getMapId(), bot->GetTeamId());
if (bot->m_taxi.IsTaximaskNodeKnown(node))
return false;
return true;
}
bool RpgStartQuestTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.IsCreature() && !guidP.IsGameObject())
return false;
if (AI_VALUE(bool, "can fight equal"))
{
if (AI_VALUE2(bool, "can accept quest npc", guidP.GetEntry()))
return true;
}
else
{
if (AI_VALUE2(bool, "can accept quest low level npc", guidP.GetEntry()))
return true;
}
return false;
}
bool RpgEndQuestTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.IsCreature() && !guidP.IsGameObject())
return false;
if (AI_VALUE2(bool, "can turn in quest npc", guidP.GetEntry()))
return true;
return false;
}
bool RpgBuyTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_VENDOR))
return false;
if (AI_VALUE(uint8, "durability") > 50)
return false;
if (!AI_VALUE(bool, "can sell")) //Need better condition.
return false;
return true;
}
bool RpgSellTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_VENDOR))
return false;
if (!AI_VALUE(bool, "can sell"))
return false;
return true;
}
bool RpgRepairTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_REPAIR))
return false;
if (AI_VALUE2_LAZY(bool, "group or", "should sell,can sell,following party,near leader"))
return true;
if (AI_VALUE2_LAZY(bool, "group or", "should repair,can repair,following party,near leader"))
return true;
return false;
}
bool RpgTrainTrigger::IsTrainerOf(CreatureTemplate const* cInfo, Player* pPlayer)
{
switch (cInfo->trainer_type)
{
case TRAINER_TYPE_CLASS:
if (pPlayer->getClass() != cInfo->trainer_class)
{
return false;
}
break;
case TRAINER_TYPE_PETS:
if (pPlayer->getClass() != CLASS_HUNTER)
{
return false;
}
break;
case TRAINER_TYPE_MOUNTS:
if (cInfo->trainer_race && pPlayer->getRace() != cInfo->trainer_race)
{
// Allowed to train if exalted
if (FactionTemplateEntry const* faction_template = sFactionTemplateStore.LookupEntry(cInfo->faction))
{
if (pPlayer->GetReputationRank(faction_template->faction) == REP_EXALTED)
return true;
}
return false;
}
break;
case TRAINER_TYPE_TRADESKILLS:
if (cInfo->trainer_spell && !pPlayer->HasSpell(cInfo->trainer_spell))
{
return false;
}
break;
default:
return false; // checked and error output at creature_template loading
}
return true;
}
bool RpgTrainTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_TRAINER))
return false;
CreatureTemplate const* cInfo = guidP.GetCreatureTemplate();
if (!IsTrainerOf(cInfo, bot))
return false;
// check present spell in trainer spell list
TrainerSpellData const* cSpells = sObjectMgr->GetNpcTrainerSpells(guidP.GetEntry());
if (!cSpells)
{
return false;
}
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction);
float fDiscountMod = bot->GetReputationPriceDiscount(factionTemplate);
TrainerSpellMap trainer_spells;
if (cSpells)
trainer_spells.insert(cSpells->spellList.begin(), cSpells->spellList.end());
for (TrainerSpellMap::const_iterator itr = trainer_spells.begin(); itr != trainer_spells.end(); ++itr)
{
TrainerSpell const* tSpell = &itr->second;
if (!tSpell)
continue;
TrainerSpellState state = bot->GetTrainerSpellState(tSpell);
if (state != TRAINER_SPELL_GREEN)
continue;
uint32 spellId = tSpell->spell;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
if (!spellInfo)
continue;
uint32 cost = uint32(floor(tSpell->spellCost * fDiscountMod));
if (cost > AI_VALUE2(uint32, "free money for", (uint32)NeedMoneyFor::spells))
continue;
return true;
}
return false;
}
bool RpgHealTrigger::IsActive()
{
if (!botAI->HasStrategy("heal", BOT_STATE_COMBAT))
return false;
GuidPosition guidP(getGuidP());
Unit* unit = guidP.GetUnit();
if (!unit)
return false;
if (!unit->IsFriendlyTo(bot))
return false;
if (unit->isDead() || unit->GetHealthPct() >= 100)
return false;
return true;
}
bool RpgHomeBindTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_INNKEEPER))
return false;
if (AI_VALUE(WorldPosition, "home bind").distance(bot) < 500.0f)
return false;
return true;
}
bool RpgQueueBGTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.IsCreature())
return false;
if (AI_VALUE(BattlegroundTypeId, "rpg bg type") == BATTLEGROUND_TYPE_NONE)
return false;
return true;
}
bool RpgBuyPetitionTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.HasNpcFlag(UNIT_NPC_FLAG_PETITIONER))
return false;
if (!BuyPetitionAction::canBuyPetition(bot))
return false;
return true;
}
bool RpgUseTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.IsGameObject())
return false;
GameObjectTemplate const* goInfo = guidP.GetGameObjectTemplate();
switch (goInfo->type)
{
case GAMEOBJECT_TYPE_BINDER:
case GAMEOBJECT_TYPE_GENERIC:
case GAMEOBJECT_TYPE_TEXT:
case GAMEOBJECT_TYPE_GOOBER:
case GAMEOBJECT_TYPE_TRANSPORT:
case GAMEOBJECT_TYPE_AREADAMAGE:
case GAMEOBJECT_TYPE_CAMERA:
case GAMEOBJECT_TYPE_MAP_OBJECT:
case GAMEOBJECT_TYPE_MO_TRANSPORT:
case GAMEOBJECT_TYPE_DUEL_ARBITER:
case GAMEOBJECT_TYPE_FISHINGNODE:
case GAMEOBJECT_TYPE_GUARDPOST:
case GAMEOBJECT_TYPE_SPELLCASTER:
case GAMEOBJECT_TYPE_FISHINGHOLE:
case GAMEOBJECT_TYPE_AURA_GENERATOR:
return false;
default:
break;
}
return true;
}
bool RpgSpellTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (guidP.IsPlayer())
return false;
if (!guidP.GetWorldObject())
return false;
return true;
}
bool RpgCraftTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (guidP.IsPlayer())
return false;
if (!guidP.GetWorldObject())
return false;
return true;
}
bool RpgTradeUsefulTrigger::IsActive()
{
GuidPosition guidP(getGuidP());
if (!guidP.IsPlayer())
return false;
Player* player = guidP.GetPlayer();
if (!player)
return false;
//More code/botAI-value here to see if bot is friendly enough.
bool isFriend = false;
if (player->GetGuildId() != bot->GetGuildId())
isFriend = true;
if (bot->GetGroup() == player->GetGroup() && !urand(0, 5))
isFriend = true;
if (!urand(0, 20))
isFriend = true;
if (!isFriend)
return false;
if (!player->IsWithinLOSInMap(bot))
return false;
if (player->GetTrader() && player->GetTrader() != bot)
return false;
if (bot->GetTrader() && bot->GetTrader() != player)
return false;
if (AI_VALUE(std::vector<Item*>, "items useful to give").empty())
return false;
return true;
}
bool RpgDuelTrigger::IsActive()
{
if (!botAI->HasStrategy("start duel", BOT_STATE_NON_COMBAT))
return false;
GuidPosition guidP(getGuidP());
if (!guidP.IsPlayer())
return false;
Player* player = guidP.GetPlayer();
if (!player)
return false;
if (player->getLevel() > bot->getLevel() + 3)
return false;
if (bot->getLevel() > player->getLevel() + 20)
return false;
// caster or target already have requested duel
if (bot->duel || player->duel || !player->GetSocial() || player->GetSocial()->HasIgnore(bot->GetGUID()))
return false;
AreaTableEntry const* targetAreaEntry = sAreaTableStore.LookupEntry(player->GetAreaId());
if (targetAreaEntry && !(targetAreaEntry->flags & AREA_FLAG_ALLOW_DUELS))
{
// Dueling isn't allowed here
return false;
}
if (!AI_VALUE(GuidVector, "all targets").empty())
return false;
return true;
}

View File

@@ -0,0 +1,198 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RPGTRIGGERS_H
#define _PLAYERBOT_RPGTRIGGERS_H
#include "Trigger.h"
class Event;
class GuidPosition;
class PlayerbotAI;
struct CreatureTemplate;
class NoRpgTargetTrigger : public Trigger
{
public:
NoRpgTargetTrigger(PlayerbotAI* botAI, std::string const name = "no rpg target", int checkInterval = 1) : Trigger(botAI, name, checkInterval) { }
bool IsActive() override;
};
class HasRpgTargetTrigger : public NoRpgTargetTrigger
{
public:
HasRpgTargetTrigger(PlayerbotAI* botAI, std::string const name = "has rpg target", int checkInterval = 1) : NoRpgTargetTrigger(botAI, name, checkInterval) { }
bool IsActive() override;
};
class FarFromRpgTargetTrigger : public NoRpgTargetTrigger
{
public:
FarFromRpgTargetTrigger(PlayerbotAI* botAI, std::string const name = "far from rpg target", int checkInterval = 1) : NoRpgTargetTrigger(botAI, name, checkInterval) { }
bool IsActive() override;
};
class NearRpgTargetTrigger : public FarFromRpgTargetTrigger
{
public:
NearRpgTargetTrigger(PlayerbotAI* botAI, std::string const name = "near rpg target", int checkInterval = 1) : FarFromRpgTargetTrigger(botAI, name, checkInterval) { }
bool IsActive() override;
};
//Sub actions:
class RpgTrigger : public FarFromRpgTargetTrigger
{
public:
RpgTrigger(PlayerbotAI* botAI, std::string const name = "sub rpg", int checkInterval = 2) : FarFromRpgTargetTrigger(botAI, name, checkInterval) { }
GuidPosition getGuidP();
bool IsActive() override;
Event Check() override;
};
class RpgTaxiTrigger : public RpgTrigger
{
public:
RpgTaxiTrigger(PlayerbotAI* botAI, std::string const name = "rpg taxi") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgDiscoverTrigger : public RpgTrigger
{
public:
RpgDiscoverTrigger(PlayerbotAI* botAI, std::string const name = "rpg discover") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgStartQuestTrigger : public RpgTrigger
{
public:
RpgStartQuestTrigger(PlayerbotAI* botAI, std::string const name = "rpg start quest") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgEndQuestTrigger : public RpgTrigger
{
public:
RpgEndQuestTrigger(PlayerbotAI* botAI, std::string const name = "rpg end quest") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgBuyTrigger : public RpgTrigger
{
public:
RpgBuyTrigger(PlayerbotAI* botAI, std::string const name = "rpg buy") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgSellTrigger : public RpgTrigger
{
public:
RpgSellTrigger(PlayerbotAI* botAI, std::string const name = "rpg sell") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgRepairTrigger : public RpgTrigger
{
public:
RpgRepairTrigger(PlayerbotAI* botAI, std::string const name = "rpg repair") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgTrainTrigger : public RpgTrigger
{
public:
RpgTrainTrigger(PlayerbotAI* botAI, std::string const name = "rpg train") : RpgTrigger(botAI, name) { }
static bool IsTrainerOf(CreatureTemplate const* cInfo, Player* pPlayer);
bool IsActive() override;
};
class RpgHealTrigger : public RpgTrigger
{
public:
RpgHealTrigger(PlayerbotAI* botAI, std::string const name = "rpg heal") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgHomeBindTrigger : public RpgTrigger
{
public:
RpgHomeBindTrigger(PlayerbotAI* botAI, std::string const name = "rpg home bind") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgQueueBGTrigger : public RpgTrigger
{
public:
RpgQueueBGTrigger(PlayerbotAI* botAI, std::string const name = "rpg queue bg") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgBuyPetitionTrigger : public RpgTrigger
{
public:
RpgBuyPetitionTrigger(PlayerbotAI* botAI, std::string const name = "rpg buy petition") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgUseTrigger : public RpgTrigger
{
public:
RpgUseTrigger(PlayerbotAI* botAI, std::string const name = "rpg use") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgSpellTrigger : public RpgTrigger
{
public:
RpgSpellTrigger(PlayerbotAI* botAI, std::string const name = "rpg spell") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgCraftTrigger : public RpgTrigger
{
public:
RpgCraftTrigger(PlayerbotAI* botAI, std::string const name = "rpg craft") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgTradeUsefulTrigger : public RpgTrigger
{
public:
RpgTradeUsefulTrigger(PlayerbotAI* botAI, std::string const name = "rpg trade useful") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
class RpgDuelTrigger : public RpgTrigger
{
public:
RpgDuelTrigger(PlayerbotAI* botAI, std::string const name = "rpg duel") : RpgTrigger(botAI, name) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,11 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "RtiTriggers.h"
#include "Playerbots.h"
bool NoRtiTrigger::IsActive()
{
return !AI_VALUE(Unit*, "rti target");
}

View File

@@ -0,0 +1,20 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_RTITRIGGERS_H
#define _PLAYERBOT_RTITRIGGERS_H
#include "Trigger.h"
class PlayerbotAI;
class NoRtiTrigger : public Trigger
{
public:
NoRtiTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no rti target") { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,181 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "StuckTriggers.h"
#include "CellImpl.h"
#include "PathGenerator.h"
#include "Playerbots.h"
bool MoveStuckTrigger::IsActive()
{
if (botAI->HasActivePlayerMaster())
return false;
if (!botAI->AllowActivity(ALL_ACTIVITY))
return false;
WorldPosition botPos(bot);
LogCalculatedValue<WorldPosition>* posVal = dynamic_cast<LogCalculatedValue<WorldPosition>*>(context->GetUntypedValue("current position"));
if (posVal->LastChangeDelay() > 5 * MINUTE)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in the same position for {} seconds",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
return true;
}
bool longLog = false;
for (auto tPos : posVal->ValueLog())
{
uint32 timePassed = time(0) - tPos.second;
if (timePassed > 10 * MINUTE)
{
if (botPos.fDist(tPos.first) > 50.0f)
return false;
longLog = true;
}
}
if (longLog)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in the same position for 10mins",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
}
return longLog;
}
bool MoveLongStuckTrigger::IsActive()
{
if (botAI->HasActivePlayerMaster())
return false;
if (!botAI->AllowActivity(ALL_ACTIVITY))
return false;
WorldPosition botPos(bot);
Cell cell(bot->GetPositionX(), bot->GetPositionY());
GridCoord grid = botPos.getGridCoord();
if (grid.x_coord < 0 || grid.x_coord >= MAX_NUMBER_OF_GRIDS)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in grid {},{} on map {}",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), grid.x_coord, grid.y_coord, botPos.getMapId());
return true;
}
if (grid.y_coord < 0 || grid.y_coord >= MAX_NUMBER_OF_GRIDS)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in grid {},{} on map {}",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), grid.x_coord, grid.y_coord, botPos.getMapId());
return true;
}
if (cell.GridX() > 0 && cell.GridY() > 0 && !MMAP::MMapFactory::createOrGetMMapMgr()->loadMap(botPos.getMapId(), cell.GridX(), cell.GridY()))
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in unloaded grid {},{} on map {}",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), grid.x_coord, grid.y_coord, botPos.getMapId());
return true;
}
LogCalculatedValue<WorldPosition>* posVal = dynamic_cast<LogCalculatedValue<WorldPosition>*>(context->GetUntypedValue("current position"));
if (posVal->LastChangeDelay() > 10 * MINUTE)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in the same position for {} seconds",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
return true;
}
MemoryCalculatedValue<uint32>* expVal = dynamic_cast<MemoryCalculatedValue<uint32>*>(context->GetUntypedValue("experience"));
if (expVal->LastChangeDelay() < 15 * MINUTE)
return false;
bool longLog = false;
for (auto tPos : posVal->ValueLog())
{
uint32 timePassed = time(0) - tPos.second;
if (timePassed > 15 * MINUTE)
{
if (botPos.fDist(tPos.first) > 50.0f)
return false;
longLog = true;
}
}
if (longLog)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in the same position for 15mins",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
}
return longLog;
}
bool CombatStuckTrigger::IsActive()
{
if (!bot->IsInCombat())
return false;
if (botAI->HasActivePlayerMaster())
return false;
if (!botAI->AllowActivity(ALL_ACTIVITY))
return false;
WorldPosition botPos(bot);
MemoryCalculatedValue<bool>* combatVal = dynamic_cast<MemoryCalculatedValue<bool>*>(context->GetUntypedValue("combat::self target"));
if (combatVal->LastChangeDelay() > 5 * MINUTE)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in combat for {} seconds",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
return true;
}
return false;
}
bool CombatLongStuckTrigger::IsActive()
{
if (!bot->IsInCombat())
return false;
if (botAI->HasActivePlayerMaster())
return false;
if (!botAI->AllowActivity(ALL_ACTIVITY))
return false;
WorldPosition botPos(bot);
MemoryCalculatedValue<bool>* combatVal = dynamic_cast<MemoryCalculatedValue<bool>*>(context->GetUntypedValue("combat::self target"));
if (combatVal->LastChangeDelay() > 15 * MINUTE)
{
// LOG_INFO("playerbots", "Bot {} {}:{} <{}> was in combat for {} seconds",
// bot->GetGUID().ToString().c_str(), bot->GetTeamId() == TEAM_ALLIANCE ? "A" : "H", bot->getLevel(), bot->GetName(), posVal->LastChangeDelay());
return true;
}
return false;
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_STUCKTRIGGERS_H
#define _PLAYERBOT_STUCKTRIGGERS_H
#include "Trigger.h"
class MoveStuckTrigger : public Trigger
{
public:
MoveStuckTrigger(PlayerbotAI* botAI) : Trigger(botAI, "move stuck", 5) { }
bool IsActive() override;
};
class MoveLongStuckTrigger : public Trigger
{
public:
MoveLongStuckTrigger(PlayerbotAI* botAI) : Trigger(botAI, "move long stuck", 5) { }
bool IsActive() override;
};
class CombatStuckTrigger : public Trigger
{
public:
CombatStuckTrigger(PlayerbotAI* botAI) : Trigger(botAI, "combat stuck", 5) { }
bool IsActive() override;
};
class CombatLongStuckTrigger : public Trigger
{
public:
CombatLongStuckTrigger(PlayerbotAI* botAI) : Trigger(botAI, "combat long stuck", 5) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,48 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "TravelTriggers.h"
#include "Playerbots.h"
#include "ServerFacade.h"
bool NoTravelTargetTrigger::IsActive()
{
return !context->GetValue<TravelTarget*>("travel target")->Get()->isActive();
}
bool FarFromTravelTargetTrigger::IsActive()
{
return context->GetValue<TravelTarget*>("travel target")->Get()->isTraveling();
}
bool NearDarkPortalTrigger::IsActive()
{
return bot->GetAreaId() == 72;
}
bool AtDarkPortalAzerothTrigger::IsActive()
{
if (bot->GetAreaId() == 72)
{
if (sServerFacade->GetDistance2d(bot, -11906.9f, -3208.53f) < 20.0f)
{
return true;
}
}
return false;
}
bool AtDarkPortalOutlandTrigger::IsActive()
{
if (bot->GetAreaId() == 3539)
{
if (sServerFacade->GetDistance2d(bot, -248.1939f, 921.919f) < 10.0f)
{
return true;
}
}
return false;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_TRAVELTRIGGERS_H
#define _PLAYERBOT_TRAVELTRIGGERS_H
#include "Trigger.h"
class PlayerbotAI;
class NoTravelTargetTrigger : public Trigger
{
public:
NoTravelTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "no travel target") { }
bool IsActive() override;
};
class FarFromTravelTargetTrigger : public Trigger
{
public:
FarFromTravelTargetTrigger(PlayerbotAI* botAI) : Trigger(botAI, "far from travel target") { }
bool IsActive() override;
};
class NearDarkPortalTrigger : public Trigger
{
public:
NearDarkPortalTrigger(PlayerbotAI* botAI) : Trigger(botAI, "near dark portal", 10) { }
virtual bool IsActive();
};
class AtDarkPortalAzerothTrigger : public Trigger
{
public:
AtDarkPortalAzerothTrigger(PlayerbotAI* botAI) : Trigger(botAI, "at dark portal azeroth", 10) { }
bool IsActive() override;
};
class AtDarkPortalOutlandTrigger : public Trigger
{
public:
AtDarkPortalOutlandTrigger(PlayerbotAI* botAI) : Trigger(botAI, "at dark portal outland", 10) { }
bool IsActive() override;
};
#endif

View File

@@ -0,0 +1,325 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_TRIGGERCONTEXT_H
#define _PLAYERBOT_TRIGGERCONTEXT_H
#include "GenericTriggers.h"
#include "CureTriggers.h"
#include "GuildTriggers.h"
#include "LootTriggers.h"
#include "LfgTriggers.h"
#include "PvpTriggers.h"
#include "RpgTriggers.h"
#include "RtiTriggers.h"
#include "StuckTriggers.h"
#include "TravelTriggers.h"
#include "NamedObjectContext.h"
class PlayerbotAI;
class TriggerContext : public NamedObjectContext<Trigger>
{
public:
TriggerContext()
{
creators["return"] = &TriggerContext::_return;
creators["sit"] = &TriggerContext::sit;
creators["collision"] = &TriggerContext::collision;
creators["timer"] = &TriggerContext::Timer;
creators["random"] = &TriggerContext::Random;
creators["seldom"] = &TriggerContext::seldom;
creators["often"] = &TriggerContext::often;
creators["target critical health"] = &TriggerContext::TargetCriticalHealth;
creators["critical health"] = &TriggerContext::CriticalHealth;
creators["low health"] = &TriggerContext::LowHealth;
creators["medium health"] = &TriggerContext::MediumHealth;
creators["almost full health"] = &TriggerContext::AlmostFullHealth;
creators["low mana"] = &TriggerContext::LowMana;
creators["medium mana"] = &TriggerContext::MediumMana;
creators["high mana"] = &TriggerContext::HighMana;
creators["almost full mana"] = &TriggerContext::AlmostFullMana;
creators["party member critical health"] = &TriggerContext::PartyMemberCriticalHealth;
creators["party member low health"] = &TriggerContext::PartyMemberLowHealth;
creators["party member medium health"] = &TriggerContext::PartyMemberMediumHealth;
creators["party member almost full health"] = &TriggerContext::PartyMemberAlmostFullHealth;
creators["protect party member"] = &TriggerContext::protect_party_member;
creators["light rage available"] = &TriggerContext::LightRageAvailable;
creators["medium rage available"] = &TriggerContext::MediumRageAvailable;
creators["high rage available"] = &TriggerContext::HighRageAvailable;
creators["light energy available"] = &TriggerContext::LightEnergyAvailable;
creators["medium energy available"] = &TriggerContext::MediumEnergyAvailable;
creators["high energy available"] = &TriggerContext::HighEnergyAvailable;
creators["loot available"] = &TriggerContext::LootAvailable;
creators["no attackers"] = &TriggerContext::NoAttackers;
creators["no target"] = &TriggerContext::NoTarget;
creators["target in sight"] = &TriggerContext::TargetInSight;
creators["not dps target active"] = &TriggerContext::not_dps_target_active;
creators["not dps aoe target active"] = &TriggerContext::not_dps_aoe_target_active;
creators["has nearest adds"] = &TriggerContext::has_nearest_adds;
creators["enemy player inear"] = &TriggerContext::enemy_player_near;
creators["tank assist"] = &TriggerContext::TankAssist;
creators["lose aggro"] = &TriggerContext::LoseAggro;
creators["has aggro"] = &TriggerContext::HasAggro;
creators["light aoe"] = &TriggerContext::LightAoe;
creators["medium aoe"] = &TriggerContext::MediumAoe;
creators["high aoe"] = &TriggerContext::HighAoe;
creators["enemy out of melee"] = &TriggerContext::EnemyOutOfMelee;
creators["enemy out of spell"] = &TriggerContext::EnemyOutOfSpell;
creators["enemy too close for spell"] = &TriggerContext::enemy_too_close_for_spell;
creators["enemy too close for shoot"] = &TriggerContext::enemy_too_close_for_shoot;
creators["enemy too close for melee"] = &TriggerContext::enemy_too_close_for_melee;
creators["enemy is close"] = &TriggerContext::enemy_is_close;
creators["party member to heal out of spell range"] = &TriggerContext::party_member_to_heal_out_of_spell_range;
creators["combo points available"] = &TriggerContext::ComboPointsAvailable;
creators["medium threat"] = &TriggerContext::MediumThreat;
creators["dead"] = &TriggerContext::Dead;
creators["corpse near"] = &TriggerContext::corpse_near;
creators["party member dead"] = &TriggerContext::PartyMemberDead;
creators["no pet"] = &TriggerContext::no_pet;
creators["has attackers"] = &TriggerContext::has_attackers;
creators["no possible targets"] = &TriggerContext::no_possible_targets;
creators["possible adds"] = &TriggerContext::possible_adds;
creators["no drink"] = &TriggerContext::no_drink;
creators["no food"] = &TriggerContext::no_food;
creators["panic"] = &TriggerContext::panic;
creators["outnumbered"] = &TriggerContext::outnumbered;
creators["behind target"] = &TriggerContext::behind_target;
creators["not behind target"] = &TriggerContext::not_behind_target;
creators["not facing target"] = &TriggerContext::not_facing_target;
creators["far from master"] = &TriggerContext::far_from_master;
creators["far from loot target"] = &TriggerContext::far_from_loot_target;
creators["can loot"] = &TriggerContext::can_loot;
creators["swimming"] = &TriggerContext::swimming;
creators["target changed"] = &TriggerContext::target_changed;
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["invalid target"] = &TriggerContext::invalid_target;
creators["lfg proposal active"] = &TriggerContext::lfg_proposal_active;
creators["unknown dungeon"] = &TriggerContext::unknown_dungeon;
creators["random bot update"] = &TriggerContext::random_bot_update_trigger;
creators["no non bot players around"] = &TriggerContext::no_non_bot_players_around;
creators["new player nearby"] = &TriggerContext::new_player_nearby;
creators["no rpg target"] = &TriggerContext::no_rpg_target;
creators["has rpg target"] = &TriggerContext::has_rpg_target;
creators["far from rpg target"] = &TriggerContext::far_from_rpg_target;
creators["near rpg target"] = &TriggerContext::near_rpg_target;
creators["no travel target"] = &TriggerContext::no_travel_target;
creators["far from travel target"] = &TriggerContext::far_from_travel_target;
creators["no rti target"] = &TriggerContext::no_rti;
creators["give food"] = &TriggerContext::give_food;
creators["give water"] = &TriggerContext::give_water;
creators["bg waiting"] = &TriggerContext::bg_waiting;
creators["bg active"] = &TriggerContext::bg_active;
creators["bg invite active"] = &TriggerContext::bg_invite_active;
creators["player has no flag"] = &TriggerContext::player_has_no_flag;
creators["player has flag"] = &TriggerContext::player_has_flag;
creators["team has flag"] = &TriggerContext::team_has_flag;
creators["enemy team has flag"] = &TriggerContext::enemy_team_has_flag;
creators["enemy flagcarrier near"] = &TriggerContext::enemy_flagcarrier_near;
creators["in Battleground"] = &TriggerContext::player_is_in_BATTLEGROUND;
creators["in Battleground without flag"] = &TriggerContext::player_is_in_BATTLEGROUND_no_flag;
creators["wants in bg"] = &TriggerContext::player_wants_in_bg;
creators["mounted"] = &TriggerContext::mounted;
// move to/enter dark portal if near
creators["near dark portal"] = &TriggerContext::near_dark_portal;
creators["at dark portal azeroth"] = &TriggerContext::at_dark_portal_azeroth;
creators["at dark portal outland"] = &TriggerContext::at_dark_portal_outland;
creators["vehicle near"] = &TriggerContext::vehicle_near;
creators["in vehicle"] = &TriggerContext::in_vehicle;
creators["need world buff"] = &TriggerContext::need_world_buff;
creators["falling"] = &TriggerContext::falling;
creators["falling far"] = &TriggerContext::falling_far;
creators["move stuck"] = &TriggerContext::move_stuck;
creators["move long stuck"] = &TriggerContext::move_long_stuck;
creators["combat stuck"] = &TriggerContext::combat_stuck;
creators["combat long stuck"] = &TriggerContext::combat_long_stuck;
creators["petition signed"] = &TriggerContext::petition_signed;
creators["buy tabard"] = &TriggerContext::buy_tabard;
creators["leave large guild"] = &TriggerContext::leave_large_guild;
creators["rpg"] = &TriggerContext::rpg;
creators["rpg taxi"] = &TriggerContext::rpg_taxi;
creators["rpg discover"] = &TriggerContext::rpg_discover;
creators["rpg start quest"] = &TriggerContext::rpg_start_quest;
creators["rpg end quest"] = &TriggerContext::rpg_end_quest;
creators["rpg buy"] = &TriggerContext::rpg_buy;
creators["rpg sell"] = &TriggerContext::rpg_sell;
creators["rpg repair"] = &TriggerContext::rpg_repair;
creators["rpg train"] = &TriggerContext::rpg_train;
creators["rpg heal"] = &TriggerContext::rpg_heal;
creators["rpg home bind"] = &TriggerContext::rpg_home_bind;
creators["rpg queue bg"] = &TriggerContext::rpg_queue_bg;
creators["rpg buy petition"] = &TriggerContext::rpg_buy_petition;
creators["rpg use"] = &TriggerContext::rpg_use;
creators["rpg spell"] = &TriggerContext::rpg_spell;
creators["rpg craft"] = &TriggerContext::rpg_craft;
creators["rpg trade useful"] = &TriggerContext::rpg_trade_useful;
creators["rpg duel"] = &TriggerContext::rpg_duel;
}
private:
static Trigger* give_food(PlayerbotAI* botAI) { return new GiveFoodTrigger(botAI); }
static Trigger* give_water(PlayerbotAI* botAI) { return new GiveWaterTrigger(botAI); }
static Trigger* no_rti(PlayerbotAI* botAI) { return new NoRtiTrigger(botAI); }
static Trigger* _return(PlayerbotAI* botAI) { return new ReturnTrigger(botAI); }
static Trigger* sit(PlayerbotAI* botAI) { return new SitTrigger(botAI); }
static Trigger* far_from_rpg_target(PlayerbotAI* botAI) { return new FarFromRpgTargetTrigger(botAI); }
static Trigger* near_rpg_target(PlayerbotAI* botAI) { return new NearRpgTargetTrigger(botAI); }
static Trigger* far_from_travel_target(PlayerbotAI* botAI) { return new FarFromTravelTargetTrigger(botAI); }
static Trigger* no_travel_target(PlayerbotAI* botAI) { return new NoTravelTargetTrigger(botAI); }
static Trigger* no_rpg_target(PlayerbotAI* botAI) { return new NoRpgTargetTrigger(botAI); }
static Trigger* has_rpg_target(PlayerbotAI* botAI) { return new HasRpgTargetTrigger(botAI); }
static Trigger* collision(PlayerbotAI* botAI) { return new CollisionTrigger(botAI); }
static Trigger* lfg_proposal_active(PlayerbotAI* botAI) { return new LfgProposalActiveTrigger(botAI); }
static Trigger* unknown_dungeon(PlayerbotAI* botAI) { return new UnknownDungeonTrigger(botAI); }
static Trigger* invalid_target(PlayerbotAI* botAI) { return new InvalidTargetTrigger(botAI); }
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* 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); }
static Trigger* possible_adds(PlayerbotAI* botAI) { return new PossibleAddsTrigger(botAI); }
static Trigger* can_loot(PlayerbotAI* botAI) { return new CanLootTrigger(botAI); }
static Trigger* far_from_loot_target(PlayerbotAI* botAI) { return new FarFromCurrentLootTrigger(botAI); }
static Trigger* far_from_master(PlayerbotAI* botAI) { return new FarFromMasterTrigger(botAI); }
static Trigger* behind_target(PlayerbotAI* botAI) { return new IsBehindTargetTrigger(botAI); }
static Trigger* not_behind_target(PlayerbotAI* botAI) { return new IsNotBehindTargetTrigger(botAI); }
static Trigger* not_facing_target(PlayerbotAI* botAI) { return new IsNotFacingTargetTrigger(botAI); }
static Trigger* panic(PlayerbotAI* botAI) { return new PanicTrigger(botAI); }
static Trigger* outnumbered(PlayerbotAI* botAI) { return new OutNumberedTrigger(botAI); }
static Trigger* no_drink(PlayerbotAI* botAI) { return new NoDrinkTrigger(botAI); }
static Trigger* no_food(PlayerbotAI* botAI) { return new NoFoodTrigger(botAI); }
static Trigger* LightAoe(PlayerbotAI* botAI) { return new LightAoeTrigger(botAI); }
static Trigger* MediumAoe(PlayerbotAI* botAI) { return new MediumAoeTrigger(botAI); }
static Trigger* HighAoe(PlayerbotAI* botAI) { return new HighAoeTrigger(botAI); }
static Trigger* LoseAggro(PlayerbotAI* botAI) { return new LoseAggroTrigger(botAI); }
static Trigger* HasAggro(PlayerbotAI* botAI) { return new HasAggroTrigger(botAI); }
static Trigger* LowHealth(PlayerbotAI* botAI) { return new LowHealthTrigger(botAI); }
static Trigger* MediumHealth(PlayerbotAI* botAI) { return new MediumHealthTrigger(botAI); }
static Trigger* AlmostFullHealth(PlayerbotAI* botAI) { return new AlmostFullHealthTrigger(botAI); }
static Trigger* CriticalHealth(PlayerbotAI* botAI) { return new CriticalHealthTrigger(botAI); }
static Trigger* TargetCriticalHealth(PlayerbotAI* botAI) { return new TargetCriticalHealthTrigger(botAI); }
static Trigger* LowMana(PlayerbotAI* botAI) { return new LowManaTrigger(botAI); }
static Trigger* MediumMana(PlayerbotAI* botAI) { return new MediumManaTrigger(botAI); }
static Trigger* HighMana(PlayerbotAI* botAI) { return new HighManaTrigger(botAI); }
static Trigger* AlmostFullMana(PlayerbotAI* botAI) { return new AlmostFullManaTrigger(botAI); }
static Trigger* LightRageAvailable(PlayerbotAI* botAI) { return new LightRageAvailableTrigger(botAI); }
static Trigger* MediumRageAvailable(PlayerbotAI* botAI) { return new MediumRageAvailableTrigger(botAI); }
static Trigger* HighRageAvailable(PlayerbotAI* botAI) { return new HighRageAvailableTrigger(botAI); }
static Trigger* LightEnergyAvailable(PlayerbotAI* botAI) { return new LightEnergyAvailableTrigger(botAI); }
static Trigger* MediumEnergyAvailable(PlayerbotAI* botAI) { return new MediumEnergyAvailableTrigger(botAI); }
static Trigger* HighEnergyAvailable(PlayerbotAI* botAI) { return new HighEnergyAvailableTrigger(botAI); }
static Trigger* LootAvailable(PlayerbotAI* botAI) { return new LootAvailableTrigger(botAI); }
static Trigger* NoAttackers(PlayerbotAI* botAI) { return new NoAttackersTrigger(botAI); }
static Trigger* TankAssist(PlayerbotAI* botAI) { return new TankAssistTrigger(botAI); }
static Trigger* Timer(PlayerbotAI* botAI) { return new TimerTrigger(botAI); }
static Trigger* NoTarget(PlayerbotAI* botAI) { return new NoTargetTrigger(botAI); }
static Trigger* TargetInSight(PlayerbotAI* botAI) { return new TargetInSightTrigger(botAI); }
static Trigger* not_dps_target_active(PlayerbotAI* botAI) { return new NotDpsTargetActiveTrigger(botAI); }
static Trigger* not_dps_aoe_target_active(PlayerbotAI* botAI) { return new NotDpsAoeTargetActiveTrigger(botAI); }
static Trigger* has_nearest_adds(PlayerbotAI* botAI) { return new HasNearestAddsTrigger(botAI); }
static Trigger* enemy_player_near(PlayerbotAI* botAI) { return new EnemyPlayerNear(botAI); }
static Trigger* Random(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "random", 20); }
static Trigger* seldom(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "seldom", 300); }
static Trigger* often(PlayerbotAI* botAI) { return new RandomTrigger(botAI, "often", 5); }
static Trigger* EnemyOutOfMelee(PlayerbotAI* botAI) { return new EnemyOutOfMeleeTrigger(botAI); }
static Trigger* EnemyOutOfSpell(PlayerbotAI* botAI) { return new EnemyOutOfSpellRangeTrigger(botAI); }
static Trigger* enemy_too_close_for_spell(PlayerbotAI* botAI) { return new EnemyTooCloseForSpellTrigger(botAI); }
static Trigger* enemy_too_close_for_shoot(PlayerbotAI* botAI) { return new EnemyTooCloseForShootTrigger(botAI); }
static Trigger* enemy_too_close_for_melee(PlayerbotAI* botAI) { return new EnemyTooCloseForMeleeTrigger(botAI); }
static Trigger* enemy_is_close(PlayerbotAI* botAI) { return new EnemyIsCloseTrigger(botAI); }
static Trigger* party_member_to_heal_out_of_spell_range(PlayerbotAI* botAI) { return new PartyMemberToHealOutOfSpellRangeTrigger(botAI); }
static Trigger* ComboPointsAvailable(PlayerbotAI* botAI) { return new ComboPointsAvailableTrigger(botAI); }
static Trigger* MediumThreat(PlayerbotAI* botAI) { return new MediumThreatTrigger(botAI); }
static Trigger* Dead(PlayerbotAI* botAI) { return new DeadTrigger(botAI); }
static Trigger* corpse_near(PlayerbotAI* botAI) { return new CorpseNearTrigger(botAI); }
static Trigger* PartyMemberDead(PlayerbotAI* botAI) { return new PartyMemberDeadTrigger(botAI); }
static Trigger* PartyMemberLowHealth(PlayerbotAI* botAI) { return new PartyMemberLowHealthTrigger(botAI); }
static Trigger* PartyMemberMediumHealth(PlayerbotAI* botAI) { return new PartyMemberMediumHealthTrigger(botAI); }
static Trigger* PartyMemberAlmostFullHealth(PlayerbotAI* botAI) { return new PartyMemberAlmostFullHealthTrigger(botAI); }
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_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); }
static Trigger* new_player_nearby(PlayerbotAI* botAI) { return new NewPlayerNearbyTrigger(botAI); }
static Trigger* bg_waiting(PlayerbotAI* botAI) { return new BgWaitingTrigger(botAI); }
static Trigger* bg_active(PlayerbotAI* botAI) { return new BgActiveTrigger(botAI); }
static Trigger* bg_invite_active(PlayerbotAI* botAI) { return new BgInviteActiveTrigger(botAI); }
static Trigger* player_has_no_flag(PlayerbotAI* botAI) { return new PlayerHasNoFlag(botAI); }
static Trigger* player_has_flag(PlayerbotAI* botAI) { return new PlayerHasFlag(botAI); }
static Trigger* team_has_flag(PlayerbotAI* botAI) { return new TeamHasFlag(botAI); }
static Trigger* enemy_team_has_flag(PlayerbotAI* botAI) { return new EnemyTeamHasFlag(botAI); }
static Trigger* enemy_flagcarrier_near(PlayerbotAI* botAI) { return new EnemyFlagCarrierNear(botAI); }
static Trigger* player_is_in_BATTLEGROUND(PlayerbotAI* botAI) { return new PlayerIsInBattleground(botAI); }
static Trigger* player_is_in_BATTLEGROUND_no_flag(PlayerbotAI* botAI) { return new PlayerIsInBattlegroundWithoutFlag(botAI); }
static Trigger* mounted(PlayerbotAI* botAI) { return new IsMountedTrigger(botAI); }
static Trigger* at_dark_portal_outland(PlayerbotAI* botAI) { return new AtDarkPortalOutlandTrigger(botAI); }
static Trigger* at_dark_portal_azeroth(PlayerbotAI* botAI) { return new AtDarkPortalAzerothTrigger(botAI); }
static Trigger* in_vehicle(PlayerbotAI* botAI) { return new InVehicleTrigger(botAI); }
static Trigger* vehicle_near(PlayerbotAI* botAI) { return new VehicleNearTrigger(botAI); }
static Trigger* near_dark_portal(PlayerbotAI* botAI) { return new NearDarkPortalTrigger(botAI); }
static Trigger* need_world_buff(PlayerbotAI* botAI) { return new NeedWorldBuffTrigger(botAI); }
static Trigger* falling(PlayerbotAI* botAI) { return new IsFallingTrigger(botAI); }
static Trigger* falling_far(PlayerbotAI* botAI) { return new IsFallingFarTrigger(botAI); }
static Trigger* move_stuck(PlayerbotAI* botAI) { return new MoveStuckTrigger(botAI); }
static Trigger* move_long_stuck(PlayerbotAI* botAI) { return new MoveLongStuckTrigger(botAI); }
static Trigger* combat_stuck(PlayerbotAI* botAI) { return new CombatStuckTrigger(botAI); }
static Trigger* combat_long_stuck(PlayerbotAI* botAI) { return new CombatLongStuckTrigger(botAI); }
static Trigger* player_wants_in_bg(PlayerbotAI* botAI) { return new PlayerWantsInBattlegroundTrigger(botAI); }
static Trigger* petition_signed(PlayerbotAI* botAI) { return new PetitionTurnInTrigger(botAI); }
static Trigger* buy_tabard(PlayerbotAI* botAI) { return new BuyTabardTrigger(botAI); }
static Trigger* leave_large_guild(PlayerbotAI* botAI) { return new LeaveLargeGuildTrigger(botAI); }
static Trigger* rpg(PlayerbotAI* botAI) { return new RpgTrigger(botAI); }
static Trigger* rpg_taxi(PlayerbotAI* botAI) { return new RpgTaxiTrigger(botAI); }
static Trigger* rpg_discover(PlayerbotAI* botAI) { return new RpgDiscoverTrigger(botAI); }
static Trigger* rpg_start_quest(PlayerbotAI* botAI) { return new RpgStartQuestTrigger(botAI); }
static Trigger* rpg_end_quest(PlayerbotAI* botAI) { return new RpgEndQuestTrigger(botAI); }
static Trigger* rpg_buy(PlayerbotAI* botAI) { return new RpgBuyTrigger(botAI); }
static Trigger* rpg_sell(PlayerbotAI* botAI) { return new RpgSellTrigger(botAI); }
static Trigger* rpg_repair(PlayerbotAI* botAI) { return new RpgRepairTrigger(botAI); }
static Trigger* rpg_train(PlayerbotAI* botAI) { return new RpgTrainTrigger(botAI); }
static Trigger* rpg_heal(PlayerbotAI* botAI) { return new RpgHealTrigger(botAI); }
static Trigger* rpg_home_bind(PlayerbotAI* botAI) { return new RpgHomeBindTrigger(botAI); }
static Trigger* rpg_queue_bg(PlayerbotAI* botAI) { return new RpgQueueBGTrigger(botAI); }
static Trigger* rpg_buy_petition(PlayerbotAI* botAI) { return new RpgBuyPetitionTrigger(botAI); }
static Trigger* rpg_use(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); }
static Trigger* rpg_spell(PlayerbotAI* botAI) { return new RpgUseTrigger(botAI); }
static Trigger* rpg_craft(PlayerbotAI* botAI) { return new RpgCraftTrigger(botAI); }
static Trigger* rpg_trade_useful(PlayerbotAI* botAI) { return new RpgTradeUsefulTrigger(botAI); }
static Trigger* rpg_duel(PlayerbotAI* botAI) { return new RpgDuelTrigger(botAI); }
};
#endif

View File

@@ -0,0 +1,66 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "WithinAreaTrigger.h"
#include "LastMovementValue.h"
#include "Playerbots.h"
bool WithinAreaTrigger::IsActive()
{
LastMovement& movement = context->GetValue<LastMovement&>("last area trigger")->Get();
if (!movement.lastAreaTrigger)
return false;
AreaTrigger const* at = sObjectMgr->GetAreaTrigger(movement.lastAreaTrigger);
if (!at)
return false;
if (!sObjectMgr->GetAreaTriggerTeleport(movement.lastAreaTrigger))
return false;
return IsPointInAreaTriggerZone(at, bot->GetMapId(), bot->GetPositionX(), bot->GetPositionY(), bot->GetPositionZ(), 0.5f);
}
bool WithinAreaTrigger::IsPointInAreaTriggerZone(AreaTrigger const* atEntry, uint32 mapid, float x, float y, float z, float delta)
{
if (mapid != atEntry->map)
return false;
if (atEntry->radius > 0)
{
// if we have radius check it
float dist2 = (x - atEntry->x) * (x - atEntry->x) + (y - atEntry->y) * (y - atEntry->y) + (z - atEntry->z) * (z - atEntry->z);
if (dist2 > (atEntry->radius + delta) * (atEntry->radius + delta))
return false;
}
else
{
// we have only extent
// rotate the players position instead of rotating the whole cube, that way we can make a simplified
// is-in-cube check and we have to calculate only one point instead of 4
// 2PI = 360, keep in mind that ingame orientation is counter-clockwise
double rotation = 2 * M_PI - atEntry->orientation;
double sinVal = sin(rotation);
double cosVal = cos(rotation);
float playerBoxDistX = x - atEntry->x;
float playerBoxDistY = y - atEntry->y;
float rotPlayerX = float(atEntry->x + playerBoxDistX * cosVal - playerBoxDistY * sinVal);
float rotPlayerY = float(atEntry->y + playerBoxDistY * cosVal + playerBoxDistX * sinVal);
// box edges are parallel to coordiante axis, so we can treat every dimension independently :D
float dz = z - atEntry->z;
float dx = rotPlayerX - atEntry->x;
float dy = rotPlayerY - atEntry->y;
if ((fabs(dx) > atEntry->x / 2 + delta) || (fabs(dy) > atEntry->y / 2 + delta) || (fabs(dz) > atEntry->z / 2 + delta))
{
return false;
}
}
return true;
}

View File

@@ -0,0 +1,25 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_WITHINAREATRIGGER_H
#define _PLAYERBOT_WITHINAREATRIGGER_H
#include "Trigger.h"
class PlayerbotAI;
struct AreaTrigger;
class WithinAreaTrigger : public Trigger
{
public:
WithinAreaTrigger(PlayerbotAI* botAI) : Trigger(botAI, "within area trigger") { }
bool IsActive() override;
private:
bool IsPointInAreaTriggerZone(AreaTrigger const* atEntry, uint32 mapid, float x, float y, float z, float delta);
};
#endif

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#include "WorldPacketTrigger.h"
#include "Playerbots.h"
void WorldPacketTrigger::ExternalEvent(WorldPacket& revData, Player* eventOwner)
{
packet = revData;
owner = eventOwner;
triggered = true;
}
Event WorldPacketTrigger::Check()
{
if (!triggered)
return Event();
return Event(getName(), packet, owner);
}
void WorldPacketTrigger::Reset()
{
triggered = false;
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_WORLDPACKETTRIGGER_H
#define _PLAYERBOT_WORLDPACKETTRIGGER_H
#include "Trigger.h"
class Event;
class Player;
class PlayerbotAI;
class WorldPacket;
class WorldPacketTrigger : public Trigger
{
public:
WorldPacketTrigger(PlayerbotAI* botAI, std::string const command) : Trigger(botAI, command), triggered(false) { }
void ExternalEvent(WorldPacket& packet, Player* owner = nullptr) override;
Event Check() override;
void Reset() override;
private:
WorldPacket packet;
bool triggered;
Player* owner;
};
#endif

View File

@@ -0,0 +1,114 @@
/*
* Copyright (C) 2016+ AzerothCore <www.azerothcore.org>, released under GNU GPL v2 license, you may redistribute it and/or modify it under version 2 of the License, or (at your option), any later version.
*/
#ifndef _PLAYERBOT_WORLDPACKETTRIGGERCONTEXT_H
#define _PLAYERBOT_WORLDPACKETTRIGGERCONTEXT_H
#include "WorldPacketTrigger.h"
#include "WithinAreaTrigger.h"
#include "NamedObjectContext.h"
class WorldPacketTriggerContext : public NamedObjectContext<Trigger>
{
public:
WorldPacketTriggerContext()
{
creators["gossip hello"] = &WorldPacketTriggerContext::gossip_hello;
creators["group invite"] = &WorldPacketTriggerContext::group_invite;
creators["group set leader"] = &WorldPacketTriggerContext::group_set_leader;
creators["not enough money"] = &WorldPacketTriggerContext::no_money;
creators["not enough reputation"] = &WorldPacketTriggerContext::no_reputation;
creators["cannot equip"] = &WorldPacketTriggerContext::cannot_equip;
creators["use game object"] = &WorldPacketTriggerContext::use_game_object;
creators["complete quest"] = &WorldPacketTriggerContext::complete_quest;
creators["accept quest"] = &WorldPacketTriggerContext::accept_quest;
creators["quest share"] = &WorldPacketTriggerContext::quest_share;
creators["loot roll"] = &WorldPacketTriggerContext::loot_roll;
creators["resurrect request"] = &WorldPacketTriggerContext::resurrect_request;
creators["area trigger"] = &WorldPacketTriggerContext::area_trigger;
creators["within area trigger"] = &WorldPacketTriggerContext::within_area_trigger;
creators["check mount state"] = &WorldPacketTriggerContext::check_mount_state;
creators["activate taxi"] = &WorldPacketTriggerContext::taxi;
creators["trade status"] = &WorldPacketTriggerContext::trade_status;
creators["loot response"] = &WorldPacketTriggerContext::loot_response;
creators["out of react range"] = &WorldPacketTriggerContext::out_of_react_range;
creators["quest objective completed"] = &WorldPacketTriggerContext::quest_objective_completed;
creators["item push result"] = &WorldPacketTriggerContext::item_push_result;
creators["party command"] = &WorldPacketTriggerContext::party_command;
creators["taxi done"] = &WorldPacketTriggerContext::taxi_done;
creators["cast failed"] = &WorldPacketTriggerContext::cast_failed;
creators["duel requested"] = &WorldPacketTriggerContext::duel_requested;
creators["ready check"] = &WorldPacketTriggerContext::ready_check;
creators["ready check finished"] = &WorldPacketTriggerContext::ready_check_finished;
creators["uninvite"] = &WorldPacketTriggerContext::uninvite;
creators["uninvite guid"] = &WorldPacketTriggerContext::uninvite_guid;
creators["lfg join"] = &WorldPacketTriggerContext::lfg_update;
creators["lfg proposal"] = &WorldPacketTriggerContext::lfg_proposal;
creators["lfg role check"] = &WorldPacketTriggerContext::lfg_role_check;
creators["lfg leave"] = &WorldPacketTriggerContext::lfg_leave;
creators["guild invite"] = &WorldPacketTriggerContext::guild_invite;
creators["petition offer"] = &WorldPacketTriggerContext::petition_offer;
creators["lfg teleport"] = &WorldPacketTriggerContext::lfg_teleport;
creators["inventory change failure"] = &WorldPacketTriggerContext::inventory_change_failure;
creators["bg status"] = &WorldPacketTriggerContext::bg_status;
creators["levelup"] = &WorldPacketTriggerContext::levelup;
creators["xpgain"] = &WorldPacketTriggerContext::xpgain;
creators["see spell"] = &WorldPacketTriggerContext::seespell;
creators["release spirit"] = &WorldPacketTriggerContext::release_spirit;
creators["revive from corpse"] = &WorldPacketTriggerContext::revive_from_corpse;
creators["receive emote"] = &WorldPacketTriggerContext::receive_emote;
creators["receive text emote"] = &WorldPacketTriggerContext::receive_text_emote;
creators["arena team invite"] = &WorldPacketTriggerContext::arena_team_invite;
}
private:
static Trigger* inventory_change_failure(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "inventory change failure"); }
static Trigger* guild_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "guild invite"); }
static Trigger* lfg_teleport(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg teleport"); }
static Trigger* lfg_leave(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg leave"); }
static Trigger* lfg_proposal(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg proposal"); }
static Trigger* lfg_role_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg role check"); }
static Trigger* lfg_update(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "lfg join"); }
static Trigger* uninvite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite"); }
static Trigger* uninvite_guid(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "uninvite guid"); }
static Trigger* ready_check_finished(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check finished"); }
static Trigger* ready_check(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "ready check"); }
static Trigger* duel_requested(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "duel requested"); }
static Trigger* cast_failed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cast failed"); }
static Trigger* taxi_done(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "taxi done"); }
static Trigger* party_command(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "party command"); }
static Trigger* item_push_result(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "item push result"); }
static Trigger* quest_objective_completed(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "quest objective completed"); }
static Trigger* out_of_react_range(PlayerbotAI* botAI) { return new OutOfReactRangeTrigger(botAI); }
static Trigger* loot_response(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot response"); }
static Trigger* trade_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "trade status"); }
static Trigger* cannot_equip(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "cannot equip"); }
static Trigger* check_mount_state(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "check mount state"); }
static Trigger* area_trigger(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "area trigger"); }
static Trigger* within_area_trigger(PlayerbotAI* botAI) { return new WithinAreaTrigger(botAI); }
static Trigger* resurrect_request(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "resurrect request"); }
static Trigger* gossip_hello(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "gossip hello"); }
static Trigger* group_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group invite"); }
static Trigger* group_set_leader(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "group set leader"); }
static Trigger* no_money(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough money"); }
static Trigger* no_reputation(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "not enough reputation"); }
static Trigger* use_game_object(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "use game object"); }
static Trigger* complete_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "complete quest"); }
static Trigger* accept_quest(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "accept quest"); }
static Trigger* quest_share(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "quest share"); }
static Trigger* loot_roll(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "loot roll"); }
static Trigger* taxi(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "activate taxi"); }
static Trigger* bg_status(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "bg status"); }
static Trigger* levelup(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "levelup"); }
static Trigger* xpgain(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "xpgain"); }
static Trigger* petition_offer(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "petition offer"); }
static Trigger* seespell(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "see spell"); }
static Trigger* release_spirit(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "release spirit"); }
static Trigger* revive_from_corpse(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "revive from corpse"); }
static Trigger* receive_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive emote"); }
static Trigger* receive_text_emote(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "receive text emote"); }
static Trigger* arena_team_invite(PlayerbotAI* botAI) { return new WorldPacketTrigger(botAI, "arena team invite"); }
};
#endif