mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
[8874] Extract player skills from data blob.
Thanks to vladimir for the update query. Please make sure to make BACKUPs before you update your database. The update might take a while depending on the size of your database. Signed-off-by: hunuza <hunuza@gmail.com>
This commit is contained in:
parent
689d931f63
commit
4a6da1ad32
8 changed files with 356 additions and 166 deletions
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
DROP TABLE IF EXISTS `character_db_version`;
|
DROP TABLE IF EXISTS `character_db_version`;
|
||||||
CREATE TABLE `character_db_version` (
|
CREATE TABLE `character_db_version` (
|
||||||
`required_8843_01_characters` bit(1) default NULL
|
`required_8874_01_characters_character_skills` bit(1) default NULL
|
||||||
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
|
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Last applied sql update to DB';
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
@ -690,6 +690,28 @@ LOCK TABLES `character_reputation` WRITE;
|
||||||
/*!40000 ALTER TABLE `character_reputation` ENABLE KEYS */;
|
/*!40000 ALTER TABLE `character_reputation` ENABLE KEYS */;
|
||||||
UNLOCK TABLES;
|
UNLOCK TABLES;
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Table structure for table `character_skills`
|
||||||
|
--
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `character_skills`;
|
||||||
|
CREATE TABLE `character_skills` (
|
||||||
|
`guid` int(11) unsigned NOT NULL COMMENT 'Global Unique Identifier',
|
||||||
|
`skill` mediumint(9) unsigned NOT NULL,
|
||||||
|
`value` mediumint(9) unsigned NOT NULL,
|
||||||
|
`max` mediumint(9) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (`guid`,`skill`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System';
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Dumping data for table `character_skills`
|
||||||
|
--
|
||||||
|
|
||||||
|
LOCK TABLES `character_skills` WRITE;
|
||||||
|
/*!40000 ALTER TABLE `character_skills` DISABLE KEYS */;
|
||||||
|
/*!40000 ALTER TABLE `character_skills` ENABLE KEYS */;
|
||||||
|
UNLOCK TABLES;
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Table structure for table `character_social`
|
-- Table structure for table `character_social`
|
||||||
--
|
--
|
||||||
|
|
|
||||||
50
sql/updates/8874_01_characters_character_skills.sql
Normal file
50
sql/updates/8874_01_characters_character_skills.sql
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
ALTER TABLE character_db_version CHANGE COLUMN required_8843_01_characters required_8874_01_characters_character_skills bit;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `character_skills`;
|
||||||
|
CREATE TABLE `character_skills` (
|
||||||
|
`guid` int(11) unsigned NOT NULL COMMENT 'Global Unique Identifier',
|
||||||
|
`skill` mediumint(9) unsigned NOT NULL,
|
||||||
|
`value` int(11) unsigned NOT NULL,
|
||||||
|
`max` mediumint(9) unsigned NOT NULL,
|
||||||
|
i mediumint(9),
|
||||||
|
PRIMARY KEY (`guid`,`skill`,`i`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Player System';
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS temp_skills;
|
||||||
|
CREATE TABLE temp_skills (
|
||||||
|
i int(11) unsigned NOT NULL,
|
||||||
|
PRIMARY KEY (i)
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO temp_skills VALUES
|
||||||
|
( 0),( 1),( 2),( 3),( 4),( 5),( 6),( 7),( 8),( 9),(10),(11),(12),(13),(14),(15),(16),(17),(18),(19),
|
||||||
|
(20),(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31),(32),(33),(34),(35),(36),(37),(38),(39),
|
||||||
|
(40),(41),(42),(43),(44),(45),(46),(47),(48),(49),(50),(51),(52),(53),(54),(55),(56),(57),(58),(59),
|
||||||
|
(60),(61),(62),(63),(64),(65),(66),(67),(68),(69),(70),(71),(72),(73),(74),(75),(76),(77),(78),(79),
|
||||||
|
(80),(81),(82),(83),(84),(85),(86),(87),(88),(89),(90),(91),(92),(93),(94),(95),(96),(97),(98),(99),
|
||||||
|
(100),(101),(102),(103),(104),(105),(106),(107),(108),(109),(110),(111),(112),(113),(114),(115),(116),(117),(118),(119),
|
||||||
|
(120),(121),(122),(123),(124),(125),(126),(127);
|
||||||
|
|
||||||
|
INSERT INTO character_skills SELECT
|
||||||
|
guid,
|
||||||
|
((SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 610+3*i))+2, length(SUBSTRING_INDEX(data, ' ', 610+3*i+1))- length(SUBSTRING_INDEX(data, ' ', 610+3*i)) - 1)) & 0xFFFF) as skill,
|
||||||
|
(SUBSTRING(data, length(SUBSTRING_INDEX(data, ' ', 610+3*i+1))+2, length(SUBSTRING_INDEX(data, ' ', 610+3*i+2))- length(SUBSTRING_INDEX(data, ' ', 610+3*i+1)) - 1)) as value,
|
||||||
|
(0) as max,
|
||||||
|
i
|
||||||
|
FROM characters, temp_skills;
|
||||||
|
|
||||||
|
DELETE FROM character_skills WHERE skill = 0;
|
||||||
|
DROP TABLE IF EXISTS temp_skills;
|
||||||
|
|
||||||
|
UPDATE character_skills
|
||||||
|
SET max = ((value & 0xFFFF0000) >> 16);
|
||||||
|
|
||||||
|
UPDATE character_skills
|
||||||
|
SET value = (value & 0xFFFF);
|
||||||
|
|
||||||
|
ALTER IGNORE TABLE character_skills
|
||||||
|
CHANGE COLUMN value value mediumint(9) unsigned NOT NULL,
|
||||||
|
DROP PRIMARY KEY,
|
||||||
|
ADD PRIMARY KEY (guid,skill),
|
||||||
|
DROP COLUMN i;
|
||||||
|
|
@ -174,6 +174,7 @@ pkgdata_DATA = \
|
||||||
8863_01_mangos_spell_proc_event.sql \
|
8863_01_mangos_spell_proc_event.sql \
|
||||||
8873_01_mangos_spell_proc_event.sql \
|
8873_01_mangos_spell_proc_event.sql \
|
||||||
8873_02_mangos_spell_learn_spell.sql \
|
8873_02_mangos_spell_learn_spell.sql \
|
||||||
|
8874_01_characters_character_skills.sql \
|
||||||
README
|
README
|
||||||
|
|
||||||
## Additional files to include when running 'make dist'
|
## Additional files to include when running 'make dist'
|
||||||
|
|
@ -328,4 +329,5 @@ EXTRA_DIST = \
|
||||||
8863_01_mangos_spell_proc_event.sql \
|
8863_01_mangos_spell_proc_event.sql \
|
||||||
8873_01_mangos_spell_proc_event.sql \
|
8873_01_mangos_spell_proc_event.sql \
|
||||||
8873_02_mangos_spell_learn_spell.sql \
|
8873_02_mangos_spell_learn_spell.sql \
|
||||||
|
8874_01_characters_character_skills.sql \
|
||||||
README
|
README
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,7 @@ bool LoginQueryHolder::Initialize()
|
||||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid));
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS, "SELECT setguid, setindex, name, iconname, item0, item1, item2, item3, item4, item5, item6, item7, item8, item9, item10, item11, item12, item13, item14, item15, item16, item17, item18 FROM character_equipmentsets WHERE guid = '%u' ORDER BY setindex", GUID_LOPART(m_guid));
|
||||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, "SELECT instance_id, team, join_x, join_y, join_z, join_o, join_map, taxi_start, taxi_end, mount_spell FROM character_battleground_data WHERE guid = '%u'", GUID_LOPART(m_guid));
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBGDATA, "SELECT instance_id, team, join_x, join_y, join_z, join_o, join_map, taxi_start, taxi_end, mount_spell FROM character_battleground_data WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||||
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, "SELECT type, time, data FROM character_account_data WHERE guid='%u'", GUID_LOPART(m_guid));
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADACCOUNTDATA, "SELECT type, time, data FROM character_account_data WHERE guid='%u'", GUID_LOPART(m_guid));
|
||||||
|
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5026,15 +5026,12 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
|
||||||
if(!skill_id)
|
if(!skill_id)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
uint16 i=0;
|
SkillStatusMap::iterator itr = mSkillStatus.find(skill_id);
|
||||||
for (; i < PLAYER_MAX_SKILLS; ++i)
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill_id)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(i>=PLAYER_MAX_SKILLS)
|
|
||||||
return false;
|
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 value = SKILL_VALUE(data);
|
||||||
uint32 max = SKILL_MAX(data);
|
uint32 max = SKILL_MAX(data);
|
||||||
|
|
||||||
|
|
@ -5047,7 +5044,9 @@ bool Player::UpdateSkill(uint32 skill_id, uint32 step)
|
||||||
if(new_value > max)
|
if(new_value > max)
|
||||||
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);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,skill_id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -5156,13 +5155,13 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 i=0;
|
SkillStatusMap::iterator itr = mSkillStatus.find(SkillId);
|
||||||
for (; i < PLAYER_MAX_SKILLS; ++i)
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
if ( SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_INDEX(i))) == SkillId ) break;
|
|
||||||
if ( i >= PLAYER_MAX_SKILLS )
|
|
||||||
return false;
|
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 SkillValue = SKILL_VALUE(data);
|
||||||
uint16 MaxValue = SKILL_MAX(data);
|
uint16 MaxValue = SKILL_MAX(data);
|
||||||
|
|
||||||
|
|
@ -5177,7 +5176,9 @@ bool Player::UpdateSkillPro(uint16 SkillId, int32 Chance, uint32 step)
|
||||||
if(new_value > MaxValue)
|
if(new_value > MaxValue)
|
||||||
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)
|
for(uint32* bsl = &bonusSkillLevels[0]; *bsl; ++bsl)
|
||||||
{
|
{
|
||||||
if((SkillValue < *bsl && new_value >= *bsl))
|
if((SkillValue < *bsl && new_value >= *bsl))
|
||||||
|
|
@ -5275,19 +5276,20 @@ void Player::UpdateCombatSkills(Unit *pVictim, WeaponAttackType attType, bool de
|
||||||
|
|
||||||
void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent)
|
void Player::ModifySkillBonus(uint32 skillid,int32 val, bool talent)
|
||||||
{
|
{
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skillid);
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skillid)
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
{
|
|
||||||
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));
|
|
||||||
return;
|
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()
|
void Player::UpdateSkillsForLevel()
|
||||||
|
|
@ -5297,10 +5299,12 @@ void Player::UpdateSkillsForLevel()
|
||||||
|
|
||||||
bool alwaysMaxSkill = sWorld.getConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL);
|
bool alwaysMaxSkill = sWorld.getConfig(CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL);
|
||||||
|
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
|
||||||
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
|
|
||||||
{
|
{
|
||||||
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);
|
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(pskill);
|
||||||
if(!pSkill)
|
if(!pSkill)
|
||||||
|
|
@ -5309,37 +5313,52 @@ void Player::UpdateSkillsForLevel()
|
||||||
if(GetSkillRangeType(pSkill,false) != SKILL_RANGE_LEVEL)
|
if(GetSkillRangeType(pSkill,false) != SKILL_RANGE_LEVEL)
|
||||||
continue;
|
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 max = SKILL_MAX(data);
|
||||||
uint32 val = SKILL_VALUE(data);
|
uint32 val = SKILL_VALUE(data);
|
||||||
|
|
||||||
/// update only level dependent max skill values
|
/// update only level dependent max skill values
|
||||||
if(max!=1)
|
if(max!=1)
|
||||||
{
|
{
|
||||||
/// miximize skill always
|
/// maximize skill always
|
||||||
if(alwaysMaxSkill)
|
if(alwaysMaxSkill)
|
||||||
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(maxSkill,maxSkill));
|
{
|
||||||
/// update max skill value if current max skill not maximized
|
SetUInt32Value(valueIndex, MAKE_SKILL_VALUE(maxSkill,maxSkill));
|
||||||
else if(max != maxconfskill)
|
if(itr->second.uState != SKILL_NEW)
|
||||||
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),MAKE_SKILL_VALUE(val,maxSkill));
|
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()
|
void Player::UpdateSkillsToMaxSkillsForLevel()
|
||||||
{
|
{
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
for(SkillStatusMap::iterator itr = mSkillStatus.begin(); itr != mSkillStatus.end(); ++itr)
|
||||||
if (GetUInt32Value(PLAYER_SKILL_INDEX(i)))
|
|
||||||
{
|
{
|
||||||
uint32 pskill = GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF;
|
if(itr->second.uState == SKILL_DELETED)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32 pskill = itr->first;
|
||||||
if( IsProfessionOrRidingSkill(pskill))
|
if( IsProfessionOrRidingSkill(pskill))
|
||||||
continue;
|
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 max = SKILL_MAX(data);
|
||||||
|
|
||||||
if(max > 1)
|
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)
|
if(pskill == SKILL_DEFENSE)
|
||||||
UpdateDefenseBonusesMod();
|
UpdateDefenseBonusesMod();
|
||||||
|
|
@ -5353,15 +5372,16 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
||||||
if(!id)
|
if(!id)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint16 i=0;
|
SkillStatusMap::iterator itr = mSkillStatus.find(id);
|
||||||
for (; i < PLAYER_MAX_SKILLS; ++i)
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == id) break;
|
|
||||||
|
|
||||||
if(i<PLAYER_MAX_SKILLS) //has skill
|
//has skill
|
||||||
|
if(itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED)
|
||||||
{
|
{
|
||||||
if(currVal)
|
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);
|
learnSkillRewardedSpells(id, currVal);
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL,id);
|
||||||
|
|
@ -5369,9 +5389,15 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
||||||
else //remove
|
else //remove
|
||||||
{
|
{
|
||||||
// clear skill fields
|
// clear skill fields
|
||||||
SetUInt32Value(PLAYER_SKILL_INDEX(i),0);
|
SetUInt32Value(PLAYER_SKILL_INDEX(itr->second.pos),0);
|
||||||
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i),0);
|
SetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos),0);
|
||||||
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),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
|
// remove all spells that related to this skill
|
||||||
for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j)
|
for (uint32 j=0; j<sSkillLineAbilityStore.GetNumRows(); ++j)
|
||||||
|
|
@ -5382,7 +5408,7 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
||||||
}
|
}
|
||||||
else if(currVal) //add
|
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)))
|
if (!GetUInt32Value(PLAYER_SKILL_INDEX(i)))
|
||||||
{
|
{
|
||||||
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
|
SkillLineEntry const *pSkill = sSkillLineStore.LookupEntry(id);
|
||||||
|
|
@ -5400,6 +5426,15 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
|
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL,id);
|
||||||
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_LEARN_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
|
// apply skill bonuses
|
||||||
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
|
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
|
||||||
|
|
||||||
|
|
@ -5424,15 +5459,11 @@ void Player::SetSkill(uint32 id, uint16 currVal, uint16 maxVal)
|
||||||
|
|
||||||
bool Player::HasSkill(uint32 skill) const
|
bool Player::HasSkill(uint32 skill) const
|
||||||
{
|
{
|
||||||
if(!skill)return false;
|
if(!skill)
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
return false;
|
||||||
{
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
return (itr != mSkillStatus.end() && itr->second.uState != SKILL_DELETED);
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Player::GetSkillValue(uint32 skill) const
|
uint16 Player::GetSkillValue(uint32 skill) const
|
||||||
|
|
@ -5440,78 +5471,71 @@ uint16 Player::GetSkillValue(uint32 skill) const
|
||||||
if(!skill)
|
if(!skill)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
return 0;
|
||||||
{
|
|
||||||
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i));
|
|
||||||
|
|
||||||
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
|
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
|
||||||
result += SKILL_TEMP_BONUS(bonus);
|
|
||||||
result += SKILL_PERM_BONUS(bonus);
|
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos))));
|
||||||
return result < 0 ? 0 : result;
|
result += SKILL_TEMP_BONUS(bonus);
|
||||||
}
|
result += SKILL_PERM_BONUS(bonus);
|
||||||
}
|
return result < 0 ? 0 : result;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Player::GetMaxSkillValue(uint32 skill) const
|
uint16 Player::GetMaxSkillValue(uint32 skill) const
|
||||||
{
|
{
|
||||||
if(!skill)return 0;
|
if(!skill)
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
return 0;
|
||||||
{
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
|
||||||
{
|
|
||||||
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i));
|
|
||||||
|
|
||||||
int32 result = int32(SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
result += SKILL_TEMP_BONUS(bonus);
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
result += SKILL_PERM_BONUS(bonus);
|
return 0;
|
||||||
return result < 0 ? 0 : result;
|
|
||||||
}
|
uint32 bonus = GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos));
|
||||||
}
|
|
||||||
return 0;
|
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
|
uint16 Player::GetPureMaxSkillValue(uint32 skill) const
|
||||||
{
|
{
|
||||||
if(!skill)return 0;
|
if(!skill)
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
return 0;
|
||||||
{
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
|
return 0;
|
||||||
}
|
|
||||||
}
|
return SKILL_MAX(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Player::GetBaseSkillValue(uint32 skill) const
|
uint16 Player::GetBaseSkillValue(uint32 skill) const
|
||||||
{
|
{
|
||||||
if(!skill)return 0;
|
if(!skill)
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
return 0;
|
||||||
{
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
int32 result = int32(SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i))));
|
return 0;
|
||||||
result += SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
|
|
||||||
return result < 0 ? 0 : result;
|
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;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 Player::GetPureSkillValue(uint32 skill) const
|
uint16 Player::GetPureSkillValue(uint32 skill) const
|
||||||
{
|
{
|
||||||
if(!skill)return 0;
|
if(!skill)
|
||||||
for (uint16 i=0; i < PLAYER_MAX_SKILLS; ++i)
|
return 0;
|
||||||
{
|
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
|
return 0;
|
||||||
}
|
|
||||||
}
|
return SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(itr->second.pos)));
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int16 Player::GetSkillPermBonusValue(uint32 skill) const
|
int16 Player::GetSkillPermBonusValue(uint32 skill) const
|
||||||
|
|
@ -5519,15 +5543,11 @@ int16 Player::GetSkillPermBonusValue(uint32 skill) const
|
||||||
if(!skill)
|
if(!skill)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < PLAYER_MAX_SKILLS; ++i)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
return 0;
|
||||||
{
|
|
||||||
return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return SKILL_PERM_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
int16 Player::GetSkillTempBonusValue(uint32 skill) const
|
int16 Player::GetSkillTempBonusValue(uint32 skill) const
|
||||||
|
|
@ -5535,15 +5555,11 @@ int16 Player::GetSkillTempBonusValue(uint32 skill) const
|
||||||
if(!skill)
|
if(!skill)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (int i = 0; i < PLAYER_MAX_SKILLS; ++i)
|
SkillStatusMap::const_iterator itr = mSkillStatus.find(skill);
|
||||||
{
|
if(itr == mSkillStatus.end() || itr->second.uState == SKILL_DELETED)
|
||||||
if ((GetUInt32Value(PLAYER_SKILL_INDEX(i)) & 0x0000FFFF) == skill)
|
return 0;
|
||||||
{
|
|
||||||
return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return SKILL_TEMP_BONUS(GetUInt32Value(PLAYER_SKILL_BONUS_INDEX(itr->second.pos)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::SendInitialActionButtons() const
|
void Player::SendInitialActionButtons() const
|
||||||
|
|
@ -14487,7 +14503,7 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
|
||||||
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
|
SetUInt32Value(PLAYER_TRACK_CREATURES, 0 );
|
||||||
SetUInt32Value(PLAYER_TRACK_RESOURCES, 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
|
// make sure the unit is considered out of combat for proper loading
|
||||||
ClearInCombat();
|
ClearInCombat();
|
||||||
|
|
@ -15751,6 +15767,7 @@ void Player::SaveToDB()
|
||||||
_SaveSpellCooldowns();
|
_SaveSpellCooldowns();
|
||||||
_SaveActions();
|
_SaveActions();
|
||||||
_SaveAuras();
|
_SaveAuras();
|
||||||
|
_SaveSkills();
|
||||||
m_achievementMgr.SaveToDB();
|
m_achievementMgr.SaveToDB();
|
||||||
m_reputationMgr.SaveToDB();
|
m_reputationMgr.SaveToDB();
|
||||||
_SaveEquipmentSets();
|
_SaveEquipmentSets();
|
||||||
|
|
@ -16031,6 +16048,46 @@ void Player::_SaveDailyQuestStatus()
|
||||||
GetGUIDLow(), GetUInt32Value(PLAYER_FIELD_DAILY_QUESTS_1+quest_daily_idx),uint64(m_lastDailyQuestTime));
|
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()
|
void Player::_SaveSpells()
|
||||||
{
|
{
|
||||||
for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();)
|
for (PlayerSpellMap::iterator itr = m_spells.begin(), next = m_spells.begin(); itr != m_spells.end();)
|
||||||
|
|
@ -19882,43 +19939,78 @@ void Player::learnSpellHighRank(uint32 spellid)
|
||||||
sSpellMgr.doForHighRanks(spellid,worker);
|
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
|
uint32 count = 0;
|
||||||
for (uint32 i = 0; i < PLAYER_MAX_SKILLS; ++i)
|
if (result)
|
||||||
{
|
{
|
||||||
SetUInt32Value(PLAYER_SKILL_BONUS_INDEX(i),0);
|
do
|
||||||
|
|
||||||
// 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))
|
|
||||||
{
|
{
|
||||||
case SKILL_RANGE_LANGUAGE: // 300..300
|
Field *fields = result->Fetch();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 vskill = SKILL_VALUE(GetUInt32Value(PLAYER_SKILL_VALUE_INDEX(i)));
|
uint16 skill = fields[0].GetUInt16();
|
||||||
learnSkillRewardedSpells(id, vskill);
|
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
|
// special settings
|
||||||
|
|
|
||||||
|
|
@ -563,6 +563,25 @@ enum QuestSlotStateMask
|
||||||
QUEST_STATE_FAIL = 0x0002
|
QUEST_STATE_FAIL = 0x0002
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum SkillUpdateState
|
||||||
|
{
|
||||||
|
SKILL_UNCHANGED = 0,
|
||||||
|
SKILL_CHANGED = 1,
|
||||||
|
SKILL_NEW = 2,
|
||||||
|
SKILL_DELETED = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SkillStatusData
|
||||||
|
{
|
||||||
|
SkillStatusData(uint8 _pos, SkillUpdateState _uState) : pos(_pos), uState(_uState)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
uint8 pos;
|
||||||
|
SkillUpdateState uState;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef UNORDERED_MAP<uint32, SkillStatusData> SkillStatusMap;
|
||||||
|
|
||||||
class Quest;
|
class Quest;
|
||||||
class Spell;
|
class Spell;
|
||||||
class Item;
|
class Item;
|
||||||
|
|
@ -884,7 +903,8 @@ enum PlayerLoginQueryIndex
|
||||||
PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS = 20,
|
PLAYER_LOGIN_QUERY_LOADEQUIPMENTSETS = 20,
|
||||||
PLAYER_LOGIN_QUERY_LOADBGDATA = 21,
|
PLAYER_LOGIN_QUERY_LOADBGDATA = 21,
|
||||||
PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 22,
|
PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 22,
|
||||||
MAX_PLAYER_LOGIN_QUERY = 23
|
PLAYER_LOGIN_QUERY_LOADSKILLS = 23,
|
||||||
|
MAX_PLAYER_LOGIN_QUERY = 24
|
||||||
};
|
};
|
||||||
|
|
||||||
enum PlayerDelayedOperations
|
enum PlayerDelayedOperations
|
||||||
|
|
@ -2296,7 +2316,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void _LoadQuestStatus(QueryResult *result);
|
void _LoadQuestStatus(QueryResult *result);
|
||||||
void _LoadDailyQuestStatus(QueryResult *result);
|
void _LoadDailyQuestStatus(QueryResult *result);
|
||||||
void _LoadGroup(QueryResult *result);
|
void _LoadGroup(QueryResult *result);
|
||||||
void _LoadSkills();
|
void _LoadSkills(QueryResult *result);
|
||||||
void _LoadSpells(QueryResult *result);
|
void _LoadSpells(QueryResult *result);
|
||||||
void _LoadFriendList(QueryResult *result);
|
void _LoadFriendList(QueryResult *result);
|
||||||
bool _LoadHomeBind(QueryResult *result);
|
bool _LoadHomeBind(QueryResult *result);
|
||||||
|
|
@ -2315,6 +2335,7 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
void _SaveMail();
|
void _SaveMail();
|
||||||
void _SaveQuestStatus();
|
void _SaveQuestStatus();
|
||||||
void _SaveDailyQuestStatus();
|
void _SaveDailyQuestStatus();
|
||||||
|
void _SaveSkills();
|
||||||
void _SaveSpells();
|
void _SaveSpells();
|
||||||
void _SaveEquipmentSets();
|
void _SaveEquipmentSets();
|
||||||
void _SaveBGData();
|
void _SaveBGData();
|
||||||
|
|
@ -2362,6 +2383,8 @@ class MANGOS_DLL_SPEC Player : public Unit
|
||||||
|
|
||||||
QuestStatusMap mQuestStatus;
|
QuestStatusMap mQuestStatus;
|
||||||
|
|
||||||
|
SkillStatusMap mSkillStatus;
|
||||||
|
|
||||||
uint32 m_GuildIdInvited;
|
uint32 m_GuildIdInvited;
|
||||||
uint32 m_ArenaTeamIdInvited;
|
uint32 m_ArenaTeamIdInvited;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __REVISION_NR_H__
|
#ifndef __REVISION_NR_H__
|
||||||
#define __REVISION_NR_H__
|
#define __REVISION_NR_H__
|
||||||
#define REVISION_NR "8873"
|
#define REVISION_NR "8874"
|
||||||
#endif // __REVISION_NR_H__
|
#endif // __REVISION_NR_H__
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#ifndef __REVISION_SQL_H__
|
#ifndef __REVISION_SQL_H__
|
||||||
#define __REVISION_SQL_H__
|
#define __REVISION_SQL_H__
|
||||||
#define REVISION_DB_CHARACTERS "required_8843_01_characters"
|
#define REVISION_DB_CHARACTERS "required_8874_01_characters_character_skills"
|
||||||
#define REVISION_DB_MANGOS "required_8873_02_mangos_spell_learn_spell"
|
#define REVISION_DB_MANGOS "required_8873_02_mangos_spell_learn_spell"
|
||||||
#define REVISION_DB_REALMD "required_8728_01_realmd_account"
|
#define REVISION_DB_REALMD "required_8728_01_realmd_account"
|
||||||
#endif // __REVISION_SQL_H__
|
#endif // __REVISION_SQL_H__
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue