Merge branch 'master' into Playerbot
This commit is contained in:
@@ -42,7 +42,7 @@ bool ArenaSpectator::HandleSpectatorSpectateCommand(ChatHandler* handler, std::s
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player->getClass() == CLASS_DEATH_KNIGHT && player->GetMapId() == 609)
|
||||
if (player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && player->GetMapId() == 609)
|
||||
{
|
||||
handler->PSendSysMessage("Death Knights can't spectate before finishing questline.");
|
||||
return true;
|
||||
|
||||
@@ -1055,7 +1055,7 @@ namespace lfg
|
||||
baseAP = p->GetTotalAttackPowerValue(BASE_ATTACK);
|
||||
rangedAP = p->GetTotalAttackPowerValue(RANGED_ATTACK);
|
||||
maxPower = 0;
|
||||
if (p->getClass() == CLASS_DRUID)
|
||||
if (p->IsClass(CLASS_DRUID))
|
||||
maxPower = p->GetMaxPower(POWER_MANA);
|
||||
else
|
||||
maxPower = (p->getPowerType() == POWER_RAGE || p->getPowerType() == POWER_RUNIC_POWER) ? p->GetMaxPower(p->getPowerType()) / 10 : p->GetMaxPower(p->getPowerType());
|
||||
|
||||
@@ -1196,8 +1196,8 @@ bool Creature::isCanInteractWithBattleMaster(Player* player, bool msg) const
|
||||
bool Creature::isCanTrainingAndResetTalentsOf(Player* player) const
|
||||
{
|
||||
return player->GetLevel() >= 10
|
||||
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
|
||||
&& player->getClass() == GetCreatureTemplate()->trainer_class;
|
||||
&& GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS
|
||||
&& player->IsClass((Classes)GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER);
|
||||
}
|
||||
|
||||
bool Creature::IsValidTrainerForPlayer(Player* player, uint32* npcFlags /*= nullptr*/) const
|
||||
@@ -1211,7 +1211,7 @@ bool Creature::IsValidTrainerForPlayer(Player* player, uint32* npcFlags /*= null
|
||||
{
|
||||
case TRAINER_TYPE_CLASS:
|
||||
case TRAINER_TYPE_PETS:
|
||||
if (m_creatureInfo->trainer_class && m_creatureInfo->trainer_class != player->getClass())
|
||||
if (m_creatureInfo->trainer_class && !player->IsClass((Classes)m_creatureInfo->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
|
||||
{
|
||||
if (npcFlags)
|
||||
*npcFlags &= ~UNIT_NPC_FLAG_TRAINER_CLASS;
|
||||
|
||||
@@ -107,7 +107,7 @@ void Pet::AddToWorld()
|
||||
{
|
||||
if (Player* owner = GetOwner())
|
||||
{
|
||||
if (getPetType() == SUMMON_PET && owner->getClass() == CLASS_WARLOCK)
|
||||
if (getPetType() == SUMMON_PET && owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET))
|
||||
{
|
||||
owner->SetLastPetSpell(GetUInt32Value(UNIT_CREATED_BY_SPELL));
|
||||
}
|
||||
@@ -238,7 +238,7 @@ bool Pet::LoadPetFromDB(Player* owner, uint32 petEntry, uint32 petnumber, bool c
|
||||
bool forceLoadFromDB = false;
|
||||
sScriptMgr->OnBeforeLoadPetFromDB(owner, petEntry, petnumber, current, forceLoadFromDB);
|
||||
|
||||
if (!forceLoadFromDB && (owner->getClass() == CLASS_DEATH_KNIGHT && !owner->CanSeeDKPet())) // DK Pet exception
|
||||
if (!forceLoadFromDB && (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) && !owner->CanSeeDKPet())) // DK Pet exception
|
||||
return false;
|
||||
|
||||
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(petInfo->CreatedBySpellId);
|
||||
@@ -1043,12 +1043,12 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
||||
if (petType == MAX_PET_TYPE)
|
||||
{
|
||||
// The petType was not overwritten by the hook, continue with default initialization
|
||||
if (owner->getClass() == CLASS_WARLOCK ||
|
||||
owner->getClass() == CLASS_SHAMAN || // Fire Elemental
|
||||
owner->getClass() == CLASS_DEATH_KNIGHT || // Risen Ghoul
|
||||
owner->getClass() == CLASS_MAGE) // Water Elemental with glyph
|
||||
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET) ||
|
||||
owner->IsClass(CLASS_SHAMAN, CLASS_CONTEXT_PET) || // Fire Elemental
|
||||
owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET) || // Risen Ghoul
|
||||
owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET)) // Water Elemental with glyph
|
||||
petType = SUMMON_PET;
|
||||
else if (owner->getClass() == CLASS_HUNTER)
|
||||
else if (owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
{
|
||||
petType = HUNTER_PET;
|
||||
}
|
||||
@@ -1080,7 +1080,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
|
||||
SetModifierValue(UNIT_MOD_ARMOR, BASE_VALUE, float(petlevel * 50));
|
||||
|
||||
uint32 attackTime = BASE_ATTACK_TIME;
|
||||
if (owner->getClass() != CLASS_HUNTER && cinfo->BaseAttackTime >= 1000)
|
||||
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET) && cinfo->BaseAttackTime >= 1000)
|
||||
attackTime = cinfo->BaseAttackTime;
|
||||
|
||||
SetAttackTime(BASE_ATTACK, attackTime);
|
||||
@@ -2299,17 +2299,14 @@ bool Pet::IsPermanentPetFor(Player* owner) const
|
||||
switch (getPetType())
|
||||
{
|
||||
case SUMMON_PET:
|
||||
switch (owner->getClass())
|
||||
{
|
||||
case CLASS_WARLOCK:
|
||||
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
|
||||
case CLASS_MAGE:
|
||||
return GetEntry() == 37994;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
if (owner->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET))
|
||||
return GetCreatureTemplate()->type == CREATURE_TYPE_DEMON;
|
||||
else if (owner->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
|
||||
return GetCreatureTemplate()->type == CREATURE_TYPE_UNDEAD;
|
||||
else if (owner->IsClass(CLASS_MAGE, CLASS_CONTEXT_PET))
|
||||
return GetEntry() == 37994;
|
||||
else
|
||||
return false;
|
||||
case HUNTER_PET:
|
||||
return true;
|
||||
default:
|
||||
|
||||
@@ -204,12 +204,13 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon)
|
||||
if (_victim->GetTypeId() == TYPEID_PLAYER)
|
||||
player->KilledPlayerCredit();
|
||||
}
|
||||
|
||||
// Give XP only in PvE or in battlegrounds.
|
||||
// Give reputation and kill credit only in PvE.
|
||||
if (!_isPvP || _isBattleGround)
|
||||
{
|
||||
float xpRate = _group ? _groupRate * float(player->GetLevel()) / _aliveSumLevel : /*Personal rate is 100%.*/ 1.0f; // Group rate depends on the sum of levels.
|
||||
sScriptMgr->OnRewardKillRewarder(player, isDungeon, xpRate); // Personal rate is 100%.
|
||||
sScriptMgr->OnRewardKillRewarder(player, this, isDungeon, xpRate); // Personal rate is 100%.
|
||||
|
||||
if (_xp)
|
||||
{
|
||||
@@ -290,3 +291,13 @@ void KillRewarder::Reward()
|
||||
if (Map* map = _victim->FindMap())
|
||||
map->UpdateEncounterState(ENCOUNTER_CREDIT_KILL_CREATURE, _victim->GetEntry(), _victim);
|
||||
}
|
||||
|
||||
Unit* KillRewarder::GetVictim()
|
||||
{
|
||||
return _victim;
|
||||
}
|
||||
|
||||
Player* KillRewarder::GetKiller()
|
||||
{
|
||||
return _killer;
|
||||
}
|
||||
|
||||
@@ -30,6 +30,8 @@ public:
|
||||
KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
|
||||
|
||||
void Reward();
|
||||
Unit* GetVictim();
|
||||
Player* GetKiller();
|
||||
|
||||
private:
|
||||
void _InitXP(Player* player);
|
||||
|
||||
@@ -553,7 +553,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
||||
SetUInt32Value(PLAYER_FIELD_YESTERDAY_CONTRIBUTION, 0);
|
||||
|
||||
// set starting level
|
||||
uint32 start_level = getClass() != CLASS_DEATH_KNIGHT
|
||||
uint32 start_level = !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_LEVEL)
|
||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_LEVEL);
|
||||
|
||||
@@ -568,7 +568,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
||||
|
||||
InitRunes();
|
||||
|
||||
SetUInt32Value(PLAYER_FIELD_COINAGE, getClass() != CLASS_DEATH_KNIGHT
|
||||
SetUInt32Value(PLAYER_FIELD_COINAGE, !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT)
|
||||
? sWorld->getIntConfig(CONFIG_START_PLAYER_MONEY)
|
||||
: sWorld->getIntConfig(CONFIG_START_HEROIC_PLAYER_MONEY));
|
||||
SetHonorPoints(sWorld->getIntConfig(CONFIG_START_HONOR_POINTS));
|
||||
@@ -587,13 +587,13 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
||||
InitPrimaryProfessions(); // to max set before any spell added
|
||||
|
||||
// apply original stats mods before spell loading or item equipment that call before equip _RemoveStatsMods()
|
||||
if (getPowerType() == POWER_MANA)
|
||||
if (HasActivePowerType(POWER_MANA))
|
||||
{
|
||||
UpdateMaxPower(POWER_MANA); // Update max Mana (for add bonus from intellect)
|
||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
||||
}
|
||||
|
||||
if (getPowerType() == POWER_RUNIC_POWER)
|
||||
if (HasActivePowerType(POWER_RUNIC_POWER))
|
||||
{
|
||||
SetPower(POWER_RUNE, 8);
|
||||
SetMaxPower(POWER_RUNE, 8);
|
||||
@@ -633,7 +633,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, CharacterCreateInfo* createInfo
|
||||
switch (iProto->Spells[0].SpellCategory)
|
||||
{
|
||||
case SPELL_CATEGORY_FOOD: // food
|
||||
count = getClass() == CLASS_DEATH_KNIGHT ? 10 : 4;
|
||||
count = IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) ? 10 : 4;
|
||||
break;
|
||||
case SPELL_CATEGORY_DRINK: // drink
|
||||
count = 2;
|
||||
@@ -1269,6 +1269,15 @@ bool Player::BuildEnumData(PreparedQueryResult result, WorldPacket* data)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::IsClass(Classes unitClass, ClassContext context) const
|
||||
{
|
||||
Optional<bool> scriptResult = sScriptMgr->OnPlayerIsClass(this, unitClass, context);
|
||||
if (scriptResult != std::nullopt)
|
||||
return *scriptResult;
|
||||
else
|
||||
return (getClass() == unitClass);
|
||||
}
|
||||
|
||||
void Player::ToggleAFK()
|
||||
{
|
||||
ToggleFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
|
||||
@@ -1460,7 +1469,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
|
||||
}
|
||||
else
|
||||
{
|
||||
if (getClass() == CLASS_DEATH_KNIGHT && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && GetMapId() == 609 && !IsGameMaster() && !HasSpell(50977))
|
||||
{
|
||||
SendTransferAborted(mapid, TRANSFER_ABORT_UNIQUE_MESSAGE, 1);
|
||||
return false;
|
||||
@@ -1745,7 +1754,7 @@ void Player::RegenerateAll()
|
||||
Regenerate(POWER_MANA);
|
||||
|
||||
// Runes act as cooldowns, and they don't need to send any data
|
||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
{
|
||||
// xinef: implement grace
|
||||
@@ -1775,7 +1784,7 @@ void Player::RegenerateAll()
|
||||
}
|
||||
|
||||
Regenerate(POWER_RAGE);
|
||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
Regenerate(POWER_RUNIC_POWER);
|
||||
|
||||
m_regenTimerCount -= 2000;
|
||||
@@ -2019,22 +2028,21 @@ void Player::RegenerateHealth()
|
||||
void Player::ResetAllPowers()
|
||||
{
|
||||
SetHealth(GetMaxHealth());
|
||||
switch (getPowerType())
|
||||
if (HasActivePowerType(POWER_MANA))
|
||||
{
|
||||
case POWER_MANA:
|
||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
||||
break;
|
||||
case POWER_RAGE:
|
||||
SetPower(POWER_RAGE, 0);
|
||||
break;
|
||||
case POWER_ENERGY:
|
||||
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
|
||||
break;
|
||||
case POWER_RUNIC_POWER:
|
||||
SetPower(POWER_RUNIC_POWER, 0);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
SetPower(POWER_MANA, GetMaxPower(POWER_MANA));
|
||||
}
|
||||
if (HasActivePowerType(POWER_RAGE))
|
||||
{
|
||||
SetPower(POWER_RAGE, 0);
|
||||
}
|
||||
if (HasActivePowerType(POWER_ENERGY))
|
||||
{
|
||||
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
|
||||
}
|
||||
if (HasActivePowerType(POWER_RUNIC_POWER))
|
||||
{
|
||||
SetPower(POWER_RUNIC_POWER, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2107,7 +2115,7 @@ Creature* Player::GetNPCIfCanInteractWith(ObjectGuid guid, uint32 npcflagmask)
|
||||
|
||||
// pussywizard: many npcs have missing conditions for class training and rogue trainer can for eg. train dual wield to a shaman :/ too many to change in sql and watch in the future
|
||||
// pussywizard: this function is not used when talking, but when already taking action (buy spell, reset talents, show spell list)
|
||||
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && getClass() != creature->GetCreatureTemplate()->trainer_class)
|
||||
if (npcflagmask & (UNIT_NPC_FLAG_TRAINER | UNIT_NPC_FLAG_TRAINER_CLASS) && creature->GetCreatureTemplate()->trainer_type == TRAINER_TYPE_CLASS && !IsClass((Classes)creature->GetCreatureTemplate()->trainer_class, CLASS_CONTEXT_CLASS_TRAINER))
|
||||
return nullptr;
|
||||
|
||||
return creature;
|
||||
@@ -2714,6 +2722,14 @@ void Player::InitStatsForLevel(bool reapplyMods)
|
||||
pet->SynchronizeLevelWithOwner();
|
||||
}
|
||||
|
||||
bool Player::HasActivePowerType(Powers power)
|
||||
{
|
||||
if (sScriptMgr->OnPlayerHasActivePowerType(this, power))
|
||||
return true;
|
||||
else
|
||||
return (getPowerType() == power);
|
||||
}
|
||||
|
||||
void Player::SendInitialSpells()
|
||||
{
|
||||
uint32 curTime = GameTime::GetGameTimeMS().count();
|
||||
@@ -6388,7 +6404,7 @@ void Player::DuelComplete(DuelCompleteType type)
|
||||
opponent->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL, 1);
|
||||
|
||||
// Credit for quest Death's Challenge
|
||||
if (getClass() == CLASS_DEATH_KNIGHT && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_QUEST) && opponent->GetQuestStatus(12733) == QUEST_STATUS_INCOMPLETE)
|
||||
{
|
||||
opponent->CastSpell(opponent, 52994, true);
|
||||
}
|
||||
@@ -6784,7 +6800,7 @@ void Player::_ApplyItemBonuses(ItemTemplate const* proto, uint8 slot, bool apply
|
||||
}
|
||||
|
||||
// Druids get feral AP bonus from weapon dps (also use DPS from ScalingStatValue)
|
||||
if (getClass() == CLASS_DRUID)
|
||||
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
int32 dpsMod = 0;
|
||||
int32 feral_bonus = 0;
|
||||
@@ -9841,7 +9857,7 @@ void Player::AddSpellMod(SpellModifier* mod, bool apply)
|
||||
if (apply)
|
||||
{
|
||||
m_spellMods[mod->op].push_back(mod);
|
||||
if (getClass() == CLASS_MAGE)
|
||||
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_ABILITY))
|
||||
m_spellMods[mod->op].sort(MageSpellModPred());
|
||||
else
|
||||
m_spellMods[mod->op].sort(SpellModPred());
|
||||
@@ -10275,7 +10291,7 @@ bool Player::ActivateTaxiPathTo(std::vector<uint32> const& nodes, Creature* npc
|
||||
// only one mount ID for both sides. Probably not good to use 315 in case DBC nodes
|
||||
// change but I couldn't find a suitable alternative. OK to use class because only DK
|
||||
// can use this taxi.
|
||||
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == nullptr || (sourcenode == 315 && getClass() == CLASS_DEATH_KNIGHT));
|
||||
uint32 mount_display_id = sObjectMgr->GetTaxiMountDisplayId(sourcenode, GetTeamId(true), npc == nullptr || (sourcenode == 315 && IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TAXI)));
|
||||
|
||||
// in spell case allow 0 model
|
||||
if ((mount_display_id == 0 && spellid == 0) || sourcepath == 0)
|
||||
@@ -11324,7 +11340,7 @@ WorldLocation Player::GetStartPosition() const
|
||||
{
|
||||
PlayerInfo const* info = sObjectMgr->GetPlayerInfo(getRace(true), getClass());
|
||||
uint32 mapId = info->mapId;
|
||||
if (getClass() == CLASS_DEATH_KNIGHT && HasSpell(50977))
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_INIT) && HasSpell(50977))
|
||||
return WorldLocation(0, 2352.0f, -5709.0f, 154.5f, 0.0f);
|
||||
return WorldLocation(mapId, info->positionX, info->positionY, info->positionZ, 0);
|
||||
}
|
||||
@@ -11818,7 +11834,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
|
||||
{
|
||||
skillValue = maxValue;
|
||||
}
|
||||
else if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
else if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_SKILL))
|
||||
{
|
||||
skillValue = std::min(std::max<uint16>({ 1, uint16((GetLevel() - 1) * 5) }), maxValue);
|
||||
}
|
||||
@@ -11851,7 +11867,7 @@ void Player::LearnDefaultSkill(uint32 skillId, uint16 rank)
|
||||
{
|
||||
skillValue = maxValue;
|
||||
}
|
||||
else if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
else if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_SKILL))
|
||||
{
|
||||
skillValue = std::min(std::max<uint16>({ uint16(1), uint16((GetLevel() - 1) * 5) }), maxValue);
|
||||
}
|
||||
@@ -13376,7 +13392,7 @@ static RuneType runeSlotTypes[MAX_RUNES] =
|
||||
|
||||
void Player::InitRunes()
|
||||
{
|
||||
if (getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
m_runes = new Runes;
|
||||
@@ -13542,7 +13558,7 @@ uint32 Player::CalculateTalentsPoints() const
|
||||
uint32 base_talent = GetLevel() < 10 ? 0 : GetLevel() - 9;
|
||||
|
||||
uint32 talentPointsForLevel = 0;
|
||||
if (getClass() != CLASS_DEATH_KNIGHT || GetMapId() != 609)
|
||||
if (!IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TALENT_POINT_CALC) || GetMapId() != 609)
|
||||
{
|
||||
talentPointsForLevel = base_talent;
|
||||
}
|
||||
@@ -14174,19 +14190,21 @@ void Player::ResummonPetTemporaryUnSummonedIfAny()
|
||||
|
||||
bool Player::CanResummonPet(uint32 spellid)
|
||||
{
|
||||
if (getClass() == CLASS_DEATH_KNIGHT)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_PET))
|
||||
{
|
||||
if (CanSeeDKPet())
|
||||
return true;
|
||||
else if (spellid == 52150) // Raise Dead
|
||||
return false;
|
||||
}
|
||||
else if (getClass() == CLASS_MAGE)
|
||||
|
||||
if (IsClass(CLASS_MAGE, CLASS_CONTEXT_PET))
|
||||
{
|
||||
if (HasSpell(31687) && HasAura(70937)) //Has [Summon Water Elemental] spell and [Glyph of Eternal Water].
|
||||
return true;
|
||||
}
|
||||
else if (getClass() == CLASS_HUNTER)
|
||||
|
||||
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -15171,7 +15189,7 @@ void Player::ActivateSpec(uint8 spec)
|
||||
AutoUnequipOffhandIfNeed();
|
||||
|
||||
// Xinef: Patch 3.2.0: Switching spec removes paladins spell Righteous Fury (25780)
|
||||
if (getClass() == CLASS_PALADIN)
|
||||
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_ABILITY))
|
||||
RemoveAurasDueToSpell(25780);
|
||||
|
||||
// Xinef: Remove talented single target auras at other targets
|
||||
|
||||
@@ -1112,6 +1112,8 @@ public:
|
||||
|
||||
static bool BuildEnumData(PreparedQueryResult result, WorldPacket* data);
|
||||
|
||||
[[nodiscard]] bool IsClass(Classes playerClass, ClassContext context = CLASS_CONTEXT_NONE) const override;
|
||||
|
||||
void SetInWater(bool apply);
|
||||
|
||||
[[nodiscard]] bool IsInWater() const override { return m_isInWater; }
|
||||
@@ -1170,6 +1172,8 @@ public:
|
||||
|
||||
void InitStatsForLevel(bool reapplyMods = false);
|
||||
|
||||
[[nodiscard]] bool HasActivePowerType(Powers power) override;
|
||||
|
||||
// .cheat command related
|
||||
[[nodiscard]] bool GetCommandStatus(uint32 command) const { return _activeCheats & command; }
|
||||
void SetCommandStatusOn(uint32 command) { _activeCheats |= command; }
|
||||
|
||||
@@ -109,7 +109,7 @@ void Player::PrepareGossipMenu(WorldObject* source, uint32 menuId /*= 0*/, bool
|
||||
canTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_STABLEPET:
|
||||
if (getClass() != CLASS_HUNTER)
|
||||
if (!IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
canTalk = false;
|
||||
break;
|
||||
case GOSSIP_OPTION_QUESTGIVER:
|
||||
|
||||
@@ -133,8 +133,6 @@ void Player::SetSheath(SheathState sheathed)
|
||||
|
||||
uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) const
|
||||
{
|
||||
uint8 playerClass = getClass();
|
||||
|
||||
uint8 slots[4];
|
||||
slots[0] = NULL_SLOT;
|
||||
slots[1] = NULL_SLOT;
|
||||
@@ -246,23 +244,23 @@ uint8 Player::FindEquipSlot(ItemTemplate const* proto, uint32 slot, bool swap) c
|
||||
switch (proto->SubClass)
|
||||
{
|
||||
case ITEM_SUBCLASS_ARMOR_LIBRAM:
|
||||
if (playerClass == CLASS_PALADIN)
|
||||
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||
break;
|
||||
case ITEM_SUBCLASS_ARMOR_IDOL:
|
||||
if (playerClass == CLASS_DRUID)
|
||||
if (IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||
break;
|
||||
case ITEM_SUBCLASS_ARMOR_TOTEM:
|
||||
if (playerClass == CLASS_SHAMAN)
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||
break;
|
||||
case ITEM_SUBCLASS_ARMOR_MISC:
|
||||
if (playerClass == CLASS_WARLOCK)
|
||||
if (IsClass(CLASS_WARLOCK, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||
break;
|
||||
case ITEM_SUBCLASS_ARMOR_SIGIL:
|
||||
if (playerClass == CLASS_DEATH_KNIGHT)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
slots[0] = EQUIPMENT_SLOT_RANGED;
|
||||
break;
|
||||
}
|
||||
@@ -2270,16 +2268,13 @@ InventoryResult Player::CanUseItem(Item* pItem, bool not_loading) const
|
||||
// In fact it's a visual bug, everything works properly... I need sniffs of operations with
|
||||
// binded to account items from off server.
|
||||
|
||||
switch (getClass())
|
||||
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_SHAMAN:
|
||||
allowEquip = (itemSkill == SKILL_MAIL);
|
||||
break;
|
||||
case CLASS_PALADIN:
|
||||
case CLASS_WARRIOR:
|
||||
allowEquip = (itemSkill == SKILL_PLATE_MAIL);
|
||||
break;
|
||||
allowEquip = (itemSkill == SKILL_PLATE_MAIL);
|
||||
}
|
||||
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
allowEquip = (itemSkill == SKILL_MAIL);
|
||||
}
|
||||
}
|
||||
if (!allowEquip && GetSkillValue(itemSkill) == 0)
|
||||
@@ -2394,39 +2389,40 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
|
||||
return EQUIP_ERR_CANT_EQUIP_SKILL;
|
||||
}
|
||||
|
||||
uint8 _class = getClass();
|
||||
|
||||
if (proto->Class == ITEM_CLASS_WEAPON && GetSkillValue(item_weapon_skills[proto->SubClass]) == 0)
|
||||
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
||||
|
||||
if (proto->Class == ITEM_CLASS_ARMOR)
|
||||
{
|
||||
// Check for shields
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD && !(_class == CLASS_PALADIN || _class == CLASS_WARRIOR || _class == CLASS_SHAMAN))
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SHIELD && !(
|
||||
IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_SHIELDS)
|
||||
|| IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_SHIELDS)
|
||||
|| IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_SHIELDS)))
|
||||
{
|
||||
return EQUIP_ERR_NO_REQUIRED_PROFICIENCY;
|
||||
}
|
||||
|
||||
// Check for librams.
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_LIBRAM && _class != CLASS_PALADIN)
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_LIBRAM && !IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
{
|
||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||
}
|
||||
|
||||
// CHeck for idols.
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_IDOL && _class != CLASS_DRUID)
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_IDOL && !IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
{
|
||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||
}
|
||||
|
||||
// Check for totems.
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_TOTEM && _class != CLASS_SHAMAN)
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_TOTEM && !IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
{
|
||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||
}
|
||||
|
||||
// Check for sigils.
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SIGIL && _class != CLASS_DEATH_KNIGHT)
|
||||
if (proto->SubClass == ITEM_SUBCLASS_ARMOR_SIGIL && !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_RELIC))
|
||||
{
|
||||
return EQUIP_ERR_YOU_CAN_NEVER_USE_THAT_ITEM;
|
||||
}
|
||||
@@ -2436,33 +2432,33 @@ InventoryResult Player::CanRollForItemInLFG(ItemTemplate const* proto, WorldObje
|
||||
proto->InventoryType != INVTYPE_CLOAK)
|
||||
{
|
||||
uint32 subclassToCompare = ITEM_SUBCLASS_ARMOR_CLOTH;
|
||||
switch (_class)
|
||||
if (IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
case CLASS_WARRIOR:
|
||||
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
||||
{
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
case CLASS_PALADIN:
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_SHAMAN:
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
||||
{
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
}
|
||||
[[fallthrough]];
|
||||
case CLASS_DRUID:
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
||||
}
|
||||
else if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
if ((proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat()))
|
||||
{
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
}
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_PLATE;
|
||||
}
|
||||
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_EQUIP_ARMOR_CLASS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_MAIL;
|
||||
}
|
||||
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
||||
}
|
||||
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_EQUIP_ARMOR_CLASS))
|
||||
{
|
||||
if (proto->HasStat(ITEM_MOD_SPELL_POWER) || proto->HasSpellPowerStat())
|
||||
{
|
||||
return EQUIP_ERR_CANT_DO_RIGHT_NOW;
|
||||
}
|
||||
subclassToCompare = ITEM_SUBCLASS_ARMOR_LEATHER;
|
||||
}
|
||||
|
||||
if (proto->SubClass > subclassToCompare)
|
||||
@@ -2772,7 +2768,7 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
|
||||
|
||||
if (pProto && IsInCombat() && (pProto->Class == ITEM_CLASS_WEAPON || pProto->InventoryType == INVTYPE_RELIC) && m_weaponChangeTimer == 0)
|
||||
{
|
||||
uint32 cooldownSpell = getClass() == CLASS_ROGUE ? 6123 : 6119;
|
||||
uint32 cooldownSpell = IsClass(CLASS_ROGUE, CLASS_CONTEXT_WEAPON_SWAP) ? 6123 : 6119;
|
||||
SpellInfo const* spellProto = sSpellMgr->GetSpellInfo(cooldownSpell);
|
||||
|
||||
if (!spellProto)
|
||||
@@ -4645,7 +4641,7 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
|
||||
}
|
||||
case ITEM_ENCHANTMENT_TYPE_TOTEM: // Shaman Rockbiter Weapon
|
||||
{
|
||||
if (getClass() == CLASS_SHAMAN)
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_ABILITY))
|
||||
{
|
||||
float addValue = 0.0f;
|
||||
if (item->GetSlot() == EQUIPMENT_SLOT_MAINHAND)
|
||||
|
||||
@@ -346,134 +346,127 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
||||
index_mod = UNIT_FIELD_RANGED_ATTACK_POWER_MODS;
|
||||
index_mult = UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER;
|
||||
|
||||
switch (getClass())
|
||||
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
case CLASS_HUNTER:
|
||||
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
|
||||
break;
|
||||
case CLASS_ROGUE:
|
||||
case CLASS_WARRIOR:
|
||||
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
switch (GetShapeshiftForm())
|
||||
{
|
||||
case FORM_CAT:
|
||||
case FORM_BEAR:
|
||||
case FORM_DIREBEAR:
|
||||
val2 = 0.0f;
|
||||
break;
|
||||
default:
|
||||
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
||||
break;
|
||||
}
|
||||
val2 = level * 2.0f + GetStat(STAT_AGILITY) - 10.0f;
|
||||
}
|
||||
else if (IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
val2 = level + GetStat(STAT_AGILITY) - 10.0f;
|
||||
}
|
||||
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
switch (GetShapeshiftForm())
|
||||
{
|
||||
case FORM_CAT:
|
||||
case FORM_BEAR:
|
||||
case FORM_DIREBEAR:
|
||||
val2 = 0.0f;
|
||||
break;
|
||||
default:
|
||||
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
val2 = GetStat(STAT_AGILITY) - 10.0f;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (getClass())
|
||||
if (IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS) || IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARRIOR, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
case CLASS_PALADIN:
|
||||
case CLASS_DEATH_KNIGHT:
|
||||
case CLASS_WARRIOR:
|
||||
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||
break;
|
||||
case CLASS_HUNTER:
|
||||
case CLASS_SHAMAN:
|
||||
case CLASS_ROGUE:
|
||||
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
|
||||
break;
|
||||
case CLASS_DRUID:
|
||||
val2 = level * 3.0f + GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||
}
|
||||
else if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_STATS) || IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_ROGUE, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f;
|
||||
}
|
||||
else if (IsClass(CLASS_DRUID, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
// Check if Predatory Strikes is skilled
|
||||
float mLevelMult = 0.0f;
|
||||
float weapon_bonus = 0.0f;
|
||||
if (IsInFeralForm())
|
||||
{
|
||||
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
|
||||
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
|
||||
{
|
||||
// Check if Predatory Strikes is skilled
|
||||
float mLevelMult = 0.0f;
|
||||
float weapon_bonus = 0.0f;
|
||||
if (IsInFeralForm())
|
||||
AuraEffect* aurEff = *itr;
|
||||
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
|
||||
{
|
||||
Unit::AuraEffectList const& mDummy = GetAuraEffectsByType(SPELL_AURA_DUMMY);
|
||||
for (Unit::AuraEffectList::const_iterator itr = mDummy.begin(); itr != mDummy.end(); ++itr)
|
||||
switch (aurEff->GetEffIndex())
|
||||
{
|
||||
AuraEffect* aurEff = *itr;
|
||||
if (aurEff->GetSpellInfo()->SpellIconID == 1563)
|
||||
case 0: // Predatory Strikes (effect 0)
|
||||
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
|
||||
break;
|
||||
case 1: // Predatory Strikes (effect 1)
|
||||
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
|
||||
{
|
||||
switch (aurEff->GetEffIndex())
|
||||
// also gains % attack power from equipped weapon
|
||||
ItemTemplate const* proto = mainHand->GetTemplate();
|
||||
if (!proto)
|
||||
continue;
|
||||
|
||||
uint32 ap = proto->getFeralBonus();
|
||||
// Get AP Bonuses from weapon
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
|
||||
{
|
||||
case 0: // Predatory Strikes (effect 0)
|
||||
mLevelMult = CalculatePct(1.0f, aurEff->GetAmount());
|
||||
if (i >= proto->StatsCount)
|
||||
break;
|
||||
case 1: // Predatory Strikes (effect 1)
|
||||
if (Item* mainHand = m_items[EQUIPMENT_SLOT_MAINHAND])
|
||||
{
|
||||
// also gains % attack power from equipped weapon
|
||||
ItemTemplate const* proto = mainHand->GetTemplate();
|
||||
if (!proto)
|
||||
continue;
|
||||
|
||||
uint32 ap = proto->getFeralBonus();
|
||||
// Get AP Bonuses from weapon
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
|
||||
{
|
||||
if (i >= proto->StatsCount)
|
||||
break;
|
||||
|
||||
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
|
||||
ap += proto->ItemStat[i].ItemStatValue;
|
||||
}
|
||||
|
||||
// Get AP Bonuses from weapon spells
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
||||
{
|
||||
// no spell
|
||||
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
|
||||
continue;
|
||||
|
||||
// check if it is valid spell
|
||||
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
|
||||
if (!spellproto)
|
||||
continue;
|
||||
|
||||
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
|
||||
ap += spellproto->Effects[j].CalcValue();
|
||||
}
|
||||
|
||||
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (proto->ItemStat[i].ItemStatType == ITEM_MOD_ATTACK_POWER)
|
||||
ap += proto->ItemStat[i].ItemStatValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (GetShapeshiftForm())
|
||||
{
|
||||
case FORM_CAT:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
|
||||
break;
|
||||
case FORM_BEAR:
|
||||
case FORM_DIREBEAR:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
|
||||
break;
|
||||
case FORM_MOONKIN:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
|
||||
// Get AP Bonuses from weapon spells
|
||||
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
|
||||
{
|
||||
// no spell
|
||||
if (!proto->Spells[i].SpellId || proto->Spells[i].SpellTrigger != ITEM_SPELLTRIGGER_ON_EQUIP)
|
||||
continue;
|
||||
|
||||
// check if it is valid spell
|
||||
SpellInfo const* spellproto = sSpellMgr->GetSpellInfo(proto->Spells[i].SpellId);
|
||||
if (!spellproto)
|
||||
continue;
|
||||
|
||||
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
|
||||
if (spellproto->Effects[j].ApplyAuraName == SPELL_AURA_MOD_ATTACK_POWER)
|
||||
ap += spellproto->Effects[j].CalcValue();
|
||||
}
|
||||
|
||||
weapon_bonus = CalculatePct(float(ap), aurEff->GetAmount());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLASS_MAGE:
|
||||
case CLASS_PRIEST:
|
||||
case CLASS_WARLOCK:
|
||||
val2 = GetStat(STAT_STRENGTH) - 10.0f;
|
||||
}
|
||||
|
||||
switch (GetShapeshiftForm())
|
||||
{
|
||||
case FORM_CAT:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f + GetStat(STAT_AGILITY) - 20.0f + weapon_bonus + m_baseFeralAP;
|
||||
break;
|
||||
case FORM_BEAR:
|
||||
case FORM_DIREBEAR:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + weapon_bonus + m_baseFeralAP;
|
||||
break;
|
||||
case FORM_MOONKIN:
|
||||
val2 = (GetLevel() * mLevelMult) + GetStat(STAT_STRENGTH) * 2.0f - 20.0f + m_baseFeralAP;
|
||||
break;
|
||||
default:
|
||||
val2 = GetStat(STAT_STRENGTH) * 2.0f - 20.0f;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (IsClass(CLASS_MAGE, CLASS_CONTEXT_STATS) || IsClass(CLASS_PRIEST, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARLOCK, CLASS_CONTEXT_STATS))
|
||||
{
|
||||
val2 = GetStat(STAT_STRENGTH) - 10.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,7 +514,7 @@ void Player::UpdateAttackPowerAndDamage(bool ranged)
|
||||
UpdateDamagePhysical(BASE_ATTACK);
|
||||
if (CanDualWield() && haveOffhandWeapon()) //allow update offhand damage only if player knows DualWield Spec and has equipped offhand weapon
|
||||
UpdateDamagePhysical(OFF_ATTACK);
|
||||
if (getClass() == CLASS_SHAMAN || getClass() == CLASS_PALADIN) // mental quickness
|
||||
if (IsClass(CLASS_SHAMAN, CLASS_CONTEXT_STATS) || IsClass(CLASS_PALADIN, CLASS_CONTEXT_STATS)) // mental quickness
|
||||
UpdateSpellDamageAndHealingBonus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -929,7 +929,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
}
|
||||
|
||||
// Rage from Damage made (only from direct weapon damage)
|
||||
if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->getPowerType() == POWER_RAGE)
|
||||
if (attacker && cleanDamage && damagetype == DIRECT_DAMAGE && attacker != victim && attacker->HasActivePowerType(POWER_RAGE))
|
||||
{
|
||||
uint32 weaponSpeedHitFactor;
|
||||
|
||||
@@ -957,10 +957,10 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
// Rage from absorbed damage
|
||||
if (cleanDamage && cleanDamage->absorbed_damage)
|
||||
{
|
||||
if (victim->getPowerType() == POWER_RAGE)
|
||||
if (victim->HasActivePowerType(POWER_RAGE))
|
||||
victim->RewardRage(cleanDamage->absorbed_damage, 0, false);
|
||||
|
||||
if (attacker && attacker->getPowerType() == POWER_RAGE )
|
||||
if (attacker && attacker->HasActivePowerType(POWER_RAGE))
|
||||
attacker->RewardRage(cleanDamage->absorbed_damage, 0, true);
|
||||
}
|
||||
|
||||
@@ -1083,7 +1083,7 @@ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage
|
||||
}
|
||||
|
||||
// Rage from damage received
|
||||
if (attacker != victim && victim->getPowerType() == POWER_RAGE)
|
||||
if (attacker != victim && victim->HasActivePowerType(POWER_RAGE))
|
||||
{
|
||||
uint32 rageDamage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
|
||||
victim->RewardRage(rageDamage, 0, false);
|
||||
@@ -6996,7 +6996,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
// Magic Absorption
|
||||
if (dummySpell->SpellIconID == 459) // only this spell has SpellIconID == 459 and dummy aura
|
||||
{
|
||||
if (getPowerType() != POWER_MANA)
|
||||
if (!HasActivePowerType(POWER_MANA))
|
||||
return false;
|
||||
|
||||
// mana reward
|
||||
@@ -7775,7 +7775,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
|
||||
// Judgement of Wisdom
|
||||
case 20186:
|
||||
{
|
||||
if (!victim || !victim->IsAlive() || victim->getPowerType() != POWER_MANA || victim->HasSpellCooldown(20268))
|
||||
if (!victim || !victim->IsAlive() || !victim->HasActivePowerType(POWER_MANA) || victim->HasSpellCooldown(20268))
|
||||
return false;
|
||||
|
||||
// 2% of base mana
|
||||
@@ -8834,7 +8834,7 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 damage, Aura* triggeredByAura, Sp
|
||||
// Convert recently used Blood Rune to Death Rune
|
||||
if (Player* player = ToPlayer())
|
||||
{
|
||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return false;
|
||||
|
||||
// xinef: not true
|
||||
@@ -9565,7 +9565,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
// Item - Death Knight T10 Melee 4P Bonus
|
||||
if (auraSpellInfo->Id == 70656)
|
||||
{
|
||||
if (GetTypeId() != TYPEID_PLAYER || getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (GetTypeId() != TYPEID_PLAYER || !IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return false;
|
||||
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
@@ -9576,7 +9576,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
|
||||
else if (auraSpellInfo->SpellIconID == 85)
|
||||
{
|
||||
Player* plr = ToPlayer();
|
||||
if (!plr || plr->getClass() != CLASS_DEATH_KNIGHT || !procSpell)
|
||||
if (!plr || !plr->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY) || !procSpell)
|
||||
return false;
|
||||
|
||||
if (!plr->IsBaseRuneSlotsOnCooldown(RUNE_BLOOD))
|
||||
@@ -13840,7 +13840,7 @@ void Unit::ClearInCombat()
|
||||
else if (Player* player = ToPlayer())
|
||||
{
|
||||
player->UpdatePotionCooldown();
|
||||
if (player->getClass() == CLASS_DEATH_KNIGHT)
|
||||
if (player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
for (uint8 i = 0; i < MAX_RUNES; ++i)
|
||||
player->SetGracePeriod(i, 0);
|
||||
}
|
||||
@@ -16378,7 +16378,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
if (procExtra & PROC_EX_DODGE)
|
||||
{
|
||||
// Update AURA_STATE on dodge
|
||||
if (getClass() != CLASS_ROGUE) // skip Rogue Riposte
|
||||
if (!IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY_REACTIVE)) // skip Rogue Riposte
|
||||
{
|
||||
ModifyAuraState(AURA_STATE_DEFENSE, true);
|
||||
StartReactiveTimer(REACTIVE_DEFENSE);
|
||||
@@ -16388,7 +16388,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
if (procExtra & PROC_EX_PARRY)
|
||||
{
|
||||
// For Hunters only Counterattack (skip Mongoose bite)
|
||||
if (getClass() == CLASS_HUNTER)
|
||||
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||
{
|
||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, true);
|
||||
StartReactiveTimer(REACTIVE_HUNTER_PARRY);
|
||||
@@ -16411,7 +16411,7 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u
|
||||
// Overpower on victim dodge
|
||||
if (procExtra & PROC_EX_DODGE)
|
||||
{
|
||||
if (getClass() == CLASS_WARRIOR)
|
||||
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||
{
|
||||
AddComboPoints(target, 1);
|
||||
StartReactiveTimer(REACTIVE_OVERPOWER);
|
||||
@@ -17218,9 +17218,9 @@ void Unit::ClearAllReactives()
|
||||
|
||||
if (HasAuraState(AURA_STATE_DEFENSE))
|
||||
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
||||
if (getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE) && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||
if (getClass() == CLASS_WARRIOR && GetTypeId() == TYPEID_PLAYER)
|
||||
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE) && GetTypeId() == TYPEID_PLAYER)
|
||||
ClearComboPoints();
|
||||
}
|
||||
|
||||
@@ -17244,11 +17244,11 @@ void Unit::UpdateReactives(uint32 p_time)
|
||||
ModifyAuraState(AURA_STATE_DEFENSE, false);
|
||||
break;
|
||||
case REACTIVE_HUNTER_PARRY:
|
||||
if (getClass() == CLASS_HUNTER && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||
if (IsClass(CLASS_HUNTER, CLASS_CONTEXT_ABILITY_REACTIVE) && HasAuraState(AURA_STATE_HUNTER_PARRY))
|
||||
ModifyAuraState(AURA_STATE_HUNTER_PARRY, false);
|
||||
break;
|
||||
case REACTIVE_OVERPOWER:
|
||||
if (getClass() == CLASS_WARRIOR)
|
||||
if (IsClass(CLASS_WARRIOR, CLASS_CONTEXT_ABILITY_REACTIVE))
|
||||
{
|
||||
ClearComboPoints();
|
||||
}
|
||||
@@ -18113,7 +18113,7 @@ void Unit::Kill(Unit* killer, Unit* victim, bool durabilityLoss, WeaponAttackTyp
|
||||
// Spirit of Redemption
|
||||
// if talent known but not triggered (check priest class for speedup check)
|
||||
bool spiritOfRedemption = false;
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && victim->getClass() == CLASS_PRIEST && !victim->ToPlayer()->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
||||
if (victim->GetTypeId() == TYPEID_PLAYER && victim->IsClass(CLASS_PRIEST, CLASS_CONTEXT_ABILITY) && !victim->ToPlayer()->HasPlayerFlag(PLAYER_FLAGS_IS_OUT_OF_BOUNDS))
|
||||
{
|
||||
if (AuraEffect* aurEff = victim->GetAuraEffectDummy(20711))
|
||||
{
|
||||
@@ -18723,7 +18723,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
GetMotionMaster()->MoveIdle();
|
||||
StopMoving();
|
||||
|
||||
if (charmer->GetTypeId() == TYPEID_PLAYER && charmer->getClass() == CLASS_WARLOCK && ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON)
|
||||
if (charmer->GetTypeId() == TYPEID_PLAYER && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM) && ToCreature()->GetCreatureTemplate()->type == CREATURE_TYPE_DEMON)
|
||||
{
|
||||
// Disable CreatureAI/SmartAI and switch to CharmAI when charmed by warlock
|
||||
Creature* charmed = ToCreature();
|
||||
@@ -18789,7 +18789,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
|
||||
playerCharmer->PossessSpellInitialize();
|
||||
break;
|
||||
case CHARM_TYPE_CHARM:
|
||||
if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
|
||||
if (GetTypeId() == TYPEID_UNIT && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM))
|
||||
{
|
||||
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||
@@ -18911,7 +18911,7 @@ void Unit::RemoveCharmedBy(Unit* charmer)
|
||||
ClearUnitState(UNIT_STATE_NO_ENVIRONMENT_UPD);
|
||||
break;
|
||||
case CHARM_TYPE_CHARM:
|
||||
if (GetTypeId() == TYPEID_UNIT && charmer->getClass() == CLASS_WARLOCK)
|
||||
if (GetTypeId() == TYPEID_UNIT && charmer->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET_CHARM))
|
||||
{
|
||||
CreatureTemplate const* cinfo = ToCreature()->GetCreatureTemplate();
|
||||
if (cinfo && cinfo->type == CREATURE_TYPE_DEMON)
|
||||
|
||||
@@ -440,6 +440,29 @@ enum DamageEffectType : uint8
|
||||
SELF_DAMAGE = 5
|
||||
};
|
||||
|
||||
// Used for IsClass hook
|
||||
enum ClassContext : uint8
|
||||
{
|
||||
CLASS_CONTEXT_NONE = 0, // Default
|
||||
CLASS_CONTEXT_INIT = 1,
|
||||
CLASS_CONTEXT_TELEPORT = 2,
|
||||
CLASS_CONTEXT_QUEST = 3,
|
||||
CLASS_CONTEXT_STATS = 4,
|
||||
CLASS_CONTEXT_TAXI = 5,
|
||||
CLASS_CONTEXT_SKILL = 6,
|
||||
CLASS_CONTEXT_TALENT_POINT_CALC = 7,
|
||||
CLASS_CONTEXT_ABILITY = 8,
|
||||
CLASS_CONTEXT_ABILITY_REACTIVE = 9,
|
||||
CLASS_CONTEXT_PET = 10,
|
||||
CLASS_CONTEXT_PET_CHARM = 11,
|
||||
CLASS_CONTEXT_EQUIP_RELIC = 12,
|
||||
CLASS_CONTEXT_EQUIP_SHIELDS = 13,
|
||||
CLASS_CONTEXT_EQUIP_ARMOR_CLASS = 14,
|
||||
CLASS_CONTEXT_WEAPON_SWAP = 15,
|
||||
CLASS_CONTEXT_GRAVEYARD = 16,
|
||||
CLASS_CONTEXT_CLASS_TRAINER = 17
|
||||
};
|
||||
|
||||
// Value masks for UNIT_FIELD_FLAGS
|
||||
// EnumUtils: DESCRIBE THIS
|
||||
enum UnitFlags : uint32
|
||||
@@ -1436,6 +1459,7 @@ public:
|
||||
void setRace(uint8 race);
|
||||
[[nodiscard]] uint32 getRaceMask() const { return 1 << (getRace(true) - 1); }
|
||||
[[nodiscard]] uint8 getClass() const { return GetByteValue(UNIT_FIELD_BYTES_0, 1); }
|
||||
[[nodiscard]] virtual bool IsClass(Classes unitClass, [[maybe_unused]] ClassContext context = CLASS_CONTEXT_NONE) const { return (getClass() == unitClass); }
|
||||
[[nodiscard]] uint32 getClassMask() const { return 1 << (getClass() - 1); }
|
||||
[[nodiscard]] uint8 getGender() const { return GetByteValue(UNIT_FIELD_BYTES_0, 2); }
|
||||
[[nodiscard]] DisplayRace GetDisplayRaceFromModelId(uint32 modelId) const;
|
||||
@@ -1472,6 +1496,7 @@ public:
|
||||
|
||||
[[nodiscard]] Powers getPowerType() const { return Powers(GetByteValue(UNIT_FIELD_BYTES_0, 3)); }
|
||||
void setPowerType(Powers power);
|
||||
[[nodiscard]] virtual bool HasActivePowerType(Powers power) { return getPowerType() == power; }
|
||||
[[nodiscard]] uint32 GetPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_POWER1) + power); }
|
||||
[[nodiscard]] uint32 GetMaxPower(Powers power) const { return GetUInt32Value(static_cast<uint16>(UNIT_FIELD_MAXPOWER1) + power); }
|
||||
void SetPower(Powers power, uint32 val, bool withPowerUpdate = true, bool fromRegenerate = false);
|
||||
|
||||
@@ -72,7 +72,7 @@ void Vehicle::Install()
|
||||
{
|
||||
if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(_vehicleInfo->m_powerDisplayId))
|
||||
_me->setPowerType(Powers(powerDisplay->PowerType));
|
||||
else if (_me->getClass() == CLASS_ROGUE)
|
||||
else if (_me->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY))
|
||||
_me->setPowerType(POWER_ENERGY);
|
||||
}
|
||||
|
||||
|
||||
@@ -1983,7 +1983,7 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
|
||||
return ERR_IN_NON_RANDOM_BG;
|
||||
|
||||
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
||||
if (member->getClass() == CLASS_DEATH_KNIGHT && member->GetMapId() == 609 && !member->IsGameMaster() && !member->HasSpell(50977))
|
||||
if (member->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && member->GetMapId() == 609 && !member->IsGameMaster() && !member->HasSpell(50977))
|
||||
return ERR_GROUP_JOIN_BATTLEGROUND_FAIL;
|
||||
|
||||
if (!member->GetBGAccessByLevel(bgTemplate->GetBgTypeID()))
|
||||
|
||||
@@ -184,7 +184,7 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
|
||||
err = ERR_BATTLEGROUND_QUEUED_FOR_RATED;
|
||||
}
|
||||
// don't let Death Knights join BG queues when they are not allowed to be teleported yet
|
||||
else if (_player->getClass() == CLASS_DEATH_KNIGHT && _player->GetMapId() == 609 && !_player->IsGameMaster() && !_player->HasSpell(50977))
|
||||
else if (_player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_TELEPORT) && _player->GetMapId() == 609 && !_player->IsGameMaster() && !_player->HasSpell(50977))
|
||||
{
|
||||
err = ERR_BATTLEGROUND_NONE;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ void WorldSession::HandleAutostoreLootItemOpcode(WorldPacket& recvData)
|
||||
{
|
||||
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
||||
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
||||
{
|
||||
player->SendLootError(lguid, lootAllowed ? LOOT_ERROR_TOO_FAR : LOOT_ERROR_DIDNT_KILL);
|
||||
@@ -162,7 +162,7 @@ void WorldSession::HandleLootMoneyOpcode(WorldPacket& /*recvData*/)
|
||||
case HighGuid::Vehicle:
|
||||
{
|
||||
Creature* creature = player->GetMap()->GetCreature(guid);
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
if (lootAllowed && creature->IsWithinDistInMap(player, INTERACTION_DISTANCE))
|
||||
{
|
||||
loot = &creature->loot;
|
||||
@@ -382,7 +382,7 @@ void WorldSession::DoLootRelease(ObjectGuid lguid)
|
||||
{
|
||||
Creature* creature = GetPlayer()->GetMap()->GetCreature(lguid);
|
||||
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->getClass() == CLASS_ROGUE && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
bool lootAllowed = creature && creature->IsAlive() == (player->IsClass(CLASS_ROGUE, CLASS_CONTEXT_ABILITY) && creature->loot.loot_type == LOOT_PICKPOCKETING);
|
||||
if (!lootAllowed || !creature->IsWithinDistInMap(_player, INTERACTION_DISTANCE))
|
||||
return;
|
||||
|
||||
|
||||
@@ -1000,11 +1000,11 @@ void ScriptMgr::PetitionShowList(Player* player, Creature* creature, uint32& Cha
|
||||
});
|
||||
}
|
||||
|
||||
void ScriptMgr::OnRewardKillRewarder(Player* player, bool isDungeon, float& rate)
|
||||
void ScriptMgr::OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
script->OnRewardKillRewarder(player, isDungeon, rate);
|
||||
script->OnRewardKillRewarder(player, rewarder, isDungeon, rate);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1046,6 +1046,19 @@ bool ScriptMgr::CanRepopAtGraveyard(Player* player)
|
||||
return true;
|
||||
}
|
||||
|
||||
Optional<bool> ScriptMgr::OnPlayerIsClass(Player const* player, Classes unitClass, ClassContext context)
|
||||
{
|
||||
if (ScriptRegistry<PlayerScript>::ScriptPointerList.empty())
|
||||
return {};
|
||||
for (auto const& [scriptID, script] : ScriptRegistry<PlayerScript>::ScriptPointerList)
|
||||
{
|
||||
Optional<bool> scriptResult = script->OnPlayerIsClass(player, unitClass, context);
|
||||
if (scriptResult)
|
||||
return scriptResult;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure)
|
||||
{
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
@@ -1054,6 +1067,21 @@ void ScriptMgr::OnGetMaxSkillValue(Player* player, uint32 skill, int32& result,
|
||||
});
|
||||
}
|
||||
|
||||
bool ScriptMgr::OnPlayerHasActivePowerType(Player const* player, Powers power)
|
||||
{
|
||||
auto ret = IsValidBoolScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
return script->OnPlayerHasActivePowerType(player, power);
|
||||
});
|
||||
|
||||
if (ret && *ret)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ScriptMgr::OnUpdateGatheringSkill(Player *player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32 &gain) {
|
||||
ExecuteScript<PlayerScript>([&](PlayerScript* script)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
// TODO to remove
|
||||
#include "AchievementMgr.h"
|
||||
#include "KillRewarder.h"
|
||||
|
||||
class PlayerScript : public ScriptObject
|
||||
{
|
||||
@@ -315,7 +316,7 @@ public:
|
||||
|
||||
virtual void PetitionShowList(Player* /*player*/, Creature* /*creature*/, uint32& /*CharterEntry*/, uint32& /*CharterDispayID*/, uint32& /*CharterCost*/) { }
|
||||
|
||||
virtual void OnRewardKillRewarder(Player* /*player*/, bool /*isDungeon*/, float& /*rate*/) { }
|
||||
virtual void OnRewardKillRewarder(Player* /*player*/, KillRewarder* /*rewarder*/, bool /*isDungeon*/, float& /*rate*/) { }
|
||||
|
||||
[[nodiscard]] virtual bool CanGiveMailRewardAtGiveLevel(Player* /*player*/, uint8 /*level*/) { return true; }
|
||||
|
||||
@@ -323,8 +324,12 @@ public:
|
||||
|
||||
[[nodiscard]] virtual bool CanRepopAtGraveyard(Player* /*player*/) { return true; }
|
||||
|
||||
[[nodiscard]] virtual Optional<bool> OnPlayerIsClass(Player const* /*player*/, Classes /*playerClass*/, ClassContext /*context*/) { return std::nullopt; }
|
||||
|
||||
virtual void OnGetMaxSkillValue(Player* /*player*/, uint32 /*skill*/, int32& /*result*/, bool /*IsPure*/) { }
|
||||
|
||||
[[nodiscard]] virtual bool OnPlayerHasActivePowerType(Player const* /*player*/, Powers /*power*/) { return false; }
|
||||
|
||||
/**
|
||||
* @brief This hook called before gathering skill gain is applied to the character.
|
||||
*
|
||||
|
||||
@@ -430,11 +430,13 @@ public: /* PlayerScript */
|
||||
bool CanSendMail(Player* player, ObjectGuid receiverGuid, ObjectGuid mailbox, std::string& subject, std::string& body, uint32 money, uint32 COD, Item* item);
|
||||
void PetitionBuy(Player* player, Creature* creature, uint32& charterid, uint32& cost, uint32& type);
|
||||
void PetitionShowList(Player* player, Creature* creature, uint32& CharterEntry, uint32& CharterDispayID, uint32& CharterCost);
|
||||
void OnRewardKillRewarder(Player* player, bool isDungeon, float& rate);
|
||||
void OnRewardKillRewarder(Player* player, KillRewarder* rewarder, bool isDungeon, float& rate);
|
||||
bool CanGiveMailRewardAtGiveLevel(Player* player, uint8 level);
|
||||
void OnDeleteFromDB(CharacterDatabaseTransaction trans, uint32 guid);
|
||||
bool CanRepopAtGraveyard(Player* player);
|
||||
std::optional<bool> OnPlayerIsClass(Player const* player, Classes playerClass, ClassContext context);
|
||||
void OnGetMaxSkillValue(Player* player, uint32 skill, int32& result, bool IsPure);
|
||||
bool OnPlayerHasActivePowerType(Player const* player, Powers power);
|
||||
void OnUpdateGatheringSkill(Player* player, uint32 skillId, uint32 currentLevel, uint32 gray, uint32 green, uint32 yellow, uint32& gain);
|
||||
void OnUpdateCraftingSkill(Player* player, SkillLineAbilityEntry const* skill, uint32 currentLevel, uint32& gain);
|
||||
bool OnUpdateFishingSkill(Player* player, int32 skill, int32 zone_skill, int32 chance, int32 roll);
|
||||
|
||||
@@ -79,6 +79,7 @@ class WorldSocket;
|
||||
enum ArenaTeamInfoType : uint8;
|
||||
enum AuraRemoveMode : uint8;
|
||||
enum BattlegroundDesertionType : uint8;
|
||||
enum ClassContext : uint8;
|
||||
enum ContentLevels : uint8;
|
||||
enum DamageEffectType : uint8;
|
||||
enum EnchantmentSlot : uint8;
|
||||
|
||||
@@ -2027,7 +2027,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
|
||||
if (!target->HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
|
||||
{
|
||||
target->SetShapeshiftForm(FORM_NONE);
|
||||
if (target->getClass() == CLASS_DRUID)
|
||||
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
|
||||
{
|
||||
target->setPowerType(POWER_MANA);
|
||||
// Remove movement impairing effects also when shifting out
|
||||
@@ -2106,7 +2106,7 @@ void AuraEffect::HandleAuraModShapeshift(AuraApplication const* aurApp, uint8 mo
|
||||
if (target->GetTypeId() == TYPEID_PLAYER)
|
||||
target->ToPlayer()->InitDataForForm();
|
||||
|
||||
if (target->getClass() == CLASS_DRUID)
|
||||
if (target->IsClass(CLASS_DRUID, CLASS_CONTEXT_ABILITY))
|
||||
{
|
||||
// Dash
|
||||
if (AuraEffect* aurEff = target->GetAuraEffect(SPELL_AURA_MOD_INCREASE_SPEED, SPELLFAMILY_DRUID, 0, 0, 0x8))
|
||||
@@ -6038,7 +6038,7 @@ void AuraEffect::HandleAuraConvertRune(AuraApplication const* aurApp, uint8 mode
|
||||
|
||||
Player* player = target->ToPlayer();
|
||||
|
||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
uint32 runes = m_amount;
|
||||
@@ -6244,7 +6244,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
|
||||
{
|
||||
// Converts up to 10 rage per second into health for $d. Each point of rage is converted into ${$m2/10}.1% of max health.
|
||||
// Should be manauser
|
||||
if (target->getPowerType() != POWER_RAGE)
|
||||
if (!target->HasActivePowerType(POWER_RAGE))
|
||||
break;
|
||||
uint32 rage = target->GetPower(POWER_RAGE);
|
||||
// Nothing todo
|
||||
@@ -6310,7 +6310,7 @@ void AuraEffect::HandlePeriodicDummyAuraTick(Unit* target, Unit* caster) const
|
||||
{
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
return;
|
||||
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
// timer expired - remove death runes
|
||||
@@ -7082,7 +7082,7 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con
|
||||
{
|
||||
Powers PowerType = Powers(GetMiscValue());
|
||||
|
||||
if (!caster || !caster->IsAlive() || !target->IsAlive() || target->getPowerType() != PowerType)
|
||||
if (!caster || !caster->IsAlive() || !target->IsAlive() || !target->HasActivePowerType(PowerType))
|
||||
return;
|
||||
|
||||
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
||||
@@ -7189,7 +7189,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons
|
||||
{
|
||||
Powers PowerType = Powers(GetMiscValue());
|
||||
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && target->getPowerType() != PowerType && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||
if (target->GetTypeId() == TYPEID_PLAYER && !target->HasActivePowerType(PowerType) && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||
return;
|
||||
|
||||
if (!target->IsAlive() || !target->GetMaxPower(PowerType))
|
||||
@@ -7223,7 +7223,7 @@ void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) con
|
||||
{
|
||||
Powers PowerType = Powers(GetMiscValue());
|
||||
|
||||
if (!caster || !target->IsAlive() || target->getPowerType() != PowerType)
|
||||
if (!caster || !target->IsAlive() || !target->HasActivePowerType(PowerType))
|
||||
return;
|
||||
|
||||
if (target->HasUnitState(UNIT_STATE_ISOLATED) || target->IsImmunedToDamageOrSchool(GetSpellInfo()))
|
||||
|
||||
@@ -1876,7 +1876,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
|
||||
break;
|
||||
if (target->GetTypeId() != TYPEID_PLAYER)
|
||||
break;
|
||||
if (target->ToPlayer()->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!target->ToPlayer()->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
break;
|
||||
|
||||
// aura removed - remove death runes
|
||||
|
||||
@@ -4807,7 +4807,7 @@ void Spell::SendSpellGo()
|
||||
}
|
||||
|
||||
if ((m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
&& (m_caster->getClass() == CLASS_DEATH_KNIGHT)
|
||||
&& (m_caster->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
&& m_spellInfo->RuneCostID
|
||||
&& m_spellInfo->PowerType == POWER_RUNE)
|
||||
{
|
||||
@@ -5396,7 +5396,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
|
||||
return SPELL_CAST_OK;
|
||||
}
|
||||
|
||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return SPELL_CAST_OK;
|
||||
|
||||
SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(RuneCostID);
|
||||
@@ -5437,7 +5437,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 RuneCostID)
|
||||
|
||||
void Spell::TakeRunePower(bool didHit)
|
||||
{
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER || m_caster->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_caster->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
SpellRuneCostEntry const* runeCostData = sSpellRuneCostStore.LookupEntry(m_spellInfo->RuneCostID);
|
||||
@@ -6173,7 +6173,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
// Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER)
|
||||
if (Unit* target = m_targets.GetUnitTarget())
|
||||
if (target != m_caster && target->getPowerType() != Powers(m_spellInfo->Effects[i].MiscValue))
|
||||
if (target != m_caster && !target->HasActivePowerType(Powers(m_spellInfo->Effects[i].MiscValue)))
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
break;
|
||||
}
|
||||
@@ -6408,7 +6408,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
return SPELL_FAILED_ALREADY_HAVE_CHARM;
|
||||
}
|
||||
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK && strict)
|
||||
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->IsClass(CLASS_WARLOCK, CLASS_CONTEXT_PET) && strict)
|
||||
if (Pet* pet = m_caster->ToPlayer()->GetPet())
|
||||
pet->CastSpell(pet, 32752, true, nullptr, nullptr, pet->GetGUID()); //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
|
||||
|
||||
@@ -6702,7 +6702,7 @@ SpellCastResult Spell::CheckCast(bool strict)
|
||||
if (!m_targets.GetUnitTarget())
|
||||
return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
|
||||
|
||||
if (m_targets.GetUnitTarget()->getPowerType() != POWER_MANA)
|
||||
if (!m_targets.GetUnitTarget()->HasActivePowerType(POWER_MANA))
|
||||
return SPELL_FAILED_BAD_TARGETS;
|
||||
|
||||
break;
|
||||
|
||||
@@ -1345,7 +1345,7 @@ void Spell::EffectPowerDrain(SpellEffIndex effIndex)
|
||||
|
||||
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||
|
||||
if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != PowerType || damage < 0)
|
||||
if (!unitTarget || !unitTarget->IsAlive() || !unitTarget->HasActivePowerType(PowerType) || damage < 0)
|
||||
return;
|
||||
|
||||
// add spell damage bonus
|
||||
@@ -1424,7 +1424,7 @@ void Spell::EffectPowerBurn(SpellEffIndex effIndex)
|
||||
|
||||
Powers PowerType = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||
|
||||
if (!unitTarget || !unitTarget->IsAlive() || unitTarget->getPowerType() != PowerType || damage < 0)
|
||||
if (!unitTarget || !unitTarget->IsAlive() || !unitTarget->HasActivePowerType(PowerType) || damage < 0)
|
||||
return;
|
||||
|
||||
// burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn)
|
||||
@@ -1877,7 +1877,7 @@ void Spell::EffectEnergize(SpellEffIndex effIndex)
|
||||
|
||||
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && m_spellInfo->SpellFamilyName != SPELLFAMILY_POTION
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->HasActivePowerType(power) && m_spellInfo->SpellFamilyName != SPELLFAMILY_POTION
|
||||
&& !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||
return;
|
||||
|
||||
@@ -1982,7 +1982,7 @@ void Spell::EffectEnergizePct(SpellEffIndex effIndex)
|
||||
|
||||
Powers power = Powers(m_spellInfo->Effects[effIndex].MiscValue);
|
||||
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && unitTarget->getPowerType() != power && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||
if (unitTarget->GetTypeId() == TYPEID_PLAYER && !unitTarget->HasActivePowerType(power) && !m_spellInfo->HasAttribute(SPELL_ATTR7_ONLY_IN_SPELLBOOK_UNTIL_LEARNED))
|
||||
return;
|
||||
|
||||
uint32 maxPower = unitTarget->GetMaxPower(power);
|
||||
@@ -3077,7 +3077,7 @@ void Spell::EffectTameCreature(SpellEffIndex /*effIndex*/)
|
||||
if (creatureTarget->IsPet())
|
||||
return;
|
||||
|
||||
if (m_caster->getClass() != CLASS_HUNTER)
|
||||
if (!m_caster->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
return;
|
||||
|
||||
// cast finish successfully
|
||||
@@ -3209,7 +3209,7 @@ void Spell::EffectSummonPet(SpellEffIndex effIndex)
|
||||
pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
|
||||
|
||||
// Reset cooldowns
|
||||
if (owner->getClass() != CLASS_HUNTER)
|
||||
if (!owner->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
{
|
||||
pet->m_CreatureSpellCooldowns.clear();
|
||||
owner->PetSpellInitialize();
|
||||
@@ -5746,7 +5746,7 @@ void Spell::EffectActivateRune(SpellEffIndex effIndex)
|
||||
|
||||
Player* player = m_caster->ToPlayer();
|
||||
|
||||
if (player->getClass() != CLASS_DEATH_KNIGHT)
|
||||
if (!player->IsClass(CLASS_DEATH_KNIGHT, CLASS_CONTEXT_ABILITY))
|
||||
return;
|
||||
|
||||
// needed later
|
||||
@@ -5814,7 +5814,7 @@ void Spell::EffectCreateTamedPet(SpellEffIndex effIndex)
|
||||
if (effectHandleMode != SPELL_EFFECT_HANDLE_HIT_TARGET)
|
||||
return;
|
||||
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || unitTarget->getClass() != CLASS_HUNTER)
|
||||
if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER || unitTarget->GetPetGUID() || !unitTarget->IsClass(CLASS_HUNTER, CLASS_CONTEXT_PET))
|
||||
return;
|
||||
|
||||
uint32 creatureEntry = m_spellInfo->Effects[effIndex].MiscValue;
|
||||
|
||||
Reference in New Issue
Block a user