Merge remote branch 'origin/master' into 330

This commit is contained in:
tomrus88 2009-11-30 01:29:59 +03:00
commit 90ee507cf7
83 changed files with 1629 additions and 737 deletions

View file

@ -1335,7 +1335,7 @@ void Player::Update( uint32 p_time )
SendUpdateToOutOfRangeGroupMembers();
Pet* pet = GetPet();
if(pet && !IsWithinDistInMap(pet, OWNER_MAX_DISTANCE) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
if(pet && !pet->IsWithinDistInMap(this, GetMap()->GetVisibilityDistance()) && (GetCharmGUID() && (pet->GetGUID() != GetCharmGUID())))
{
RemovePet(pet, PET_SAVE_NOT_IN_SLOT, true);
}
@ -1651,7 +1651,7 @@ bool Player::TeleportTo(uint32 mapid, float x, float y, float z, float orientati
if (!(options & TELE_TO_NOT_UNSUMMON_PET))
{
//same map, only remove pet if out of range for new position
if(pet && !pet->IsWithinDist3d(x,y,z, OWNER_MAX_DISTANCE))
if(pet && !pet->IsWithinDist3d(x,y,z,GetMap()->GetVisibilityDistance()))
UnsummonPetTemporaryIfAny();
}
@ -5025,15 +5025,12 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if(!skill_id)
return false;
uint16 i=0;
for (; i < PLAYER_MAX_SKILLS; ++i)
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill_id)
break;
if(i>=PLAYER_MAX_SKILLS)
SkillStatusMap::iterator itr = mSkillStatus.find(skill_id);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
uint32 data = GetUInt32Value(valueIndex);
uint32 value = SKILL_VALUE(data);
uint32 max = SKILL_MAX(data);
@ -5046,7 +5043,9 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
if(new_value > max)
new_value = max;
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,max));
SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(new_value,max));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,skill_id);
return true;
}
@ -5155,13 +5154,13 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
return false;
}
uint16 i=0;
for (; i < PLAYER_MAX_SKILLS; ++i)
if ( SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_INDEX(i))) == SkillId ) break;
if ( i >= PLAYER_MAX_SKILLS )
SkillStatusMap::iterator itr = mSkillStatus.find(SkillId);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return false;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
uint32 data = GetUInt32Value(valueIndex);
uint16 SkillValue = SKILL_VALUE(data);
uint16 MaxValue = SKILL_MAX(data);
@ -5176,7 +5175,9 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
if(new_value > MaxValue)
new_value = MaxValue;
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(new_value,MaxValue));
SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(new_value,MaxValue));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl)
{
if((SkillValue < *bsl && new_value >= *bsl))
@ -5274,19 +5275,20 @@ void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool de
void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent)
{
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skillid)
{
uint32 bonus_val = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i));
int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val);
int16 perm_bonus = SKILL_PERM_BONUS(bonus_val);
if(talent) // permanent bonus stored in high part
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val));
else // temporary/item bonus stored in low part
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus));
SkillStatusMap::const_iterator itr = mSkillStatus.find(skillid);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return;
}
uint32 bonusIndex = PLAYER_SKILL_BONUS_INDEX(itr->second.pos);
uint32 bonus_val = GetUInt32Value(bonusIndex);
int16 temp_bonus = SKILL_TEMP_BONUS(bonus_val);
int16 perm_bonus = SKILL_PERM_BONUS(bonus_val);
if(talent) // permanent bonus stored in high part
SetUInt32Value(bonusIndex,MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val));
else // temporary/item bonus stored in low part
SetUInt32Value(bonusIndex,MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus));
}
void Player::UpdateSkillsForLevel()
@ -5296,10 +5298,12 @@ void Player::UpdateSkillsForLevel()
bool alwaysMaxSkill = sWorld.getConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL);
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
{
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
if(itr->second.uState == SKILL_DELETED)
continue;
uint32 pskill = itr->first;
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(pskill);
if(!pSkill)
@ -5308,37 +5312,52 @@ void Player::UpdateSkillsForLevel()
if(GetSkillRangeType(pSkill,false) != SKILL_RANGE_LEVEL)
continue;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
uint32 data = GetUInt32Value(valueIndex);
uint32 max = SKILL_MAX(data);
uint32 val = SKILL_VALUE(data);
/// update only level dependent max skill values
if(max!=1)
{
/// miximize skill always
/// maximize skill always
if(alwaysMaxSkill)
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(maxSkill,maxSkill));
/// update max skill value if current max skill not maximized
else if(max != maxconfskill)
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,maxSkill));
{
SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill,maxSkill));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
}
else if(max != maxconfskill) /// update max skill value if current max skill not maximized
{
SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(val,maxSkill));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
}
}
}
}
void Player::UpdateSkillsToMaxSkillsForLevel()
{
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
{
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
if(itr->second.uState == SKILL_DELETED)
continue;
uint32 pskill = itr->first;
if( IsProfessionOrRidingSkill(pskill))
continue;
uint32 data = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i));
uint32 valueIndex = PLAYER_SKILL_VALUE_INDEX(itr->second.pos);
uint32 data = GetUInt32Value(valueIndex);
uint32 max = SKILL_MAX(data);
if(max > 1)
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(max,max));
{
SetUInt32Value(valueIndex,MAKE_SKILL_VALUE(max,max));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
}
if(pskill == SKILL_DEFENSE)
UpdateDefenseBonusesMod();
@ -5352,15 +5371,16 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
if(!id)
return;
uint16 i=0;
for (; i < PLAYER_MAX_SKILLS; ++i)
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == id) break;
SkillStatusMap::iterator itr = mSkillStatus.find(id);
if(i<PLAYER_MAX_SKILLS) //has skill
//has skill
if(itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED)
{
if(currVal)
{
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(currVal,maxVal));
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),MAKE_SKILL_VALUE(currVal,maxVal));
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_CHANGED;
learnSkillRewardedSpells(id, currVal);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id);
@ -5368,9 +5388,15 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
else //remove
{
// clear skill fields
SetUInt32Value(PLAYER_SKILL_INDEX(i),0);
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),0);
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos),0);
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),0);
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos),0);
// mark as deleted or simply remove from map if not saved yet
if(itr->second.uState != SKILL_NEW)
itr->second.uState = SKILL_DELETED;
else
mSkillStatus.erase(itr);
// remove all spells that related to this skill
for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j)
@ -5381,7 +5407,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
}
else if(currVal) //add
{
for (i=0; i < PLAYER_MAX_SKILLS; ++i)
for (int i=0; i < PLAYER_MAX_SKILLS; ++i)
if (!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
{
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
@ -5399,6 +5425,15 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id);
// insert new entry or update if not deleted old entry yet
if(itr != mSkillStatus.end())
{
itr->second.pos = i;
itr->second.uState = SKILL_CHANGED;
}
else
mSkillStatus.insert(SkillStatusMap::value_type(id, SkillStatusData(i, SKILL_NEW)));
// apply skill bonuses
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
@ -5423,15 +5458,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
bool Player::HasSkill(uint32 skill) const
{
if(!skill)return false;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
return true;
}
}
return false;
if(!skill)
return false;
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED);
}
uint16 Player::GetSkillValue(uint32 skill) const
@ -5439,78 +5470,71 @@ uint16 Player::GetSkillValue(uint32 skill) const
if(!skill)
return 0;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i));
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
result += SKILL_TEMP_BONUS(bonus);
result += SKILL_PERM_BONUS(bonus);
return result < 0 ? 0 : result;
}
}
return 0;
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
result += SKILL_TEMP_BONUS(bonus);
result += SKILL_PERM_BONUS(bonus);
return result < 0 ? 0 : result;
}
uint16 Player::GetMaxSkillValue(uint32 skill) const
{
if(!skill)return 0;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i));
if(!skill)
return 0;
int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
result += SKILL_TEMP_BONUS(bonus);
result += SKILL_PERM_BONUS(bonus);
return result < 0 ? 0 : result;
}
}
return 0;
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
result += SKILL_TEMP_BONUS(bonus);
result += SKILL_PERM_BONUS(bonus);
return result < 0 ? 0 : result;
}
uint16 Player::GetPureMaxSkillValue(uint32 skill) const
{
if(!skill)return 0;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
}
}
return 0;
if(!skill)
return 0;
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
}
uint16 Player::GetBaseSkillValue(uint32 skill) const
{
if(!skill)return 0;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
return result < 0 ? 0 : result;
}
}
return 0;
if(!skill)
return 0;
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
return result < 0 ? 0 : result;
}
uint16 Player::GetPureSkillValue(uint32 skill) const
{
if(!skill)return 0;
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
}
}
return 0;
if(!skill)
return 0;
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
}
int16 Player::GetSkillPermBonusValue(uint32 skill) const
@ -5518,15 +5542,11 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const
if(!skill)
return 0;
for (int i = 0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
}
}
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
return 0;
return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
}
int16 Player::GetSkillTempBonusValue(uint32 skill) const
@ -5534,15 +5554,11 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const
if(!skill)
return 0;
for (int i = 0; i < PLAYER_MAX_SKILLS; ++i)
{
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
{
return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
}
}
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
return 0;
return 0;
return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
}
void Player::SendInitialActionButtons() const
@ -9005,11 +9021,11 @@ uint8 Player::_CanStoreItem_InBag( uint8 bag, ItemPosCountVec &dest, ItemPrototy
Item* pItem2 = GetItemByPos( bag, j );
// ignore move item (this slot will be empty at move)
if (pItem2==pSrcItem)
if (pItem2 == pSrcItem)
pItem2 = NULL;
// if merge skip empty, if !merge skip non-empty
if ((pItem2!=NULL)!=merge)
if ((pItem2 != NULL) != merge)
continue;
if (pItem2)
@ -9066,7 +9082,7 @@ uint8 Player::_CanStoreItem_InInventorySlots( uint8 slot_begin, uint8 slot_end,
pItem2 = NULL;
// if merge skip empty, if !merge skip non-empty
if ((pItem2!=NULL)!=merge)
if ((pItem2 != NULL) != merge)
continue;
if (pItem2)
@ -9971,6 +9987,9 @@ uint8 Player::CanBankItem( uint8 bag, uint8 slot, ItemPosCountVec &dest, Item *p
if (!pItem)
return swap ? EQUIP_ERR_ITEMS_CANT_BE_SWAPPED : EQUIP_ERR_ITEM_NOT_FOUND;
if (pItem->m_lootGenerated)
return EQUIP_ERR_ITEM_LOCKED;
uint32 count = pItem->GetCount();
sLog.outDebug( "STORAGE: CanBankItem bag = %u, slot = %u, item = %u, count = %u", bag, slot, pItem->GetEntry(), pItem->GetCount());
@ -14484,7 +14503,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
_LoadSkills();
// cleanup aura list explicitly before skill load wher some spells can be applied
RemoveAllAuras();
_LoadSkills(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSKILLS));
// make sure the unit is considered out of combat for proper loading
ClearInCombat();
@ -14742,7 +14764,7 @@ void Player::_LoadActions(QueryResult *result)
void Player::_LoadAuras(QueryResult *result, uint32 timediff)
{
RemoveAllAuras();
//RemoveAllAuras(); -- some spells casted before aura load, for example in LoadSkills, aura list explcitly cleaned early
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow());
@ -15748,6 +15770,7 @@ void Player::SaveToDB()
_SaveSpellCooldowns();
_SaveActions();
_SaveAuras();
_SaveSkills();
m_achievementMgr.SaveToDB();
m_reputationMgr.SaveToDB();
_SaveEquipmentSets();
@ -16028,6 +16051,46 @@ void Player::_SaveDailyQuestStatus()
GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime));
}
void Player::_SaveSkills()
{
// we don't need transactions here.
for( SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); )
{
if(itr->second.uState == SKILL_UNCHANGED)
{
++itr;
continue;
}
if(itr->second.uState == SKILL_DELETED)
{
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), itr->first );
mSkillStatus.erase(itr++);
continue;
}
uint32 valueData = GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos));
uint16 value = SKILL_VALUE(valueData);
uint16 max = SKILL_MAX(valueData);
switch (itr->second.uState)
{
case SKILL_NEW:
CharacterDatabase.PExecute("INSERT INTO character_skills (guid, skill, value, max) VALUES ('%u', '%u', '%u', '%u')",
GetGUIDLow(), itr->first, value, max);
break;
case SKILL_CHANGED:
CharacterDatabase.PExecute("UPDATE character_skills SET value = '%u',max = '%u'WHERE guid = '%u' AND skill = '%u' ",
value, max, GetGUIDLow(), itr->first );
break;
};
itr->second.uState = SKILL_UNCHANGED;
++itr;
}
}
void Player::_SaveSpells()
{
for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();)
@ -18092,12 +18155,27 @@ bool Player::IsVisibleGloballyFor( Player* u ) const
return true;
}
template<class T>
inline void BeforeVisibilityDestroy(T* /*t*/, Player* /*p*/)
{
}
template<>
inline void BeforeVisibilityDestroy<Creature>(Creature* t, Player* p)
{
if (p->GetPetGUID()==t->GetGUID() && ((Creature*)t)->isPet())
((Pet*)t)->Remove(PET_SAVE_NOT_IN_SLOT, true);
}
void Player::UpdateVisibilityOf(WorldObject const* viewPoint, WorldObject* target)
{
if(HaveAtClient(target))
{
if(!target->isVisibleForInState(this, viewPoint, true))
{
if (target->GetTypeId()==TYPEID_UNIT)
BeforeVisibilityDestroy<Creature>((Creature*)target,this);
target->DestroyForPlayer(this);
m_clientGUIDs.erase(target->GetGUID());
@ -18151,6 +18229,8 @@ void Player::UpdateVisibilityOf(WorldObject const* viewPoint, T* target, UpdateD
{
if(!target->isVisibleForInState(this,viewPoint,true))
{
BeforeVisibilityDestroy<T>(target,this);
target->BuildOutOfRangeUpdateBlock(&data);
m_clientGUIDs.erase(target->GetGUID());
@ -19862,43 +19942,78 @@ void Player::learnSpellHighRank(uint32 spellid)
sSpellMgr.doForHighRanks(spellid,worker);
}
void Player::_LoadSkills()
void Player::_LoadSkills(QueryResult *result)
{
// Note: skill data itself loaded from `data` field. This is only cleanup part of load
// 0 1 2
// SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
// reset skill modifiers and set correct unlearn flags
for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i)
uint32 count = 0;
if (result)
{
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
// set correct unlearn bit
uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
if(!id) continue;
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
if(!pSkill) continue;
// enable unlearn button for primary professions only
if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,1));
else
SetUInt32Value(PLAYER_SKILL_INDEX(i), MAKE_PAIR32(id,0));
// set fixed skill ranges
switch(GetSkillRangeType(pSkill,false))
do
{
case SKILL_RANGE_LANGUAGE: // 300..300
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(300,300));
break;
case SKILL_RANGE_MONO: // 1..1, grey monolite bar
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(1,1));
break;
default:
break;
}
Field *fields = result->Fetch();
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
learnSkillRewardedSpells(id, vskill);
uint16 skill = fields[0].GetUInt16();
uint16 value = fields[1].GetUInt16();
uint16 max = fields[2].GetUInt16();
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(skill);
if(!pSkill)
{
sLog.outError("Character %u has skill %u that does not exist.", GetGUIDLow(), skill);
continue;
}
// set fixed skill ranges
switch(GetSkillRangeType(pSkill,false))
{
case SKILL_RANGE_LANGUAGE: // 300..300
value = max = 300;
break;
case SKILL_RANGE_MONO: // 1..1, grey monolite bar
value = max = 1;
break;
default:
break;
}
if(value == 0)
{
sLog.outError("Character %u has skill %u with value 0. Will be deleted.", GetGUIDLow(), skill);
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u' AND skill = '%u' ", GetGUIDLow(), skill );
continue;
}
// enable unlearn button for primary professions only
if (pSkill->categoryId == SKILL_CATEGORY_PROFESSION)
SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill,1));
else
SetUInt32Value(PLAYER_SKILL_INDEX(count), MAKE_PAIR32(skill,0));
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count),MAKE_SKILL_VALUE(value, max));
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count),0);
mSkillStatus.insert(SkillStatusMap::value_type(skill, SkillStatusData(count, SKILL_UNCHANGED)));
learnSkillRewardedSpells(skill, value);
++count;
if(count >= PLAYER_MAX_SKILLS) // client limit
{
sLog.outError("Character %u has more than %u skills.", PLAYER_MAX_SKILLS);
break;
}
} while (result->NextRow());
delete result;
}
for (; count < PLAYER_MAX_SKILLS; ++count)
{
SetUInt32Value(PLAYER_SKILL_INDEX(count), 0);
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(count),0);
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(count),0);
}
// special settings