Add possibility for second glyph set.

Signed-off-by: hunuza <hunuza@gmail.com>
This commit is contained in:
hunuza 2010-02-14 12:25:59 +01:00
parent 97cdb501a8
commit 282e0fd8aa
5 changed files with 189 additions and 31 deletions

View file

@ -501,6 +501,28 @@ LOCK TABLES `character_gifts` WRITE;
/*!40000 ALTER TABLE `character_gifts` ENABLE KEYS */; /*!40000 ALTER TABLE `character_gifts` ENABLE KEYS */;
UNLOCK TABLES; UNLOCK TABLES;
--
-- Table structure for table `character_glyphs`
--
DROP TABLE IF EXISTS `character_glyphs`;
CREATE TABLE `character_glyphs` (
`guid` int(11) unsigned NOT NULL,
`spec` tinyint(3) unsigned NOT NULL DEFAULT '0',
`slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
`glyph` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`spec`,`slot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `character_glyphs`
--
LOCK TABLES `character_glyphs` WRITE;
/*!40000 ALTER TABLE `character_glyphs` DISABLE KEYS */;
/*!40000 ALTER TABLE `character_glyphs` ENABLE KEYS */;
UNLOCK TABLES;
-- --
-- Table structure for table `character_homebind` -- Table structure for table `character_homebind`
-- --

View file

@ -0,0 +1,18 @@
DROP TABLE IF EXISTS `character_glyphs`;
CREATE TABLE `character_glyphs` (
`guid` int(11) unsigned NOT NULL,
`spec` tinyint(3) unsigned NOT NULL DEFAULT '0',
`slot` tinyint(3) unsigned NOT NULL DEFAULT '0',
`glyph` int(11) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`guid`,`spec`,`slot`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- Extract values from data blob fields and insert them into character_glyphs
INSERT INTO `character_glyphs` SELECT `guid`, 0, 0, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1319), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
INSERT INTO `character_glyphs` SELECT `guid`, 0, 1, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1320), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
INSERT INTO `character_glyphs` SELECT `guid`, 0, 2, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1321), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
INSERT INTO `character_glyphs` SELECT `guid`, 0, 3, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1322), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
INSERT INTO `character_glyphs` SELECT `guid`, 0, 4, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1323), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
INSERT INTO `character_glyphs` SELECT `guid`, 0, 5, (CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`, ' ', 1324), ' ', -1) AS UNSIGNED)) AS `glyph` FROM `characters`;
DELETE FROM character_glyphs WHERE glyph = 0;

View file

@ -98,6 +98,7 @@ bool LoginQueryHolder::Initialize()
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)); res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSKILLS, "SELECT skill, value, max FROM character_skills WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGLYPHS, "SELECT spec, slot, glyph FROM character_glyphs WHERE guid='%u'", GUID_LOPART(m_guid));
return res; return res;
} }

View file

@ -4090,6 +4090,7 @@ void Player::DeleteFromDB(uint64 playerguid, uint32 accountId, bool updateRealmC
CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_action WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_gifts WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_homebind WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_homebind WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM character_instance WHERE guid = '%u'",guid);
CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u'",guid); CharacterDatabase.PExecute("DELETE FROM group_instance WHERE leaderGuid = '%u'",guid);
@ -14999,8 +15000,10 @@ bool Player::LoadFromDB( uint32 guid, SqlQueryHolder *holder )
m_specsCount = fields[59].GetUInt8(); m_specsCount = fields[59].GetUInt8();
m_activeSpec = fields[60].GetUInt8(); m_activeSpec = fields[60].GetUInt8();
_LoadGlyphs(holder->GetResult(PLAYER_LOGIN_QUERY_LOADGLYPHS));
_LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff); _LoadAuras(holder->GetResult(PLAYER_LOGIN_QUERY_LOADAURAS), time_diff);
_LoadGlyphAuras(); ApplyGlyphAuras(true);
// add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura) // add ghost flag (must be after aura load: PLAYER_FLAGS_GHOST set in aura)
if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) ) if( HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_GHOST) )
@ -15314,34 +15317,48 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true); CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
} }
void Player::_LoadGlyphAuras() void Player::_LoadGlyphs(QueryResult *result)
{ {
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) if(!result)
{ return;
if (uint32 glyph = GetGlyph(i))
{
if (GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
if (GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(GetGlyphSlot(i)))
{
if(gp->TypeFlags == gs->TypeFlags)
{
CastSpell(this, gp->SpellId, true);
continue;
}
else
sLog.outError("Player %s has glyph with typeflags %u in slot with typeflags %u, removing.", m_name.c_str(), gp->TypeFlags, gs->TypeFlags);
}
else
sLog.outError("Player %s has not existing glyph slot entry %u on index %u", m_name.c_str(), GetGlyphSlot(i), i);
}
else
sLog.outError("Player %s has not existing glyph entry %u on index %u", m_name.c_str(), glyph, i);
// On any error remove glyph // 0 1 2
SetGlyph(i, 0); // "SELECT spec, slot, glyph FROM character_glyphs WHERE guid='%u'"
do
{
Field *fields = result->Fetch();
uint8 spec = fields[0].GetUInt8();
uint8 slot = fields[1].GetUInt8();
uint32 glyph = fields[2].GetUInt32();
GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph);
if(!gp)
{
sLog.outError("Player %s has not existing glyph entry %u on index %u, spec %u", m_name.c_str(), glyph, slot, spec);
continue;
} }
}
GlyphSlotEntry const *gs = sGlyphSlotStore.LookupEntry(GetGlyphSlot(slot));
if (!gs)
{
sLog.outError("Player %s has not existing glyph slot entry %u on index %u, spec %u", m_name.c_str(), GetGlyphSlot(slot), slot, spec);
continue;
}
if(gp->TypeFlags != gs->TypeFlags)
{
sLog.outError("Player %s has glyph with typeflags %u in slot with typeflags %u, removing.", m_name.c_str(), gp->TypeFlags, gs->TypeFlags);
continue;
}
m_glyphs[spec][slot].id = glyph;
} while( result->NextRow() );
delete result;
} }
void Player::LoadCorpse() void Player::LoadCorpse()
@ -16294,6 +16311,7 @@ void Player::SaveToDB()
m_reputationMgr.SaveToDB(); m_reputationMgr.SaveToDB();
_SaveEquipmentSets(); _SaveEquipmentSets();
GetSession()->SaveTutorialsData(); // changed only while character in game GetSession()->SaveTutorialsData(); // changed only while character in game
_SaveGlyphs();
CharacterDatabase.CommitTransaction(); CharacterDatabase.CommitTransaction();
@ -16407,6 +16425,32 @@ void Player::_SaveAuras()
CharacterDatabase.Execute( ss.str().c_str() ); CharacterDatabase.Execute( ss.str().c_str() );
} }
void Player::_SaveGlyphs()
{
for (uint8 spec = 0; spec < m_specsCount; ++spec)
{
for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
{
switch(m_glyphs[spec][slot].uState)
{
case GLYPH_NEW:
CharacterDatabase.PExecute("INSERT INTO character_glyphs (guid, spec, slot, glyph) VALUES ('%u', '%u', '%u', '%u')", GetGUIDLow(), spec, slot, m_glyphs[spec][slot].GetId());
break;
case GLYPH_CHANGED:
CharacterDatabase.PExecute("UPDATE character_glyphs SET glyph = '%u' WHERE guid='%u' AND spec = '%u' AND slot = '%u'", m_glyphs[spec][slot].GetId(), GetGUIDLow(), spec, slot);
break;
case GLYPH_DELETED:
CharacterDatabase.PExecute("DELETE FROM character_glyphs WHERE guid='%u' AND spec = '%u' AND slot = '%u'",GetGUIDLow(), spec, slot);
break;
case GLYPH_UNCHANGED:
break;
}
m_glyphs[spec][slot].uState = GLYPH_UNCHANGED;
}
}
}
void Player::_SaveInventory() void Player::_SaveInventory()
{ {
// force items in buyback slots to new state // force items in buyback slots to new state
@ -20188,6 +20232,23 @@ void Player::InitGlyphsForLevel()
SetUInt32Value(PLAYER_GLYPHS_ENABLED, value); SetUInt32Value(PLAYER_GLYPHS_ENABLED, value);
} }
void Player::ApplyGlyphAuras(bool apply)
{
for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
{
if (uint32 glyph = GetGlyph(i))
{
if(GlyphPropertiesEntry const *gp = sGlyphPropertiesStore.LookupEntry(glyph))
{
if(apply)
CastSpell(this, gp->SpellId, true);
else
RemoveAurasDueToSpell(gp->SpellId);
}
}
}
}
void Player::EnterVehicle(Vehicle *vehicle) void Player::EnterVehicle(Vehicle *vehicle)
{ {
VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId()); VehicleEntry const *ve = sVehicleStore.LookupEntry(vehicle->GetVehicleId());
@ -21070,8 +21131,9 @@ void Player::BuildPlayerTalentsInfoData(WorldPacket *data)
*data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count *data << uint8(MAX_GLYPH_SLOT_INDEX); // glyphs count
// GlyphProperties.dbc
for(uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i) for(uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
*data << uint16(GetGlyph(i)); // GlyphProperties.dbc *data << uint16(m_glyphs[specIdx][i].GetId());
} }
} }
} }
@ -21337,6 +21399,8 @@ void Player::ActivateSpec(uint8 specNum)
// unlearn GetActiveSpec() talents (not learned in specNum); // unlearn GetActiveSpec() talents (not learned in specNum);
// learn specNum talents // learn specNum talents
ApplyGlyphAuras(false);
SetActiveSpec(specNum); SetActiveSpec(specNum);
// recheck action buttons (not checked at loading/spec copy) // recheck action buttons (not checked at loading/spec copy)
@ -21346,6 +21410,8 @@ void Player::ActivateSpec(uint8 specNum)
if (!IsActionButtonDataValid(itr->first,itr->second.GetAction(),itr->second.GetType(), this)) if (!IsActionButtonDataValid(itr->first,itr->second.GetAction(),itr->second.GetType(), this))
removeActionButton(m_activeSpec,itr->first); removeActionButton(m_activeSpec,itr->first);
ApplyGlyphAuras(true);
SendInitialActionButtons(); SendInitialActionButtons();
InitTalentForLevel(); InitTalentForLevel();

View file

@ -193,6 +193,52 @@ enum ActionButtonIndex
typedef std::map<uint8,ActionButton> ActionButtonList; typedef std::map<uint8,ActionButton> ActionButtonList;
enum GlyphUpdateState
{
GLYPH_UNCHANGED = 0,
GLYPH_CHANGED = 1,
GLYPH_NEW = 2,
GLYPH_DELETED = 3
};
struct Glyph
{
uint32 id;
GlyphUpdateState uState;
Glyph() : id(0), uState(GLYPH_UNCHANGED) { }
Glyph(uint32 _id, GlyphUpdateState _uState) : id(_id), uState(_uState) { }
uint32 GetId() { return id; }
void SetId(uint32 newId)
{
if(newId == id)
return;
if(id == 0 && uState == GLYPH_UNCHANGED) // not exist yet in db and already saved
{
uState = GLYPH_NEW;
}
else if (newId == 0)
{
if(uState == GLYPH_NEW) // delete before add new -> no change
uState = GLYPH_UNCHANGED;
else // delete existing data
uState = GLYPH_DELETED;
}
else if (uState != GLYPH_NEW) // if not new data, change current data
{
uState = GLYPH_CHANGED;
}
id = newId;
}
};
typedef std::map<uint16 /*pair16(spec, slot)*/,ActionButton> GlyphList;
struct PlayerCreateInfoItem struct PlayerCreateInfoItem
{ {
PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {} PlayerCreateInfoItem(uint32 id, uint32 amount) : item_id(id), item_amount(amount) {}
@ -847,7 +893,8 @@ enum PlayerLoginQueryIndex
PLAYER_LOGIN_QUERY_LOADBGDATA = 21, PLAYER_LOGIN_QUERY_LOADBGDATA = 21,
PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 22, PLAYER_LOGIN_QUERY_LOADACCOUNTDATA = 22,
PLAYER_LOGIN_QUERY_LOADSKILLS = 23, PLAYER_LOGIN_QUERY_LOADSKILLS = 23,
MAX_PLAYER_LOGIN_QUERY = 24 PLAYER_LOGIN_QUERY_LOADGLYPHS = 24,
MAX_PLAYER_LOGIN_QUERY = 25
}; };
enum PlayerDelayedOperations enum PlayerDelayedOperations
@ -1540,8 +1587,9 @@ class MANGOS_DLL_SPEC Player : public Unit
void InitGlyphsForLevel(); void InitGlyphsForLevel();
void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); } void SetGlyphSlot(uint8 slot, uint32 slottype) { SetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot, slottype); }
uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); } uint32 GetGlyphSlot(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPH_SLOTS_1 + slot); }
void SetGlyph(uint8 slot, uint32 glyph) { SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); } void SetGlyph(uint8 slot, uint32 glyph) { m_glyphs[m_activeSpec][slot].SetId(glyph); SetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot, glyph); }
uint32 GetGlyph(uint8 slot) { return GetUInt32Value(PLAYER_FIELD_GLYPHS_1 + slot); } uint32 GetGlyph(uint8 slot) { return m_glyphs[m_activeSpec][slot].GetId(); }
void ApplyGlyphAuras(bool apply);
uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); } uint32 GetFreePrimaryProfessionPoints() const { return GetUInt32Value(PLAYER_CHARACTER_POINTS2); }
void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); } void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS2, profs); }
@ -2275,7 +2323,6 @@ class MANGOS_DLL_SPEC Player : public Unit
void _LoadActions(QueryResult *result); void _LoadActions(QueryResult *result);
void _LoadAuras(QueryResult *result, uint32 timediff); void _LoadAuras(QueryResult *result, uint32 timediff);
void _LoadGlyphAuras();
void _LoadBoundInstances(QueryResult *result); void _LoadBoundInstances(QueryResult *result);
void _LoadInventory(QueryResult *result, uint32 timediff); void _LoadInventory(QueryResult *result, uint32 timediff);
void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery); void _LoadMailInit(QueryResult *resultUnread, QueryResult *resultDelivery);
@ -2292,6 +2339,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void _LoadArenaTeamInfo(QueryResult *result); void _LoadArenaTeamInfo(QueryResult *result);
void _LoadEquipmentSets(QueryResult *result); void _LoadEquipmentSets(QueryResult *result);
void _LoadBGData(QueryResult* result); void _LoadBGData(QueryResult* result);
void _LoadGlyphs(QueryResult *result);
/*********************************************************/ /*********************************************************/
/*** SAVE SYSTEM ***/ /*** SAVE SYSTEM ***/
@ -2307,6 +2355,7 @@ class MANGOS_DLL_SPEC Player : public Unit
void _SaveSpells(); void _SaveSpells();
void _SaveEquipmentSets(); void _SaveEquipmentSets();
void _SaveBGData(); void _SaveBGData();
void _SaveGlyphs();
void _SetCreateBits(UpdateMask *updateMask, Player *target) const; void _SetCreateBits(UpdateMask *updateMask, Player *target) const;
void _SetUpdateBits(UpdateMask *updateMask, Player *target) const; void _SetUpdateBits(UpdateMask *updateMask, Player *target) const;
@ -2366,6 +2415,8 @@ class MANGOS_DLL_SPEC Player : public Unit
ActionButtonList m_actionButtons[MAX_TALENT_SPEC_COUNT]; ActionButtonList m_actionButtons[MAX_TALENT_SPEC_COUNT];
Glyph m_glyphs[MAX_TALENT_SPEC_COUNT][MAX_GLYPH_SLOT_INDEX];
float m_auraBaseMod[BASEMOD_END][MOD_END]; float m_auraBaseMod[BASEMOD_END][MOD_END];
int16 m_baseRatingValue[MAX_COMBAT_RATING]; int16 m_baseRatingValue[MAX_COMBAT_RATING];
uint16 m_baseSpellPower; uint16 m_baseSpellPower;