mirror of
https://github.com/mod-playerbots/mod-playerbots
synced 2025-11-29 15:58:20 +08:00
Improve class spell and use trinket
This commit is contained in:
@@ -225,7 +225,10 @@ bool StatsCollector::SpecialSpellFilter(uint32 spellId) {
|
||||
if (type_ != CollectorType::SPELL_HEAL)
|
||||
stats[STATS_TYPE_CRIT] += 50;
|
||||
return true;
|
||||
break;
|
||||
case 59620:
|
||||
if (type_ == CollectorType::MELEE)
|
||||
stats[STATS_TYPE_ATTACK_POWER] += 120;
|
||||
return true;
|
||||
case 67702: // Death's Verdict
|
||||
stats[STATS_TYPE_ATTACK_POWER] += 225;
|
||||
return true;
|
||||
@@ -493,6 +496,13 @@ void StatsCollector::HandleApplyAura(const SpellEffectInfo& effectInfo, float mu
|
||||
case SPELL_AURA_MOD_INCREASE_HEALTH:
|
||||
stats[STATS_TYPE_STAMINA] += val * multiplier / 15;
|
||||
break;
|
||||
case SPELL_AURA_SCHOOL_ABSORB:
|
||||
{
|
||||
int32 schoolType = effectInfo.MiscValue;
|
||||
if (schoolType & SPELL_SCHOOL_MASK_NORMAL)
|
||||
stats[STATS_TYPE_STAMINA] += val * multiplier / 15;
|
||||
break;
|
||||
}
|
||||
case SPELL_AURA_MOD_ATTACK_POWER:
|
||||
stats[STATS_TYPE_ATTACK_POWER] += val * multiplier;
|
||||
break;
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "AiFactory.h"
|
||||
#include "DBCStores.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "ObjectMgr.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "SharedDefines.h"
|
||||
@@ -231,7 +232,8 @@ void StatsWeightCalculator::GenerateBasicWeights(Player* player)
|
||||
stats_weights_[STATS_TYPE_EXPERTISE] += 2.0f;
|
||||
stats_weights_[STATS_TYPE_MELEE_DPS] += 5.2f;
|
||||
}
|
||||
else if (cls == CLASS_WARLOCK || cls == CLASS_MAGE ||
|
||||
else if (cls == CLASS_WARLOCK ||
|
||||
cls == CLASS_MAGE ||
|
||||
(cls == CLASS_PRIEST && tab == PRIEST_TAB_SHADOW) || // shadow
|
||||
(cls == CLASS_SHAMAN && tab == SHAMAN_TAB_ELEMENTAL) || // element
|
||||
(cls == CLASS_DRUID && tab == DRUID_TAB_BALANCE)) // balance
|
||||
@@ -454,6 +456,16 @@ void StatsWeightCalculator::CalculateItemTypePenalty(ItemTemplate const* proto)
|
||||
{
|
||||
weight_ *= 0.1;
|
||||
}
|
||||
if (cls == CLASS_ROGUE && player_->HasAura(13964)
|
||||
&& (proto->SubClass == ITEM_SUBCLASS_WEAPON_SWORD || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
if (cls == CLASS_WARRIOR && player_->HasAura(12785)
|
||||
&& (proto->SubClass == ITEM_SUBCLASS_WEAPON_THROWN || proto->SubClass == ITEM_SUBCLASS_WEAPON_AXE2))
|
||||
{
|
||||
weight_ *= 1.1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -154,6 +154,9 @@ public:
|
||||
creators["give water"] = &ActionContext::give_water;
|
||||
creators["mount"] = &ActionContext::mount;
|
||||
creators["war stomp"] = &ActionContext::war_stomp;
|
||||
creators["blood fury"] = &ActionContext::blood_fury;
|
||||
creators["berserking"] = &ActionContext::berserking;
|
||||
creators["use trinket"] = &ActionContext::use_trinket;
|
||||
creators["auto talents"] = &ActionContext::auto_talents;
|
||||
creators["auto learn spell"] = &ActionContext::auto_learn_spell;
|
||||
creators["auto share quest"] = &ActionContext::auto_share_quest;
|
||||
@@ -324,6 +327,9 @@ private:
|
||||
static Action* try_emergency(PlayerbotAI* botAI) { return new TryEmergencyAction(botAI); }
|
||||
static Action* mount(PlayerbotAI* botAI) { return new CastSpellAction(botAI, "mount"); }
|
||||
static Action* war_stomp(PlayerbotAI* botAI) { return new CastWarStompAction(botAI); }
|
||||
static Action* blood_fury(PlayerbotAI* botAI) { return new CastBloodFuryAction(botAI); }
|
||||
static Action* berserking(PlayerbotAI* botAI) { return new CastBerserkingAction(botAI); }
|
||||
static Action* use_trinket(PlayerbotAI* botAI) { return new UseTrinketAction(botAI); }
|
||||
static Action* auto_talents(PlayerbotAI* botAI) { return new AutoSetTalentsAction(botAI); }
|
||||
static Action* auto_learn_spell(PlayerbotAI* botAI) { return new AutoLearnSpellAction(botAI); }
|
||||
static Action* auto_share_quest(PlayerbotAI* ai) { return new AutoShareQuestAction(ai); }
|
||||
|
||||
@@ -36,9 +36,9 @@ bool TogglePetSpellAutoCastAction::Execute(Event event)
|
||||
continue;
|
||||
|
||||
bool shouldApply = true;
|
||||
// imp's spell, felhunte's intelligence, ghoul's leap, cat stealth
|
||||
// imp's spell, felhunte's intelligence, cat stealth
|
||||
if (spellId == 4511 || spellId == 1742 || spellId == 54424 || spellId == 57564 || spellId == 57565 ||
|
||||
spellId == 57566 || spellId == 57567 || spellId == 47482 || spellId == 24450)
|
||||
spellId == 57566 || spellId == 57567 || spellId == 24450)
|
||||
{
|
||||
shouldApply = false;
|
||||
}
|
||||
@@ -72,7 +72,7 @@ bool PetAttackAction::Execute(Event event)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// pet->SetReactState(REACT_DEFENSIVE);
|
||||
pet->SetReactState(REACT_PASSIVE);
|
||||
pet->ClearUnitState(UNIT_STATE_FOLLOW);
|
||||
pet->AttackStop();
|
||||
pet->SetTarget(target->GetGUID());
|
||||
|
||||
@@ -6,8 +6,13 @@
|
||||
#include "GenericSpellActions.h"
|
||||
|
||||
#include "Event.h"
|
||||
#include "ItemTemplate.h"
|
||||
#include "ObjectDefines.h"
|
||||
#include "Opcodes.h"
|
||||
#include "Player.h"
|
||||
#include "Playerbots.h"
|
||||
#include "ServerFacade.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
CastSpellAction::CastSpellAction(PlayerbotAI* botAI, std::string const spell)
|
||||
: Action(botAI, spell), range(botAI->GetRange("spell")), spell(spell)
|
||||
@@ -124,11 +129,35 @@ bool CastSpellAction::isUseful()
|
||||
CastMeleeSpellAction::CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell) : CastSpellAction(botAI, spell)
|
||||
{
|
||||
range = ATTACK_DISTANCE;
|
||||
// Unit* target = AI_VALUE(Unit*, "current target");
|
||||
// if (target)
|
||||
// range = bot->GetMeleeRange(target);
|
||||
}
|
||||
|
||||
// range = target->GetCombinedCombatReach();
|
||||
bool CastMeleeSpellAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (!bot->IsWithinMeleeRange(target))
|
||||
return false;
|
||||
|
||||
return CastSpellAction::isUseful();
|
||||
}
|
||||
|
||||
CastMeleeDebuffSpellAction::CastMeleeDebuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool isOwner, float needLifeTime) : CastDebuffSpellAction(botAI, spell, isOwner, needLifeTime)
|
||||
{
|
||||
range = ATTACK_DISTANCE;
|
||||
}
|
||||
|
||||
bool CastMeleeDebuffSpellAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
if (!target)
|
||||
return false;
|
||||
|
||||
if (!bot->IsWithinMeleeRange(target))
|
||||
return false;
|
||||
|
||||
return CastDebuffSpellAction::isUseful();
|
||||
}
|
||||
|
||||
bool CastAuraSpellAction::isUseful()
|
||||
@@ -209,17 +238,7 @@ CastShootAction::CastShootAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "s
|
||||
|
||||
NextAction** CastSpellAction::getPrerequisites()
|
||||
{
|
||||
if (spell == "mount")
|
||||
return nullptr;
|
||||
|
||||
if (range > botAI->GetRange("spell"))
|
||||
return nullptr;
|
||||
else if (range > ATTACK_DISTANCE)
|
||||
return NextAction::merge(NextAction::array(0, new NextAction("reach spell"), nullptr),
|
||||
Action::getPrerequisites());
|
||||
else
|
||||
return NextAction::merge(NextAction::array(0, new NextAction("reach melee"), nullptr),
|
||||
Action::getPrerequisites());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Value<Unit*>* CastDebuffSpellOnAttackerAction::GetTargetValue()
|
||||
@@ -271,6 +290,70 @@ bool CastVehicleSpellAction::Execute(Event event)
|
||||
return botAI->CastVehicleSpell(spellId, GetTarget());
|
||||
}
|
||||
|
||||
bool UseTrinketAction::Execute(Event event)
|
||||
{
|
||||
Item* trinket1 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET1);
|
||||
|
||||
if (trinket1 && UseTrinket(trinket1))
|
||||
return true;
|
||||
|
||||
Item* trinket2 = bot->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_TRINKET2);
|
||||
|
||||
if (trinket2 && UseTrinket(trinket2))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UseTrinketAction::UseTrinket(Item* item)
|
||||
{
|
||||
if (bot->CanUseItem(item) != EQUIP_ERR_OK)
|
||||
return false;
|
||||
|
||||
if (bot->IsNonMeleeSpellCast(true))
|
||||
return false;
|
||||
|
||||
uint8 bagIndex = item->GetBagSlot();
|
||||
uint8 slot = item->GetSlot();
|
||||
uint8 spell_index = 0;
|
||||
uint8 cast_count = 1;
|
||||
ObjectGuid item_guid = item->GetGUID();
|
||||
uint32 glyphIndex = 0;
|
||||
uint8 castFlags = 0;
|
||||
uint32 targetFlag = TARGET_FLAG_NONE;
|
||||
uint32 spellId = 0;
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
||||
{
|
||||
if (item->GetTemplate()->Spells[i].SpellId > 0 && item->GetTemplate()->Spells[i].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE)
|
||||
{
|
||||
spellId = item->GetTemplate()->Spells[i].SpellId;
|
||||
if (!botAI->CanCastSpell(spellId, bot, false))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!spellId)
|
||||
return false;
|
||||
WorldPacket packet(CMSG_USE_ITEM);
|
||||
packet << bagIndex << slot << cast_count << spellId << item_guid << glyphIndex << castFlags;
|
||||
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (target)
|
||||
{
|
||||
targetFlag = TARGET_FLAG_UNIT;
|
||||
packet << targetFlag << target->GetGUID().WriteAsPacked();
|
||||
}
|
||||
else
|
||||
{
|
||||
targetFlag = TARGET_FLAG_NONE;
|
||||
packet << targetFlag << bot->GetPackGUID();
|
||||
}
|
||||
bot->GetSession()->HandleUseItemOpcode(packet);
|
||||
return true;
|
||||
}
|
||||
|
||||
Value<Unit*>* BuffOnMainTankAction::GetTargetValue() { return context->GetValue<Unit*>("main tank", spell); }
|
||||
|
||||
bool CastDebuffSpellAction::isUseful()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "Action.h"
|
||||
#include "PlayerbotAI.h"
|
||||
#include "PlayerbotAIConfig.h"
|
||||
#include "UseItemAction.h"
|
||||
#include "Value.h"
|
||||
|
||||
class PlayerbotAI;
|
||||
@@ -52,6 +53,7 @@ class CastMeleeSpellAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastMeleeSpellAction(PlayerbotAI* botAI, std::string const spell);
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastDebuffSpellAction : public CastAuraSpellAction
|
||||
@@ -67,6 +69,13 @@ private:
|
||||
float needLifeTime;
|
||||
};
|
||||
|
||||
class CastMeleeDebuffSpellAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastMeleeDebuffSpellAction(PlayerbotAI* botAI, std::string const spell, bool isOwner = false, float needLifeTime = 8.0f);
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastDebuffSpellOnAttackerAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
@@ -245,10 +254,31 @@ public:
|
||||
CastManaTapAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "mana tap") {}
|
||||
};
|
||||
|
||||
class CastWarStompAction : public CastSpellAction
|
||||
class CastWarStompAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
CastWarStompAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "war stomp") {}
|
||||
CastWarStompAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "war stomp") {}
|
||||
};
|
||||
|
||||
class CastBloodFuryAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastBloodFuryAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "blood fury") {}
|
||||
};
|
||||
|
||||
class CastBerserkingAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastBerserkingAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "berserking") {}
|
||||
};
|
||||
|
||||
class UseTrinketAction : public Action
|
||||
{
|
||||
public:
|
||||
UseTrinketAction(PlayerbotAI* botAI) : Action(botAI, "use trinket") {}
|
||||
bool Execute(Event event) override;
|
||||
protected:
|
||||
bool UseTrinket(Item* trinket);
|
||||
};
|
||||
|
||||
class CastSpellOnEnemyHealerAction : public CastSpellAction
|
||||
|
||||
@@ -143,7 +143,10 @@ std::vector<std::pair<uint32, std::string>> ListSpellsAction::GetSpellList(std::
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
|
||||
if (!spellInfo)
|
||||
continue;
|
||||
|
||||
|
||||
if (spellInfo->IsPassive())
|
||||
continue;
|
||||
|
||||
SkillLineAbilityEntry const* skillLine = skillSpells[itr->first];
|
||||
if (skill != SKILL_NONE && (!skillLine || skillLine->SkillLine != skill))
|
||||
continue;
|
||||
|
||||
@@ -110,11 +110,11 @@ public:
|
||||
CastIcyTouchAction(PlayerbotAI* ai) : CastSpellAction(ai, "icy touch") {}
|
||||
};
|
||||
|
||||
class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnMeleeAttackerAction
|
||||
class CastIcyTouchOnAttackerAction : public CastDebuffSpellOnAttackerAction
|
||||
{
|
||||
public:
|
||||
CastIcyTouchOnAttackerAction(PlayerbotAI* botAI)
|
||||
: CastDebuffSpellOnMeleeAttackerAction(botAI, "icy touch", true, .0f)
|
||||
: CastDebuffSpellOnAttackerAction(botAI, "icy touch", true, .0f)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -232,16 +232,17 @@ public:
|
||||
CastDeathCoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death coil") {}
|
||||
};
|
||||
|
||||
class CastBloodBoilAction : public CastSpellAction
|
||||
class CastBloodBoilAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
CastBloodBoilAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "blood boil") {}
|
||||
CastBloodBoilAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "blood boil") {}
|
||||
};
|
||||
|
||||
class CastDeathAndDecayAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastDeathAndDecayAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "death and decay") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
};
|
||||
|
||||
class CastHornOfWinterAction : public CastSpellAction
|
||||
|
||||
@@ -234,10 +234,10 @@ public:
|
||||
NextAction** getAlternatives() override;
|
||||
};
|
||||
|
||||
class CastBarskinAction : public CastBuffSpellAction
|
||||
class CastBarkskinAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastBarskinAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "barskin") {}
|
||||
CastBarkskinAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "barkskin") {}
|
||||
};
|
||||
|
||||
class CastInnervateAction : public CastSpellAction
|
||||
|
||||
@@ -198,7 +198,7 @@ public:
|
||||
creators["healing touch on party"] = &DruidAiObjectContextInternal::healing_touch_on_party;
|
||||
creators["rebirth"] = &DruidAiObjectContextInternal::rebirth;
|
||||
creators["revive"] = &DruidAiObjectContextInternal::revive;
|
||||
creators["barskin"] = &DruidAiObjectContextInternal::barskin;
|
||||
creators["barkskin"] = &DruidAiObjectContextInternal::barkskin;
|
||||
creators["lacerate"] = &DruidAiObjectContextInternal::lacerate;
|
||||
creators["hurricane"] = &DruidAiObjectContextInternal::hurricane;
|
||||
creators["innervate"] = &DruidAiObjectContextInternal::innervate;
|
||||
@@ -281,7 +281,7 @@ private:
|
||||
static Action* healing_touch_on_party(PlayerbotAI* botAI) { return new CastHealingTouchOnPartyAction(botAI); }
|
||||
static Action* rebirth(PlayerbotAI* botAI) { return new CastRebirthAction(botAI); }
|
||||
static Action* revive(PlayerbotAI* botAI) { return new CastReviveAction(botAI); }
|
||||
static Action* barskin(PlayerbotAI* botAI) { return new CastBarskinAction(botAI); }
|
||||
static Action* barkskin(PlayerbotAI* botAI) { return new CastBarkskinAction(botAI); }
|
||||
static Action* lacerate(PlayerbotAI* botAI) { return new CastLacerateAction(botAI); }
|
||||
static Action* hurricane(PlayerbotAI* botAI) { return new CastHurricaneAction(botAI); }
|
||||
static Action* innervate(PlayerbotAI* botAI) { return new CastInnervateAction(botAI); }
|
||||
|
||||
@@ -43,10 +43,10 @@ public:
|
||||
CastSwipeAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "swipe") {}
|
||||
};
|
||||
|
||||
class CastDemoralizingRoarAction : public CastDebuffSpellAction
|
||||
class CastDemoralizingRoarAction : public CastMeleeDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemoralizingRoarAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "demoralizing roar") {}
|
||||
CastDemoralizingRoarAction(PlayerbotAI* botAI) : CastMeleeDebuffSpellAction(botAI, "demoralizing roar") {}
|
||||
};
|
||||
|
||||
class CastMangleBearAction : public CastMeleeSpellAction
|
||||
|
||||
@@ -27,7 +27,7 @@ private:
|
||||
{
|
||||
return new ActionNode("survival instincts",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("barskin"), nullptr),
|
||||
/*A*/ NextAction::array(0, new NextAction("barkskin"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,9 @@ void GenericDruidStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
CombatStrategy::InitTriggers(triggers);
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("barkskin", ACTION_HIGH + 7), nullptr)));
|
||||
|
||||
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("regrowth",
|
||||
// ACTION_MEDIUM_HEAL + 2), nullptr))); triggers.push_back(new TriggerNode("party member low health",
|
||||
// NextAction::array(0, new NextAction("regrowth on party", ACTION_MEDIUM_HEAL + 1), nullptr)));
|
||||
|
||||
@@ -25,14 +25,18 @@ private:
|
||||
void RacialsStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
triggers.push_back(
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("lifeblood", 71.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("medium aoe", NextAction::array(0, new NextAction("war stomp", 71.0f),
|
||||
// nullptr)));
|
||||
/*triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("war stomp", 71.0f),
|
||||
* nullptr)));*/
|
||||
/*triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("arcane torrent",
|
||||
ACTION_EMERGENCY + 6), nullptr))); triggers.push_back(new TriggerNode("medium mana", NextAction::array(0, new
|
||||
NextAction("mana tap", ACTION_EMERGENCY + 6), nullptr)));*/
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("lifeblood", ACTION_NORMAL + 5), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("war stomp", ACTION_NORMAL + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"low mana", NextAction::array(0, new NextAction("arcane torrent", ACTION_NORMAL + 5), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"generic boost", NextAction::array(0, new NextAction("blood fury", ACTION_NORMAL + 5),
|
||||
new NextAction("berserking", ACTION_NORMAL + 5),
|
||||
new NextAction("use trinket", ACTION_NORMAL + 4),
|
||||
nullptr)));
|
||||
|
||||
}
|
||||
|
||||
RacialsStrategy::RacialsStrategy(PlayerbotAI* botAI) : Strategy(botAI)
|
||||
|
||||
@@ -10,7 +10,11 @@
|
||||
class DpsHunterStrategyActionNodeFactory : public NamedObjectFactory<ActionNode>
|
||||
{
|
||||
public:
|
||||
DpsHunterStrategyActionNodeFactory() { creators["aimed shot"] = &aimed_shot; }
|
||||
DpsHunterStrategyActionNodeFactory()
|
||||
{
|
||||
creators["aimed shot"] = &aimed_shot;
|
||||
creators["steady shot"] = &steady_shot;
|
||||
}
|
||||
|
||||
private:
|
||||
static ActionNode* aimed_shot([[maybe_unused]] PlayerbotAI* botAI)
|
||||
@@ -20,6 +24,13 @@ private:
|
||||
/*A*/ NextAction::array(0, new NextAction("multi-shot"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
static ActionNode* steady_shot([[maybe_unused]] PlayerbotAI* botAI)
|
||||
{
|
||||
return new ActionNode("steady shot",
|
||||
/*P*/ nullptr,
|
||||
/*A*/ NextAction::array(0, new NextAction("arcane shot"), nullptr),
|
||||
/*C*/ nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
DpsHunterStrategy::DpsHunterStrategy(PlayerbotAI* botAI) : GenericHunterStrategy(botAI)
|
||||
@@ -32,7 +43,7 @@ NextAction** DpsHunterStrategy::getDefaultActions()
|
||||
return NextAction::array(
|
||||
0, new NextAction("kill shot", ACTION_DEFAULT + 0.6f), new NextAction("chimera shot", ACTION_DEFAULT + 0.5f),
|
||||
new NextAction("explosive shot", ACTION_DEFAULT + 0.4f), new NextAction("aimed shot", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("arcane shot", ACTION_DEFAULT + 0.2f), new NextAction("steady shot", ACTION_DEFAULT + 0.1f),
|
||||
/*new NextAction("arcane shot", ACTION_DEFAULT + 0.2f),*/ new NextAction("steady shot", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("auto shot", ACTION_DEFAULT), nullptr);
|
||||
// return NextAction::array(0, new NextAction("explosive shot", 11.0f), new NextAction("auto shot", 10.0f), new
|
||||
// NextAction("auto attack", 9.0f), nullptr);
|
||||
|
||||
@@ -97,6 +97,9 @@ void GenericHunterStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(
|
||||
new TriggerNode("misdirection on main tank",
|
||||
NextAction::array(0, new NextAction("misdirection on main tank", ACTION_HIGH + 7), NULL)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("deterrence", ACTION_HIGH + 5), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode("tranquilizing shot enrage",
|
||||
NextAction::array(0, new NextAction("tranquilizing shot", 61.0f), NULL)));
|
||||
triggers.push_back(new TriggerNode("tranquilizing shot magic",
|
||||
|
||||
@@ -32,8 +32,11 @@ public:
|
||||
BEGIN_RANGED_SPELL_ACTION(CastArcaneShotAction, "arcane shot")
|
||||
END_SPELL_ACTION()
|
||||
|
||||
BEGIN_RANGED_SPELL_ACTION(CastExplosiveShotAction, "explosive shot")
|
||||
END_SPELL_ACTION()
|
||||
class CastExplosiveShotAction : public CastDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastExplosiveShotAction(PlayerbotAI* botAI) : CastDebuffSpellAction(botAI, "explosive shot", true, 0.0f) {}
|
||||
};
|
||||
|
||||
BEGIN_RANGED_SPELL_ACTION(CastAimedShotAction, "aimed shot")
|
||||
END_SPELL_ACTION()
|
||||
@@ -160,6 +163,12 @@ public:
|
||||
CastRapidFireAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "rapid fire") {}
|
||||
};
|
||||
|
||||
class CastDeterrenceAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDeterrenceAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "deterrence") {}
|
||||
};
|
||||
|
||||
class CastReadinessAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -149,6 +149,7 @@ public:
|
||||
creators["freezing trap"] = &HunterAiObjectContextInternal::freezing_trap;
|
||||
creators["rapid fire"] = &HunterAiObjectContextInternal::rapid_fire;
|
||||
creators["boost"] = &HunterAiObjectContextInternal::rapid_fire;
|
||||
creators["deterrence"] = &HunterAiObjectContextInternal::deterrence;
|
||||
creators["readiness"] = &HunterAiObjectContextInternal::readiness;
|
||||
creators["aspect of the hawk"] = &HunterAiObjectContextInternal::aspect_of_the_hawk;
|
||||
creators["aspect of the monkey"] = &HunterAiObjectContextInternal::aspect_of_the_monkey;
|
||||
@@ -200,6 +201,7 @@ private:
|
||||
static Action* black_arrow(PlayerbotAI* botAI) { return new CastBlackArrow(botAI); }
|
||||
static Action* freezing_trap(PlayerbotAI* botAI) { return new CastFreezingTrap(botAI); }
|
||||
static Action* rapid_fire(PlayerbotAI* botAI) { return new CastRapidFireAction(botAI); }
|
||||
static Action* deterrence(PlayerbotAI* botAI) { return new CastDeterrenceAction(botAI); }
|
||||
static Action* readiness(PlayerbotAI* botAI) { return new CastReadinessAction(botAI); }
|
||||
static Action* aspect_of_the_hawk(PlayerbotAI* botAI) { return new CastAspectOfTheHawkAction(botAI); }
|
||||
static Action* aspect_of_the_monkey(PlayerbotAI* botAI) { return new CastAspectOfTheMonkeyAction(botAI); }
|
||||
|
||||
@@ -85,7 +85,7 @@ NextAction** DpsPaladinStrategy::getDefaultActions()
|
||||
return NextAction::array(0, new NextAction("crusader strike", ACTION_DEFAULT + 0.4f),
|
||||
new NextAction("judgement of wisdom", ACTION_DEFAULT + 0.3f),
|
||||
new NextAction("divine storm", ACTION_DEFAULT + 0.2f),
|
||||
new NextAction("melee consecration", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("consecration", ACTION_DEFAULT + 0.1f),
|
||||
new NextAction("melee", ACTION_DEFAULT), NULL);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ void DpsPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// triggers.push_back(new TriggerNode("repentance", NextAction::array(0, new NextAction("repentance",
|
||||
// ACTION_INTERRUPT + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"medium aoe", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 3), nullptr)));
|
||||
"medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 3), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("art of war", NextAction::array(0, new NextAction("exorcism", ACTION_HIGH + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode("target critical health",
|
||||
|
||||
@@ -17,8 +17,8 @@ void GenericPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
{
|
||||
CombatStrategy::InitTriggers(triggers);
|
||||
|
||||
// triggers.push_back(new TriggerNode("low health", NextAction::array(0, new NextAction("divine shield",
|
||||
// ACTION_CRITICAL_HEAL + 2), new NextAction("holy light", ACTION_CRITICAL_HEAL + 2), nullptr)));
|
||||
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("divine shield",
|
||||
ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("hammer of justice interrupt",
|
||||
NextAction::array(0, new NextAction("hammer of justice", ACTION_INTERRUPT), nullptr)));
|
||||
|
||||
@@ -153,13 +153,6 @@ Unit* CastRighteousDefenseAction::GetTarget()
|
||||
return current_target->GetVictim();
|
||||
}
|
||||
|
||||
bool CastMeleeConsecrationAction::isUseful()
|
||||
{
|
||||
Unit* target = GetTarget();
|
||||
// float dis = distance + CONTACT_DISTANCE;
|
||||
return target && bot->IsWithinMeleeRange(target); // sServerFacade->IsDistanceGreaterThan(AI_VALUE2(float,
|
||||
// "distance", GetTargetName()), distance);
|
||||
}
|
||||
|
||||
bool CastDivineSacrificeAction::isUseful()
|
||||
{
|
||||
|
||||
@@ -44,13 +44,6 @@ SPELL_ACTION(CastHolyShockAction, "holy shock");
|
||||
// consecration
|
||||
MELEE_ACTION(CastConsecrationAction, "consecration");
|
||||
|
||||
class CastMeleeConsecrationAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastMeleeConsecrationAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "consecration") {}
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
// repentance
|
||||
SNARE_ACTION(CastRepentanceSnareAction, "repentance");
|
||||
DEBUFF_ACTION(CastRepentanceAction, "repentance");
|
||||
@@ -67,10 +60,10 @@ BUFF_ACTION(CastDivineFavorAction, "divine favor");
|
||||
// fury
|
||||
BUFF_ACTION(CastRighteousFuryAction, "righteous fury");
|
||||
|
||||
class CastDivineStormAction : public CastBuffSpellAction
|
||||
class CastDivineStormAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
CastDivineStormAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "divine storm") {}
|
||||
CastDivineStormAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "divine storm") {}
|
||||
};
|
||||
|
||||
class CastCrusaderStrikeAction : public CastMeleeSpellAction
|
||||
|
||||
@@ -232,7 +232,6 @@ public:
|
||||
creators["concentration aura"] = &PaladinAiObjectContextInternal::concentration_aura;
|
||||
creators["holy wrath"] = &PaladinAiObjectContextInternal::holy_wrath;
|
||||
creators["consecration"] = &PaladinAiObjectContextInternal::consecration;
|
||||
creators["melee consecration"] = &PaladinAiObjectContextInternal::melee_consecration;
|
||||
creators["cleanse disease"] = &PaladinAiObjectContextInternal::cleanse_disease;
|
||||
creators["cleanse poison"] = &PaladinAiObjectContextInternal::cleanse_poison;
|
||||
creators["cleanse magic"] = &PaladinAiObjectContextInternal::cleanse_magic;
|
||||
@@ -331,7 +330,6 @@ private:
|
||||
static Action* concentration_aura(PlayerbotAI* botAI) { return new CastConcentrationAuraAction(botAI); }
|
||||
static Action* holy_wrath(PlayerbotAI* botAI) { return new CastHolyWrathAction(botAI); }
|
||||
static Action* consecration(PlayerbotAI* botAI) { return new CastConsecrationAction(botAI); }
|
||||
static Action* melee_consecration(PlayerbotAI* botAI) { return new CastMeleeConsecrationAction(botAI); }
|
||||
static Action* cleanse_poison(PlayerbotAI* botAI) { return new CastCleansePoisonAction(botAI); }
|
||||
static Action* cleanse_disease(PlayerbotAI* botAI) { return new CastCleanseDiseaseAction(botAI); }
|
||||
static Action* cleanse_magic(PlayerbotAI* botAI) { return new CastCleanseMagicAction(botAI); }
|
||||
|
||||
@@ -82,7 +82,7 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(new TriggerNode(
|
||||
"light aoe", NextAction::array(0, new NextAction("avenger's shield", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 7),
|
||||
new TriggerNode("medium aoe", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 7),
|
||||
new NextAction("avenger's shield", ACTION_HIGH + 6), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("avenger's shield", NextAction::array(0, new NextAction("avenger's shield",
|
||||
// ACTION_HIGH + 7), nullptr)));
|
||||
@@ -107,7 +107,7 @@ void TankPaladinStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
new TriggerNode("medium group heal occasion",
|
||||
NextAction::array(0, new NextAction("divine sacrifice", ACTION_HIGH + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enough mana", NextAction::array(0, new NextAction("melee consecration", ACTION_HIGH + 4), nullptr)));
|
||||
"enough mana", NextAction::array(0, new NextAction("consecration", ACTION_HIGH + 4), nullptr)));
|
||||
triggers.push_back(new TriggerNode("not facing target",
|
||||
NextAction::array(0, new NextAction("set facing", ACTION_NORMAL + 7), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
|
||||
@@ -31,8 +31,9 @@ void GenericPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// NextAction("inner focus", 42.0f), nullptr))); triggers.push_back(new TriggerNode("medium mana",
|
||||
// NextAction::array(0, new NextAction("symbol of hope", ACTION_EMERGENCY), nullptr))); triggers.push_back(new
|
||||
// TriggerNode("low mana", NextAction::array(0, new NextAction("consume magic", 10.0f), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("desperate prayer",
|
||||
// ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new
|
||||
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("desperate prayer",
|
||||
ACTION_HIGH + 5), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("enemy is close", NextAction::array(0, new
|
||||
// NextAction("elune's grace", ACTION_EMERGENCY), nullptr))); triggers.push_back(new TriggerNode("chastise",
|
||||
// NextAction::array(0, new NextAction("chastise", ACTION_INTERRUPT), nullptr)));
|
||||
triggers.push_back(new TriggerNode(
|
||||
|
||||
@@ -73,7 +73,9 @@ void HolyHealPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"party member critical health",
|
||||
NextAction::array(0, new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5),
|
||||
NextAction::array(0,
|
||||
new NextAction("guardian spirit on party", ACTION_CRITICAL_HEAL + 6),
|
||||
new NextAction("power word: shield on party", ACTION_CRITICAL_HEAL + 5),
|
||||
new NextAction("flash heal on party", ACTION_CRITICAL_HEAL + 3),
|
||||
new NextAction("prayer of mending on party", ACTION_CRITICAL_HEAL + 2), NULL)));
|
||||
|
||||
|
||||
@@ -173,4 +173,11 @@ public:
|
||||
CastMindSearAction(PlayerbotAI* ai) : CastSpellAction(ai, "mind sear") {}
|
||||
ActionThreatType getThreatType() override { return ActionThreatType::Aoe; }
|
||||
};
|
||||
|
||||
class CastGuardianSpiritOnPartyAction : public HealPartyMemberAction
|
||||
{
|
||||
public:
|
||||
CastGuardianSpiritOnPartyAction(PlayerbotAI* ai) : HealPartyMemberAction(ai, "guardian spirit", 40.0f, HealingManaEfficiency::MEDIUM) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -234,6 +234,7 @@ public:
|
||||
creators["hymn of hope"] = &PriestAiObjectContextInternal::hymn_of_hope;
|
||||
creators["divine hymn"] = &PriestAiObjectContextInternal::divine_hymn;
|
||||
creators["mind sear"] = &PriestAiObjectContextInternal::mind_sear;
|
||||
creators["guardian spirit on party"] = &PriestAiObjectContextInternal::guardian_spirit_on_party;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -339,6 +340,7 @@ private:
|
||||
static Action* hymn_of_hope(PlayerbotAI* ai) { return new CastHymnOfHopeAction(ai); }
|
||||
static Action* divine_hymn(PlayerbotAI* ai) { return new CastDivineHymnAction(ai); }
|
||||
static Action* mind_sear(PlayerbotAI* ai) { return new CastMindSearAction(ai); }
|
||||
static Action* guardian_spirit_on_party(PlayerbotAI* ai) { return new CastGuardianSpiritOnPartyAction(ai); }
|
||||
};
|
||||
|
||||
PriestAiObjectContext::PriestAiObjectContext(PlayerbotAI* botAI) : AiObjectContext(botAI)
|
||||
|
||||
@@ -23,7 +23,7 @@ CURE_TRIGGER(CureDiseaseTrigger, "cure disease", DISPEL_DISEASE);
|
||||
CURE_PARTY_TRIGGER(PartyMemberCureDiseaseTrigger, "cure disease", DISPEL_DISEASE);
|
||||
BUFF_TRIGGER_A(InnerFireTrigger, "inner fire");
|
||||
BUFF_TRIGGER_A(ShadowformTrigger, "shadowform");
|
||||
BUFF_TRIGGER(PowerInfusionTrigger, "power infusion");
|
||||
BOOST_TRIGGER(PowerInfusionTrigger, "power infusion");
|
||||
BUFF_TRIGGER(InnerFocusTrigger, "inner focus");
|
||||
BUFF_TRIGGER(ShadowProtectionTrigger, "shadow protection");
|
||||
BUFF_PARTY_TRIGGER(ShadowProtectionOnPartyTrigger, "shadow protection");
|
||||
|
||||
@@ -29,8 +29,10 @@ void ShadowPriestStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
// ACTION_MOVE + 9), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("shadowform", NextAction::array(0, new NextAction("shadowform", ACTION_HIGH), nullptr)));
|
||||
// triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("dispersion", ACTION_EMERGENCY
|
||||
// + 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("low mana", NextAction::array(0, new NextAction("dispersion", ACTION_HIGH
|
||||
+ 5), nullptr)));
|
||||
triggers.push_back(new TriggerNode("critical health", NextAction::array(0, new NextAction("dispersion", ACTION_HIGH
|
||||
+ 5), nullptr)));
|
||||
triggers.push_back(
|
||||
new TriggerNode("vampiric embrace", NextAction::array(0, new NextAction("vampiric embrace", 16.0f), nullptr)));
|
||||
triggers.push_back(
|
||||
|
||||
@@ -66,8 +66,11 @@ void AssassinationRogueStrategy::InitTriggers(std::vector<TriggerNode*>& trigger
|
||||
new TriggerNode("medium threat", NextAction::array(0, new NextAction("vanish", ACTION_HIGH), NULL)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_EMERGENCY),
|
||||
new NextAction("feint", ACTION_EMERGENCY), NULL)));
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_HIGH + 9),
|
||||
new NextAction("feint", ACTION_HIGH + 8), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("critical health", NextAction::array(0, new NextAction("cloak of shadows", ACTION_HIGH + 7), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("kick", NextAction::array(0, new NextAction("kick", ACTION_INTERRUPT + 2), NULL)));
|
||||
|
||||
@@ -108,8 +108,11 @@ void DpsRogueStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
new TriggerNode("medium threat", NextAction::array(0, new NextAction("vanish", ACTION_HIGH), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_EMERGENCY),
|
||||
new NextAction("feint", ACTION_EMERGENCY), nullptr)));
|
||||
new TriggerNode("low health", NextAction::array(0, new NextAction("evasion", ACTION_HIGH + 9),
|
||||
new NextAction("feint", ACTION_HIGH + 8), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("critical health", NextAction::array(0, new NextAction("cloak of shadows", ACTION_HIGH + 7), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("kick", NextAction::array(0, new NextAction("kick", ACTION_INTERRUPT + 2), nullptr)));
|
||||
@@ -125,6 +128,9 @@ void DpsRogueStrategy::InitTriggers(std::vector<TriggerNode*>& triggers)
|
||||
triggers.push_back(
|
||||
new TriggerNode("light aoe", NextAction::array(0, new NextAction("blade flurry", ACTION_HIGH + 3), nullptr)));
|
||||
|
||||
triggers.push_back(
|
||||
new TriggerNode("blade flurry", NextAction::array(0, new NextAction("blade flurry", ACTION_HIGH + 2), nullptr)));
|
||||
|
||||
triggers.push_back(new TriggerNode(
|
||||
"enemy out of melee",
|
||||
NextAction::array(0, new NextAction("stealth", ACTION_NORMAL + 9), new NextAction("sprint", ACTION_NORMAL + 8),
|
||||
|
||||
@@ -17,6 +17,12 @@ public:
|
||||
CastEvasionAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "evasion") {}
|
||||
};
|
||||
|
||||
class CastCloakOfShadowsAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastCloakOfShadowsAction(PlayerbotAI* botAI) : CastBuffSpellAction(botAI, "cloak of shadows") {}
|
||||
};
|
||||
|
||||
class CastHungerForBloodAction : public CastBuffSpellAction
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -76,12 +76,14 @@ public:
|
||||
creators["off hand weapon no enchant"] = &RogueTriggerFactoryInternal::off_hand_weapon_no_enchant;
|
||||
creators["tricks of the trade on main tank"] = &RogueTriggerFactoryInternal::tricks_of_the_trade_on_main_tank;
|
||||
creators["adrenaline rush"] = &RogueTriggerFactoryInternal::adrenaline_rush;
|
||||
creators["blade fury"] = &RogueTriggerFactoryInternal::blade_fury;
|
||||
creators["target with combo points almost dead"] =
|
||||
&RogueTriggerFactoryInternal::target_with_combo_points_almost_dead;
|
||||
}
|
||||
|
||||
private:
|
||||
static Trigger* adrenaline_rush(PlayerbotAI* botAI) { return new AdrenalineRushTrigger(botAI); }
|
||||
static Trigger* blade_fury(PlayerbotAI* botAI) { return new BladeFuryTrigger(botAI); }
|
||||
static Trigger* kick(PlayerbotAI* botAI) { return new KickInterruptSpellTrigger(botAI); }
|
||||
static Trigger* rupture(PlayerbotAI* botAI) { return new RuptureTrigger(botAI); }
|
||||
static Trigger* slice_and_dice(PlayerbotAI* botAI) { return new SliceAndDiceTrigger(botAI); }
|
||||
@@ -122,6 +124,7 @@ public:
|
||||
creators["eviscerate"] = &RogueAiObjectContextInternal::eviscerate;
|
||||
creators["vanish"] = &RogueAiObjectContextInternal::vanish;
|
||||
creators["evasion"] = &RogueAiObjectContextInternal::evasion;
|
||||
creators["cloak of shadows"] = &RogueAiObjectContextInternal::cloak_of_shadows;
|
||||
creators["kick"] = &RogueAiObjectContextInternal::kick;
|
||||
creators["feint"] = &RogueAiObjectContextInternal::feint;
|
||||
creators["backstab"] = &RogueAiObjectContextInternal::backstab;
|
||||
@@ -161,6 +164,7 @@ private:
|
||||
static Action* eviscerate(PlayerbotAI* botAI) { return new CastEviscerateAction(botAI); }
|
||||
static Action* vanish(PlayerbotAI* botAI) { return new CastVanishAction(botAI); }
|
||||
static Action* evasion(PlayerbotAI* botAI) { return new CastEvasionAction(botAI); }
|
||||
static Action* cloak_of_shadows(PlayerbotAI* botAI) { return new CastCloakOfShadowsAction(botAI); }
|
||||
static Action* kick(PlayerbotAI* botAI) { return new CastKickAction(botAI); }
|
||||
static Action* feint(PlayerbotAI* botAI) { return new CastFeintAction(botAI); }
|
||||
static Action* backstab(PlayerbotAI* botAI) { return new CastBackstabAction(botAI); }
|
||||
|
||||
@@ -18,34 +18,34 @@ public:
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastSinisterStrikeAction : public CastComboAction
|
||||
class CastSinisterStrikeAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastSinisterStrikeAction(PlayerbotAI* botAI) : CastComboAction(botAI, "sinister strike") {}
|
||||
CastSinisterStrikeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "sinister strike") {}
|
||||
};
|
||||
|
||||
class CastMutilateAction : public CastComboAction
|
||||
class CastMutilateAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastMutilateAction(PlayerbotAI* botAI) : CastComboAction(botAI, "mutilate") {}
|
||||
CastMutilateAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "mutilate") {}
|
||||
};
|
||||
|
||||
class CastRiposteAction : public CastComboAction
|
||||
class CastRiposteAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastRiposteAction(PlayerbotAI* botAI) : CastComboAction(botAI, "riposte") {}
|
||||
CastRiposteAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "riposte") {}
|
||||
};
|
||||
|
||||
class CastGougeAction : public CastComboAction
|
||||
class CastGougeAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastGougeAction(PlayerbotAI* botAI) : CastComboAction(botAI, "gouge") {}
|
||||
CastGougeAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "gouge") {}
|
||||
};
|
||||
|
||||
class CastBackstabAction : public CastComboAction
|
||||
class CastBackstabAction : public CastSpellAction
|
||||
{
|
||||
public:
|
||||
CastBackstabAction(PlayerbotAI* botAI) : CastComboAction(botAI, "backstab") {}
|
||||
CastBackstabAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "backstab") {}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -36,6 +36,13 @@ public:
|
||||
// bool isPossible();
|
||||
};
|
||||
|
||||
class BladeFuryTrigger : public BoostTrigger
|
||||
{
|
||||
public:
|
||||
BladeFuryTrigger(PlayerbotAI* botAI) : BoostTrigger(botAI, "blade fury") {}
|
||||
};
|
||||
|
||||
|
||||
class RuptureTrigger : public DebuffTrigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ShamanActions.h"
|
||||
|
||||
#include "Playerbots.h"
|
||||
#include "Totem.h"
|
||||
|
||||
bool CastTotemAction::isUseful()
|
||||
{
|
||||
@@ -41,7 +42,24 @@ bool CastSearingTotemAction::isUseful()
|
||||
return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", "flametongue totem");
|
||||
}
|
||||
|
||||
bool CastMagmaTotemAction::isUseful() { return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", name); }
|
||||
bool CastMagmaTotemAction::isUseful() {
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (!target || !bot->IsWithinMeleeRange(target))
|
||||
return false;
|
||||
|
||||
return CastTotemAction::isUseful() && !AI_VALUE2(bool, "has totem", name);
|
||||
}
|
||||
|
||||
bool CastFireNovaAction::isUseful() {
|
||||
Creature* fireTotem = bot->GetMap()->GetCreature(bot->m_SummonSlot[1]);
|
||||
if (!fireTotem)
|
||||
return false;
|
||||
|
||||
if (bot->GetDistance(fireTotem) > 8.0f)
|
||||
return false;
|
||||
|
||||
return CastMeleeSpellAction::isUseful();
|
||||
}
|
||||
|
||||
bool CastCleansingTotemAction::isUseful()
|
||||
{
|
||||
|
||||
@@ -231,10 +231,11 @@ public:
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastFireNovaAction : public CastSpellAction
|
||||
class CastFireNovaAction : public CastMeleeSpellAction
|
||||
{
|
||||
public:
|
||||
CastFireNovaAction(PlayerbotAI* botAI) : CastSpellAction(botAI, "fire nova") {}
|
||||
CastFireNovaAction(PlayerbotAI* botAI) : CastMeleeSpellAction(botAI, "fire nova") {}
|
||||
bool isUseful() override;
|
||||
};
|
||||
|
||||
class CastWindShearAction : public CastSpellAction
|
||||
|
||||
@@ -308,7 +308,23 @@ std::string const TwoTriggers::getName()
|
||||
return name;
|
||||
}
|
||||
|
||||
bool BoostTrigger::IsActive() { return BuffTrigger::IsActive() && AI_VALUE(uint8, "balance") <= balance; }
|
||||
bool BoostTrigger::IsActive()
|
||||
{
|
||||
if (!BuffTrigger::IsActive())
|
||||
return false;
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (target && target->ToPlayer())
|
||||
return true;
|
||||
return AI_VALUE(uint8, "balance") <= balance;
|
||||
}
|
||||
|
||||
bool GenericBoostTrigger::IsActive()
|
||||
{
|
||||
Unit* target = AI_VALUE(Unit*, "current target");
|
||||
if (target && target->ToPlayer())
|
||||
return true;
|
||||
return AI_VALUE(uint8, "balance") <= balance;
|
||||
}
|
||||
|
||||
bool ItemCountTrigger::IsActive() { return AI_VALUE2(uint32, "item count", item) < count; }
|
||||
|
||||
|
||||
@@ -409,6 +409,21 @@ protected:
|
||||
float balance;
|
||||
};
|
||||
|
||||
class GenericBoostTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
GenericBoostTrigger(PlayerbotAI* botAI, float balance = 50.f)
|
||||
: Trigger(botAI, "generic boost", 1), balance(balance)
|
||||
{
|
||||
}
|
||||
|
||||
bool IsActive() override;
|
||||
|
||||
protected:
|
||||
float balance;
|
||||
};
|
||||
|
||||
|
||||
class RandomTrigger : public Trigger
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -48,7 +48,7 @@ class LowHealthTrigger : public HealthInRangeTrigger
|
||||
{
|
||||
public:
|
||||
LowHealthTrigger(PlayerbotAI* botAI, std::string const name = "low health",
|
||||
float value = sPlayerbotAIConfig->lowHealth, float minValue = sPlayerbotAIConfig->criticalHealth)
|
||||
float value = sPlayerbotAIConfig->lowHealth, float minValue = 0)
|
||||
: HealthInRangeTrigger(botAI, name, value, minValue)
|
||||
{
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class MediumHealthTrigger : public LowHealthTrigger
|
||||
{
|
||||
public:
|
||||
MediumHealthTrigger(PlayerbotAI* botAI)
|
||||
: LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, sPlayerbotAIConfig->lowHealth)
|
||||
: LowHealthTrigger(botAI, "medium health", sPlayerbotAIConfig->mediumHealth, 0)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -89,7 +89,7 @@ class PartyMemberLowHealthTrigger : public HealthInRangeTrigger
|
||||
public:
|
||||
PartyMemberLowHealthTrigger(PlayerbotAI* botAI, std::string const name = "party member low health",
|
||||
float value = sPlayerbotAIConfig->lowHealth,
|
||||
float minValue = sPlayerbotAIConfig->criticalHealth)
|
||||
float minValue = 0)
|
||||
: HealthInRangeTrigger(botAI, name, value, minValue)
|
||||
{
|
||||
}
|
||||
@@ -111,7 +111,7 @@ class PartyMemberMediumHealthTrigger : public PartyMemberLowHealthTrigger
|
||||
public:
|
||||
PartyMemberMediumHealthTrigger(PlayerbotAI* botAI)
|
||||
: PartyMemberLowHealthTrigger(botAI, "party member medium health", sPlayerbotAIConfig->mediumHealth,
|
||||
sPlayerbotAIConfig->lowHealth)
|
||||
0)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -121,7 +121,7 @@ class PartyMemberAlmostFullHealthTrigger : public PartyMemberLowHealthTrigger
|
||||
public:
|
||||
PartyMemberAlmostFullHealthTrigger(PlayerbotAI* botAI)
|
||||
: PartyMemberLowHealthTrigger(botAI, "party member almost full health", sPlayerbotAIConfig->almostFullHealth,
|
||||
sPlayerbotAIConfig->mediumHealth)
|
||||
0)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
@@ -53,6 +53,8 @@ public:
|
||||
creators["party member medium health"] = &TriggerContext::PartyMemberMediumHealth;
|
||||
creators["party member almost full health"] = &TriggerContext::PartyMemberAlmostFullHealth;
|
||||
|
||||
creators["generic boost"] = &TriggerContext::generic_boost;
|
||||
|
||||
creators["protect party member"] = &TriggerContext::protect_party_member;
|
||||
|
||||
creators["light rage available"] = &TriggerContext::LightRageAvailable;
|
||||
@@ -318,6 +320,7 @@ private:
|
||||
{
|
||||
return new PartyMemberAlmostFullHealthTrigger(botAI);
|
||||
}
|
||||
static Trigger* generic_boost(PlayerbotAI* botAI) { return new GenericBoostTrigger(botAI); }
|
||||
static Trigger* PartyMemberCriticalHealth(PlayerbotAI* botAI)
|
||||
{
|
||||
return new PartyMemberCriticalHealthTrigger(botAI);
|
||||
|
||||
@@ -66,8 +66,13 @@ uint8 BalancePercentValue::Calculate()
|
||||
|
||||
playerLevel += player->GetLevel();
|
||||
}
|
||||
uint32 memberCount = group->GetMembersCount();
|
||||
playerLevel /= memberCount;
|
||||
if (memberCount <= 10)
|
||||
playerLevel *= memberCount;
|
||||
else
|
||||
playerLevel *= 10;
|
||||
}
|
||||
|
||||
GuidVector v = context->GetValue<GuidVector>("attackers")->Get();
|
||||
for (ObjectGuid const guid : v)
|
||||
{
|
||||
@@ -89,7 +94,7 @@ uint8 BalancePercentValue::Calculate()
|
||||
level *= 3;
|
||||
break;
|
||||
case CREATURE_ELITE_WORLDBOSS:
|
||||
level *= 50;
|
||||
level *= 30;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ Unit* AttackerWithoutAuraTargetValue::Calculate()
|
||||
if (!unit || !unit->IsAlive())
|
||||
continue;
|
||||
|
||||
if (bot->GetDistance(unit) > botAI->GetRange(range))
|
||||
if (!bot->IsWithinCombatRange(unit, botAI->GetRange(range)))
|
||||
continue;
|
||||
|
||||
if (unit->GetHealth() < max_health)
|
||||
|
||||
@@ -41,6 +41,8 @@ Unit* PartyMemberToHeal::Calculate()
|
||||
for (GroupReference* gref = group->GetFirstMember(); gref; gref = gref->next())
|
||||
{
|
||||
Player* player = gref->GetSource();
|
||||
if (player->IsGameMaster())
|
||||
continue;
|
||||
if (player && player->IsAlive())
|
||||
{
|
||||
uint8 health = player->GetHealthPct();
|
||||
|
||||
@@ -103,7 +103,8 @@ bool PartyMemberValue::Check(Unit* player)
|
||||
{
|
||||
// return player && player != bot && player->GetMapId() == bot->GetMapId() && bot->IsWithinDistInMap(player,
|
||||
// sPlayerbotAIConfig->sightDistance, false);
|
||||
return player && player->GetMapId() == bot->GetMapId() &&
|
||||
bool isGM = player->ToPlayer() && player->ToPlayer()->IsGameMaster();
|
||||
return player && player->GetMapId() == bot->GetMapId() && !isGM &&
|
||||
bot->GetDistance(player) < sPlayerbotAIConfig->spellDistance * 2 &&
|
||||
bot->IsWithinLOS(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
|
||||
}
|
||||
|
||||
@@ -20,14 +20,21 @@ BUFF_ACTION(CastBerserkerStanceAction, "berserker stance");
|
||||
// shouts
|
||||
BUFF_ACTION(CastBattleShoutAction, "battle shout");
|
||||
MELEE_ACTION_U(CastBattleShoutTauntAction, "battle shout", CastSpellAction::isUseful()); // useful to rebuff
|
||||
DEBUFF_ACTION_R(CastDemoralizingShoutAction, "demoralizing shout", 8.0f); // low range debuff
|
||||
class CastDemoralizingShoutWithoutLifeTimeCheckAction : public CastDebuffSpellAction
|
||||
// DEBUFF_ACTION_R(CastDemoralizingShoutAction, "demoralizing shout", 8.0f); // low range debuff
|
||||
|
||||
class CastDemoralizingShoutAction : public CastMeleeDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemoralizingShoutAction(PlayerbotAI* botAI)
|
||||
: CastMeleeDebuffSpellAction(botAI, "demoralizing shout") {}
|
||||
};
|
||||
|
||||
class CastDemoralizingShoutWithoutLifeTimeCheckAction : public CastMeleeDebuffSpellAction
|
||||
{
|
||||
public:
|
||||
CastDemoralizingShoutWithoutLifeTimeCheckAction(PlayerbotAI* botAI)
|
||||
: CastDebuffSpellAction(botAI, "demoralizing shout", false, 0.0f)
|
||||
: CastMeleeDebuffSpellAction(botAI, "demoralizing shout", false, 0.0f)
|
||||
{
|
||||
range = 8.0f;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -63,7 +70,7 @@ DEBUFF_ACTION(CastShatteringThrowAction, "shattering throw");
|
||||
MELEE_ACTION(CastMortalStrikeAction, "mortal strike");
|
||||
BUFF_ACTION(CastSweepingStrikesAction, "sweeping strikes");
|
||||
// arms talents 3.3.5
|
||||
BUFF_ACTION(CastBladestormAction, "bladestorm");
|
||||
MELEE_ACTION(CastBladestormAction, "bladestorm");
|
||||
|
||||
// fury
|
||||
MELEE_ACTION(CastCleaveAction, "cleave");
|
||||
|
||||
Reference in New Issue
Block a user