142#include <boost/dynamic_bitset.hpp>
143#include <G3D/g3dmath.h>
147#define DEATH_EXPIRE_STEP (5*MINUTE)
148#define MAX_DEATH_COUNT 3
322 sWorld->IncreasePlayerCount();
353 _restMgr = std::make_unique<RestMgr>(
this);
368 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end(); ++itr)
371 for (ItemMap::iterator iter =
mMitems.begin(); iter !=
mMitems.end(); ++iter)
374 for (
size_t x = 0; x <
ItemSetEff.size(); x++)
380 sWorld->DecreasePlayerCount();
403 TC_LOG_ERROR(
"entities.player.cheat",
"Player::Create: Possible hacking attempt: Account {} tried to create a character named '{}' with an invalid race/class pair ({}/{}) - refusing to do so.",
414 TC_LOG_ERROR(
"entities.player.cheat",
"Player::Create: Possible hacking attempt: Account {} tried to create a character named '{}' with an invalid character class ({}) - refusing to do so (wrong DBC-files?)",
421 TC_LOG_ERROR(
"entities.player.cheat",
"Player::Create: Possible hacking-attempt: Account {} tried creating a character named '{}' with invalid appearance attributes - refusing to do so",
439 transport->AddPassenger(
this);
443 transport->CalculatePassengerPosition(x, y, z, &o);
459 TC_LOG_ERROR(
"entities.player.cheat",
"Player::Create: Possible hacking attempt: Account {} tried to create a character named '{}' with an invalid gender ({}) - refusing to do so",
515 for (PlayerCreateInfoActions::const_iterator action_itr = info->
action.begin(); action_itr != info->
action.end(); ++action_itr)
572 TC_LOG_DEBUG(
"entities.player.items",
"Player::StoreNewItemInBestSlots: Player '{}' ({}) creates initial item (ItemID: {}, Count: {})",
602 TC_LOG_ERROR(
"entities.player.items",
"Player::StoreNewItemInBestSlots: Player '{}' ({}) can't equip or store initial item (ItemID: {}, Race: {}, Class: {}, InventoryResult: {})",
675 TC_LOG_DEBUG(
"entities.player",
"Player::EnvironmentalDamage: Player '{}' ({}) fall to death, losing {}% durability",
701 return UnderWaterTime;
740 uint8 damagePercent = 10;
747 damage +=
urand(0, pow(10, std::max(0, (
int32)log10(damage) - 1)));
869 uint8 drunk = currentDrunkValue ? --currentDrunkValue : 0;
888 if (newDrunkValue > 100)
908 if (newDrunkenState == oldDrunkenState)
965 if (!aura->IsPermanent())
966 aura->SetDuration(aura->GetSpellInfo()->GetMaxDuration());
981 using namespace std::string_view_literals;
998 if (q_status.
Timer <= p_time)
1006 q_status.
Timer -= p_time;
1101 if (itr->second < now)
1118 if (!
GetMap()->IsDungeon())
1231 return TeleportTo({ .Location =
WorldLocation(mapid, x, y, z, orientation), .InstanceId = instanceId }, options, teleportSpellId);
1236 return TeleportTo({ .Location = loc, .InstanceId = instanceId }, options, teleportSpellId);
1243 TC_LOG_ERROR(
"maps",
"Player::TeleportTo: Invalid map ({}) or invalid coordinates ({}) given when teleporting player '{}' ({}, MapID: {}, {}).",
1268 TC_LOG_DEBUG(
"maps",
"Player '{}' ({}) using client without required expansion tried teleporting to non accessible map (MapID: {})",
1273 transport->RemovePassenger(
this);
1296 transport->RemovePassenger(
this);
1372 options &= ~TELE_TO_SEAMLESS;
1440 if (teleportSpellId)
1444 transferPending.
Ship.emplace();
1447 transferPending.
Ship->ID = transportSpawn->TransportGameObjectId;
1451 transferPending.
Ship->OriginMapID = -1;
1538 g->SendUpdateToPlayer(
GetGUID());
1584 for (ItemMap::iterator iter =
mMitems.begin(); iter !=
mMitems.end(); ++iter)
1585 iter->second->RemoveFromWorld();
1589 TC_LOG_ERROR(
"entities.player",
"Player::RemoveFromWorld: Player '{}' ({}) has viewpoint (Entry:{}, Type: {}) when removed from world",
1605 bool requireImmunityPurgesEffectAttribute )
const
1627 uint32 regeneratedRunes = 0;
1629 while (regeneratedRunes < MAX_RECHARGING_RUNES && m_runes->CooldownOrder.size() > regenIndex)
1631 uint8 runeToRegen =
m_runes->CooldownOrder[regenIndex];
1675 float addvalue = 0.0f;
1717 addvalue *=
sWorld->getRate(RatesForPower[power]);
1734 addvalue = -std::abs(addvalue);
1737 else if (curValue < powerType->CenterPower)
1739 addvalue = std::abs(addvalue);
1747 int32 integerValue =
int32(std::fabs(addvalue));
1749 if (addvalue < 0.0f)
1751 if (curValue <= minPower)
1754 else if (addvalue > 0.0f)
1756 if (curValue >= maxPower)
1762 bool forcesSetPower =
false;
1763 if (addvalue < 0.0f)
1765 if (curValue > minPower + integerValue)
1767 curValue -= integerValue;
1772 curValue = minPower;
1774 forcesSetPower =
true;
1779 if (curValue + integerValue <= maxPower)
1781 curValue += integerValue;
1786 curValue = maxPower;
1788 forcesSetPower =
true;
1793 curValue = maxPower;
1824 if (curValue >= maxValue)
1828 float addValue = 0.0f;
1836 addValue = HealthIncreaseRate;
1843 addValue = 0.015f * ((float)
GetMaxHealth()) * HealthIncreaseRate;
1860 if (addValue < 0.0f)
1936 auto hasNpcFlags = [&]()
1938 if (!npcFlags && !npcFlags2)
2020 return areaTriggerActionSet->GetFlags().HasFlag(flag);
2100 if (
sWorld->IsFFAPvPRealm())
2135 channel->SetInvisible(
this, !on);
2145 case 3:
return false;
2151 return p ==
this || (
GetGroup() !=
nullptr &&
2197 int32 playerLevelDelta = 0;
2201 playerLevelDelta = -1;
2222 sScriptMgr->OnGivePlayerXP(
this, xp, victim);
2267 if (level == oldLevel)
2280 packet.
Level = level;
2330 artifact->CheckArtifactRelicSlotUnlock(
this);
2340 pet->SynchronizeLevelWithOwner();
2353 if (level > oldLevel)
2360 sScriptMgr->OnPlayerLevelChanged(
this, oldLevel);
2483 for (
uint16 i = 0; i < 3; ++i)
2576 pet->SynchronizeLevelWithOwner();
2585 for (PlayerSpellMap::value_type
const& spell :
m_spells)
2590 if (!spell.second.active || spell.second.disabled)
2594 if (spell.second.favorite)
2609 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end(); ++itr)
2611 if ((*itr)->messageID ==
id)
2642 notify.
Delay = 0.0f;
2654 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end(); ++itr)
2656 if ((*itr)->deliver_time > cTime)
2692 TC_LOG_ERROR(
"spells",
"Player::AddTalent: Spell (ID: {}) does not exist.", talent->
SpellID);
2702 PlayerTalentMap::iterator itr =
GetTalentMap(spec)->find(talent->
ID);
2759 return &auraLocation->Loc;
2772 TC_LOG_ERROR(
"spells",
"Player::AddSpell: Spell (ID: {}) does not exist. deleting for all characters in `character_spell`.", spellId);
2777 TC_LOG_ERROR(
"spells",
"Player::AddSpell: Spell (ID: {}) does not exist", spellId);
2787 TC_LOG_ERROR(
"spells",
"Player::AddSpell: Spell (ID: {}) is invalid. deleting for all characters in `character_spell`.", spellId);
2792 TC_LOG_ERROR(
"spells",
"Player::AddSpell: Spell (ID: {}) is invalid", spellId);
2799 bool dependent_set =
false;
2800 bool disabled_case =
false;
2801 bool superceded_old =
false;
2803 PlayerSpellMap::iterator itr =
m_spells.find(spellId);
2810 uint32 next_active_spell_id = 0;
2820 next_active_spell_id = next;
2827 itr->second.dependent == dependent && itr->second.disabled == disabled)
2838 itr->second.dependent = dependent;
2841 dependent_set =
true;
2844 if (itr->second.TraitDefinitionId != traitDefinitionId)
2846 if (itr->second.TraitDefinitionId)
2850 itr->second.TraitDefinitionId = traitDefinitionId;
2853 itr->second.favorite = favorite;
2856 if (itr->second.active != active && itr->second.state !=
PLAYERSPELL_REMOVED && !itr->second.disabled)
2858 itr->second.active = active;
2860 if (!
IsInWorld() && !learning && !dependent_set)
2872 if (next_active_spell_id)
2877 unlearnedSpells.
SpellID.push_back(spellId);
2889 itr->second.disabled = disabled;
2894 disabled_case =
true;
2896 else switch (itr->second.state)
2909 if (!
IsInWorld() && !learning && !dependent_set)
2923 AddSpell(prev_spell, active,
true,
true, disabled,
false, fromSkill);
2928 std::pair<PlayerSpellMap::iterator, bool> inserted =
m_spells.emplace(std::piecewise_construct, std::forward_as_tuple(spellId), std::forward_as_tuple());
2933 newspell.
active = active;
2937 if (traitDefinitionId)
2943 for (PlayerSpellMap::iterator itr2 =
m_spells.begin(); itr2 !=
m_spells.end(); ++itr2)
2954 if (itr2->second.active)
2962 itr2->second.active =
false;
2965 superceded_old =
true;
2987 bool castSpell =
false;
3007 if (traitDefinitionId)
3011 int32 traitEntryIndex = traitConfig->Entries.FindIndexIf([traitDefinitionId](
UF::TraitEntry const& traitEntry)
3016 if (traitEntryIndex >= 0)
3017 rank = traitConfig->Entries[traitEntryIndex].Rank + traitConfig->Entries[traitEntryIndex].GrantedRanks;
3025 if (traitDefinitionEffectPoint->EffectIndex >=
int32(spellInfo->
GetEffects().size()))
3028 float basePoints =
sDB2Manager.GetCurveValueAt(traitDefinitionEffectPoint->CurveID, rank);
3044 if (traitDefinitionId)
3046 if (traitDefinition->OverridesSpellID)
3061 if (spellLearnSkill->skill != fromSkill)
3066 if (skill_value < spellLearnSkill->value)
3067 skill_value = spellLearnSkill->value;
3069 uint16 new_skill_max_value = spellLearnSkill->maxvalue;
3071 if (new_skill_max_value == 0)
3079 new_skill_max_value = 300;
3085 new_skill_max_value = 1;
3098 skill_value = new_skill_max_value;
3102 if (skill_max_value < new_skill_max_value)
3103 skill_max_value = new_skill_max_value;
3105 SetSkill(spellLearnSkill->skill, spellLearnSkill->step, skill_value, skill_max_value);
3111 for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx)
3117 if (_spell_idx->second->SkillLine == fromSkill)
3130 for (SpellLearnSpellMap::const_iterator itr2 = spell_bounds.first; itr2 != spell_bounds.second; ++itr2)
3132 if (!itr2->second.AutoLearned)
3134 if (!
IsInWorld() || !itr2->second.Active)
3135 AddSpell(itr2->second.Spell, itr2->second.Active,
true,
true,
false);
3140 if (itr2->second.OverridesSpell && itr2->second.Active)
3147 for (SkillLineAbilityMap::const_iterator _spell_idx = skill_bounds.first; _spell_idx != skill_bounds.second; ++_spell_idx)
3161 return active && !disabled && !superceded_old;
3166 PlayerSpellMap::iterator itr =
m_spells.find(spellId);
3179 PlayerSpellMap::iterator itr =
m_spells.find(spellId);
3194 bool need_cast = (!spellInfo->
Stances || (form && (spellInfo->
Stances & (
UI64LIT(1) << (form - 1)))) ||
3203 if (spellEffectInfo.IsAura())
3218 PlayerSpellMap::iterator itr =
m_spells.find(spell_id);
3220 bool disabled = (itr !=
m_spells.end()) ? itr->second.disabled :
false;
3221 bool active = disabled ? itr->second.active :
true;
3222 bool favorite = itr !=
m_spells.end() ? itr->second.favorite :
false;
3224 bool learning =
AddSpell(spell_id, active,
true, dependent,
false,
false, fromSkill, favorite, traitDefinitionId);
3231 learnedSpellInfo.
SpellID = spell_id;
3232 learnedSpellInfo.
Favorite = favorite;
3243 PlayerSpellMap::iterator iter =
m_spells.find(nextSpell);
3244 if (iter !=
m_spells.end() && iter->second.disabled)
3249 for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequiringSpell.first; itr2 != spellsRequiringSpell.second; ++itr2)
3251 PlayerSpellMap::iterator iter2 =
m_spells.find(itr2->second);
3252 if (iter2 !=
m_spells.end() && iter2->second.disabled)
3262 PlayerSpellMap::iterator itr =
m_spells.find(spell_id);
3278 for (SpellsRequiringSpellMap::const_iterator itr2 = spellsRequiringSpell.first; itr2 != spellsRequiringSpell.second; ++itr2)
3286 bool cur_active = itr->second.active;
3287 bool cur_dependent = itr->second.dependent;
3292 itr->second.disabled = disabled;
3323 if (spellLearnSkill)
3332 while (!prevSkill && prev_spell)
3334 prev_spell =
sSpellMgr->GetPrevSpellInChain(prev_spell);
3335 prevSkill =
sSpellMgr->GetSpellLearnSkill(
sSpellMgr->GetFirstSpellInChain(prev_spell));
3347 if (new_skill_max_value == 0)
3355 new_skill_max_value = 300;
3361 new_skill_max_value = 1;
3374 skill_value = new_skill_max_value;
3377 else if (skill_value > prevSkill->
value)
3378 skill_value = prevSkill->
value;
3380 if (skill_max_value > new_skill_max_value)
3381 skill_max_value = new_skill_max_value;
3383 if (skill_value > new_skill_max_value)
3384 skill_value = new_skill_max_value;
3394 for (SpellLearnSpellMap::const_iterator itr2 = spell_bounds.first; itr2 != spell_bounds.second; ++itr2)
3396 bool hasOtherSpellTeachingThis = std::ranges::any_of(
sSpellMgr->GetSpellLearnedBySpellMapBounds(itr2->second.Spell), [&](
SpellLearnSpellNode const* learnNode)
3398 if (learnNode->SourceSpell == spell_id)
3400 if (!learnNode->Active)
3402 return HasSpell(learnNode->SourceSpell);
3405 if (hasOtherSpellTeachingThis)
3409 if (itr2->second.OverridesSpell)
3414 bool prev_activate =
false;
3420 if (cur_active && spellInfo->
IsRanked())
3423 PlayerSpellMap::iterator prev_itr =
m_spells.find(prev_id);
3426 if (prev_itr->second.dependent != cur_dependent)
3428 prev_itr->second.dependent = cur_dependent;
3434 if (!prev_itr->second.active && learn_low_rank)
3436 if (
AddSpell(prev_id,
true,
false, prev_itr->second.dependent, prev_itr->second.disabled))
3440 prev_activate =
true;
3447 if (traitDefinitionId)
3475 unlearnedSpells.
SpellID.push_back(spell_id);
3487 itr->second.favorite = favorite;
3501 return cooldown < 10min
3502 && categoryCooldown < 10min
3507 if (removeActivePetCooldowns)
3509 pet->GetSpellHistory()->ResetAllCooldowns();
3531 return (new_cost < 10*
GOLD ? 10*
GOLD : new_cost);
3538 if (new_cost > 50*
GOLD)
3547 sScriptMgr->OnPlayerTalentsReset(
this, noCost);
3623 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end(); ++itr)
3624 if ((*itr)->messageID ==
id)
3699 m_unitData->WriteUpdate(*data, mask,
true,
this, target);
3703 m_playerData->WriteUpdate(*data, mask2,
true,
this, target);
3712 if (requestedObjectMask.IsAnySet())
3717 if (unitMask.IsAnySet())
3722 if (playerMask.IsAnySet())
3725 if (target ==
this && requestedActivePlayerMask.IsAnySet())
3729 std::size_t sizePos = buffer.
wpos();
3735 m_objectData->WriteUpdate(buffer, requestedObjectMask,
true,
this, target);
3738 m_unitData->WriteUpdate(buffer, unitMask,
true,
this, target);
3741 m_playerData->WriteUpdate(buffer, playerMask,
true,
this, target);
3744 m_activePlayerData->WriteUpdate(buffer, requestedActivePlayerMask,
true,
this, target);
3796 PlayerSpellMap::const_iterator itr =
m_spells.find(spell);
3798 !itr->second.disabled);
3803 PlayerTalentMap::const_iterator itr =
GetTalentMap(group)->find(talentId);
3809 PlayerSpellMap::const_iterator itr =
m_spells.find(spell);
3811 itr->second.active && !itr->second.disabled);
3830 updateRealmChars =
false;
3838 name = characterInfo->
Name;
3842 else if (characterInfo)
3856 if (characterInfo->
Level < charDeleteMinLvl)
3866 guild->DeleteMember(trans, playerguid,
false,
false);
3877 if (
Group* group =
sGroupMgr->GetGroupByDbStoreId((*resultGroup)[0].GetUInt32()))
3883 switch (charDeleteMethod)
3894 std::unordered_map<uint64, std::vector<Item*>> itemsByMail;
3922 std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData;
3924 azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult);
3928 Field* fields = resultItems->Fetch();
3931 itemsByMail[mailId].push_back(mailItem);
3933 }
while (resultItems->NextRow());
3938 Field* mailFields = resultMail->Fetch();
3944 std::string subject = mailFields[4].
GetString();
3945 std::string body = mailFields[5].
GetString();
3947 bool has_items = mailFields[7].
GetBool();
3953 trans->Append(stmt);
3962 trans->Append(stmt);
3969 draft =
MailDraft(mailTemplateId,
false);
3971 auto itemsItr = itemsByMail.find(mail_id);
3972 if (itemsItr != itemsByMail.end())
3974 for (
Item* item : itemsItr->second)
3978 itemsByMail.erase(itemsItr);
3983 trans->Append(stmt);
3989 while (resultMail->NextRow());
3992 for (
auto&& kvp : itemsByMail)
3993 for (
Item* item : kvp.second)
4007 uint32 petguidlow = (*resultPets)[0].GetUInt32();
4009 }
while (resultPets->NextRow());
4022 playerFriend->GetSocial()->RemoveFromSocialList(playerguid,
SOCIAL_FLAG_ALL);
4025 }
while (resultFriends->NextRow());
4030 trans->Append(stmt);
4034 trans->Append(stmt);
4038 trans->Append(stmt);
4042 trans->Append(stmt);
4046 trans->Append(stmt);
4050 trans->Append(stmt);
4054 trans->Append(stmt);
4058 trans->Append(stmt);
4062 trans->Append(stmt);
4066 trans->Append(stmt);
4070 trans->Append(stmt);
4074 trans->Append(stmt);
4078 trans->Append(stmt);
4082 trans->Append(stmt);
4086 trans->Append(stmt);
4090 trans->Append(stmt);
4094 trans->Append(stmt);
4098 trans->Append(stmt);
4102 trans->Append(stmt);
4106 trans->Append(stmt);
4110 trans->Append(stmt);
4114 trans->Append(stmt);
4118 trans->Append(stmt);
4122 trans->Append(stmt);
4126 trans->Append(stmt);
4130 trans->Append(stmt);
4134 trans->Append(stmt);
4138 trans->Append(stmt);
4142 trans->Append(stmt);
4146 trans->Append(stmt);
4150 trans->Append(stmt);
4154 trans->Append(stmt);
4158 trans->Append(stmt);
4162 trans->Append(stmt);
4166 trans->Append(stmt);
4170 trans->Append(stmt);
4174 trans->Append(stmt);
4178 trans->Append(stmt);
4182 trans->Append(stmt);
4186 trans->Append(stmt);
4190 trans->Append(stmt);
4194 trans->Append(stmt);
4198 trans->Append(stmt);
4202 trans->Append(stmt);
4207 trans->Append(stmt);
4211 trans->Append(stmt);
4215 trans->Append(stmt);
4219 trans->Append(stmt);
4223 trans->Append(stmt);
4227 trans->Append(stmt);
4231 trans->Append(stmt);
4235 trans->Append(stmt);
4239 trans->Append(stmt);
4243 trans->Append(stmt);
4247 trans->Append(stmt);
4251 trans->Append(stmt);
4255 trans->Append(stmt);
4259 trans->Append(stmt);
4264 loginTransaction->Append(loginStmt);
4269 loginTransaction->Append(loginStmt);
4277 trans->Append(stmt);
4281 trans->Append(stmt);
4291 trans->Append(stmt);
4296 TC_LOG_ERROR(
"entities.player.cheat",
"Player::DeleteFromDB: Tried to delete player ({}) with unsupported delete method ({}).",
4297 playerguid.
ToString(), charDeleteMethod);
4299 if (trans->GetSize() > 0)
4307 if (updateRealmChars)
4308 sWorld->UpdateRealmCharCount(accountId);
4334 TC_LOG_INFO(
"entities.player",
"Player::DeleteOldCharacters: Deleting all characters which have been deleted {} days before...", keepDays);
4342 TC_LOG_DEBUG(
"entities.player",
"Player::DeleteOldCharacters: Found {} character(s) to delete", result->GetRowCount());
4345 Field* fields = result->Fetch();
4346 Player::DeleteFromDB(ObjectGuid::Create<HighGuid::Player>(fields[0].GetUInt64()), fields[1].GetUInt32(),
true,
true);
4348 while (result->NextRow());
4402 if (corpseReclaimDelay >= 0)
4445 if (restore_percent > 0.0f)
4520 if (corpseReclaimDelay >= 0)
4546 if (!corpse->
Create(
GetMap()->GenerateLowGuid<HighGuid::Corpse>(),
this))
4575 uint32 itemInventoryType;
4577 itemInventoryType = itemEntry->InventoryType;
4581 corpse->
SetItem(i, itemDisplayId | (itemInventoryType << 24));
4592 if (!
GetMap()->Instanceable())
4602 if (triggerSave && !
GetSession()->PlayerLogoutWithSave())
4629 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
4642 if (!pMaxDurability)
4647 uint32 pDurabilityLoss =
uint32(pMaxDurability*percent);
4649 if (pDurabilityLoss < 1)
4650 pDurabilityLoss = 1;
4673 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
4686 int32 pNewDurability = pOldDurability - points;
4688 if (pNewDurability < 0)
4690 else if (pNewDurability > pMaxDurability)
4691 pNewDurability = pMaxDurability;
4693 if (pOldDurability != pNewDurability)
4696 if (pNewDurability == 0 && pOldDurability > 0 && item->
IsEquipped())
4702 if (pNewDurability > 0 && pOldDurability == 0 && item->
IsEquipped())
4721 std::list<std::pair<Item*, uint64>> itemRepairCostStore;
4727 if (
uint64 cost = item->CalculateDurabilityRepairCost(discountMod))
4728 itemRepairCostStore.push_back(std::make_pair(item, cost));
4736 if (
uint64 cost = item->CalculateDurabilityRepairCost(discountMod))
4737 itemRepairCostStore.push_back(std::make_pair(item, cost));
4742 for (
auto const& [item, cost] : itemRepairCostStore)
4758 if (availableGuildMoney == 0)
4762 itemRepairCostStore.sort([](
auto const& a,
auto const& b) ->
bool {
return a.second < b.second; });
4767 for (
auto const& [item, cost] : itemRepairCostStore)
4769 uint64 newTotalCost = totalCost + cost;
4773 totalCost = newTotalCost;
4788 for (
auto const& [item, cost] : itemRepairCostStore)
4797 for (
auto const& [item, cost] : itemRepairCostStore)
4814 TC_LOG_DEBUG(
"entities.player.items",
"Player::DurabilityRepair: Player '{}' ({}) has not enough money to repair item",
4839 bool shouldResurrect =
false;
4843 shouldResurrect =
true;
4849 closestGrave = bf->GetClosestGraveyard(
this);
4851 closestGrave =
sObjectMgr->GetWorldSafeLoc(instance->GetEntranceLocation());
4868 packet.
Loc = closestGrave->
Loc;
4942 Channel* usedChannel =
nullptr;
4945 if (channel->GetChannelId() == channelEntry->ID)
4947 usedChannel = channel;
4952 Channel* removeChannel =
nullptr;
4953 Channel* joinChannel =
nullptr;
4954 bool sendRemove =
true;
4966 if (joinChannel != usedChannel)
4968 removeChannel = usedChannel;
4972 joinChannel =
nullptr;
4979 removeChannel = usedChannel;
5000 (*i)->LeaveChannel(
this);
5010 TC_LOG_ERROR(
"spells",
"Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})",
5023 TC_LOG_ERROR(
"spells",
"Player::HandleBaseModValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})",
5071 float amount = 0.0f;
5078 if (skipEnchantSlot == slot)
5082 if (!enchantmentEntry)
5087 switch (enchantmentEntry->
Effect[i])
5123 TC_LOG_ERROR(
"spells",
"Player::GetBaseModValue: Invalid BaseModGroup/BaseModType ({}/{}) for player '{}' ({})",
5135 TC_LOG_ERROR(
"spells",
"Player::GetTotalBaseModValue: Invalid BaseModGroup ({}) for player '{}' ({})",
5281 return 1.0f / value;
5289 return float(1.0f - pow(0.99f, baseResult)) * 100.0f;
5294 uint32 diminishingCurveId = 0;
5339 if (diminishingCurveId)
5340 return sDB2Manager.GetCurveValueAt(diminishingCurveId, bonusValue);
5347 float baseExpertise = 7.5f;
5371 if (aurEff->GetMiscValueB() & (1 << cr))
5375 if (aurEff->GetMiscValue() & (1 << dependentRating))
5384 if (aurEff->GetMiscValue() & (1 << cr))
5517 if (tmpitem && !tmpitem->
IsBroken())
5530 if (SkillValue >= GrayLevel)
5532 if (SkillValue >= GreenLevel)
5534 if (SkillValue >= YellowLevel)
5544 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateCraftSkill: Player '{}' ({}), SpellID: {}",
5549 for (SkillLineAbilityMap::const_iterator _spell_idx = bounds.first; _spell_idx != bounds.second; ++_spell_idx)
5551 if (_spell_idx->second->SkillupSkillLineID)
5565 _spell_idx->second->TrivialSkillLineRankHigh,
5566 (_spell_idx->second->TrivialSkillLineRankHigh + _spell_idx->second->TrivialSkillLineRankLow)/2,
5567 _spell_idx->second->TrivialSkillLineRankLow),
5576 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateGatherSkill: Player '{}' ({}), SkillID: {}, SkillLevel: {}, RedLevel: {})",
5585 uint32 baseSkillLevelStep = 30;
5586 uint32 yellowLevel = redLevel + baseSkillLevelStep;
5587 uint32 greenLevel = yellowLevel + baseSkillLevelStep;
5588 uint32 grayLevel = greenLevel + baseSkillLevelStep;
5592 if (go->GetGOInfo()->GetTrivialSkillLow())
5593 yellowLevel = go->GetGOInfo()->GetTrivialSkillLow();
5595 if (go->GetGOInfo()->GetTrivialSkillHigh())
5596 grayLevel = go->GetGOInfo()->GetTrivialSkillHigh();
5598 greenLevel = (yellowLevel + grayLevel) / 2;
5623 if (SkillValue < 75)
5626 if (SkillValue <= 300)
5627 return SkillValue / 44;
5629 return SkillValue / 31;
5637 if (!fishingSkill || !
HasSkill(fishingSkill))
5664 uint32 const bonusSkillLevels[] = { 75, 150, 225, 300, 375, 450, 525, 600, 700, 850 };
5666 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateSkillPro: Player '{}' ({}), SkillID: {}, Chance: {:3.1f}%)",
5673 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateSkillPro: Player '{}' ({}), SkillID: {}, Chance: {:3.1f}% missed",
5678 SkillStatusMap::iterator itr =
mSkillStatus.find(skillId);
5685 if (!max || !value || value >= max)
5688 if (
irand(1, 1000) > chance)
5690 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateSkillPro: Player '{}' ({}), SkillID: {}, Chance: {:3.1f}% missed",
5695 uint16 new_value = value + step;
5696 if (new_value > max)
5703 for (
uint32 bsl : bonusSkillLevels)
5705 if (value < bsl && new_value >= bsl)
5714 TC_LOG_DEBUG(
"entities.player.skills",
"Player::UpdateSkillPro: Player '{}' ({}), SkillID: {}, Chance: {:3.1f}% taken",
5721 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skillid);
5731 if (std::vector<SkillLineEntry const*>
const* childSkillLines =
sDB2Manager.GetSkillLinesForParentSkill(skillid))
5746 uint32 pskill = itr->first;
5789 TC_LOG_ERROR(
"misc",
"Player::SetSkill: Skill (SkillID: {}) not found in SkillLineStore for player '{}' ({})",
5797 auto refreshSkillBonusAuras = [&]
5801 if (effect->GetMiscValue() ==
int32(
id))
5805 if (effect->GetMiscValue() ==
int32(
id))
5810 if (effect->GetMiscValue() ==
int32(
id))
5829 if (newVal < currVal)
5840 if (newVal > currVal)
5861 if (freeProfessionSlot != -1)
5864 refreshSkillBonusAuras();
5870 else if (currVal && !newVal)
5875 if (professionSlot != -1)
5894 StoreItem(professionItemDest, professionItem,
true);
5913 itr->second.uState = itr->second.uState !=
SKILL_NEW
5918 if (std::vector<SkillLineAbilityEntry const*>
const* skillLineAbilities =
sDB2Manager.GetSkillLineAbilitiesBySkill(
id))
5922 if (std::vector<SkillLineEntry const*>
const* childSkillLines =
sDB2Manager.GetSkillLinesForParentSkill(
id))
5924 SetSkill(childSkillLine->ID, 0, 0, 0);
5930 uint8 skillSlot = 0;
5965 if (std::vector<SkillLineEntry const*>
const* childSkillLines =
sDB2Manager.GetSkillLinesForParentSkill(
id))
5968 SetSkill(childSkillLine->ID, 0, 0, 0);
5971 if (freeProfessionSlot != -1)
5993 refreshSkillBonusAuras();
6016 if (std::vector<SkillLineEntry const*>
const* childSkillLines =
sDB2Manager.GetSkillLinesForParentSkill(skillEntry->
ID))
6022 if (expansion == skillLineExpansion)
6023 return childSkillLine->ID;
6034 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6043 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6055 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6062 return result < 0 ? 0 : result;
6070 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6077 return result < 0 ? 0 : result;
6085 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6097 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6103 return result < 0 ? 0 : result;
6111 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6123 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6135 SkillStatusMap::const_iterator itr =
mSkillStatus.find(skill);
6159 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Action {} not added into button {} for player {} ({}): button must be < {}",
6166 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Action {} not added into button {} for player {} ({}): action must be < {}",
6176 TC_LOG_DEBUG(
"entities.player",
"Player::IsActionButtonDataValid: Spell action {} not added into button {} for player {} ({}): spell does not exist. This can be due to a character imported from a different expansion",
6184 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Item action {} not added into button {} for player {} ({}): item not exist",
6191 if (!
GetSession()->GetBattlePetMgr()->
GetPet(ObjectGuid::Create<HighGuid::BattlePet>(action)))
6193 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Companion action {} not added into button {} for player {} ({}): companion does not exist",
6204 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Mount action {} not added into button {} for player {} ({}): mount does not exist",
6211 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Mount action {} not added into button {} for player {} ({}): Player does not know this mount",
6224 TC_LOG_ERROR(
"entities.player",
"Player::IsActionButtonDataValid: Unknown action type {}", type);
6242 TC_LOG_DEBUG(
"entities.player",
"Player::AddActionButton: Player '{}' ({}) added action '{}' (type {}) to button '{}'",
6258 TC_LOG_DEBUG(
"entities.player",
"Player::RemoveActionButton: Player '{}' ({}) removed action button '{}'",
6268 return &buttonItr->second;
6312 if (skipped_rcvr !=
this)
6359 TC_LOG_ERROR(
"entities.player",
"Player '{}' ({}) discovered unknown area (x: {} y: {} z: {} map: {})",
6382 int16 areaLevel = std::min(std::max(
int16(
GetLevel()), areaLevels->MinLevel), areaLevels->MaxLevel);
6391 int32 exploration_percent = 100 - ((diff - 5) * 5);
6392 if (exploration_percent < 0)
6393 exploration_percent = 0;
6405 XP = std::max(minScaledXP, XP);
6455 uint32 newzone = 0, newarea = 0;
6489 switch (rEntry->Alliance)
6492 case 1:
return HORDE;
6495 TC_LOG_ERROR(
"entities.player",
"Race ({}) has wrong teamid ({}) in DBC: wrong DBC files?",
uint32(race), rEntry->Alliance);
6498 TC_LOG_ERROR(
"entities.player",
"Race ({}) not found in DBC: wrong DBC files?",
uint32(race));
6506 return TeamId(rEntry->Alliance);
6508 TC_LOG_ERROR(
"entities.player",
"Race ({}) not found in DBC: wrong DBC files?", race);
6516 return faction->FactionGroup;
6538 bool noBonuses =
false;
6544 float percent = 100.0f;
6554 percent += rep > 0 ? repMod : -repMod;
6579 if (percent <= 0.0f)
6585 float repRate = 0.0f;
6589 repRate = repData->creatureRate;
6592 repRate = repData->questRate;
6595 repRate = repData->questDailyRate;
6598 repRate = repData->questWeeklyRate;
6601 repRate = repData->questMonthlyRate;
6604 repRate = repData->questRepeatableRate;
6607 repRate = repData->spellRate;
6612 if (repRate <= 0.0f)
6666 uint32 ChampioningFaction = 0;
6684 donerep1 =
int32(donerep1 * rate);
6695 donerep2 =
int32(donerep2 * rate);
6717 bool noQuestBonus =
false;
6722 noQuestBonus =
true;
6730 rep = questFactionRewEntry->Difficulty[field];
6764 time_t yesterday = today -
DAY;
6816 float honor_f = (float)honor;
6823 victim_guid = victim->
GetGUID();
6834 if (v_level <= k_grey)
6844 uint32 victim_title = plrVictim->m_playerData->PlayerTitle;
6850 if (victim_title == 0)
6851 victim_guid.
Clear();
6852 else if (victim_title < 15)
6853 victim_rank = victim_title + 4;
6854 else if (victim_title < 29)
6855 victim_rank = victim_title - 14 + 4;
6857 victim_guid.
Clear();
6882 if (victim !=
nullptr)
6885 honor_f /= groupsize;
6894 honor =
int32(honor_f);
6903 data.
Target = victim_guid;
6904 data.
Rank = victim_rank;
6965 if (!rewardPackEntry)
6973 if (std::vector<RewardPackXCurrencyTypeEntry const*>
const* rewardCurrencyTypes =
sDB2Manager.GetRewardPackCurrencyTypesByRewardID(rewardPackEntry->
ID))
6975 AddCurrency(currency->CurrencyTypeID, currency->Quantity );
6977 if (std::vector<RewardPackXItemEntry const*>
const* rewardPackXItems =
sDB2Manager.GetRewardPackItemsByRewardID(rewardPackEntry->
ID))
6979 AddItem(rewardPackXItem->ItemID, rewardPackXItem->ItemQuantity);
6986 uint32 newHonorXP = currentHonorXP + xp;
6992 while (newHonorXP >= nextHonorLevelXP)
6994 newHonorXP -= nextHonorLevelXP;
7009 if (level == oldHonorLevel)
7033 Field* fields = result->Fetch();
7052 }
while (result->NextRow());
7064 switch (itr->second.state)
7070 stmt->
setUInt32(2, itr->second.Quantity);
7071 stmt->
setUInt32(3, itr->second.WeeklyQuantity);
7072 stmt->
setUInt32(4, itr->second.TrackedQuantity);
7073 stmt->
setUInt32(5, itr->second.IncreasedCapQuantity);
7074 stmt->
setUInt32(6, itr->second.EarnedQuantity);
7076 trans->Append(stmt);
7080 stmt->
setUInt32(0, itr->second.Quantity);
7081 stmt->
setUInt32(1, itr->second.WeeklyQuantity);
7082 stmt->
setUInt32(2, itr->second.TrackedQuantity);
7083 stmt->
setUInt32(3, itr->second.IncreasedCapQuantity);
7084 stmt->
setUInt32(4, itr->second.EarnedQuantity);
7088 trans->Append(stmt);
7120 record.
Type = currency->
ID;
7121 record.
Quantity = itr->second.Quantity;
7123 if ((itr->second.WeeklyQuantity / currency->
GetScaler()) > 0)
7141 packet.
Data.push_back(record);
7160 itr->second.Quantity = amount;
7161 itr->second.WeeklyQuantity = 0;
7162 itr->second.TrackedQuantity = 0;
7163 itr->second.IncreasedCapQuantity = 0;
7164 itr->second.EarnedQuantity = 0;
7186 bool isGainOnRefund = [&]() ->
bool
7219 heartOfAzeroth->ToAzeriteItem()->GiveXP(
uint64(amount));
7228 itr->second.Quantity = 0;
7229 itr->second.WeeklyQuantity = 0;
7230 itr->second.TrackedQuantity = 0;
7231 itr->second.IncreasedCapQuantity = 0;
7232 itr->second.EarnedQuantity = 0;
7240 if (weeklyCap && amount > 0 && (itr->second.WeeklyQuantity + amount) > weeklyCap)
7241 amount = weeklyCap - itr->second.WeeklyQuantity;
7245 if (maxCap && amount > 0 && (itr->second.Quantity + amount) > maxCap)
7246 amount = maxCap - itr->second.Quantity;
7250 if (amount < 0 &&
uint32(std::abs(amount)) > itr->second.Quantity)
7251 amount = itr->second.Quantity * -1;
7259 itr->second.Quantity += amount;
7261 if (amount > 0 && !ignoreCaps)
7264 itr->second.WeeklyQuantity += amount;
7267 itr->second.TrackedQuantity += amount;
7270 itr->second.EarnedQuantity += amount;
7272 if (!isGainOnRefund)
7283 packet.
Type = currency->
ID;
7284 packet.
Quantity = itr->second.Quantity;
7287 if ((itr->second.WeeklyQuantity / currency->
GetScaler()) > 0)
7361 itr->second.IncreasedCapQuantity += amount;
7368 packet.
Type = currency->
ID;
7369 packet.
Quantity = itr->second.Quantity;
7372 if ((itr->second.WeeklyQuantity / currency->
GetScaler()) > 0)
7400 itr->second.WeeklyQuantity = 0;
7413 return itr->second.Quantity;
7422 return itr->second.WeeklyQuantity;
7431 return itr->second.TrackedQuantity;
7440 return itr->second.IncreasedCapQuantity;
7456 return maxQuantity + increasedCap;
7515 Field* fields = result->Fetch();
7527 fields = result->Fetch();
7590 if (area && area->
GetFlags().HasFlag(areaRestFlag))
7603 if (oldArea != newArea)
7621 if (oldZone != newZone)
7678 sScriptMgr->OnPlayerUpdateZone(
this, newZone, newArea);
7679 if (oldZone != newZone)
7698 vignette->FillPacket(vignetteUpdate.
Added);
7699 else if (vignette->ZoneID == oldZone)
7700 vignetteUpdate.
Removed.push_back(vignette->Guid);
7703 if (!vignetteUpdate.
Added.
IDs.empty() || !vignetteUpdate.
Removed.empty())
7744 switch (overrideZonePvpType)
7774 if (!
duel->OutOfBoundsTime)
7778 duel->OutOfBoundsTime = currTime + 10;
7787 duel->OutOfBoundsTime = 0;
7791 else if (currTime >=
duel->OutOfBoundsTime)
7815 TC_LOG_DEBUG(
"entities.unit",
"Player::DuelComplete: Player '{}' ({}), Opponent: '{}' ({})",
7839 sScriptMgr->OnPlayerDuelEnd(opponent,
this, type);
7855 if (!opponent->
IsPvP())
7865 opponent->
CastSpell(opponent, 52994,
true);
7878 opponent->
CastSpell(opponent, 52852,
true);
7883 duel->Initiator->RemoveGameObject(obj,
true);
7887 for (AuraApplicationMap::iterator i = itsAuras.begin(); i != itsAuras.end();)
7889 Aura const* aura = i->second->GetBase();
7897 for (AuraApplicationMap::iterator i = myAuras.begin(); i != myAuras.end();)
7899 Aura const* aura = i->second->GetBase();
7919 opponent->
duel.reset(
nullptr);
7920 duel.reset(
nullptr);
7945 if (updateItemAuras)
7957 TC_LOG_DEBUG(
"entities.player.items",
"Player::_ApplyItemMods: completed");
7967 float combatRatingMultiplier = 1.0f;
8221 float damage = 0.0f;
8223 float minDamage, maxDamage;
8224 proto->
GetDamage(itemLevel, minDamage, maxDamage);
8299 int32 const spellId = effect->SpellID;
8334 float amount = 0.0f;
8364 for (
auto itr = spells.begin(); itr != spells.end(); ++itr)
8428 for (AuraApplicationMap::const_iterator itr = range.first; itr != range.second; ++itr)
8429 if (!item || itr->second->GetBase()->GetCastItemGUID() == item->
GetGUID())
8433 TC_LOG_DEBUG(
"entities.player",
"Player::ApplyEquipSpell: Player '{}' ({}) cast {} equip spell (ID: {})",
8464 removeItemPassive.
SpellID = spellInfo->
Id;
8493 for (
size_t setindex = 0; setindex <
ItemSetEff.size(); ++setindex)
8529 if (!artifactPowerRank)
8554 if (powerAura->
HasEffect(auraEffect->GetEffIndex()))
8600 for (
uint32 azeriteItemMilestonePowerId : azeriteItem->m_azeriteItemData->UnlockedEssenceMilestones)
8606 if (selectedEssences->AzeriteEssenceID[slot])
8607 ApplyAzeriteEssence(azeriteItem, selectedEssences->AzeriteEssenceID[slot], azeriteItem->GetEssenceRank(selectedEssences->AzeriteEssenceID[slot]),
8627 CastSpell(
this, azeritePower->SpellID, item);
8636 for (
uint32 currentRank = 1; currentRank <= rank; ++currentRank)
8641 if (major && currentRank == 1)
8670 if (powerSpell->IsPassive())
8702 if (!target || !target->
IsAlive() || target ==
this)
8767 TC_LOG_ERROR(
"entities.player.items",
"Player::CastItemCombatSpell: Player '{}' ({}) cast unknown item spell (ID: {})",
8779 else if (chance > 100.0f)
8823 TC_LOG_ERROR(
"entities.player.items",
"Player::CastItemCombatSpell: Player '{}' ({}) cast unknown spell (EnchantID: {}, SpellID: {}), ignoring",
8835 chance = (float)entry->
Chance;
8862 int32 const lvlPenaltyFactor = 4;
8864 int32 const effectPct = std::max(0, 100 - (lvlDifference * lvlPenaltyFactor));
8867 if (spellEffectInfo.IsEffect())
8890 TC_LOG_ERROR(
"entities.player",
"Player::CastItemUseSpell: Item (Entry: {}) has wrong spell id {}, ignoring", item->
GetEntry(), effectData->SpellID);
8925 TC_LOG_ERROR(
"entities.player",
"Player::CastItemUseSpell: Enchant {}, cast unknown spell {}", pEnchant->
ID, pEnchant->
EffectArg[s]);
8953 return effectData->TriggerType == ITEM_SPELLTRIGGER_ON_LOOTED;
8956 if (lootedEffectItr != item->
GetEffects().end())
8959 CastSpell(
this, (*lootedEffectItr)->SpellID, item);
8981 TC_LOG_DEBUG(
"entities.player.items",
"_RemoveAllItemMods start.");
9016 TC_LOG_DEBUG(
"entities.player.items",
"_RemoveAllItemMods complete.");
9021 TC_LOG_DEBUG(
"entities.player.items",
"_ApplyAllItemMods start.");
9060 TC_LOG_DEBUG(
"entities.player.items",
"_ApplyAllItemMods complete.");
9116 auto itr = std::find_if(
m_AELootView.begin(),
m_AELootView.end(), [&lootWorldObjectGuid](std::pair<ObjectGuid const, Loot*>
const& lootView)
9118 return lootView.second->GetOwnerGUID() == lootWorldObjectGuid;
9120 return itr !=
m_AELootView.end() ? itr->second :
nullptr;
9127 return roll->IsLootItem(lootObjectGuid, lootListId);
9201 TC_LOG_DEBUG(
"loot",
"Player::SendLoot: Player: '{}' ({}), Loot: {}",
9228 lootResponse.
LootObj = lootObj;
9229 lootResponse.
Owner = owner;
9246 packet.
Owner = owner;
9255 worldstate.
Value = value;
9256 worldstate.
Hidden = hidden;
9266 TC_LOG_DEBUG(
"network",
"Player::SendInitWorldStates: Sending SMSG_INIT_WORLD_STATES for Map: {}, Zone: {}", mapId, zoneId);
9269 packet.
MapID = mapId;
9281 npcInteraction.
Npc = guid;
9283 npcInteraction.
Success =
true;
9291 respecWipeConfirm.
Cost = cost;
9413 if (!isProfessionTool)
9432 if (professionSlot == -1)
9435 if (isProfessionTool)
9457 for (
uint8 i = 0; i < 4; ++i)
9458 if (slots[i] == slot)
9464 for (
uint8 i = 0; i < 4; ++i)
9473 uint32 minItemLevel = std::numeric_limits<uint32>::max();
9474 uint8 minItemLevelIndex = 0;
9475 for (
uint8 i = 0; i < 4; ++i)
9481 uint32 itemLevel = equipped->GetItemLevel(
this);
9482 if (itemLevel < minItemLevel)
9484 minItemLevel = itemLevel;
9485 minItemLevelIndex = i;
9491 return slots[minItemLevelIndex];
9501 uint32 freeSlotCount = 0;
9554 return freeSlotCount;
9565 InventoryResult ires = CanUnequipItem(pItem->GetPos(), false);
9566 if (ires == EQUIP_ERR_OK)
9568 tempcount += pItem->GetCount();
9569 if (tempcount >= count)
9570 return ItemSearchCallbackResult::Stop;
9593 ForEachItem(location, [&count, item, skipItem, countGems](
Item* pItem)
9595 if (pItem != skipItem)
9615 if (item != skipItem)
9617 if (pProto->GetItemLimitCategory() == limitCategory)
9627 std::vector<Item*> itemList = std::vector<Item*>();
9631 itemList.push_back(item);
9641 Item* result =
nullptr;
9647 return ItemSearchCallbackResult::Stop;
9657 uint8 bag = pos >> 8;
9658 uint8 slot = pos & 255;
9667 return pBag->GetItemByPos(slot);
9690 return item->
ToBag();
9702 default:
return nullptr;
9748 Item* result =
nullptr;
9754 return ItemSearchCallbackResult::Stop;
9821 uint8 bag = pos >> 8;
9822 uint8 slot = pos & 255;
9840 if (bag ==
NULL_BAG && !explicit_pos)
9892 return slot < pBag->GetBagSize();
9905 std::vector<Item*> unstorableItems;
9909 unstorableItems.push_back(unstorableItem);
9911 if (!unstorableItems.empty())
9913 std::size_t fullBatches = unstorableItems.size() /
MAX_MAIL_ITEMS;
9917 auto sendItemsBatch = [
this, &trans, &unstorableItems](std::size_t batchNumber, std::size_t batchSize)
9920 for (std::size_t j = 0; j < batchSize; ++j)
9926 for (std::size_t batch = 0; batch < fullBatches; ++batch)
9930 sendItemsBatch(fullBatches, remainder);
9948 return !
ForEachItem(location, [item, count, ¤tCount](
Item* pItem)
9952 currentCount += pItem->GetCount();
9953 if (currentCount >= count)
9954 return ItemSearchCallbackResult::Stop;
9968 if (pItem->
GetSlot() != except_slot)
9970 if (pItem->GetEntry() == item)
9971 tempcount += pItem->GetCount();
9974 tempcount += pItem->GetGemCountWithID(item);
9976 if (tempcount >= count)
9977 return ItemSearchCallbackResult::Stop;
9989 if (pItem->
GetSlot() == except_slot)
9996 if (tempcount >= count)
10008 if (pItem->
GetSlot() == except_slot)
10016 if (tempcount >= count)
10028 if (no_space_count)
10029 *no_space_count = count;
10045 if (no_space_count)
10046 *no_space_count = count + curcount - pProto->
GetMaxCount();
10057 if (no_space_count)
10058 *no_space_count = count;
10066 if (curcount + count >
uint32(limitQuantity))
10068 if (no_space_count)
10069 *no_space_count = count + curcount - limitQuantity;
10070 if (offendingItemId)
10071 *offendingItemId = pProto->
GetId();
10087 return CanStoreItem(bag, slot, dest, item, count,
nullptr,
false, no_space_count);
10143 if (pItem2 == pSrcItem)
10161 if (!pItem2 || swap)
10205 if (need_space > count)
10206 need_space = count;
10211 dest.push_back(newPosition);
10212 count -= need_space;
10220 if (bag == skip_bag)
10225 if (!pBag || pBag == pSrcItem)
10251 if (j == skip_slot)
10257 if (pItem2 == pSrcItem)
10261 if ((pItem2 !=
nullptr) != merge)
10276 if (need_space > count)
10277 need_space = count;
10282 dest.push_back(newPosition);
10283 count -= need_space;
10298 for (
uint32 j = slot_begin; j < slot_end; j++)
10307 if (pItem2 == pSrcItem)
10311 if ((pItem2 !=
nullptr) != merge)
10326 if (need_space > count)
10327 need_space = count;
10332 dest.push_back(newPosition);
10333 count -= need_space;
10344 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanStoreItem: Bag: {}, Slot: {}, Item: {}, Count: {}", bag, slot, entry, count);
10349 if (no_space_count)
10350 *no_space_count = count;
10359 if (no_space_count)
10360 *no_space_count = count;
10366 if (no_space_count)
10367 *no_space_count = count;
10373 uint32 no_similar_count = 0;
10378 if (no_space_count)
10379 *no_space_count = count + no_similar_count;
10385 if (no_similar_count == 0)
10387 if (no_space_count)
10388 *no_space_count = count + no_similar_count;
10400 if (no_similar_count == 0)
10402 if (no_space_count)
10403 *no_space_count = count + no_similar_count;
10414 if (count == no_similar_count)
10416 if (no_space_count)
10417 *no_space_count = no_similar_count;
10420 count -= no_similar_count;
10592 if (no_space_count)
10593 *no_space_count = count + no_similar_count;
10629 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
10641 for (
int k = 0; k < count; ++k)
10644 Item* item = items[k];
10650 uint32_t remaining_count = item->
GetCount();
10652 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanStoreItems: Player '{}' ({}), Index: {} ItemID: {}, Count: {}",
10678 bool b_found =
false;
10688 b_found = remaining_count == 0;
10705 for (
uint32 j = 0; j < bag->GetBagSize(); j++)
10714 b_found = remaining_count == 0;
10731 bool b_found =
false;
10737 pBagProto = bag->GetTemplate();
10743 for (
uint32 j = 0; j < bag->GetBagSize(); j++)
10763 bool b_found =
false;
10784 pBagProto = bag->GetTemplate();
10790 for (
uint32 j = 0; j < bag->GetBagSize(); j++)
10832 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanEquipItem: Player '{}' ({}), Slot: {}, Item: {}, Count: {}",
10955 if (
ItemTemplate const* pBagProto = pBag->GetTemplate())
10956 if (pBagProto->GetClass() == pProto->
GetClass() && (!swap || pBag->GetSlot() != eslot))
11004 if (offItem && (!not_loading ||
11025 if (!childEquipement)
11070 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanUnequipItem: Player '{}' ({}), Slot: {}, Item: {}, Count: {}",
11109 if (reagentBankOnly)
11122 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanBankItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}, Count: {}",
11138 TC_LOG_ERROR(
"entities.player.cheat",
"Possible hacking attempt: Player {} ({}) tried to move token [{} entry: {}] out of the currency bag!",
11153 if (!pItem->
IsBag())
11244 if (!reagentBankOnly)
11296 if (!reagentBankOnly)
11316 TC_LOG_DEBUG(
"entities.player.items",
"Player::CanUseItem: Player '{}' ({}), Item: {}",
11319 if (!
IsAlive() && not_loading)
11340 bool allowEquip =
false;
11412 if (proto->
Effects.size() >= 2)
11413 if (proto->
Effects[0]->SpellID == 483 || proto->
Effects[0]->SpellID == 55884)
11426 if (restrictOnlyLfg)
11470 std::vector<int32>
const* bonusListIDs ,
bool addToCollection )
11473 for (ItemPosCountVec::const_iterator itr = pos.begin(); itr != pos.end(); ++itr)
11474 count += itr->count;
11477 bool hadBoundItemObjective =
false;
11479 if (hadBoundItemObjective)
11506 std::ostringstream ss;
11507 GuidSet::const_iterator itr = allowedLooters.begin();
11508 ss << itr->GetCounter();
11509 for (++itr; itr != allowedLooters.end(); ++itr)
11510 ss <<
' ' << itr->GetCounter();
11518 if (addToCollection)
11527 if (
Item* childItem =
StoreNewItem(childDest, childTemplate->GetId(), update, {}, {}, context,
nullptr, addToCollection))
11529 childItem->SetCreator(item->
GetGUID());
11548 Item* lastItem = pItem;
11549 for (ItemPosCountVec::const_iterator itr = dest.begin(); itr != dest.end();)
11552 uint32 count = itr->count;
11556 if (itr == dest.end())
11558 lastItem =
_StoreItem(pos, pItem, count,
false, update);
11562 lastItem =
_StoreItem(pos, pItem, count,
true, update);
11576 uint8 bag = pos >> 8;
11577 uint8 slot = pos & 255;
11579 TC_LOG_DEBUG(
"entities.player.items",
"Player::_StoreItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {} ({}), Count: {}",
11679 return equippedItem;
11690 uint8 bag = pos >> 8;
11691 uint8 slot = pos & 255;
11715 TC_LOG_ERROR(
"entities.player",
"Player::EquipItem: Weapon switch cooldown spell {} for player '{}' ({}) couldn't be found in Spell.dbc",
11808 if (childItem->GetPos() != childDest)
11813 RemoveItem(childItem->GetBagSlot(), childItem->GetSlot(),
true);
11838 else if (
IsBankPos(parentBag, parentSlot))
11859 RemoveItem(childItem->GetBagSlot(), childItem->GetSlot(),
false);
11867 else if (
IsBankPos(parentBag, parentSlot))
11889 uint32 count = childItem->GetCount();
11894 RemoveItem(childItem->GetBagSlot(), childItem->GetSlot(),
true);
11907 uint8 slot = pos & 255;
11958 TC_LOG_DEBUG(
"entities.player.items",
"Player::SetVisibleItemSlot: Player '{}' ({}), Slot: {}, Item: {}",
11989 TC_LOG_DEBUG(
"entities.player.items",
"Player::RemoveItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}",
12049 pBag->RemoveItem(slot, update);
12071 it->SetNotRefundable(
this,
false,
nullptr,
false);
12074 if (it->IsInWorld())
12076 it->RemoveFromWorld();
12077 it->DestroyForPlayer(
this);
12092 if (pLastItem == pItem)
12116 TC_LOG_DEBUG(
"entities.player.items",
"Player::DestroyItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}",
12185 pBag->RemoveItem(slot, update);
12214 TC_LOG_DEBUG(
"entities.player.items",
"Player::DestroyItemCount: Player '{}' ({}), Item: {}, Count: {}",
12224 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12226 if (item->GetCount() + remcount <= count)
12229 remcount += item->GetCount();
12232 if (remcount >= count)
12237 item->SetCount(item->GetCount() - count + remcount);
12240 item->SendUpdateToPlayer(
this);
12253 for (
uint32 j = 0; j < bag->GetBagSize(); j++)
12255 if (
Item* item = bag->GetItemByPos(j))
12257 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12260 if (item->GetCount() + remcount <= count)
12262 remcount += item->GetCount();
12265 if (remcount >= count)
12270 item->SetCount(item->GetCount() - count + remcount);
12273 item->SendUpdateToPlayer(
this);
12288 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12290 if (item->GetCount() + remcount <= count)
12294 remcount += item->GetCount();
12297 if (remcount >= count)
12303 item->SetCount(item->GetCount() - count + remcount);
12306 item->SendUpdateToPlayer(
this);
12319 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12321 if (item->GetCount() + remcount <= count)
12323 remcount += item->GetCount();
12325 if (remcount >= count)
12330 item->SetCount(item->GetCount() - count + remcount);
12333 item->SendUpdateToPlayer(
this);
12346 for (
uint32 j = 0; j < bag->GetBagSize(); j++)
12348 if (
Item* item = bag->GetItemByPos(j))
12350 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12353 if (item->GetCount() + remcount <= count)
12355 remcount += item->GetCount();
12358 if (remcount >= count)
12363 item->SetCount(item->GetCount() - count + remcount);
12366 item->SendUpdateToPlayer(
this);
12381 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12383 if (item->GetCount() + remcount <= count)
12387 remcount += item->GetCount();
12389 if (remcount >= count)
12395 item->SetCount(item->GetCount() - count + remcount);
12398 item->SendUpdateToPlayer(
this);
12410 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12412 if (item->GetCount() + remcount <= count)
12415 remcount += item->GetCount();
12418 if (remcount >= count)
12423 item->SetCount(item->GetCount() - count + remcount);
12426 item->SendUpdateToPlayer(
this);
12438 if (item->GetEntry() == itemEntry && !item->IsInTrade())
12440 if (item->GetCount() + remcount <= count)
12443 remcount += item->GetCount();
12446 if (remcount >= count)
12451 item->SetCount(item->GetCount() - count + remcount);
12454 item->SendUpdateToPlayer(
this);
12466 TC_LOG_DEBUG(
"entities.player.items",
"Player::DestroyZoneLimitedItem: In map {} and area {} for player '{}' ({})",
12473 if (pItem->IsLimitedToAnotherMapOrZone(
GetMapId(), new_zone))
12479 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
12480 if (
Item* pItem = pBag->GetItemByPos(j))
12481 if (pItem->IsLimitedToAnotherMapOrZone(
GetMapId(), new_zone))
12487 if (pItem->IsLimitedToAnotherMapOrZone(
GetMapId(), new_zone))
12495 TC_LOG_DEBUG(
"entities.player.items",
"Player::DestroyConjuredItems: Player '{}' ({})",
12502 if (pItem->IsConjuredConsumable())
12508 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
12509 if (
Item* pItem = pBag->GetItemByPos(j))
12510 if (pItem->IsConjuredConsumable())
12516 if (pItem->IsConjuredConsumable())
12522 Item* result =
nullptr;
12528 return ItemSearchCallbackResult::Stop;
12542 std::vector<Item*> itemList = std::vector<Item*>();
12546 itemList.push_back(item);
12558 TC_LOG_DEBUG(
"entities.player.items",
"Player::DestroyItemCount: Player '{}' ({}), Item ({}, Entry: {}), Count: {}",
12580 uint8 srcbag = src >> 8;
12581 uint8 srcslot = src & 255;
12583 uint8 dstbag = dst >> 8;
12584 uint8 dstslot = dst & 255;
12601 if (pSrcItem->
GetCount() == count)
12622 TC_LOG_DEBUG(
"entities.player.items",
"Player::SplitItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}, Count: {}",
12696 uint8 srcbag = src >> 8;
12697 uint8 srcslot = src & 255;
12699 uint8 dstbag = dst >> 8;
12700 uint8 dstslot = dst & 255;
12716 SwapItem(parentItem->GetPos(), dst);
12729 SwapItem(parentItem->GetPos(), src);
12735 TC_LOG_DEBUG(
"entities.player.items",
"Player::SwapItem: Player '{}' ({}), Bag: {}, Slot: {}, Item: {}",
12759 if (
IsBagPos(src) && srcslot == dstbag)
12766 if (
IsBagPos(dst) && srcbag == dstslot)
12849 if (!pSrcItem->
IsBag() && !pDstItem->
IsBag())
12855 msg =
CanStoreItem(dstbag, dstslot, sDest, pSrcItem,
false);
12857 msg =
CanBankItem(dstbag, dstslot, sDest, pSrcItem,
false);
12910 msg =
CanStoreItem(dstbag, dstslot, sDest, pSrcItem,
true);
12912 msg =
CanBankItem(dstbag, dstslot, sDest, pSrcItem,
true);
12930 msg =
CanStoreItem(srcbag, srcslot, sDest2, pDstItem,
true);
12932 msg =
CanBankItem(srcbag, srcslot, sDest2, pDstItem,
true);
12950 if (
Bag* srcBag = pSrcItem->
ToBag())
12952 if (
Bag* dstBag = pDstItem->
ToBag())
12954 Bag* emptyBag =
nullptr;
12955 Bag* fullBag =
nullptr;
12956 if (srcBag->IsEmpty() && !
IsBagPos(src))
12961 else if (dstBag->IsEmpty() && !
IsBagPos(dst))
12968 if (emptyBag && fullBag)
13007 emptyBag->
StoreItem(count, bagItem,
true);
13049 bool released =
false;
13109 if (oldest_time > i_time)
13111 oldest_time = i_time;
13117 slot = oldest_slot;
13121 TC_LOG_DEBUG(
"entities.player.items",
"Player::AddItemToBuyBackSlot: Player '{}' ({}), Item: {}, Slot: {}",
13142 TC_LOG_DEBUG(
"entities.player.items",
"Player::GetItemFromBuyBackSlot: Player '{}' ({}), Slot: {}",
13151 TC_LOG_DEBUG(
"entities.player.items",
"Player::RemoveItemFromBuyBackSlot: Player '{}' ({}), Slot: {}",
13232 packet.
Muid = item;
13241 sellResponse.
ItemGUIDs.push_back(guid);
13242 sellResponse.
Reason = msg;
13352 TC_LOG_DEBUG(
"entities.player.items",
"Player::UpdateItemDuration: Player '{}' ({}), Time: {}, RealTimeOnly: {}",
13371 if (!itr->item->GetEnchantmentId(itr->slot))
13375 else if (itr->leftduration <= time)
13378 itr->item->ClearEnchantment(itr->slot);
13381 else if (itr->leftduration > time)
13383 itr->leftduration -= time;
13406 if (itr->item == item)
13421 if (itr->item == item)
13434 if (itr->slot == slot)
13436 if (itr->item && itr->item->GetEnchantmentId(slot))
13439 if (
sSpellMgr->IsArenaAllowedEnchancment(itr->item->GetEnchantmentId(slot)))
13447 itr->item->ClearEnchantment(slot);
13462 if (!
sSpellMgr->IsArenaAllowedEnchancment(pItem->GetEnchantmentId(slot)))
13463 pItem->ClearEnchantment(slot);
13468 for (
uint32 j = 0; j < pBag->GetBagSize(); j++)
13469 if (
Item* pItem = pBag->GetItemByPos(j))
13470 if (!
sSpellMgr->IsArenaAllowedEnchancment(pItem->GetEnchantmentId(slot)))
13471 pItem->ClearEnchantment(slot);
13485 if (itr->item == item && itr->slot == slot)
13487 itr->item->SetEnchantmentDuration(itr->slot, itr->leftduration,
this);
13545 if (gemTemplate->GetRequiredSkill() &&
GetSkillValue(gemTemplate->GetRequiredSkill()) < gemTemplate->GetRequiredSkillRank())
13557 switch (enchant_display_type)
13572 if (enchant_spell_id)
13575 CastSpell(
this, enchant_spell_id, item);
13592 scalingLevel = minLevel;
13594 scalingLevel = maxLevel;
13599 enchant_amount = std::max(enchant_amount, 1u);
13615 scalingLevel = minLevel;
13617 scalingLevel = maxLevel;
13623 enchant_amount = std::max(enchant_amount, 1u);
13625 TC_LOG_DEBUG(
"entities.player.items",
"Adding {} to stat nb {}", enchant_amount, enchant_spell_id);
13626 switch (enchant_spell_id)
13629 TC_LOG_DEBUG(
"entities.player.items",
"+ {} MANA", enchant_amount);
13633 TC_LOG_DEBUG(
"entities.player.items",
"+ {} HEALTH", enchant_amount);
13637 TC_LOG_DEBUG(
"entities.player.items",
"+ {} AGILITY", enchant_amount);
13642 TC_LOG_DEBUG(
"entities.player.items",
"+ {} STRENGTH", enchant_amount);
13647 TC_LOG_DEBUG(
"entities.player.items",
"+ {} INTELLECT", enchant_amount);
13657 TC_LOG_DEBUG(
"entities.player.items",
"+ {} STAMINA", enchant_amount);
13663 TC_LOG_DEBUG(
"entities.player.items",
"+ {} DEFENSE", enchant_amount);
13667 TC_LOG_DEBUG(
"entities.player.items",
"+ {} DODGE", enchant_amount);
13671 TC_LOG_DEBUG(
"entities.player.items",
"+ {} PARRY", enchant_amount);
13675 TC_LOG_DEBUG(
"entities.player.items",
"+ {} SHIELD_BLOCK", enchant_amount);
13679 TC_LOG_DEBUG(
"entities.player.items",
"+ {} MELEE_HIT", enchant_amount);
13683 TC_LOG_DEBUG(
"entities.player.items",
"+ {} RANGED_HIT", enchant_amount);
13687 TC_LOG_DEBUG(
"entities.player.items",
"+ {} SPELL_HIT", enchant_amount);
13691 TC_LOG_DEBUG(
"entities.player.items",
"+ {} MELEE_CRIT", enchant_amount);
13695 TC_LOG_DEBUG(
"entities.player.items",
"+ {} RANGED_CRIT", enchant_amount);
13699 TC_LOG_DEBUG(
"entities.player.items",
"+ {} SPELL_CRIT", enchant_amount);
13734 TC_LOG_DEBUG(
"entities.player.items",
"+ {} HIT", enchant_amount);
13740 TC_LOG_DEBUG(
"entities.player.items",
"+ {} CRITICAL", enchant_amount);
13754 TC_LOG_DEBUG(
"entities.player.items",
"+ {} RESILIENCE", enchant_amount);
13760 TC_LOG_DEBUG(
"entities.player.items",
"+ {} HASTE", enchant_amount);
13764 TC_LOG_DEBUG(
"entities.player.items",
"+ {} EXPERTISE", enchant_amount);
13769 TC_LOG_DEBUG(
"entities.player.items",
"+ {} ATTACK_POWER", enchant_amount);
13773 TC_LOG_DEBUG(
"entities.player.items",
"+ {} RANGED_ATTACK_POWER", enchant_amount);
13777 TC_LOG_DEBUG(
"entities.player.items",
"+ {} MANA_REGENERATION", enchant_amount);
13781 TC_LOG_DEBUG(
"entities.player.items",
"+ {} ARMOR PENETRATION", enchant_amount);
13785 TC_LOG_DEBUG(
"entities.player.items",
"+ {} SPELL_POWER", enchant_amount);
13789 TC_LOG_DEBUG(
"entities.player.items",
"+ {} HEALTH_REGENERATION", enchant_amount);
13793 TC_LOG_DEBUG(
"entities.player.items",
"+ {} SPELL_PENETRATION", enchant_amount);
13797 TC_LOG_DEBUG(
"entities.player.items",
"+ {} BLOCK_VALUE", enchant_amount);
13801 TC_LOG_DEBUG(
"entities.player.items",
"+ {} MASTERY", enchant_amount);
13807 TC_LOG_DEBUG(
"entities.player.items",
"+ {} VERSATILITY", enchant_amount);
13833 TC_LOG_ERROR(
"entities.player",
"Player::ApplyEnchantment: Unknown item enchantment (ID: {}, DisplayType: {}) for player '{}' ({})",
13880 if (curr_value < Enchant->RequiredSkillRank && new_value >= Enchant->
RequiredSkillRank)
13882 else if (new_value < Enchant->RequiredSkillRank && curr_value >= Enchant->
RequiredSkillRank)
13893 if (pPrismaticEnchant && pPrismaticEnchant->
RequiredSkillID == skill_id)
13895 if (curr_value < pPrismaticEnchant->RequiredSkillRank && new_value >= pPrismaticEnchant->
RequiredSkillRank)
13897 else if (new_value < pPrismaticEnchant->RequiredSkillRank && curr_value >= pPrismaticEnchant->
RequiredSkillRank)
13915 (*itr)->SendTimeUpdate(
this);
13960 if (dungeonEncounterId)
13993 for (
auto const& [_, gossipMenuItem] : menuItemBounds)
13995 if (!gossipMenuItem.Conditions.Meets(
this, source))
13998 bool canTalk =
true;
14001 switch (gossipMenuItem.OptionNpc)
14004 if (
GetSession()->SendLearnNewTaxiNode(creature))
14012 if (!creature->isCanInteractWithBattleMaster(
this,
false))
14018 if (!creature->CanResetTalents(
this))
14053 TC_LOG_ERROR(
"sql.sql",
"Creature entry {} has an unknown gossip option icon {} for menu {}.", creature->GetEntry(),
AsUnderlyingType(gossipMenuItem.OptionNpc), gossipMenuItem.MenuID);
14061 switch (gossipMenuItem.OptionNpc)
14074 PlayerTalkClass->GetGossipMenu().AddMenuItem(gossipMenuItem, gossipMenuItem.MenuID, gossipMenuItem.OrderIndex);
14122 TC_LOG_ERROR(
"entities.player",
"Player '{}' ({}) requests invalid gossip option for GameObject (Entry: {})",
14146 bool handled =
true;
14147 switch (gossipOptionNpc)
14174 TC_LOG_ERROR(
"entities.player",
"Player '{}' ({}) requested battlegroundlist from an invalid creature ({})",
14205 sourceUnit->HandleSpellClick(
this);
14292 npcInteraction.
Success =
true;
14318 for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr)
14321 if (!itr->second.TextID)
14324 if (itr->second.Conditions.Meets(
this, source))
14325 textId = itr->second.TextID;
14341 return menuIdToShow;
14348 for (GossipMenusContainer::const_iterator itr = menuBounds.first; itr != menuBounds.second; ++itr)
14350 if (!itr->second.Conditions.Meets(
this, source))
14353 menuIdToShow = menuId;
14356 return menuIdToShow;
14383 if (questFactionGroup && raceFaction->
FactionGroup != questFactionGroup)
14384 return questLevels->MaxLevel;
14386 return questLevels->MinLevelWithDelta;
14405 int32 maxLevel = questLevels->MaxLevel;
14407 if (level >= minLevel)
14408 return std::min(level, maxLevel);
14447 for (
uint32 quest_id : objectQIR)
14458 for (
uint32 quest_id : objectQR)
14479 if (questMenu.
Empty())
14502 if (quest->IsTurnIn() && quest->IsRepeatable() && !quest->IsDailyOrWeekly() && !quest->IsMonthly())
14504 else if (quest->IsTurnIn() && !quest->IsDailyOrWeekly() && !quest->IsMonthly())
14528 if (questGiver ==
this)
14533 return sObjectMgr->GetQuestTemplate(nextQuestID);
14539 if (!
IsInMap(worldObjectQuestGiver))
14542 if (!questGiver->
hasQuest(nextQuestID))
14545 return sObjectMgr->GetQuestTemplate(nextQuestID);
14613 QuestStatusMap::iterator itr =
m_QuestStatus.find(quest_id);
14623 if (ignoredQuestObjectiveId && obj.ID == ignoredQuestObjectiveId)
14737 Item* item =
static_cast<Item*
>(questGiver);
14738 sScriptMgr->OnQuestAccept(
this, item, quest);
14743 bool destroyItem =
true;
14749 destroyItem =
false;
14755 destroyItem =
false;
14776 switch (rewardType)
14824 bool hasFilteredQuestPackageReward =
false;
14825 if (std::vector<QuestPackageItemEntry const*>
const* questPackageItems =
sDB2Manager.GetQuestPackageItems(quest->
GetQuestPackageID()))
14829 if (questPackageItem->ItemID !=
int32(rewardId))
14834 hasFilteredQuestPackageReward =
true;
14838 SendEquipError(res,
nullptr,
nullptr, questPackageItem->ItemID);
14845 if (!hasFilteredQuestPackageReward)
14847 if (std::vector<QuestPackageItemEntry const*>
const* questPackageItems =
sDB2Manager.GetQuestPackageItemsFallback(quest->
GetQuestPackageID()))
14851 if (questPackageItem->ItemID !=
int32(rewardId))
14857 SendEquipError(res,
nullptr,
nullptr, questPackageItem->ItemID);
14886 questStatusData.
Slot = log_slot;
14911 time_t endTime = 0;
14923 questStatusData.
Timer = 0;
14934 Unit* caster =
this;
14936 caster = questGiver->
ToUnit();
14950 bool updateVisibility =
false;
14967 if (updateVisibility)
14970 sScriptMgr->OnQuestStatusChange(
this, quest_id);
14971 sScriptMgr->OnQuestStatusChange(
this, quest, oldStatus, questStatusData.
Status);
15031 for (Unit::AuraEffectList::const_iterator i = ModXPPctAuras.begin(); i != ModXPPctAuras.end(); ++i)
15032 AddPct(XP, (*i)->GetAmount());
15064 bool hasFilteredQuestPackageReward =
false;
15065 if (std::vector<QuestPackageItemEntry const*>
const* questPackageItems =
sDB2Manager.GetQuestPackageItems(questPackageId))
15069 if (onlyItemId && questPackageItem->ItemID !=
int32(onlyItemId))
15074 hasFilteredQuestPackageReward =
true;
15079 SendNewItem(item, questPackageItem->ItemQuantity,
true,
false);
15085 if (!hasFilteredQuestPackageReward)
15087 if (std::vector<QuestPackageItemEntry const*>
const* questPackageItems =
sDB2Manager.GetQuestPackageItemsFallback(questPackageId))
15091 if (onlyItemId && questPackageItem->ItemID !=
int32(onlyItemId))
15098 SendNewItem(item, questPackageItem->ItemQuantity,
true,
false);
15120 int32 amountToDestroy = obj.Amount;
15122 amountToDestroy = std::numeric_limits<uint32>::max();
15140 count = std::numeric_limits<uint32>::max();
15188 switch (rewardType)
15240 int32 moneyRew = 0;
15310 Unit* caster =
this;
15312 caster = questGiver->
ToUnit();
15324 Unit* caster =
this;
15326 caster = questGiver->
ToUnit();
15351 bool updateVisibility =
false;
15367 if (nextQuest->IsAutoAccept() &&
CanAddQuest(nextQuest,
true))
15376 creatureQGiver->AI()->OnQuestReward(
this, quest, rewardType, rewardId);
15378 goQGiver->AI()->OnQuestReward(
this, quest, rewardType, rewardId);
15381 sScriptMgr->OnQuestStatusChange(
this, quest_id);
15384 if (updateVisibility)
15417 if (quest->GetLimitTime())
15422 q_status.
Timer = 0;
15433 if (itemTemplate->GetBonding() ==
BIND_QUEST)
15439 if (quest->ItemDropQuantity[i] && itemTemplate->GetBonding() ==
BIND_QUEST)
15440 DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i],
true,
true);
15453 if (quest->HasFlag(flag))
15466 if (itemTemplate->GetBonding() ==
BIND_QUEST)
15472 if (quest->ItemDropQuantity[i] && itemTemplate->GetBonding() ==
BIND_QUEST)
15473 DestroyItemCount(quest->ItemDrop[i], quest->ItemDropQuantity[i],
true,
true);
15491 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestSkill: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't have the required skill value.",
15513 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestMinLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: {}) because player '{}' ({}) doesn't have the required (min) level.",
15528 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestMaxLevel: Sent QUEST_ERR_FAILED_LOW_LEVEL (QuestID: {}) because player '{}' ({}) doesn't have the required (max) level.",
15576 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestPreviousQuest: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't have required quest {}.",
15605 for (
auto itr = bounds.first; itr != bounds.second; ++itr)
15608 uint32 exclusiveQuestId = itr->second;
15609 if (exclusiveQuestId == prevId)
15618 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't have the required quest (1).",
15634 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestDependentPreviousQuests: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't have required quest (2).",
15646 if (!breadcrumbTargetQuestId)
15655 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestBreadcrumbQuest: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: {}) because target quest (QuestID: {}) is not available to player '{}' ({}).",
15676 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestDependentBreadcrumbQuests: Sent INVALIDREASON_DONT_HAVE_REQ (QuestID: {}) because player '{}' ({}) has a breadcrumb quest towards this quest in the quest log.",
15698 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestClass: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't have required class.",
15715 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestRace: Sent QUEST_ERR_FAILED_WRONG_RACE (QuestID: {}) because player '{}' ({}) doesn't have required race.",
15732 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestReputation: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't required reputation (min).",
15749 TC_LOG_DEBUG(
"misc",
"SatisfyQuestReputation: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't required reputation (max).",
15770 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestStatus: Sent QUEST_STATUS_REWARDED (QuestID: {}) because player '{}' ({}) quest status is already REWARDED.",
15781 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestStatus: Sent QUEST_ERR_ALREADY_ON1 (QuestID: {}) because player '{}' ({}) quest status is not NONE.",
15796 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestConditions: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) doesn't meet conditions.",
15799 TC_LOG_DEBUG(
"condition",
"Player::SatisfyQuestConditions: conditions not met for quest {}", qInfo->
GetQuestId());
15812 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestTimed: Sent QUEST_ERR_ONLY_ONE_TIMED (QuestID: {}) because player '{}' ({}) is already on a timed quest.",
15827 for (
auto itr = bounds.first; itr != bounds.second; ++itr)
15829 uint32 exclude_Id = itr->second;
15843 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestExclusiveGroup: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) already did daily quests in exclusive group.",
15856 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestExclusiveGroup: Sent QUEST_ERR_NONE (QuestID: {}) because player '{}' ({}) already did quest in exclusive group.",
15900 return itr->second.find(qInfo->
GetQuestId()) == itr->second.end();
15910 TC_LOG_DEBUG(
"misc",
"Player::SatisfyQuestExpansion: Sent QUEST_ERR_FAILED_EXPANSION (QuestID: {}) because player '{}' ({}) does not have required expansion.",
16014 QuestStatusMap::const_iterator itr =
m_QuestStatus.find(quest_id);
16016 return itr->second.Status;
16029 QuestStatusMap::const_iterator itr =
m_QuestStatus.find(quest_id);
16042 if (!quest->IsTurnIn())
16045 sScriptMgr->OnQuestStatusChange(
this, questId);
16046 sScriptMgr->OnQuestStatusChange(
this, quest, oldStatus, status);
16055 QuestStatusMap::iterator itr =
m_QuestStatus.find(questId);
16060 if (objectiveItr->second.QuestStatusItr == itr)
16070 bool updateVisibility =
false;
16080 if (updateVisibility)
16097 bool updateVisibility =
false;
16119 if (updateVisibility)
16127 if (saBounds.first != saBounds.second)
16129 std::set<uint32> aurasToRemove, aurasToCast;
16130 uint32 zone = 0, area = 0;
16133 for (SpellAreaForQuestMap::const_iterator itr = saBounds.first; itr != saBounds.second; ++itr)
16136 aurasToRemove.insert(itr->second->spellId);
16138 aurasToCast.insert(itr->second->spellId);
16145 for (
auto itr = aurasToRemove.begin(); itr != aurasToRemove.end();)
16147 bool auraRemoved =
false;
16149 for (
const auto i : aurasToCast)
16153 itr = aurasToRemove.erase(itr);
16154 auraRemoved =
true;
16163 for (
auto spellId : aurasToCast)
16167 for (
auto spellId : aurasToRemove)
16171 if (updateInteractions)
16185 return *questStatus;
16201 return *questStatus;
16208 TC_LOG_ERROR(
"entities.player.quest",
"Player::GetQuestDialogStatus: Called with unexpected type (Entry: {}, Type: {}) by player '{}' ({})",
16215 for (
uint32 questId : qir)
16226 else if (quest->
IsMeta())
16240 else if (quest->
IsMeta())
16265 for (
uint32 questId : qr)
16283 else if (quest->
IsMeta())
16309 bool updateVisibility =
false;
16310 for (
uint32 const& questId : questIds)
16342 sScriptMgr->OnQuestStatusChange(
this, questId);
16351 if (updateVisibility)
16357 std::list<Creature*> creatureList;
16360 for (
Creature* creature : creatureList)
16369 creature->DespawnOrUnsummon();
16386 if (obj.ObjectID == entry)
16402 uint32 reqItemCount = obj.Amount;
16409 uint32 reqCurrencyCount = obj.Amount;
16446 return m_playerData->QuestLog[slot].ObjectiveProgress[counter];
16458 return (*
m_playerData->QuestLog[slot].ObjectiveFlags) & (1 << objectiveIndex);
16466 TC_LOG_ERROR(
"entities.player.quest",
"Player::GetQuestObjectiveData: Called for quest {} with invalid StorageIndex {} (objective data is not tracked)",
16473 TC_LOG_ERROR(
"entities.player.quest",
"Player::GetQuestObjectiveData: Player '{}' ({}) quest {} out of range StorageIndex {}",
16606 status->Explored =
true;
16622 for (
GroupReference* itr = group->GetFirstMember(); itr !=
nullptr; itr = itr->
next())
16624 Player* player = itr->GetSource();
16641}
const ItemQuestObjectiveFilters;
16646 std::vector<QuestObjective const*> updatedObjectives;
16647 std::function<bool(
QuestObjective const*)>
const* objectiveFilter =
nullptr;
16648 if (boundItemFlagRequirement)
16649 objectiveFilter = *boundItemFlagRequirement ? &ItemQuestObjectiveFilters.QuestBoundItem : &ItemQuestObjectiveFilters.NotQuestBoundItem;
16659 if (
Quest const* quest =
sObjectMgr->GetQuestTemplate(updatedObjectives[0]->QuestID))
16660 if (quest->GetSrcItemId() == entry)
16663 if (hadBoundItemObjective)
16674 uint32 questId = objectiveItr.second.QuestStatusItr->first;
16675 uint16 logSlot = objectiveItr.second.QuestStatusItr->second.Slot;
16684 if (newItemCount < objective->Amount)
16711 uint16 addKillCount = 1;
16712 uint32 real_entry = entry;
16768 std::vector<QuestObjective const*>* updatedObjectives , std::function<
bool(
QuestObjective const*)>
const* objectiveFilter )
16770 bool anyObjectiveChangedCompletionState =
false;
16771 bool updatePhaseShift =
false;
16772 bool updateZoneAuras =
false;
16774 bool anyObjectiveChangedSpawnTrackingState =
false;
16775 bool isObjectiveTypeForSpawnTracking = [&]() ->
bool
16787 if (isObjectiveTypeForSpawnTracking)
16803 uint32 questId = objectiveItr.second.QuestStatusItr->first;
16812 uint16 logSlot = objectiveItr.second.QuestStatusItr->second.Slot;
16822 if (objectiveWasComplete && addCount >= 0)
16825 if (objectiveFilter && !(*objectiveFilter)(objective))
16828 bool objectiveIsNowComplete =
false;
16837 if (addCount > 0 ? (currentProgress < objective->Amount) : (currentProgress > 0))
16839 int32 newProgress = std::clamp<int32>(currentProgress + addCount, 0, objective->
Amount);
16843 switch (objectiveType)
16870 switch (objectiveType)
16876 objectiveIsNowComplete = addCount != 0;
16891 ABORT_MSG(
"Unhandled quest objective type %u",
uint32(objectiveType));
16902 return otherObjective.Type == QUEST_OBJECTIVE_PROGRESS_BAR && !(otherObjective.Flags & QUEST_OBJECTIVE_FLAG_PART_OF_PROGRESS_BAR);
16904 if (progressBarObjectiveItr != quest->
GetObjectives().end())
16907 objectiveIsNowComplete =
true;
16916 QuestStatusData& questStatus = objectiveItr.second.QuestStatusItr->second;
16942 anyObjectiveChangedSpawnTrackingState =
true;
16946 if (objectiveWasComplete != objectiveIsNowComplete)
16947 anyObjectiveChangedCompletionState =
true;
16958 updatePhaseShift =
true;
16960 updateZoneAuras =
true;
16963 if (objectiveIsNowComplete)
16971 if (updatedObjectives)
16972 updatedObjectives->push_back(objective);
16978 if (anyObjectiveChangedCompletionState || anyObjectiveChangedSpawnTrackingState)
16981 if (updatePhaseShift)
16984 if (updateZoneAuras)
16998 for (std::pair<uint32 const, QuestStatusData>
const& questStatus :
m_QuestStatus)
17038 Quest const* qInfo =
sObjectMgr->GetQuestTemplate(objectiveItr.second.QuestStatusItr->first);
17048 if (!onlyIncomplete || !
IsQuestObjectiveComplete(objectiveItr.second.QuestStatusItr->second.Slot, qInfo, *objective))
17054 if (
QuestObjective const* objective = findObjectiveForItem(itemId))
17058 if (itemTemplate->QuestLogItemId)
17059 if (
QuestObjective const* objective = findObjectiveForItem(itemTemplate->QuestLogItemId))
17069 Quest const* qInfo =
sObjectMgr->GetQuestTemplate(objectiveStatus.QuestStatusItr->first);
17116 TC_LOG_ERROR(
"entities.player.quest",
"Player::SetQuestObjectiveData: called for quest {} with invalid StorageIndex {} (objective data is not tracked)",
17124 TC_LOG_ERROR(
"entities.player.quest",
"Player::SetQuestObjectiveData: player '{}' ({}) doesn't have quest status data (QuestID: {})",
17133 TC_LOG_ERROR(
"entities.player.quest",
"Player::SetQuestObjectiveData: player '{}' ({}) quest {} out of range StorageIndex {}",
17143 if (oldData == data)
17147 sScriptMgr->OnQuestObjectiveChange(
this, quest, objective, oldData, data);
17170 return otherObjective.Type == QUEST_OBJECTIVE_PROGRESS_BAR && !(otherObjective.Flags & QUEST_OBJECTIVE_FLAG_PART_OF_PROGRESS_BAR);
17172 if (progressBarObjectiveItr == quest->
GetObjectives().end())
17179 if (!objectiveIndex)
17183 int32 previousIndex = objectiveIndex - 1;
17184 bool objectiveSequenceSatisfied =
true;
17185 bool previousSequencedObjectiveComplete =
false;
17186 int32 previousSequencedObjectiveIndex = -1;
17192 previousSequencedObjectiveIndex = previousIndex;
17197 if (objectiveSequenceSatisfied)
17201 }
while (previousIndex >= 0);
17205 if (previousSequencedObjectiveIndex == -1)
17206 return objectiveSequenceSatisfied;
17207 if (!previousSequencedObjectiveComplete || !objectiveSequenceSatisfied)
17210 else if (!previousSequencedObjectiveComplete && previousSequencedObjectiveIndex != -1)
17221 switch (objective.
Type)
17270 TC_LOG_ERROR(
"entities.player.quest",
"Player::CanCompleteQuest: Player '{}' ({}) tried to complete a quest (ID: {}) with an unknown objective type {}",
17297 float progress = 0.0f;
17303 if (progress >= 100.0f)
17373 questGiverQuestFailed.
QuestID = questId;
17374 questGiverQuestFailed.
Reason = reason;
17384 questUpdateFailedTimer.
QuestID = questId;
17393 questGiverInvalidQuest.
Reason = reason;
17395 questGiverInvalidQuest.
ReasonText = reasonText;
17447 packet.
Count = count;
17487 questUpdateAddPvpCredit.
Count = newCount;
17497 if (itr->IsAnyTypeCreature())
17508 else if (itr->IsGameObject())
17552 if (std::vector<QuestObjective const*>
const* questObjectiveList =
sObjectMgr->GetSpawnTrackingQuestObjectiveList(spawnTrackingId))
17553 for (
QuestObjective const* questObjective : *questObjectiveList)
17555 return questObjective;
17562 if (spawnTrackingId && questObjectiveId &&
sObjectMgr->IsQuestObjectiveForSpawnTracking(spawnTrackingId, questObjectiveId))
17573 auto itr2 = itr->second.SpawnTrackingList.find(std::make_pair(questObjective->StorageIndex, spawnTrackingId));
17574 if (itr2 != itr->second.SpawnTrackingList.end())
17603 uint16 personalRatingCache[] = {0, 0, 0};
17609 Field* fields = result->Fetch();
17616 TC_LOG_ERROR(
"entities.player.loading",
"Player::_LoadArenaTeamInfo: couldn't load arenateam {}", arenaTeamId);
17623 personalRatingCache[arenaSlot] = fields[4].
GetUInt16();
17632 while (result->NextRow());
17635 for (
uint8 slot = 0; slot <= 2; ++slot)
17649 Field* fields = result->Fetch();
17663 eqSet.
Data.
Pieces[i] = ObjectGuid::Create<HighGuid::Item>(guid);
17672 }
while (result->NextRow());
17688 Field* fields = result->Fetch();
17703 for (std::size_t i = 0; i < eqSet.
Data.
Enchants.size(); ++i)
17710 }
while (result->NextRow());
17718 Field* fields = result->Fetch();
17726 fields[2].GetFloat(),
17727 fields[3].GetFloat(),
17728 fields[4].GetFloat(),
17729 fields[5].GetFloat());
17745 Field* fields = result->Fetch();
17752 in_flight = !fields[5].
GetString().empty();
17799 std::string name =
"<unknown>";
17801 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player '{}' ({}) not found in table `characters`, can't load. ", name, guid.
ToString());
17805 struct PlayerLoadData
17826 uint8 inventorySlots;
17828 std::array<BagSlotFlags, 5> bagSlotFlags;
17831 std::array<BagSlotFlags, 7> bankBagSlotFlags;
17840 std::string taximask;
17847 time_t logout_time;
17848 uint8 is_logout_resting;
17849 uint32 resettalents_cost;
17850 time_t resettalents_time;
17851 uint32 primarySpecialization;
17858 uint32 summonedPetNumber;
17862 time_t death_expire_time;
17863 std::string taxi_path;
17872 std::array<uint32, MAX_POWERS_PER_CLASS> powers;
17874 uint8 activeTalentGroup;
17876 std::string exploredZones;
17877 std::string knownTitles;
17881 uint8 fishingSteps;
17885 float honorRestBonus;
17887 int32 personalTabardEmblemStyle;
17888 int32 personalTabardEmblemColor;
17889 int32 personalTabardBorderStyle;
17890 int32 personalTabardBorderColor;
17891 int32 personalTabardBackgroundColor;
17893 explicit PlayerLoadData(
Field const* fields)
17901 gender =
Gender(fields[i++].GetUInt8());
17905 inventorySlots = fields[i++].
GetUInt8();
17909 bankSlots = fields[i++].
GetUInt8();
17914 playerFlags =
PlayerFlags(fields[i++].GetUInt32());
17916 position_x = fields[i++].
GetFloat();
17917 position_y = fields[i++].
GetFloat();
17918 position_z = fields[i++].
GetFloat();
17920 orientation = fields[i++].
GetFloat();
17922 createTime = fields[i++].
GetInt64();
17924 cinematic = fields[i++].
GetUInt8();
17927 rest_bonus = fields[i++].
GetFloat();
17928 logout_time = fields[i++].
GetInt64();
17929 is_logout_resting = fields[i++].
GetUInt8();
17930 resettalents_cost = fields[i++].
GetUInt32();
17931 resettalents_time = fields[i++].
GetInt64();
17932 primarySpecialization = fields[i++].
GetUInt32();
17939 summonedPetNumber = fields[i++].
GetUInt32();
17943 death_expire_time = fields[i++].
GetInt64();
17945 dungeonDifficulty =
Difficulty(fields[i++].GetUInt8());
17948 yesterdayKills = fields[i++].
GetUInt16();
17950 watchedFaction = fields[i++].
GetUInt32();
17953 for (
uint32& power : powers)
17956 activeTalentGroup = fields[i++].
GetUInt8();
17958 exploredZones = fields[i++].
GetString();
17960 actionBars = fields[i++].
GetUInt8();
17961 raidDifficulty =
Difficulty(fields[i++].GetUInt8());
17962 legacyRaidDifficulty =
Difficulty(fields[i++].GetUInt8());
17963 fishingSteps = fields[i++].
GetUInt8();
17967 honorRestBonus = fields[i++].
GetFloat();
17968 numRespecs = fields[i++].
GetUInt8();
17969 personalTabardEmblemStyle = fields[i++].
GetInt32();
17970 personalTabardEmblemColor = fields[i++].
GetInt32();
17971 personalTabardBorderStyle = fields[i++].
GetInt32();
17972 personalTabardBorderColor = fields[i++].
GetInt32();
17973 personalTabardBackgroundColor = fields[i++].
GetInt32();
17976 } fields(result->Fetch());
17980 if (fields.account !=
GetSession()->GetAccountId())
17982 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) loading from wrong account (is: {}, should be: {})", guid.
ToString(),
GetSession()->GetAccountId(), fields.account);
17988 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) is banned, can't load.", guid.
ToString());
17994 m_name = std::move(fields.name);
18015 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has wrong gender ({}), can't load.", guid.
ToString(),
uint32(fields.gender));
18034 std::vector<std::string_view> exploredZones =
Trinity::Tokenize(fields.exploredZones,
' ',
false);
18035 for (std::size_t i = 0; i < exploredZones.size(); ++i)
18038 std::vector<std::string_view> knownTitles =
Trinity::Tokenize(fields.knownTitles,
' ',
false);
18039 for (std::size_t i = 0; i < knownTitles.size(); ++i)
18041 Trinity::StringTo<uint64>(knownTitles[i]).value_or(
UI64LIT(0)) << (32 * (i % 2)));
18051 std::vector<UF::ChrCustomizationChoice> customizations;
18056 Field* fields = customizationsResult->Fetch();
18057 customizations.emplace_back();
18062 }
while (customizationsResult->NextRow());
18069 for (
uint32 bagIndex = 0; bagIndex < fields.bagSlotFlags.size(); ++bagIndex)
18073 for (
uint32 bagIndex = 0; bagIndex < fields.bankBagSlotFlags.size(); ++bagIndex)
18085 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has wrong Appearance values (Hair/Skin/Color), can't load.", guid.
ToString());
18096 TC_LOG_DEBUG(
"entities.player.loading",
"Player::LoadFromDB: Load Basic value of player '{}' is: ",
m_name);
18111 Relocate(fields.position_x, fields.position_y, fields.position_z, fields.orientation);
18113 uint32 mapId = fields.map;
18114 uint32 instanceId = fields.instance_id;
18134 Map* map =
nullptr;
18135 bool player_at_bg =
false;
18138 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has invalid coordinates (MapId: {} X: {} Y: {} Z: {} O: {}). Teleport to default race/class locations.",
18140 RelocateToHomebind();
18173 player_at_bg =
false;
18186 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) was in BG in database, but BG was not found and entry point was invalid! Teleport to default race/class locations.",
18188 RelocateToHomebind();
18198 else if (fields.transguid)
18200 ObjectGuid transGUID = ObjectGuid::Create<HighGuid::Transport>(fields.transguid);
18203 if (
Map* transportMap =
sMapMgr->CreateMap(mapId,
this))
18207 if (transportOnMap->GetExpectedMapId() != mapId)
18211 transportMap =
sMapMgr->CreateMap(mapId,
this);
18216 transport = transportOnMap;
18222 float x = fields.trans_x, y = fields.trans_y, z = fields.trans_z, o = fields.trans_o;
18232 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has invalid transport coordinates (X: {} Y: {} Z: {} O: {}). Teleport to bind location.",
18237 RelocateToHomebind();
18249 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has problems with transport guid ({}). Teleport to bind location.",
18250 guid.
ToString(), fields.transguid);
18252 RelocateToHomebind();
18256 else if (!fields.taxi_path.empty())
18263 for (
int i = 0; i < 2; ++i)
18275 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has wrong data in taxi destination list ({}), teleport to homebind.",
GetGUID().
ToString(), fields.taxi_path);
18276 RelocateToHomebind();
18280 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has too short taxi destination list ({}), teleport to original node.",
GetGUID().
ToString(), fields.taxi_path);
18301 else if (mapEntry->
IsDungeon() && instanceId)
18304 map =
sMapMgr->FindMap(mapId, instanceId);
18308 mapEntry =
sMapStore.LookupEntry(mapId);
18314 TC_LOG_DEBUG(
"entities.player.loading",
"Player::LoadFromDB: Player '{}' ({}) using client without required expansion tried login at non accessible map {}",
18316 RelocateToHomebind();
18323 map =
sMapMgr->CreateMap(mapId,
this);
18325 bool check =
false;
18329 areaTrigger =
sObjectMgr->GetGoBackTrigger(mapId);
18337 areaTrigger =
sObjectMgr->GetGoBackTrigger(mapId);
18340 else if (instanceId && !
sInstanceLockMgr.FindActiveInstanceLock(guid, { mapId, map->GetDifficultyID() }))
18342 areaTrigger =
sObjectMgr->GetMapEntranceTrigger(mapId);
18355 map =
sMapMgr->CreateMap(mapId,
this);
18362 RelocateToHomebind();
18363 map =
sMapMgr->CreateMap(mapId,
this);
18366 TC_LOG_ERROR(
"entities.player.loading",
"Player::LoadFromDB: Player '{}' ({}) Map: {}, X: {}, Y: {}, Z: {}, O: {}. Invalid default map coordinates or instance couldn't be created.",
18389 time_t logoutTime = time_t(fields.logout_time);
18413 TC_LOG_WARN(
"entities.player.loading",
"Player::LoadFromDB: Player ({}) has invalid taximask ({}) in DB. Forced partial load.",
GetGUID().
ToString(), fields.taximask);
18415 uint32 extraflags = fields.extra_flags;
18421 TC_LOG_ERROR(
"entities.player.cheat",
"Player::LoadFromDB: Player ({}) tried to login while forced to rename, can't load.'",
GetGUID().
ToString());
18459 uint32 lootSpecId = fields.lootSpecId;
18461 if (chrSpec->ClassID ==
GetClass())
18538 uint32 curTitle = fields.chosenTitle;
18539 if (curTitle && !
HasTitle(curTitle))
18549 uint32 savedHealth = fields.health;
18566 uint32 loadedPowers = 0;
18571 uint32 savedPower = fields.powers[loadedPowers];
18573 SetPower(
Powers(i), (savedPower > maxPower) ? maxPower : savedPower);
18589 while (runes < maxRunes)
18596 SetPersonalTabard(fields.personalTabardEmblemStyle, fields.personalTabardEmblemColor, fields.personalTabardBorderStyle,
18597 fields.personalTabardBorderColor, fields.personalTabardBackgroundColor);
18599 TC_LOG_DEBUG(
"entities.player.loading",
"Player::LoadFromDB: The value of player '{}' after load item and aura is: ",
m_name);
18663 std::unique_ptr<Garrison> garrison = std::make_unique<Garrison>(
this);
18677 float bubble0 = 0.031f;
18679 float bubble1 = 0.125f;
18680 float bubble = fields.is_logout_resting > 0
18688 if (
GetSession()->GetBattlePetMgr()->IsBattlePetSystemEnabled())
18701 if (
GetSession()->GetCollectionMgr()->HasTransmogIllusion(transmogIllusion->ID))
18720 if (!quest->IsUnavailable() &&
CanTakeQuest(quest,
false))
18733 Field* fields = result->Fetch();
18736 std::string name = fields[1].
GetString();
18755 _CUFProfiles[id] = std::make_unique<CUFProfile>(name, frameHeight, frameWidth, sortBy, healthText, boolOptions, topPoint, bottomPoint, leftPoint, topOffset, bottomOffset, leftOffset);
18757 while (result->NextRow());
18762 if (!creature->
isDead())
18812 Field* fields = result->Fetch();
18821 TC_LOG_DEBUG(
"entities.player",
"Player::_LoadActions: Player '{}' ({}) has an invalid action button (Button: {}, Action: {}, Type: {}). It will be deleted at next save. This can be due to a player changing their talents.",
18827 }
while (result->NextRow());
18841 std::map<AuraKey, AuraLoadEffectInfo> effectInfo;
18846 Field* fields = effectResult->Fetch();
18850 std::span<uint8 const> rawGuidBytes = fields[0].
GetBinaryView();
18867 while (effectResult->NextRow());
18878 Field* fields = auraResult->Fetch();
18879 std::span<uint8 const> rawGuidBytes = fields[0].
GetBinaryView();
18903 TC_LOG_ERROR(
"entities.player",
"Player::_LoadAuras: Player '{}' ({}) has an invalid aura (SpellID: {}), ignoring.",
18910 TC_LOG_ERROR(
"entities.player",
"Player::_LoadAuras: Player '{}' ({}) has an invalid aura difficulty {} (SpellID: {}), ignoring.",
18929 if (remainCharges <= 0/* || remainCharges > spellproto->procCharges*/)
18937 AuraCreateInfo createInfo(castId, spellInfo, difficulty, key.EffectMask,
this);
18941 .
SetCastItem(itemGuid, castItemId, castItemLevel);
18945 if (!aura->CanBeSaved())
18951 aura->SetLoadedState(maxDuration, remainTime, remainCharges, stackCount, recalculateMask, info.
Amounts.data());
18952 aura->ApplyForTargets();
18953 TC_LOG_DEBUG(
"entities.player",
"Player::_LoadAuras: Added aura (SpellID: {}, EffectMask: {}) to player '{} ({})",
18957 while (auraResult->NextRow());
18981 Field* fields = result->Fetch();
18982 _corpseLocation.
WorldRelocate(fields[0].GetUInt16(), fields[1].GetFloat(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat());
19029 std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData;
19031 azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult);
19037 std::map<ObjectGuid, Bag*> bagMap;
19038 std::map<ObjectGuid, Item*> invalidBagMap;
19039 std::list<Item*> problematicItems;
19046 Field* fields = result->Fetch();
19047 if (
Item* item =
_LoadItem(trans, zoneId, timeDiff, fields))
19051 if (item->GetTemplate()->GetArtifactID() && addionalDataPtr->Artifact)
19052 item->LoadArtifactData(
this, addionalDataPtr->Artifact->Xp, addionalDataPtr->Artifact->ArtifactAppearanceId,
19053 addionalDataPtr->Artifact->ArtifactTierId, addionalDataPtr->Artifact->ArtifactPowers);
19055 if (addionalDataPtr->AzeriteItem)
19057 azeriteItem->LoadAzeriteItemData(
this, *addionalDataPtr->AzeriteItem);
19059 if (addionalDataPtr->AzeriteEmpoweredItem)
19061 azeriteEmpoweredItem->LoadAzeriteEmpoweredItemData(
this, *addionalDataPtr->AzeriteEmpoweredItem);
19075 parent->SetChildItem(item->GetGUID());
19076 item->CopyArtifactDataFromParent(parent);
19080 TC_LOG_ERROR(
"entities.player",
"Player::_LoadInventory: Player '{}' ({}) has child item ({}, entry: {}) which can't be loaded into inventory because parent item was not found (Bag {}, slot: {}). Item will be sent by mail.",
19082 item->DeleteFromInventoryDB(trans);
19083 problematicItems.push_back(item);
19091 item->SetContainer(
nullptr);
19092 item->SetSlot(slot);
19113 item =
BankItem(dest, item,
true);
19121 bagMap[item->GetGUID()] = pBag;
19126 invalidBagMap[item->GetGUID()] = item;
19132 std::map<ObjectGuid, Bag*>::iterator itr = bagMap.find(bagGuid);
19133 if (itr != bagMap.end())
19136 err =
CanStoreItem(itr->second->GetSlot(), slot, dest, item);
19140 else if (invalidBagMap.find(bagGuid) != invalidBagMap.end())
19142 std::map<ObjectGuid, Item*>::iterator invalidBagItr = invalidBagMap.find(bagGuid);
19143 if (std::find(problematicItems.begin(), problematicItems.end(), invalidBagItr->second) != problematicItems.end())
19148 TC_LOG_ERROR(
"entities.player",
"Player::_LoadInventory: Player '{}' ({}) has item ({}, entry: {}) which doesnt have a valid bag (Bag {}, slot: {}). Possible cheat?",
19150 item->DeleteFromInventoryDB(trans);
19161 TC_LOG_ERROR(
"entities.player",
"Player::_LoadInventory: Player '{}' ({}) has item ({}, entry: {}) which can't be loaded into inventory (Bag {}, slot: {}) by reason {}. Item will be sent by mail.",
19163 item->DeleteFromInventoryDB(trans);
19164 problematicItems.push_back(item);
19167 }
while (result->NextRow());
19172 while (!problematicItems.empty())
19176 MailDraft draft(subject,
"There were problems with equipping item(s).");
19179 draft.
AddItem(problematicItems.front());
19180 problematicItems.pop_front();
19201 Field* fields = result->Fetch();
19211 std::vector<int32> bonusListIDs;
19212 for (std::string_view bonusListIDtoken :
Trinity::Tokenize(fields[8].GetStringView(),
' ',
false))
19213 if (
Optional<int32> bonusListID = Trinity::StringTo<int32>(bonusListIDtoken))
19214 bonusListIDs.push_back(*bonusListID);
19218 TC_LOG_ERROR(
"entities.player",
"Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid id (item id: {}, entry: {}).",
19223 if (!
sObjectMgr->GetItemTemplate(itemEntry))
19225 TC_LOG_ERROR(
"entities.player",
"Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid entry (item id: {}, entry: {}).",
19232 TC_LOG_ERROR(
"entities.player",
"Player::_LoadVoidStorage: Player '{}' ({}) has an item with an invalid slot (item id: {}, entry: {}, slot: {}).",
19238 context, bonusListIDs);
19247 while (result->NextRow());
19252 Item* item =
nullptr;
19257 bool remove =
false;
19266 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadInventory: player ({}, name: '{}', map: {}) has item ({}) limited to another map ({}). Deleting item.",
19273 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadInventory: player ({}, name: '{}', diff: {}) has conjured item ({}) with expired lifetime (15 minutes). Deleting item.",
19281 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadInventory: player ({}, name: '{}') has item ({}) with expired refund time ({}). Deleting refund data and removing refundable flag.",
19286 trans->Append(stmt);
19304 TC_LOG_WARN(
"entities.player.loading",
"Player::_LoadInventory: player ({}, name: '{}') has item ({}) with refundable flags, but without data in item_refund_instance. Removing flag.",
19317 for (std::string_view guidStr :
Trinity::Tokenize((*result)[0].GetStringView(),
' ',
false))
19318 looters.insert(ObjectGuid::Create<HighGuid::Player>(Trinity::StringTo<uint64>(guidStr).value_or(
UI64LIT(0))));
19330 TC_LOG_WARN(
"entities.player.loading",
"Player::_LoadInventory: player ({}, name: '{}') has item ({}) with ITEM_FLAG_BOP_TRADEABLE flag, but without data in item_soulbound_trade_data. Removing flag.",
19335 else if (proto->GetHolidayID())
19340 for (GameEventMgr::ActiveEvents::const_iterator itr = activeEventsList.begin(); itr != activeEventsList.end(); ++itr)
19342 if (events[*itr].holiday_id == proto->GetHolidayID())
19352 TC_LOG_ERROR(
"entities.player",
"Player::_LoadInventory: player ({}, name: '{}') has a broken item (GUID: {}, entry: {}) in inventory. Deleting item.",
19367 TC_LOG_ERROR(
"entities.player",
"Player::_LoadInventory: player ({}, name: '{}') has an unknown item (entry: {}) in inventory. Deleting item.",
19386 TC_LOG_ERROR(
"entities.player",
"Player '{}' ({}) has unknown item in mailed items (GUID: {}, Entry: {}) in mail ({}), deleted.",
19387 player ? player->
GetName() :
"<unknown>", playerGuid.
ToString(), itemGuid, itemEntry, mailId);
19393 trans->Append(stmt);
19406 if (!item->
LoadFromDB(itemGuid, ownerGuid, fields, itemEntry))
19408 TC_LOG_ERROR(
"entities.player",
"Player::_LoadMailedItems: Item (GUID: {}) in mail ({}) doesn't exist, deleted from mail.", itemGuid, mailId);
19425 addionalData->
Artifact->ArtifactTierId, addionalData->
Artifact->ArtifactPowers);
19429 azeriteItem->LoadAzeriteItemData(player, *addionalData->
AzeriteItem);
19433 azeriteEmpoweredItem->LoadAzeriteEmpoweredItemData(player, *addionalData->
AzeriteEmpoweredItem);
19437 mail->
AddItem(itemGuid, itemEntry);
19448 std::unordered_map<uint64, Mail*> mailById;
19454 Field* fields = mailsResult->Fetch();
19482 while (mailsResult->NextRow());
19485 if (mailItemsResult)
19487 std::unordered_map<ObjectGuid::LowType, ItemAdditionalLoadInfo> additionalData;
19489 azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult);
19493 Field* fields = mailItemsResult->Fetch();
19496 }
while (mailItemsResult->NextRow());
19509 time_t lastDailyReset =
sWorld->GetNextDailyQuestsResetTime() -
DAY;
19510 time_t lastWeeklyReset =
sWorld->GetNextWeeklyQuestsResetTime() -
WEEK;
19516 Field* fields = result->Fetch();
19533 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatus: Player '{}' ({}) has invalid quest {} status ({}), replaced by QUEST_STATUS_INCOMPLETE(3).",
19539 questStatusData.
AcceptTime = time_t(fields[3].GetInt64());
19551 time_t endTime = time_t(fields[4].GetInt64());
19558 questStatusData.
Timer = 1;
19565 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadQuestStatus: Quest status is {{{}}} for quest {{{}}} for player ({})", questStatusData.
Status, quest_id,
GetGUID().
ToString());
19570 questStatusData.
Slot = slot;
19572 auto questStatusItr =
m_QuestStatus.emplace(quest_id, std::move(questStatusData)).first;
19590 while (result->NextRow());
19608 Field* fields = result->Fetch();
19620 auto objectiveItr = std::find_if(quest->
Objectives.begin(), quest->
Objectives.end(), [=](
QuestObjective const& objective) { return uint8(objective.StorageIndex) == storageIndex; });
19621 if (objectiveItr != quest->
Objectives.end())
19624 if (!objectiveItr->IsStoringFlag())
19630 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatusObjectives: Player '{}' ({}) has quest {} out of range objective index {}.",
GetName(),
GetGUID().
ToString(), questID, storageIndex);
19633 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatusObjectives: Player {} ({}) does not have quest {} but has objective data for it.",
GetName(),
GetGUID().
ToString(), questID);
19635 while (result->NextRow());
19649 Field* fields = result->Fetch();
19661 auto objectiveItr = std::find_if(quest->
Objectives.begin(), quest->
Objectives.end(), [=](
QuestObjective const& objective) { return uint8(objective.StorageIndex) == storageIndex; });
19662 if (objectiveItr != quest->
Objectives.end())
19666 if (
sObjectMgr->IsQuestObjectiveForSpawnTracking(spawnTrackingId, objectiveItr->ID))
19667 questStatusData.
SpawnTrackingList.insert(std::make_pair(storageIndex, spawnTrackingId));
19669 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player '{}' ({}) has objective {} (quest {}) with unrelated spawn tracking {}.",
GetName(),
GetGUID().
ToString(), objectiveItr->ID, questID, spawnTrackingId);
19672 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player '{}' ({}) has quest {} out of range objective index {}.",
GetName(),
GetGUID().
ToString(), questID, storageIndex);
19675 TC_LOG_ERROR(
"entities.player",
"Player::_LoadQuestStatusObjectiveSpawnTrackings: Player {} ({}) does not have quest {} but has objective spawn trackings for it.",
GetName(),
GetGUID().
ToString(), questID);
19676 }
while (result->NextRow());
19688 Field* fields = result->Fetch();
19714 if (std::vector<QuestPackageItemEntry const*>
const* questPackageItems =
sDB2Manager.GetQuestPackageItems(quest->
GetQuestPackageID()))
19724 while (result->NextRow());
19738 Field* fields = result->Fetch();
19742 if (qQuest->IsDFQuest())
19760 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadDailyQuestStatus: Loaded daily quest cooldown (QuestID: {}) for player '{}' ({})",
19763 while (result->NextRow());
19777 Field* fields = result->Fetch();
19786 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadWeeklyQuestStatus: Loaded weekly quest cooldown (QuestID: {}) for player '{}' ({})",
19789 while (result->NextRow());
19803 Field* fields = result->Fetch();
19814 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadSeasonalQuestStatus: Loaded seasonal quest cooldown (QuestID: {}) for player '{}' ({})",
19817 while (result->NextRow());
19831 Field* fields = result->Fetch();
19840 TC_LOG_DEBUG(
"entities.player.loading",
"Player::_LoadMonthlyQuestStatus: Loaded monthly quest cooldown (QuestID: {}) for player '{}' ({})",
19843 while (result->NextRow());
19855 AddSpell((*result)[0].GetUInt32(), (*result)[1].GetBool(),
false,
false, (*result)[2].GetBool(),
true);
19856 while (result->NextRow());
19859 if (favoritesResult)
19863 auto itr =
m_spells.find((*favoritesResult)[0].GetUInt32());
19865 itr->second.favorite =
true;
19866 }
while (favoritesResult->NextRow());
19880 Field* fields = result->Fetch();
19885 TC_LOG_ERROR(
"spells",
"Player::_LoadStoredAuraTeleportLocations: Player {} ({}) spell (ID: {}) does not exist",
19890 WorldLocation location(fields[1].GetUInt32(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat());
19893 TC_LOG_ERROR(
"spells",
"Player::_LoadStoredAuraTeleportLocations: Player {} ({}) spell (ID: {}) has invalid position on map {}, {{{}}}.",
19899 storedLocation.
Loc = location;
19902 while (result->NextRow());
19911 if (
Group* group =
sGroupMgr->GetGroupByDbStoreId((*result)[0].GetUInt32()))
19913 if (group->IsLeader(
GetGUID()))
19954 instanceInfo.
LockList.reserve(instanceLocks.size());
19956 for (
InstanceLock const* instanceLock : instanceLocks)
19958 instanceInfo.
LockList.emplace_back();
19961 lockInfos.
InstanceID = instanceLock->GetInstanceId();
19962 lockInfos.
MapID = instanceLock->GetMapId();
19963 lockInfos.
DifficultyID = instanceLock->GetDifficultyId();
19964 lockInfos.
TimeRemaining =
int32(std::max(std::chrono::duration_cast<Seconds>(instanceLock->GetEffectiveExpiryTime() - now).count(),
SI64LIT(0)));
19965 lockInfos.
CompletedMask = instanceLock->GetData()->CompletedEncountersMask;
19967 lockInfos.
Locked = !instanceLock->IsExpired();
19968 lockInfos.
Extended = instanceLock->IsExtended();
19978 uint8 LevelMin = 0;
19979 uint8 LevelMax = 0;
19980 int32 failedMapDifficultyXCondition = 0;
19982 uint32 missingQuest = 0;
19983 uint32 missingAchievement = 0;
19995 for (
auto&& itr : *mapDifficultyConditions)
19999 failedMapDifficultyXCondition = itr.first;
20020 missingItem = ar->
item;
20023 missingItem = ar->
item2;
20040 if (LevelMin || LevelMax || failedMapDifficultyXCondition || missingItem || missingQuest || missingAchievement)
20049 else if (mapDiff->
Message[
sWorld->GetDefaultDbcLocale()][0] !=
'\0' || failedMapDifficultyXCondition)
20054 params->Arg = target_difficulty;
20055 params->MapDifficultyXConditionId = failedMapDifficultyXCondition;
20058 else if (missingItem)
20134 if (
uint32 targetInstanceId =
sMapMgr->FindInstanceIdForPlayer(targetMapId,
this))
20135 if (
Map* map =
sMapMgr->FindMap(targetMapId, targetInstanceId))
20137 if (
InstanceScript* instanceScript = instanceMap->GetInstanceScript())
20138 entranceLocation =
sObjectMgr->GetWorldSafeLoc(instanceScript->GetEntranceLocation());
20141 if (!entranceLocation)
20146 if (
InstanceLock const* instanceLock =
sInstanceLockMgr.FindActiveInstanceLock(instanceOwnerGuid, { mapEntry, sDB2Manager.GetDownscaledMapDifficultyData(targetMapId, difficulty) }))
20147 entranceLocation =
sObjectMgr->GetWorldSafeLoc(instanceLock->GetData()->EntranceWorldSafeLocId);
20150 return entranceLocation;
20158 TC_LOG_ERROR(
"entities.player",
"Player::_LoadHomeBind: Player '{}' ({}) has incorrect race/class ({}/{}) pair. Can't load.",
20168 Field* fields = result->Fetch();
20170 m_homebind.
WorldRelocate(fields[0].GetUInt16(), fields[2].GetFloat(), fields[3].GetFloat(), fields[4].GetFloat(), fields[5].GetFloat());
20187 auto saveHomebindToDb = [&]()
20208 saveHomebindToDb();
20224 saveHomebindToDb();
20227 TC_LOG_DEBUG(
"entities.player",
"Player::_LoadHomeBind: Setting home position (MapID: {}, AreaID: {}, X: {}, Y: {}, Z: {} O: {}) of player '{}' ({})",
20242 SaveToDB(loginTransaction, trans, create);
20263 TC_LOG_DEBUG(
"entities.unit",
"Player::SaveToDB: The value of player {} at save: ",
m_name);
20274 trans->Append(stmt);
20276 auto finiteAlways = [](
float f) {
return std::isfinite(f) ? f : 0.0f; };
20313 stmt->
setUInt32(index++, bankBagSlotFlag);
20332 transLowGUID = transport->GetGUID().GetCounter();
20333 stmt->
setUInt64(index++, transLowGUID);
20335 std::ostringstream ss;
20391 ss <<
uint32(item->GetTemplate()->GetInventoryType()) <<
' ' << item->GetDisplayId(
this) <<
' ';
20393 ss << enchant->ItemVisual;
20398 <<
uint32(
sItemStore.AssertEntry(item->GetVisibleEntry(
this))->SubclassID) <<
' '
20399 <<
uint32(item->GetVisibleSecondaryModifiedAppearanceId(
this)) <<
' ';
20402 ss <<
"0 0 0 0 0 ";
20416 if (std::shared_ptr<Realm const> currentRealm =
sRealmList->GetCurrentRealm())
20453 stmt->
setUInt32(index++, bankBagSlotFlag);
20489 transLowGUID = transport->GetGUID().GetCounter();
20490 stmt->
setUInt64(index++, transLowGUID);
20492 std::ostringstream ss;
20509 stmt->
setUInt32(index++, petStable->GetCurrentPet() && petStable->GetCurrentPet()->Health > 0 ? petStable->GetCurrentPet()->PetNumber : 0);
20551 ss <<
uint32(item->GetTemplate()->GetInventoryType()) <<
' ' << item->GetDisplayId(
this) <<
' ';
20553 ss << enchant->ItemVisual;
20558 <<
uint32(
sItemStore.AssertEntry(item->GetVisibleEntry(
this))->SubclassID) <<
' '
20559 <<
uint32(item->GetVisibleSecondaryModifiedAppearanceId(
this)) <<
' ';
20562 ss <<
"0 0 0 0 0 ";
20582 if (std::shared_ptr<Realm const> currentRealm =
sRealmList->GetCurrentRealm())
20591 trans->Append(stmt);
20599 trans->Append(stmt);
20654 loginTransaction->Append(loginStmt);
20664 loginTransaction->Append(loginStmt);
20680 trans->Append(stmt);
20683template<
typename iterator>
20688 trans->Append(stmt);
20690 for (
auto&& customization : customizations)
20694 stmt->
setUInt32(1, customization.ChrCustomizationOptionID);
20695 stmt->
setUInt32(2, customization.ChrCustomizationChoiceID);
20696 trans->Append(stmt);
20726 return static_cast<TraitConfigType>(*savedConfig.Type) == TraitConfigType::Combat
20727 && (static_cast<TraitCombatConfigFlags>(*savedConfig.CombatConfigFlags) & TraitCombatConfigFlags::ActiveForSpec) == TraitCombatConfigFlags::None
20728 && (static_cast<TraitCombatConfigFlags>(*savedConfig.CombatConfigFlags) & TraitCombatConfigFlags::SharedActionBars) == TraitCombatConfigFlags::None
20729 && savedConfig.LocalIdentifier == localIdent;
20732 if (usedSavedTraitConfigIndex >= 0)
20742 switch (itr->second.uState)
20750 stmt->
setUInt64(4, itr->second.GetAction());
20752 trans->Append(stmt);
20759 stmt->
setUInt64(0, itr->second.GetAction());
20765 trans->Append(stmt);
20776 trans->Append(stmt);
20791 trans->Append(stmt);
20795 trans->Append(stmt);
20800 if (!itr->second->CanBeSaved())
20803 Aura* aura = itr->second;
20804 uint32 recalculateMask = 0;
20814 stmt->
setUInt32(index++, recalculateMask);
20822 trans->Append(stmt);
20833 stmt->
setUInt8(index++, effect->GetEffIndex());
20834 stmt->
setInt32(index++, effect->GetAmount());
20835 stmt->
setInt32(index++, effect->GetBaseAmount());
20836 trans->Append(stmt);
20874 GuidSet::iterator i_next;
20883 if (iPtr->IsRefundable() && iPtr->IsRefundExpired())
20884 iPtr->SetNotRefundable(
this);
20889 TC_LOG_ERROR(
"entities.player",
"Player::_SaveInventory: Can't find item ({}) in refundable storage for player '{}' ({}), removing.",
20897 itr->item->SetEnchantmentDuration(itr->slot, itr->leftduration,
this);
20913 if (test ==
nullptr)
20917 bagTestGUID = test2->GetGUID().GetCounter();
20919 TC_LOG_ERROR(
"entities.player",
"Player::_SaveInventory: Player '{}' ({}) has incorrect values (Bag: {}, Slot: {}) for the item ({}, State: {}). The player doesn't have an item at that position.",
20926 trans->Append(stmt);
20938 else if (test != item)
20940 TC_LOG_ERROR(
"entities.player",
"Player::_SaveInventory: Player '{}' ({}) has incorrect values (Bag: {}, Slot: {}) for the item ({}). {} is there instead!",
20959 trans->Append(stmt);
20964 trans->Append(stmt);
21001 std::ostringstream bonusListIDs;
21003 bonusListIDs << bonusListID <<
' ';
21004 stmt->
setString(9, bonusListIDs.str());
21007 trans->Append(stmt);
21043 trans->Append(stmt);
21051 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end(); ++itr)
21065 trans->Append(stmt);
21069 for (std::vector<ObjectGuid::LowType>::iterator itr2 = m->
removedItems.begin(); itr2 != m->
removedItems.end(); ++itr2)
21073 trans->Append(stmt);
21083 for (MailItemInfoVec::iterator itr2 = m->
items.begin(); itr2 != m->
items.end(); ++itr2)
21092 trans->Append(stmt);
21096 trans->Append(stmt);
21101 for (PlayerMails::iterator itr =
m_mail.begin(); itr !=
m_mail.end();)
21119 bool isTransaction = bool(trans);
21120 if (!isTransaction)
21144 trans->Append(stmt);
21150 trans->Append(stmt);
21163 stmt->
setUInt8(2, obj.StorageIndex);
21165 trans->Append(stmt);
21172 trans->Append(stmt);
21174 for (
auto [questObjectiveStorageIndex, spawnTrackingId] : qData.
SpawnTrackingList)
21179 stmt->
setUInt8(2, questObjectiveStorageIndex);
21181 trans->Append(stmt);
21191 trans->Append(stmt);
21196 trans->Append(stmt);
21201 trans->Append(stmt);
21214 trans->Append(stmt);
21222 trans->Append(stmt);
21228 if (!isTransaction)
21244 trans->Append(stmt);
21252 trans->Append(stmt);
21263 trans->Append(stmt);
21276 trans->Append(stmt);
21285 trans->Append(stmt);
21299 trans->Append(stmt);
21308 uint16 eventId = iter->first;
21310 for (SeasonalQuestMapByQuest::const_iterator itr = iter->second.begin(); itr != iter->second.end(); ++itr)
21312 uint32 questId = itr->first;
21313 time_t completedTime = itr->second;
21320 trans->Append(stmt);
21333 trans->Append(stmt);
21342 trans->Append(stmt);
21364 switch (itr->second.uState)
21372 stmt->
setInt8(4, professionSlot);
21373 trans->Append(stmt);
21379 stmt->
setInt8(2, professionSlot);
21382 trans->Append(stmt);
21388 trans->Append(stmt);
21403 for (PlayerSpellMap::iterator itr =
m_spells.begin(); itr !=
m_spells.end();)
21410 trans->Append(stmt);
21416 if (!itr->second.dependent)
21421 stmt->
setBool(2, itr->second.active);
21422 stmt->
setBool(3, itr->second.disabled);
21423 trans->Append(stmt);
21429 trans->Append(stmt);
21431 if (itr->second.favorite)
21436 trans->Append(stmt);
21462 trans->Append(stmt);
21471 trans->Append(stmt);
21481 trans->Append(stmt);
21500 trans->Append(stmt);
21530 trans->Append(stmt);
21656 raidDifficultySet.
Legacy = legacy;
21671 Map* map =
sMapMgr->FindMap(itr->first, itr->second);
21672 bool forgetInstance =
false;
21677 switch (instance->Reset(method))
21681 forgetInstance =
true;
21687 forgetInstance =
true;
21697 if (forgetInstance)
21707 data.
MapID = MapId;
21720 data.
MapID = mapID;
21728 if (!dungeonEncounter)
21741 if (!dungeonEncounter)
21767 if (attackedPlayer && (attackedPlayer ==
this || (
duel &&
duel->Opponent == attackedPlayer)))
21832 duel->Opponent->SetDuelTeam(2);
21844 if (!pet_guid.
IsPet())
21870 TC_LOG_DEBUG(
"entities.pet",
"Player::RemovePet: Player '{}' ({}), Pet (Entry: {}, Mode: {}, ReturnReagent: {})",
21887 if (spellInfo->
Reagent[i] > 0)
21975 return pet && pet->PetNumber == petNumber && pet->Type ==
HUNTER_PET;
21978 bool foundPet =
false;
21979 auto activeItr = std::ranges::find_if(
m_petStable->ActivePets, petNumberPred);
21982 activeItr->reset();
21986 auto stabledItr = std::ranges::find_if(
m_petStable->StabledPets, petNumberPred);
21987 if (stabledItr !=
m_petStable->StabledPets.end())
21989 stabledItr->reset();
22008 pet->CastPetAura(petSpell);
22015 pet->RemoveAurasDueToSpell(petSpell->
GetAura(pet->GetEntry()));
22022 return summonedBattlePet;
22054 static_cast<Puppet*
>(charm)->UnSummon();
22062 TC_LOG_FATAL(
"entities.player",
"Player::StopCastingCharm Player '{}' ({}) is not able to uncharm vehicle ({}) because of missing SPELL_AURA_CONTROL_VEHICLE",
22079 TC_LOG_FATAL(
"entities.player",
"Player::StopCastingCharm: Charmed unit has charmer {}\nPlayer debug info: {}\nCharm debug info: {}",
22090 std::string _text(text);
22116 std::string _text(text);
22129 std::string _text(text);
22139 std::string _text(text);
22159 bool isAddonMessage = language ==
LANG_ADDON;
22161 if (!isAddonMessage)
22164 std::string _text(text);
22172 if (isAddonMessage)
22185 if (target->
isAFK())
22187 else if (target->
isDND())
22199 TC_LOG_ERROR(
"entities.unit",
"WorldObject::Whisper: `broadcast_text` was not {} found", textId);
22214 for (std::pair<uint32 const, LanguageDesc>
const& languageDesc :
sLanguageMgr->GetLanguageDescById(language))
22215 if (languageDesc.second.SkillId &&
HasSkill(languageDesc.second.SkillId))
22226 ItemMap::const_iterator itr =
mMitems.find(
id);
22227 return itr !=
mMitems.end() ? itr->second :
nullptr;
22239 return mMitems.erase(
id) ? true :
false;
22271 for (PetSpellMap::iterator itr = pet->
m_spells.begin(); itr != pet->
m_spells.end(); ++itr)
22325 petSpells.
Flag = 0x8;
22340 if (!
sConditionMgr->IsObjectMeetingVehicleSpellConditions(vehicle->
GetEntry(), spellId,
this, vehicle))
22342 TC_LOG_DEBUG(
"condition",
"Player::VehicleSpellInitialize: Player '{}' ({}) doesn't meet conditions for vehicle (Entry: {}, Spell: {})",
22348 vehicle->
CastSpell(vehicle, spellInfo->
Id,
true);
22368 TC_LOG_ERROR(
"entities.player",
"Player::CharmSpellInitialize(): Player '{}' ({}) has a charm ({}) but no no charminfo!",
22407 if (!mod || !spellInfo)
22461 if (spellModOpBegin ==
m_spellMods.
end() || (*spellModOpBegin)->op != op)
22470 auto typeBegin = spellModOpBegin;
22472 while (typeBegin != end && (*typeBegin)->op == op)
22474 if ((*typeBegin)->type == type)
22489 bool operator==(std::vector<SpellModifier*>::const_iterator
const& itr)
const
22491 return itr == end || (*itr)->op != op || (*itr)->type != type;
22494 std::vector<SpellModifier*>::const_iterator end;
22498 return EndSentinel{ .end =
m_spellMods.
end(), .op = op, .type = type };
22516 modInstantSpell = mod;
22521 if (!modInstantSpell)
22530 modInstantSpell = mod;
22536 if (modInstantSpell)
22619 if (base + *flat == T(0))
22629 if (base >= T(10000) && value <= -100)
22643 if (base + *flat == T(0))
22653 if (base >= T(10000) && value <= -1.0f)
22670 float totalmul = 1.0f;
22671 int32 totalflat = 0;
22675 basevalue = T(
double(basevalue + totalflat) * totalmul);
22710 boost::dynamic_bitset<uint32> mask;
22713 boost::from_block_range(
22718 for (std::size_t classIndex = mask.find_first(); classIndex !=
decltype(mask)::npos; classIndex = mask.find_next(classIndex))
22728 if (spellMod->
mask[classIndex / 32] & (1u << (classIndex % 32)))
22739 if (spellMod->
mask[classIndex / 32] & (1u << (classIndex % 32)))