|
|
|
@@ -4252,6 +4252,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
|
|
|
|
|
CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid = '%u'",guid);
|
|
|
|
|
CharacterDatabase.PExecute("DELETE FROM character_queststatus_daily WHERE guid = '%u'",guid);
|
|
|
|
|
CharacterDatabase.PExecute("DELETE FROM character_talent WHERE guid = '%u'",guid);
|
|
|
|
|
CharacterDatabase.PExecute("DELETE FROM character_skills WHERE guid = '%u'",guid);
|
|
|
|
|
CharacterDatabase.CommitTransaction();
|
|
|
|
|
|
|
|
|
|
//loginDatabase.PExecute("UPDATE realmcharacters SET numchars = numchars - 1 WHERE acctid = %d AND realmid = %d", accountId, realmID);
|
|
|
|
@@ -5294,15 +5295,12 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
|
|
|
|
|
if(skill_id == SKILL_FIST_WEAPONS)
|
|
|
|
|
skill_id = SKILL_UNARMED;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
@@ -5315,7 +5313,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;
|
|
|
|
|
}
|
|
|
|
@@ -5424,13 +5424,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);
|
|
|
|
|
|
|
|
|
@@ -5445,7 +5445,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))
|
|
|
|
@@ -5544,19 +5546,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));
|
|
|
|
|
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(PLAYER_SKILL_BONUS_INDEX(i),MAKE_SKILL_BONUS(temp_bonus,perm_bonus+val));
|
|
|
|
|
SetUInt32Value(bonusIndex,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));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
SetUInt32Value(bonusIndex,MAKE_SKILL_BONUS(temp_bonus+val,perm_bonus));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Player::UpdateSkillsForLevel()
|
|
|
|
@@ -5566,11 +5569,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)
|
|
|
|
|
continue;
|
|
|
|
@@ -5578,38 +5582,51 @@ 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();
|
|
|
|
|
}
|
|
|
|
@@ -5622,16 +5639,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);
|
|
|
|
@@ -5639,9 +5656,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)
|
|
|
|
@@ -5652,7 +5675,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);
|
|
|
|
@@ -5670,6 +5693,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);
|
|
|
|
|
|
|
|
|
@@ -5694,14 +5726,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
|
|
|
|
|
|
|
|
|
bool Player::HasSkill(uint32 skill) const
|
|
|
|
|
{
|
|
|
|
|
if (!skill)
|
|
|
|
|
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;
|
|
|
|
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
|
|
|
|
return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16 Player::GetSkillValue(uint32 skill) const
|
|
|
|
@@ -5709,19 +5738,16 @@ 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))));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16 Player::GetMaxSkillValue(uint32 skill) const
|
|
|
|
@@ -5729,60 +5755,54 @@ 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));
|
|
|
|
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
|
|
|
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint16 Player::GetPureMaxSkillValue(uint32 skill) const
|
|
|
|
|
{
|
|
|
|
|
if (!skill)
|
|
|
|
|
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)));
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
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)));
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
@@ -5790,11 +5810,11 @@ int16 Player::GetSkillPermBonusValue(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_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 SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int16 Player::GetSkillTempBonusValue(uint32 skill) const
|
|
|
|
@@ -5802,11 +5822,11 @@ int16 Player::GetSkillTempBonusValue(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_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 SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Player::SendActionButtons(uint32 state) const
|
|
|
|
@@ -15145,7 +15165,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
|
|
|
|
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
|
|
|
|
|
SetUInt32Value(PLAYER_TRACK_RESOURCES, 0 );
|
|
|
|
|
|
|
|
|
|
_LoadSkills();
|
|
|
|
|
_LoadSkills(holder->GetResult(PLAYER_LOGIN_QUERY_LOADSKILLS));
|
|
|
|
|
|
|
|
|
|
// make sure the unit is considered out of combat for proper loading
|
|
|
|
|
ClearInCombat();
|
|
|
|
@@ -16445,6 +16465,7 @@ void Player::SaveToDB()
|
|
|
|
|
_SaveSpellCooldowns();
|
|
|
|
|
_SaveActions();
|
|
|
|
|
_SaveAuras();
|
|
|
|
|
_SaveSkills();
|
|
|
|
|
m_achievementMgr.SaveToDB();
|
|
|
|
|
m_reputationMgr.SaveToDB();
|
|
|
|
|
_SaveEquipmentSets();
|
|
|
|
@@ -16693,6 +16714,45 @@ 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();)
|
|
|
|
@@ -21003,43 +21063,77 @@ void Player::learnSpellHighRank(uint32 spellid)
|
|
|
|
|
learnSpellHighRank(next);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
Field *fields = result->Fetch();
|
|
|
|
|
|
|
|
|
|
// set correct unlearn bit
|
|
|
|
|
uint32 id = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
|
|
|
|
|
if(!id) continue;
|
|
|
|
|
uint16 skill = fields[0].GetUInt16();
|
|
|
|
|
uint16 value = fields[1].GetUInt16();
|
|
|
|
|
uint16 max = fields[2].GetUInt16();
|
|
|
|
|
|
|
|
|
|
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));
|
|
|
|
|
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
|
|
|
|
|
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(300,300));
|
|
|
|
|
value = max = 300;
|
|
|
|
|
break;
|
|
|
|
|
case SKILL_RANGE_MONO: // 1..1, grey monolite bar
|
|
|
|
|
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(1,1));
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
|
|
|
|
|
learnSkillRewardedSpells(id, vskill);
|
|
|
|
|
// 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
|
|
|
|
|