mirror of
https://github.com/mod-playerbots/mod-playerbots.git
synced 2026-01-29 00:13:47 +00:00
* Enraged regen at critial health * Enraged regen action context * Enraged regen on critical health trigger * Enraged regen on critical health trigger * Added logic for Arms to use Retaliation * Added logic for Arms to use Retaliation * Used correct class enums for !players * Retaliation on medium health * Removed temp line * Added check for attacker->GetVictim() != bot * Adjusted triggers for emergency actions * Added Shattering Throw logic * Added Shattering Throw logic * Added Shattering Throw logic * Added Shattering Throw logic * Added Shattering Throw logic * Added Shattering Throw logic * Fixed ActionNode for Shattering Throw * Added debug logging * More debug logs * Better debug logs * Adjusted range on action * Adjusted priorities * More logging * Update WarriorActions.cpp * Update WarriorActions.h * Changed trigger name for differentiation * Updated to new shattering throw trigger name * Update WarriorTriggers.h with new ST name * Update ArmsWarriorStrategy.cpp * Changed priority * Shattering Throw and Retaliation stance reqs Battlestance needed for Shattering Throw and Retaliation * Created isUseful for Shattering Throw * Created isUseful for Shattering Throw * GetTarget instead of GetTargetValue * Changed to GetTarget instead of GetTargetValue * Commented out Execute function * Commented out Execute function * isPossible was failing, created basic isPossible IsImmuneToSpell was returning true for Shattering Throw 2 DAYS! :( * isPossible was failing, created basic isPossible * Added some more isPossible checks * Update WarriorActions.cpp * Missing ) * Missing ! * Removed logging * Removed logging * Clean up * Cleanup * Corrected logic for Rogue's Expose Armor trigger Logic was checking the Rogue, not the Rogue's target, for Sunder Armor before casting Expose Armor.
245 lines
6.6 KiB
C++
245 lines
6.6 KiB
C++
/*
|
|
* 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 "WarriorActions.h"
|
|
|
|
#include "Playerbots.h"
|
|
|
|
bool CastSunderArmorAction::isUseful()
|
|
{
|
|
Aura* aura = botAI->GetAura("sunder armor", GetTarget(), false, true);
|
|
return !aura || aura->GetStackAmount() < 5 || aura->GetDuration() <= 6000;
|
|
}
|
|
|
|
Value<Unit*>* CastVigilanceAction::GetTargetValue()
|
|
{
|
|
Group* group = bot->GetGroup();
|
|
if (!group)
|
|
{
|
|
return new ManualSetValue<Unit*>(botAI, nullptr);
|
|
}
|
|
|
|
Player* currentVigilanceTarget = nullptr;
|
|
Player* mainTank = nullptr;
|
|
Player* assistTank1 = nullptr;
|
|
Player* assistTank2 = nullptr;
|
|
Player* highestGearScorePlayer = nullptr;
|
|
uint32 highestGearScore = 0;
|
|
|
|
// Iterate once through the group to gather all necessary information
|
|
for (GroupReference* ref = group->GetFirstMember(); ref; ref = ref->next())
|
|
{
|
|
Player* member = ref->GetSource();
|
|
if (!member || member == bot || !member->IsAlive())
|
|
continue;
|
|
|
|
// Check if member has Vigilance applied by the bot
|
|
if (!currentVigilanceTarget && botAI->HasAura("vigilance", member, false, true))
|
|
{
|
|
currentVigilanceTarget = member;
|
|
}
|
|
|
|
// Identify Main Tank
|
|
if (!mainTank && botAI->IsMainTank(member))
|
|
{
|
|
mainTank = member;
|
|
}
|
|
|
|
// Identify Assist Tanks
|
|
if (assistTank1 == nullptr && botAI->IsAssistTankOfIndex(member, 0))
|
|
{
|
|
assistTank1 = member;
|
|
}
|
|
else if (assistTank2 == nullptr && botAI->IsAssistTankOfIndex(member, 1))
|
|
{
|
|
assistTank2 = member;
|
|
}
|
|
|
|
// Determine Highest Gear Score
|
|
uint32 gearScore = botAI->GetEquipGearScore(member, false, false);
|
|
if (gearScore > highestGearScore)
|
|
{
|
|
highestGearScore = gearScore;
|
|
highestGearScorePlayer = member;
|
|
}
|
|
}
|
|
|
|
// Determine the highest-priority target
|
|
Player* highestPriorityTarget = mainTank ? mainTank :
|
|
(assistTank1 ? assistTank1 :
|
|
(assistTank2 ? assistTank2 : highestGearScorePlayer));
|
|
|
|
// If no valid target, return nullptr
|
|
if (!highestPriorityTarget)
|
|
{
|
|
return new ManualSetValue<Unit*>(botAI, nullptr);
|
|
}
|
|
|
|
// If the current target is already the highest-priority target, do nothing
|
|
if (currentVigilanceTarget == highestPriorityTarget)
|
|
{
|
|
return new ManualSetValue<Unit*>(botAI, nullptr);
|
|
}
|
|
|
|
// Assign the new target
|
|
Unit* targetUnit = highestPriorityTarget->ToUnit();
|
|
if (targetUnit)
|
|
{
|
|
return new ManualSetValue<Unit*>(botAI, targetUnit);
|
|
}
|
|
|
|
return new ManualSetValue<Unit*>(botAI, nullptr);
|
|
}
|
|
|
|
bool CastVigilanceAction::Execute(Event event)
|
|
{
|
|
Unit* target = GetTarget();
|
|
if (!target || target == bot)
|
|
return false;
|
|
|
|
return botAI->CastSpell("vigilance", target);
|
|
}
|
|
|
|
bool CastRetaliationAction::isUseful()
|
|
{
|
|
// Spell cooldown check
|
|
if (!bot->HasSpell(20230))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Spell cooldown check
|
|
if (bot->HasSpellCooldown(20230))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
uint8 meleeAttackers = 0;
|
|
GuidVector attackers = AI_VALUE(GuidVector, "attackers");
|
|
|
|
for (ObjectGuid const& guid : attackers)
|
|
{
|
|
Unit* attacker = botAI->GetUnit(guid);
|
|
if (!attacker || !attacker->IsAlive() || attacker->GetVictim() != bot)
|
|
continue;
|
|
|
|
// Check if the attacker is melee-based using unit_class
|
|
if (attacker->GetTypeId() == TYPEID_UNIT)
|
|
{
|
|
Creature* creature = attacker->ToCreature();
|
|
if (creature && (creature->IsClass(CLASS_WARRIOR)
|
|
|| creature->IsClass(CLASS_ROGUE)
|
|
|| creature->IsClass(CLASS_PALADIN)))
|
|
{
|
|
++meleeAttackers;
|
|
}
|
|
}
|
|
else if (attacker->GetTypeId() == TYPEID_PLAYER)
|
|
{
|
|
Player* playerAttacker = attacker->ToPlayer();
|
|
if (playerAttacker && botAI->IsMelee(playerAttacker)) // Reuse existing Player melee check
|
|
{
|
|
++meleeAttackers;
|
|
}
|
|
}
|
|
|
|
// Early exit if we already have enough melee attackers
|
|
if (meleeAttackers >= 2)
|
|
break;
|
|
}
|
|
|
|
// Only cast Retaliation if there are at least 2 melee attackers and the buff is not active
|
|
return meleeAttackers >= 2 && !botAI->HasAura("retaliation", bot);
|
|
}
|
|
|
|
Unit* CastShatteringThrowAction::GetTarget()
|
|
{
|
|
GuidVector enemies = AI_VALUE(GuidVector, "possible targets");
|
|
|
|
for (ObjectGuid const& guid : enemies)
|
|
{
|
|
Unit* enemy = botAI->GetUnit(guid);
|
|
if (!enemy || !enemy->IsAlive() || enemy->IsFriendlyTo(bot))
|
|
continue;
|
|
|
|
if (bot->IsWithinDistInMap(enemy, 25.0f) &&
|
|
(enemy->HasAura(642) || // Divine Shield
|
|
enemy->HasAura(45438) || // Ice Block
|
|
enemy->HasAura(41450))) // Blessing of Protection
|
|
{
|
|
return enemy;
|
|
}
|
|
}
|
|
|
|
return nullptr; // No valid target
|
|
}
|
|
|
|
bool CastShatteringThrowAction::isUseful()
|
|
{
|
|
|
|
// Spell cooldown check
|
|
if (!bot->HasSpell(64382))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Spell cooldown check
|
|
if (bot->HasSpellCooldown(64382))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
GuidVector enemies = AI_VALUE(GuidVector, "possible targets");
|
|
|
|
for (ObjectGuid const& guid : enemies)
|
|
{
|
|
Unit* enemy = botAI->GetUnit(guid);
|
|
if (!enemy || !enemy->IsAlive() || enemy->IsFriendlyTo(bot))
|
|
continue;
|
|
|
|
// Check if the enemy is within 25 yards and has the specific auras
|
|
if (bot->IsWithinDistInMap(enemy, 25.0f) &&
|
|
(enemy->HasAura(642) || // Divine Shield
|
|
enemy->HasAura(45438) || // Ice Block
|
|
enemy->HasAura(41450))) // Blessing of Protection
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false; // No valid targets within range
|
|
}
|
|
|
|
bool CastShatteringThrowAction::isPossible()
|
|
{
|
|
Unit* target = GetTarget();
|
|
if (!target)
|
|
return false;
|
|
|
|
// Range check: Shattering Throw is 30 yards
|
|
if (!bot->IsWithinDistInMap(target, 30.0f))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Check line of sight
|
|
if (!bot->IsWithinLOSInMap(target))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// If the minimal checks above pass, simply return true.
|
|
return true;
|
|
}
|
|
|
|
bool CastShatteringThrowAction::Execute(Event event)
|
|
{
|
|
Unit* target = GetTarget();
|
|
if (!target)
|
|
return false;
|
|
|
|
return botAI->CastSpell("shattering throw", target);
|
|
}
|