Skip to content

Commit

Permalink
Core/PlayerAI: More follow-up. Helper functions and some internal cle…
Browse files Browse the repository at this point in the history
…anup.

(cherry picked from commit 5a3a21c)
  • Loading branch information
Treeston authored and Shauren committed Apr 8, 2016
1 parent adc7ee0 commit f5a1b75
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 38 deletions.
93 changes: 59 additions & 34 deletions src/server/game/AI/PlayerAI/PlayerAI.cpp
Expand Up @@ -26,54 +26,79 @@ enum Spells
SPELL_SHOOT = 3018,
SPELL_THROW = 2764,
SPELL_SHOOT_WAND = 5019,

/* Paladin */
PASSIVE_ILLUMINATION = 20215,

/* Priest */
SPELL_SOUL_WARDING = 63574,
SPELL_SPIRIT_REDEMPTION = 20711,
SPELL_SHADOWFORM = 15473,

/* Shaman */
SPELL_TIDAL_FORCE = 582,
SPELL_MANA_TIDE_TOTEM = 590,
SPELL_SHA_NATURE_SWIFT = 591,
SPELL_STORMSTRIKE = 17364,

/* Druid */
SPELL_MOONKIN_FORM = 24858,
SPELL_SWIFTMEND = 18562,
SPELL_DRU_NATURE_SWIFT = 17116,
SPELL_TREE_OF_LIFE = 33891
};
PlayerAI::PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _isRangedAttacker(false)

bool PlayerAI::IsPlayerHealer(Player const* who)
{
switch (who->getClass())
{
case CLASS_WARRIOR:
case CLASS_HUNTER:
case CLASS_ROGUE:
case CLASS_DEATH_KNIGHT:
case CLASS_MAGE:
case CLASS_WARLOCK:
default:
return false;
case CLASS_PALADIN:
return who->HasSpell(PASSIVE_ILLUMINATION);
case CLASS_PRIEST:
return who->HasSpell(SPELL_SOUL_WARDING) || who->HasSpell(SPELL_SPIRIT_REDEMPTION);
case CLASS_SHAMAN:
return who->HasSpell(SPELL_MANA_TIDE_TOTEM) || who->HasSpell(SPELL_SHA_NATURE_SWIFT) || who->HasSpell(SPELL_TIDAL_FORCE);
case CLASS_DRUID:
return who->HasSpell(SPELL_SWIFTMEND) || who->HasSpell(SPELL_DRU_NATURE_SWIFT) || who->HasSpell(SPELL_TREE_OF_LIFE);
}
}

bool PlayerAI::IsPlayerRangedAttacker(Player const* who)
{
switch (me->getClass())
switch (who->getClass())
{
case CLASS_WARRIOR:
_isRangedAttacker = false;
break;
case CLASS_PALADIN:
_isRangedAttacker = false;
break;
case CLASS_ROGUE:
case CLASS_DEATH_KNIGHT:
default:
return false;
case CLASS_MAGE:
case CLASS_WARLOCK:
return true;
case CLASS_HUNTER:
{
// check if we have a ranged weapon equipped
Item const* rangedSlot = me->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
Item const* rangedSlot = who->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_RANGED);
if (ItemTemplate const* rangedTemplate = rangedSlot ? rangedSlot->GetTemplate() : nullptr)
if ((1 << rangedTemplate->GetSubClass()) & ITEM_SUBCLASS_MASK_WEAPON_RANGED)
{
_isRangedAttacker = true;
break;
}
_isRangedAttacker = false;
break;
return true;
return false;
}
case CLASS_ROGUE:
_isRangedAttacker = false;
break;
case CLASS_PRIEST:
_isRangedAttacker = me->GetSpecId(me->GetActiveTalentGroup()) == TALENT_SPEC_PRIEST_SHADOW;
break;
case CLASS_DEATH_KNIGHT:
_isRangedAttacker = false;
break;
return who->HasSpell(SPELL_SHADOWFORM);
case CLASS_SHAMAN:
_isRangedAttacker = me->GetSpecId(me->GetActiveTalentGroup()) == TALENT_SPEC_SHAMAN_ELEMENTAL;
break;
case CLASS_MAGE:
_isRangedAttacker = true;
break;
case CLASS_WARLOCK:
_isRangedAttacker = true;
break;
return !who->HasSpell(SPELL_STORMSTRIKE);
case CLASS_DRUID:
_isRangedAttacker = me->GetSpecId(me->GetActiveTalentGroup()) == TALENT_SPEC_DRUID_BALANCE;
break;
default:
TC_LOG_WARN("entities.unit", "Possessed player %s (possessed by %s) does not have any recognized class (class = %u).", me->GetGUID().ToString().c_str(), me->GetCharmerGUID().ToString().c_str(), me->getClass());
break;
return who->HasSpell(SPELL_MOONKIN_FORM);
}
}

Expand Down
14 changes: 10 additions & 4 deletions src/server/game/AI/PlayerAI/PlayerAI.h
Expand Up @@ -25,20 +25,26 @@
class TC_GAME_API PlayerAI : public UnitAI
{
public:
explicit PlayerAI(Player* player);
explicit PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _isSelfHealer(PlayerAI::IsPlayerHealer(player)), _isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player)) { }

void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy

// helper functions to determine player info
static bool IsPlayerHealer(Player const* who);
bool IsHealer(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfHealer : IsPlayerHealer(who); }
static bool IsPlayerRangedAttacker(Player const* who);
bool IsRangedAttacker(Player const* who = nullptr) const { return (!who || who == me) ? _isSelfRangedAttacker : IsPlayerRangedAttacker(who); }

protected:
Player* const me;
void SetIsRangedAttacker(bool state) { _isRangedAttacker = state; }
bool IsRangedAttacker() const { return _isRangedAttacker; }
void SetIsRangedAttacker(bool state) { _isSelfRangedAttacker = state; } // this allows overriding of the default ranged attacker detection

void DoRangedAttackIfReady();
void DoAutoAttackIfReady();

private:
bool _isRangedAttacker;
bool _isSelfHealer;
bool _isSelfRangedAttacker;
};

class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI
Expand Down

0 comments on commit f5a1b75

Please sign in to comment.