aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Entities/Player
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2016-01-24 15:56:10 +0100
committerShauren <shauren.trinity@gmail.com>2016-05-20 23:46:17 +0200
commit5c2c9a684f1458da0cea1f3536622add77ef1324 (patch)
treed3a2a349e8bed9a31cf417ce93830d508ecea46b /src/server/game/Entities/Player
parent65c0a0ee4d5c299f3caab04b6cb3fcd7a4a93e2e (diff)
Core/DataStores: Updated dbc/db2 to 7.0.1.20810
Diffstat (limited to 'src/server/game/Entities/Player')
-rw-r--r--src/server/game/Entities/Player/Player.cpp306
-rw-r--r--src/server/game/Entities/Player/Player.h59
2 files changed, 142 insertions, 223 deletions
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 90f1c829bb9..38a47d999a9 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -421,7 +421,7 @@ bool Player::Create(ObjectGuid::LowType guidlow, WorldPackets::Character::Charac
return false;
}
- if (!ValidateAppearance(createInfo->Race, createInfo->Class, createInfo->Sex, createInfo->HairStyle, createInfo->HairColor, createInfo->Face, createInfo->FacialHairStyle, createInfo->Skin, true))
+ if (!ValidateAppearance(createInfo->Race, createInfo->Class, createInfo->Sex, createInfo->HairStyle, createInfo->HairColor, createInfo->Face, createInfo->FacialHairStyle, createInfo->Skin, createInfo->CustomDisplay, true))
{
TC_LOG_ERROR("entities.player", "Player::Create: Possible hacking-attempt: Account %u tried creating a character named '%s' with invalid appearance attributes - refusing to do so",
GetSession()->GetAccountId(), m_name.c_str());
@@ -1805,20 +1805,21 @@ void Player::RegenerateAll()
// Runes act as cooldowns, and they don't need to send any data
if (getClass() == CLASS_DEATH_KNIGHT)
{
- for (uint8 i = 0; i < MAX_RUNES; i += 2)
+ uint32 regeneratedRunes = 0;
+ uint32 regenIndex = 0;
+ while (regeneratedRunes < MAX_RECHARGING_RUNES && !m_runes->CooldownOrder.empty())
{
- uint8 runeToRegen = i;
- uint32 cd = GetRuneCooldown(i);
- uint32 secondRuneCd = GetRuneCooldown(i + 1);
- // Regenerate second rune of the same type only after first rune is off the cooldown
- if (secondRuneCd && (cd > secondRuneCd || !cd))
+ uint8 runeToRegen = m_runes->CooldownOrder[regenIndex++];
+ uint32 runeCooldown = GetRuneCooldown(runeToRegen);
+ if (runeCooldown > m_regenTimer)
{
- runeToRegen = i + 1;
- cd = secondRuneCd;
+ SetRuneCooldown(runeToRegen, runeCooldown - m_regenTimer);
+ ++regenIndex;
}
+ else
+ SetRuneCooldown(runeCooldown, 0);
- if (cd)
- SetRuneCooldown(runeToRegen, (cd > m_regenTimer) ? cd - m_regenTimer : 0);
+ ++regeneratedRunes;
}
}
@@ -2055,8 +2056,8 @@ void Player::ResetAllPowers()
case POWER_RUNIC_POWER:
SetPower(POWER_RUNIC_POWER, 0);
break;
- case POWER_ECLIPSE:
- SetPower(POWER_ECLIPSE, 0);
+ case POWER_LUNAR_POWER:
+ SetPower(POWER_LUNAR_POWER, 0);
break;
default:
break;
@@ -3142,12 +3143,12 @@ bool Player::AddSpell(uint32 spellId, bool active, bool learning, bool dependent
if (!pSkill)
continue;
- if (pSkill->ID == fromSkill)
+ if (_spell_idx->second->SkillLine == fromSkill)
continue;
// Runeforging special case
- if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(pSkill->ID)) || ((pSkill->ID == SKILL_RUNEFORGING_2) && _spell_idx->second->TrivialSkillLineRankHigh == 0))
- if (SkillRaceClassInfoEntry const* rcInfo = GetSkillRaceClassInfo(pSkill->ID, getRace(), getClass()))
+ if ((_spell_idx->second->AquireMethod == SKILL_LINE_ABILITY_LEARNED_ON_SKILL_LEARN && !HasSkill(_spell_idx->second->SkillLine)) || ((_spell_idx->second->SkillLine == SKILL_RUNEFORGING_2) && _spell_idx->second->TrivialSkillLineRankHigh == 0))
+ if (SkillRaceClassInfoEntry const* rcInfo = sDB2Manager.GetSkillRaceClassInfo(_spell_idx->second->SkillLine, getRace(), getClass()))
LearnDefaultSkill(rcInfo);
}
}
@@ -3230,7 +3231,7 @@ bool Player::IsNeedCastPassiveSpellAtLearn(SpellInfo const* spellInfo) const
bool Player::IsCurrentSpecMasterySpell(SpellInfo const* spellInfo) const
{
if (ChrSpecializationEntry const* chrSpec = sChrSpecializationStore.LookupEntry(GetSpecId(GetActiveTalentGroup())))
- return spellInfo->Id == chrSpec->MasterySpellID[0] || spellInfo->Id == chrSpec->MasterySpellID[1];
+ return spellInfo->Id == chrSpec->MasterySpellID;
return false;
}
@@ -3968,6 +3969,10 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt64(0, guid);
trans->Append(stmt);
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_GEMS_BY_OWNER);
+ stmt->setUInt64(0, guid);
+ trans->Append(stmt);
+
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_ITEM_INSTANCE_BY_OWNER);
stmt->setUInt64(0, guid);
trans->Append(stmt);
@@ -4217,7 +4222,7 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, uint32(GetMaxPower(POWER_ENERGY)*restore_percent));
SetPower(POWER_FOCUS, uint32(GetMaxPower(POWER_FOCUS)*restore_percent));
- SetPower(POWER_ECLIPSE, 0);
+ SetPower(POWER_LUNAR_POWER, 0);
}
// trigger update zone for alive state zone updates
@@ -5326,7 +5331,7 @@ void Player::UpdateSkillsForLevel()
continue;
uint32 pskill = itr->first;
- SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass());
+ SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(pskill, getRace(), getClass());
if (!rcEntry)
continue;
@@ -5363,7 +5368,7 @@ void Player::UpdateSkillsToMaxSkillsForLevel()
continue;
uint32 pskill = itr->first;
- SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(pskill, getRace(), getClass());
+ SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(pskill, getRace(), getClass());
if (!rcEntry)
continue;
@@ -6129,7 +6134,7 @@ void Player::RewardReputation(Quest const* quest)
else
{
uint32 row = ((quest->RewardFactionValue[i] < 0) ? 1 : 0) + 1;
- if (QuestFactionRewEntry const* questFactionRewEntry = sQuestFactionRewardStore.LookupEntry(row))
+ if (QuestFactionRewardEntry const* questFactionRewEntry = sQuestFactionRewardStore.LookupEntry(row))
{
uint32 field = abs(quest->RewardFactionValue[i]);
rep = questFactionRewEntry->QuestRewFactionValue[field];
@@ -9764,7 +9769,7 @@ bool Player::HasItemTotemCategory(uint32 TotemCategory) const
for (uint8 i = EQUIPMENT_SLOT_START; i < INVENTORY_SLOT_ITEM_END; ++i)
{
item = GetUseableItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory))
+ if (item && DB2Manager::IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory))
return true;
}
@@ -9777,7 +9782,7 @@ bool Player::HasItemTotemCategory(uint32 TotemCategory) const
for (uint32 j = 0; j < bag->GetBagSize(); ++j)
{
item = GetUseableItemByPos(i, j);
- if (item && IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory))
+ if (item && DB2Manager::IsTotemCategoryCompatibleWith(item->GetTemplate()->GetTotemCategory(), TotemCategory))
return true;
}
}
@@ -12763,20 +12768,23 @@ void Player::ApplyEnchantment(Item* item, EnchantmentSlot slot, bool apply, bool
if (pEnchant->RequiredSkillID > 0 && pEnchant->RequiredSkillRank > GetSkillValue(pEnchant->RequiredSkillID))
return;
- // Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2
- if (ItemTemplate const* gem = sObjectMgr->GetItemTemplate(pEnchant->SRCItemID))
- if (gem->GetRequiredSkill() && GetSkillValue(gem->GetRequiredSkill()) < gem->GetRequiredSkillRank())
- return;
// If we're dealing with a gem inside a prismatic socket we need to check the prismatic socket requirements
// rather than the gem requirements itself. If the socket has no color it is a prismatic socket.
- if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3)
- && !item->GetSocketColor(slot - SOCK_ENCHANTMENT_SLOT))
+ if ((slot == SOCK_ENCHANTMENT_SLOT || slot == SOCK_ENCHANTMENT_SLOT_2 || slot == SOCK_ENCHANTMENT_SLOT_3))
{
- // Check if the requirements for the prismatic socket are met before applying the gem stats
- SpellItemEnchantmentEntry const* pPrismaticEnchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
- if (!pPrismaticEnchant || (pPrismaticEnchant->RequiredSkillID > 0 && pPrismaticEnchant->RequiredSkillRank > GetSkillValue(pPrismaticEnchant->RequiredSkillID)))
- return;
+ if (!item->GetSocketColor(slot - SOCK_ENCHANTMENT_SLOT))
+ {
+ // Check if the requirements for the prismatic socket are met before applying the gem stats
+ SpellItemEnchantmentEntry const* pPrismaticEnchant = sSpellItemEnchantmentStore.LookupEntry(item->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
+ if (!pPrismaticEnchant || (pPrismaticEnchant->RequiredSkillID > 0 && pPrismaticEnchant->RequiredSkillRank > GetSkillValue(pPrismaticEnchant->RequiredSkillID)))
+ return;
+ }
+
+ // Cogwheel gems dont have requirement data set in SpellItemEnchantment.dbc, but they do have it in Item-sparse.db2
+ if (ItemTemplate const* gem = sObjectMgr->GetItemTemplate(item->GetDynamicValue(ITEM_DYNAMIC_FIELD_GEMS, uint32(slot - SOCK_ENCHANTMENT_SLOT))))
+ if (gem->GetRequiredSkill() && GetSkillValue(gem->GetRequiredSkill()) < gem->GetRequiredSkillRank())
+ return;
}
if (!item->IsBroken())
@@ -16357,7 +16365,8 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_HAIR_COLOR_ID),
GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_FACE_ID),
GetByteValue(PLAYER_BYTES_2, PLAYER_BYTES_2_OFFSET_FACIAL_STYLE),
- GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID)))
+ GetByteValue(PLAYER_BYTES, PLAYER_BYTES_OFFSET_SKIN_ID),
+ std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE>{ fields[14].GetUInt8(), fields[15].GetUInt8(), fields[16].GetUInt8() }))
{
TC_LOG_ERROR("entities.player", "Player::LoadFromDB: Player (%s) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.ToString().c_str());
return false;
@@ -16922,7 +16931,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
for (; loadedPowers < MAX_POWERS_PER_CLASS; ++loadedPowers)
SetUInt32Value(UNIT_FIELD_POWER + loadedPowers, 0);
- SetPower(POWER_ECLIPSE, 0);
+ SetPower(POWER_LUNAR_POWER, 0);
TC_LOG_DEBUG("entities.player.loading", "Player::LoadFromDB: The value of player '%s' after load item and aura is: ", m_name.c_str());
outDebugValues();
@@ -17265,8 +17274,8 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
{
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
// SELECT ii.guid, ii.itemEntry, ii.creatorGuid, ii.giftCreatorGuid, ii.count, ii.duration, ii.charges, ii.flags, ii.enchantments, ii.randomPropertyId, ii.durability, ii.playedTime, ii.text, ii.transmogrification, ii.upgradeId
- // 15 16 17 18 19 20 21 22
- // ii.enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, ii.bonusListIDs, bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot
+ // 15 16 17 18 19 20 21 22 23 24 25
+ // ii.enchantIllusion, battlePetSpeciesId, battlePetBreedData, battlePetLevel, battlePetDisplayId, ii.bonusListIDs, ig.gemItemId1, ig.gemItemId2, ig.gemItemId3, bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid WHERE ci.guid = ? ORDER BY bag, slot
//NOTE: the "order by `bag`" is important because it makes sure
//the bagMap is filled before items in the bags are loaded
//NOTE2: the "order by `slot`" is needed because mainhand weapons are (wrongly?)
@@ -17288,8 +17297,8 @@ void Player::_LoadInventory(PreparedQueryResult result, uint32 timeDiff)
Field* fields = result->Fetch();
if (Item* item = _LoadItem(trans, zoneId, timeDiff, fields))
{
- ObjectGuid bagGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[21].GetUInt64()) : ObjectGuid::Empty;
- uint8 slot = fields[22].GetUInt8();
+ ObjectGuid bagGuid = fields[21].GetUInt64() ? ObjectGuid::Create<HighGuid::Item>(fields[24].GetUInt64()) : ObjectGuid::Empty;
+ uint8 slot = fields[25].GetUInt8();
GetSession()->GetCollectionMgr()->CheckHeirloomUpgrades(item);
@@ -21560,23 +21569,11 @@ bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
if (i == slot)
continue;
Item* pItem2 = GetItemByPos(INVENTORY_SLOT_BAG_0, i);
- if (pItem2 && !pItem2->IsBroken() && pItem2->GetTemplate()->GetSocketColor(0))
+ if (pItem2 && !pItem2->IsBroken())
{
- for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
+ for (uint32 gemItemId : pItem2->GetDynamicValues(ITEM_DYNAMIC_FIELD_GEMS))
{
- uint32 enchant_id = pItem2->GetEnchantmentId(EnchantmentSlot(enchant_slot));
- if (!enchant_id)
- continue;
-
- SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
- if (!enchantEntry)
- continue;
-
- uint32 gemid = enchantEntry->SRCItemID;
- if (!gemid)
- continue;
-
- ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemid);
+ ItemTemplate const* gemProto = sObjectMgr->GetItemTemplate(gemItemId);
if (!gemProto)
continue;
@@ -21584,13 +21581,11 @@ bool Player::EnchantmentFitsRequirements(uint32 enchantmentcondition, int8 slot)
if (!gemProperty)
continue;
- uint8 GemColor = gemProperty->Type;
+ uint32 GemColor = gemProperty->Type;
for (uint8 b = 0, tmpcolormask = 1; b < 4; b++, tmpcolormask <<= 1)
- {
if (tmpcolormask & GemColor)
++curcount[b];
- }
}
}
}
@@ -23498,7 +23493,7 @@ void Player::ResurrectUsingRequestDataImpl()
SetPower(POWER_RAGE, 0);
SetPower(POWER_ENERGY, GetMaxPower(POWER_ENERGY));
SetPower(POWER_FOCUS, GetMaxPower(POWER_FOCUS));
- SetPower(POWER_ECLIPSE, 0);
+ SetPower(POWER_LUNAR_POWER, 0);
if (uint32 aura = _resurrectionData->Aura)
CastSpell(this, aura, true, nullptr, nullptr, _resurrectionData->GUID);
@@ -24005,16 +24000,16 @@ uint32 Player::GetBarberShopCost(BarberShopStyleEntry const* newHairStyle, uint8
void Player::InitGlyphsForLevel()
{
- uint32 slotMask = 0;
- uint8 slot = 0;
- uint8 level = getLevel();
- for (GlyphSlotEntry const* gs : sDB2Manager.GetGlyphSlots())
- {
- if (level >= ((gs->Tooltip + 1) * 25))
- slotMask |= 1 << slot;
+ //uint32 slotMask = 0;
+ //uint8 slot = 0;
+ //uint8 level = getLevel();
+ //for (GlyphSlotEntry const* gs : sDB2Manager.GetGlyphSlots())
+ //{
+ // if (level >= ((gs->Tooltip + 1) * 25))
+ // slotMask |= 1 << slot;
- SetGlyphSlot(slot++, gs->ID);
- }
+ // SetGlyphSlot(slot++, gs->ID);
+ //}
}
void Player::SetGlyph(uint8 slot, uint32 glyph)
@@ -24095,7 +24090,7 @@ bool Player::isTotalImmunity() const
return false;
}
-uint32 Player::GetRuneTypeBaseCooldown() const
+uint32 Player::GetRuneBaseCooldown() const
{
float cooldown = RUNE_BASE_COOLDOWN;
@@ -24133,72 +24128,33 @@ void Player::SetRuneCooldown(uint8 index, uint32 cooldown, bool casted /*= false
SetRuneTimer(index, 0);
}
- m_runes->runes[index].Cooldown = cooldown;
+ m_runes->Cooldown[index] = cooldown;
m_runes->SetRuneState(index, (cooldown == 0) ? true : false);
}
-void Player::SetRuneConvertAura(uint8 index, AuraEffect const* aura)
-{
- m_runes->runes[index].ConvertAura = aura;
-}
-
-void Player::AddRuneByAuraEffect(uint8 index, RuneType newType, AuraEffect const* aura)
+void Runes::SetRuneState(uint8 index, bool set /*= true*/)
{
- SetRuneConvertAura(index, aura); ConvertRune(index, newType);
-}
-
-void Player::RemoveRunesByAuraEffect(AuraEffect const* aura)
-{
- for (uint8 i = 0; i < MAX_RUNES; ++i)
+ auto itr = std::find(CooldownOrder.begin(), CooldownOrder.end(), index);
+ if (set)
{
- if (m_runes->runes[i].ConvertAura == aura)
- {
- ConvertRune(i, GetBaseRune(i));
- SetRuneConvertAura(i, nullptr);
- }
+ RuneState |= (1 << index); // usable
+ if (itr == CooldownOrder.end())
+ CooldownOrder.push_back(index);
}
-}
-
-void Player::RestoreBaseRune(uint8 index)
-{
- AuraEffect const* aura = m_runes->runes[index].ConvertAura;
- // If rune was converted by a non-passive aura that still active we should keep it converted
- if (aura && !(aura->GetSpellInfo()->Attributes & SPELL_ATTR0_PASSIVE))
- return;
- ConvertRune(index, GetBaseRune(index));
- SetRuneConvertAura(index, nullptr);
- // Don't drop passive talents providing rune convertion
- if (!aura || aura->GetAuraType() != SPELL_AURA_CONVERT_RUNE)
- return;
- for (uint8 i = 0; i < MAX_RUNES; ++i)
+ else
{
- if (aura == m_runes->runes[i].ConvertAura)
- return;
+ RuneState &= ~(1 << index); // on cooldown
+ if (itr != CooldownOrder.end())
+ CooldownOrder.erase(itr);
}
- aura->GetBase()->Remove();
-}
-
-void Player::ConvertRune(uint8 index, RuneType newType)
-{
- SetCurrentRune(index, newType);
-
- WorldPackets::Spells::ConvertRune data;
- data.Index = index;
- data.Rune = newType;
- GetSession()->SendPacket(data.Write());
}
-void Player::ResyncRunes(uint8 count) const
+void Player::ResyncRunes() const
{
- WorldPackets::Spells::ResyncRunes data(count);
+ WorldPackets::Spells::ResyncRunes data(MAX_RUNES);
+ for (uint32 i = 0; i < MAX_RUNES; ++i)
+ data.Runes.push_back(uint8(255 - (GetRuneCooldown(i) * 51)));
- for (uint32 i = 0; i < count; ++i)
- {
- WorldPackets::Spells::ResyncRunes::ResyncRune rune;
- rune.RuneType = GetCurrentRune(i); // rune type
- rune.Cooldown = uint8(255 - (GetRuneCooldown(i) * 51)); // passed cooldown time (0-255)
- data.Runes.push_back(rune);
- }
GetSession()->SendPacket(data.Write());
}
@@ -24209,16 +24165,6 @@ void Player::AddRunePower(uint8 index) const
GetSession()->SendPacket(&data);
}
-static RuneType runeSlotTypes[MAX_RUNES] =
-{
- /*0*/ RUNE_BLOOD,
- /*1*/ RUNE_BLOOD,
- /*2*/ RUNE_UNHOLY,
- /*3*/ RUNE_UNHOLY,
- /*4*/ RUNE_FROST,
- /*5*/ RUNE_FROST
-};
-
void Player::InitRunes()
{
if (getClass() != CLASS_DEATH_KNIGHT)
@@ -24228,20 +24174,14 @@ void Player::InitRunes()
if (runeIndex == MAX_POWERS)
return;
- m_runes = new Runes;
-
- m_runes->runeState = 0;
- m_runes->lastUsedRune = RUNE_BLOOD;
+ m_runes = new Runes();
+ m_runes->RuneState = 0;
for (uint8 i = 0; i < MAX_RUNES; ++i)
{
- SetBaseRune(i, runeSlotTypes[i]); // init base types
- SetCurrentRune(i, runeSlotTypes[i]); // init current types
SetRuneCooldown(i, 0); // reset cooldowns
SetRuneTimer(i, 0xFFFFFFFF); // Reset rune flags
SetLastRuneGraceTimer(i, 0);
- SetRuneConvertAura(i, nullptr);
- m_runes->SetRuneState(i);
}
// set a base regen timer equal to 10 sec
@@ -24249,15 +24189,6 @@ void Player::InitRunes()
SetStatFloatValue(UNIT_FIELD_POWER_REGEN_INTERRUPTED_FLAT_MODIFIER + runeIndex, 0.1f);
}
-bool Player::IsBaseRuneSlotsOnCooldown(RuneType runeType) const
-{
- for (uint8 i = 0; i < MAX_RUNES; ++i)
- if (GetBaseRune(i) == runeType && GetRuneCooldown(i) == 0)
- return false;
-
- return true;
-}
-
void Player::AutoStoreLoot(uint8 bag, uint8 slot, uint32 loot_id, LootStore const& store, bool broadcast)
{
Loot loot;
@@ -24400,7 +24331,7 @@ void Player::_LoadSkills(PreparedQueryResult result)
uint16 value = fields[1].GetUInt16();
uint16 max = fields[2].GetUInt16();
- SkillRaceClassInfoEntry const* rcEntry = GetSkillRaceClassInfo(skill, getRace(), getClass());
+ SkillRaceClassInfoEntry const* rcEntry = sDB2Manager.GetSkillRaceClassInfo(skill, getRace(), getClass());
if (!rcEntry)
{
TC_LOG_ERROR("entities.player", "Player::_LoadSkills: Player '%s' (%s, Race: %u, Class: %u) has forbidden skill %u for his race/class combination",
@@ -24512,16 +24443,9 @@ InventoryResult Player::CanEquipUniqueItem(Item* pItem, uint8 eslot, uint32 limi
return res;
// check unique-equipped on gems
- for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT+3; ++enchant_slot)
+ for (uint32 gemItemId : pItem->GetDynamicValues(ITEM_DYNAMIC_FIELD_GEMS))
{
- uint32 enchant_id = pItem->GetEnchantmentId(EnchantmentSlot(enchant_slot));
- if (!enchant_id)
- continue;
- SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
- if (!enchantEntry)
- continue;
-
- ItemTemplate const* pGem = sObjectMgr->GetItemTemplate(enchantEntry->SRCItemID);
+ ItemTemplate const* pGem = sObjectMgr->GetItemTemplate(gemItemId);
if (!pGem)
continue;
@@ -24679,6 +24603,11 @@ void Player::CompletedAchievement(AchievementEntry const* entry)
m_achievementMgr->CompletedAchievement(entry, this);
}
+bool Player::ModifierTreeSatisfied(uint32 modifierTreeId) const
+{
+ return m_achievementMgr->ModifierTreeSatisfied(modifierTreeId);
+}
+
bool Player::LearnTalent(uint32 talentId)
{
TalentEntry const* talentInfo = sTalentStore.LookupEntry(talentId);
@@ -25306,9 +25235,8 @@ void Player::ActivateTalentGroup(uint8 spec)
if (CanUseMastery())
if (ChrSpecializationEntry const* specialization = sChrSpecializationStore.LookupEntry(GetSpecId(GetActiveTalentGroup())))
- for (uint32 i = 0; i < MAX_MASTERY_SPELLS; ++i)
- if (uint32 mastery = specialization->MasterySpellID[i])
- LearnSpell(mastery, false);
+ if (uint32 mastery = specialization->MasterySpellID)
+ LearnSpell(mastery, false);
// set glyphs
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
@@ -26088,7 +26016,19 @@ void Player::SendSupercededSpell(uint32 oldSpell, uint32 newSpell) const
uint32 Player::CalculateTalentsTiers() const
{
- uint32 const* rowLevels = (getClass() != CLASS_DEATH_KNIGHT) ? DefaultTalentRowLevels : DKTalentRowLevels;
+ uint32 const* rowLevels;
+ switch (getClass())
+ {
+ case CLASS_DEATH_KNIGHT:
+ rowLevels = DKTalentRowLevels;
+ break;
+ case CLASS_DEMON_HUNTER:
+ rowLevels = DHTalentRowLevels;
+ default:
+ rowLevels = DefaultTalentRowLevels;
+ break;
+ }
+
for (uint32 i = MAX_TALENT_TIERS; i; --i)
if (getLevel() >= rowLevels[i - 1])
return i;
@@ -26219,9 +26159,8 @@ void Player::RemoveSpecializationSpells()
}
}
- for (uint32 j = 0; j < MAX_MASTERY_SPELLS; ++j)
- if (uint32 mastery = specialization->MasterySpellID[j])
- RemoveAurasDueToSpell(mastery);
+ if (uint32 mastery = specialization->MasterySpellID)
+ RemoveAurasDueToSpell(mastery);
}
}
}
@@ -26232,8 +26171,21 @@ void Player::RemoveSocial()
m_social = nullptr;
}
-// TODO: check demon hunter custom display sections
-bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create /*=false*/)
+bool IsSectionFlagValid(CharSectionsEntry const* entry, uint8 class_, bool create)
+{
+ if (create && !(entry->Flags & SECTION_FLAG_PLAYER))
+ return false;
+
+ if (class_ != CLASS_DEATH_KNIGHT && (entry->Flags & SECTION_FLAG_DEATH_KNIGHT))
+ return false;
+
+ if (class_ != CLASS_DEMON_HUNTER && (entry->Flags & SECTION_FLAG_DEMON_HUNTER))
+ return false;
+
+ return true;
+}
+
+bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> const& customDisplay, bool create /*= false*/)
{
// Check skin color
// For Skin type is always 0
@@ -26241,10 +26193,9 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha
{ // Skin Color defined as Face color, too, we check skin & face in one pass
if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACE, gender, faceID, skinColor))
{
- // Check DeathKnight exclusive
- if (((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) || (entry2->Flags & SECTION_FLAG_DEATH_KNIGHT)) && class_ != CLASS_DEATH_KNIGHT)
+ if (!IsSectionFlagValid(entry, class_, create))
return false;
- if (create && !((entry->Flags & SECTION_FLAG_PLAYER) && (entry2->Flags & SECTION_FLAG_PLAYER)))
+ if (!IsSectionFlagValid(entry2, class_, create))
return false;
}
else
@@ -26259,18 +26210,14 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha
// Check Hair
if (CharSectionsEntry const* entry = GetCharSectionEntry(race, SECTION_TYPE_HAIR, gender, hairID, hairColor))
{
- if ((entry->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT)
- return false;
- if (create && !(entry->Flags & SECTION_FLAG_PLAYER))
+ if (!IsSectionFlagValid(entry, class_, create))
return false;
if (!excludeCheck)
{
if (CharSectionsEntry const* entry2 = GetCharSectionEntry(race, SECTION_TYPE_FACIAL_HAIR, gender, facialHair, hairColor))
{
- if ((entry2->Flags & SECTION_FLAG_DEATH_KNIGHT) && class_ != CLASS_DEATH_KNIGHT)
- return false;
- if (create && !(entry2->Flags & SECTION_FLAG_PLAYER))
+ if (!IsSectionFlagValid(entry2, class_, create))
return false;
}
else
@@ -26285,6 +26232,11 @@ bool Player::ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 ha
else
return false;
+ for (uint32 i = 0; i < PLAYER_CUSTOM_DISPLAY_SIZE; ++i)
+ if (CharSectionsEntry const* entry = GetCharSectionEntry(race, CharSectionType(SECTION_TYPE_CUSTOM_DISPLAY_1 + i * 2), gender, customDisplay[i], 0))
+ if (!IsSectionFlagValid(entry, class_, create))
+ return false;
+
return true;
}
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index aa1f1d0697e..b538bbbe05c 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -447,7 +447,8 @@ struct Areas
float y2;
};
-#define MAX_RUNES 6
+#define MAX_RUNES 7
+#define MAX_RECHARGING_RUNES 3
enum RuneCooldowns
{
@@ -455,36 +456,13 @@ enum RuneCooldowns
RUNE_MISS_COOLDOWN = 1500 // cooldown applied on runes when the spell misses
};
-enum RuneType : uint8
-{
- RUNE_BLOOD = 0,
- RUNE_UNHOLY = 1,
- RUNE_FROST = 2,
- RUNE_DEATH = 3,
- NUM_RUNE_TYPES = 4
-};
-
-struct RuneInfo
-{
- RuneType BaseRune;
- RuneType CurrentRune;
- uint32 Cooldown;
- AuraEffect const* ConvertAura;
-};
-
struct Runes
{
- RuneInfo runes[MAX_RUNES];
- uint8 runeState; // mask of available runes
- RuneType lastUsedRune;
+ std::deque<uint8> CooldownOrder;
+ uint32 Cooldown[MAX_RUNES];
+ uint8 RuneState; // mask of available runes
- void SetRuneState(uint8 index, bool set = true)
- {
- if (set)
- runeState |= (1 << index); // usable
- else
- runeState &= ~(1 << index); // on cooldown
- }
+ void SetRuneState(uint8 index, bool set = true);
};
struct EnchantDuration
@@ -1162,6 +1140,7 @@ struct ResurrectionData
static uint32 const DefaultTalentRowLevels[MAX_TALENT_TIERS] = { 15, 30, 45, 60, 75, 90, 100 };
static uint32 const DKTalentRowLevels[MAX_TALENT_TIERS] = { 57, 58, 59, 60, 75, 90, 100 };
+static uint32 const DHTalentRowLevels[MAX_TALENT_TIERS] = { 99, 100, 102, 104, 106, 108, 110 };
struct TC_GAME_API PlayerTalentInfo
{
@@ -1652,7 +1631,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
static bool IsValidGender(uint8 Gender) { return Gender <= GENDER_FEMALE; }
static bool IsValidClass(uint8 Class) { return ((1 << (Class - 1)) & CLASSMASK_ALL_PLAYABLE) != 0; }
static bool IsValidRace(uint8 Race) { return ((1 << (Race - 1)) & RACEMASK_ALL_PLAYABLE) != 0; }
- static bool ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, bool create = false);
+ static bool ValidateAppearance(uint8 race, uint8 class_, uint8 gender, uint8 hairID, uint8 hairColor, uint8 faceID, uint8 facialHair, uint8 skinColor, std::array<uint8, PLAYER_CUSTOM_DISPLAY_SIZE> const& customDisplay, bool create = false);
/*********************************************************/
/*** SAVE SYSTEM ***/
@@ -2424,24 +2403,11 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
bool isAllowedToLoot(const Creature* creature);
DeclinedName const* GetDeclinedNames() const { return m_declinedname; }
- uint8 GetRunesState() const { return m_runes->runeState; }
- RuneType GetBaseRune(uint8 index) const { return RuneType(m_runes->runes[index].BaseRune); }
- RuneType GetCurrentRune(uint8 index) const { return RuneType(m_runes->runes[index].CurrentRune); }
- uint32 GetRuneCooldown(uint8 index) const { return m_runes->runes[index].Cooldown; }
- uint32 GetRuneBaseCooldown(uint8 index) const { return GetRuneTypeBaseCooldown(); }
- uint32 GetRuneTypeBaseCooldown() const;
- bool IsBaseRuneSlotsOnCooldown(RuneType runeType) const;
- RuneType GetLastUsedRune() const { return m_runes->lastUsedRune; }
- void SetLastUsedRune(RuneType type) { m_runes->lastUsedRune = type; }
- void SetBaseRune(uint8 index, RuneType baseRune) { m_runes->runes[index].BaseRune = baseRune; }
- void SetCurrentRune(uint8 index, RuneType currentRune) { m_runes->runes[index].CurrentRune = currentRune; }
+ uint8 GetRunesState() const { return m_runes->RuneState; }
+ uint32 GetRuneCooldown(uint8 index) const { return m_runes->Cooldown[index]; }
+ uint32 GetRuneBaseCooldown() const;
void SetRuneCooldown(uint8 index, uint32 cooldown, bool casted = false);
- void SetRuneConvertAura(uint8 index, AuraEffect const* aura);
- void AddRuneByAuraEffect(uint8 index, RuneType newType, AuraEffect const* aura);
- void RemoveRunesByAuraEffect(AuraEffect const* aura);
- void RestoreBaseRune(uint8 index);
- void ConvertRune(uint8 index, RuneType newType);
- void ResyncRunes(uint8 count) const;
+ void ResyncRunes() const;
void AddRunePower(uint8 index) const;
void InitRunes();
@@ -2454,6 +2420,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void StartCriteriaTimer(CriteriaTimedTypes type, uint32 entry, uint32 timeLost = 0);
void RemoveCriteriaTimer(CriteriaTimedTypes type, uint32 entry);
void CompletedAchievement(AchievementEntry const* entry);
+ bool ModifierTreeSatisfied(uint32 modifierTreeId) const;
bool HasTitle(uint32 bitIndex) const;
bool HasTitle(CharTitlesEntry const* title) const { return HasTitle(title->MaskID); }