aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/server/game/Entities/Unit/Unit.cpp3
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp21
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp57
-rw-r--r--src/server/game/Tools/PlayerDump.cpp4
-rwxr-xr-xsrc/server/game/World/World.cpp16
-rwxr-xr-xsrc/server/game/World/World.h4
-rw-r--r--src/server/scripts/Commands/cs_character.cpp2
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp6
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h2
10 files changed, 97 insertions, 20 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 8fc519b2f4a..c1f7a5a1fe5 100755
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -13659,6 +13659,9 @@ void Unit::SetLevel(uint8 lvl)
// group update
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->GetGroup())
ToPlayer()->SetGroupUpdateFlag(GROUP_UPDATE_FLAG_LEVEL);
+
+ if (GetTypeId() == TYPEID_PLAYER)
+ sWorld->UpdateCharacterNameDataLevel(ToPlayer()->GetGUIDLow(), lvl);
}
void Unit::SetHealth(uint32 val)
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 95a27fd14e1..b28f8be7805 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -7590,6 +7590,27 @@ SpellScriptsBounds ObjectMgr::GetSpellScriptsBounds(uint32 spell_id)
return SpellScriptsBounds(_spellScriptsStore.lower_bound(spell_id), _spellScriptsStore.upper_bound(spell_id));
}
+// this allows calculating base reputations to offline players, just by race and class
+int32 ObjectMgr::GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass)
+{
+ if (!factionEntry)
+ return 0;
+
+ uint32 raceMask = (1 << (race - 1));
+ uint32 classMask = (1 << (playerClass-1));
+
+ for (int i = 0; i < 4; i++)
+ {
+ if ((!factionEntry->BaseRepClassMask[i] ||
+ factionEntry->BaseRepClassMask[i] & classMask) &&
+ (!factionEntry->BaseRepRaceMask[i] ||
+ factionEntry->BaseRepRaceMask[i] & raceMask))
+ return factionEntry->BaseRepValue[i];
+ }
+
+ return 0;
+}
+
SkillRangeType GetSkillRangeType(SkillLineEntry const* pSkill, bool racial)
{
switch (pSkill->categoryId)
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index bbd95e22685..7871bbe3239 100755
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -749,6 +749,8 @@ class ObjectMgr
return NULL;
}
+ int32 GetBaseReputation(FactionEntry const* factionEntry, uint8 race, uint8 playerClass);
+
RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const
{
RepSpilloverTemplateContainer::const_iterator itr = _repSpilloverTemplateStore.find(factionId);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 5c603e46086..853e71fd732 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -660,7 +660,7 @@ void WorldSession::HandleCharCreateCallback(PreparedQueryResult result, Characte
std::string IP_str = GetRemoteAddress();
sLog->outInfo(LOG_FILTER_CHARACTER, "Account: %d (IP: %s) Create Character:[%s] (GUID: %u)", GetAccountId(), IP_str.c_str(), createInfo->Name.c_str(), newChar.GetGUIDLow());
sScriptMgr->OnPlayerCreate(&newChar);
- sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass());
+ sWorld->AddCharacterNameData(newChar.GetGUIDLow(), std::string(newChar.GetName()), newChar.getGender(), newChar.getRace(), newChar.getClass(), newChar.getLevel());
newChar.CleanupsBeforeDelete();
delete createInfo;
@@ -1625,10 +1625,14 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
uint32 lowGuid = GUID_LOPART(guid);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN);
+ // get the players old (at this moment current) race
+ CharacterNameData const* nameData = sWorld->GetCharacterNameData(lowGuid);
+ uint8 oldRace = nameData->m_race;
+ uint8 playerClass = nameData->m_class;
+ uint8 level = nameData->m_level;
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_AT_LOGIN_TITLES);
stmt->setUInt32(0, lowGuid);
-
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
@@ -1640,11 +1644,9 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
}
Field* fields = result->Fetch();
- uint32 playerClass = uint32(fields[0].GetUInt8());
- uint32 level = uint32(fields[1].GetUInt8());
- uint32 at_loginFlags = fields[2].GetUInt16();
+ uint32 at_loginFlags = fields[0].GetUInt16();
+ char const* knownTitlesStr = fields[1].GetCString();
uint32 used_loginFlag = ((recv_data.GetOpcode() == CMSG_CHAR_RACE_CHANGE) ? AT_LOGIN_CHANGE_RACE : AT_LOGIN_CHANGE_FACTION);
- char const* knownTitlesStr = fields[3].GetCString();
if (!sObjectMgr->GetPlayerInfo(race, playerClass))
{
@@ -2003,16 +2005,47 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
{
uint32 reputation_alliance = it->first;
uint32 reputation_horde = it->second;
+ uint32 newReputation = (team == TEAM_ALLIANCE) ? reputation_alliance : reputation_horde;
+ uint32 oldReputation = (team == TEAM_ALLIANCE) ? reputation_horde : reputation_alliance;
+
+ // select old standing set in db
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
+ stmt->setUInt32(0, oldReputation);
+ stmt->setUInt32(1, lowGuid);
+ PreparedQueryResult result = CharacterDatabase.Query(stmt);
+
+ if (!result)
+ {
+ WorldPacket data(SMSG_CHAR_FACTION_CHANGE, 1);
+ data << uint8(CHAR_CREATE_ERROR);
+ SendPacket(&data);
+ return;
+ }
+
+ Field* fields = result->Fetch();
+ int32 oldDBRep = fields[0].GetInt32();
+ FactionEntry const* factionEntry = sFactionStore.LookupEntry(oldReputation);
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
- stmt->setUInt32(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde));
+ // old base reputation
+ int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass);
+
+ // new base reputation
+ int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(newReputation), race, playerClass);
+
+ // final reputation shouldnt change
+ int32 FinalRep = oldDBRep + oldBaseRep;
+ int32 newDBRep = FinalRep - newBaseRep;
+
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
+ stmt->setUInt32(0, newReputation);
stmt->setUInt32(1, lowGuid);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHAR_REP_FACTION_CHANGE);
- stmt->setUInt16(0, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde));
- stmt->setUInt16(1, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance));
- stmt->setUInt32(2, lowGuid);
+ stmt->setUInt16(0, uint16(newReputation));
+ stmt->setInt32(1, newDBRep);
+ stmt->setUInt16(2, uint16(oldReputation));
+ stmt->setUInt32(3, lowGuid);
trans->Append(stmt);
}
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index f6d0de28d28..ef516a0ba4f 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -457,6 +457,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
uint8 gender = GENDER_NONE;
uint8 race = RACE_NONE;
uint8 playerClass = 0;
+ uint8 level = 1;
SQLTransaction trans = CharacterDatabase.BeginTransaction();
while (!feof(fin))
@@ -531,6 +532,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
race = uint8(atol(getnth(line, 4).c_str()));
playerClass = uint8(atol(getnth(line, 5).c_str()));
gender = uint8(atol(getnth(line, 6).c_str()));
+ level = uint8(atol(getnth(line, 7).c_str()));
if (name == "")
{
// check if the original name already exists
@@ -674,7 +676,7 @@ DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, s
CharacterDatabase.CommitTransaction(trans);
// in case of name conflict player has to rename at login anyway
- sWorld->AddCharacterNameData(guid, name, gender, race, playerClass);
+ sWorld->AddCharacterNameData(guid, name, gender, race, playerClass, level);
sObjectMgr->_hiItemGuid += items.size();
sObjectMgr->_mailId += mails.size();
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index eef53e17774..06e8d3eccbe 100755
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -2937,7 +2937,7 @@ void World::LoadCharacterNameData()
{
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loading character name data");
- QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class FROM characters WHERE deleteDate IS NULL");
+ QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL");
if (!result)
{
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "No character name data loaded, empty query");
@@ -2950,20 +2950,21 @@ void World::LoadCharacterNameData()
{
Field* fields = result->Fetch();
AddCharacterNameData(fields[0].GetUInt32(), fields[1].GetString(),
- fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/);
+ fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8() /*level*/);
++count;
} while (result->NextRow());
sLog->outInfo(LOG_FILTER_SERVER_LOADING, "Loaded name data for %u characters", count);
}
-void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass)
+void World::AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level)
{
CharacterNameData& data = _characterNameDataMap[guid];
data.m_name = name;
data.m_race = race;
data.m_gender = gender;
data.m_class = playerClass;
+ data.m_level = level;
}
void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/)
@@ -2981,6 +2982,15 @@ void World::UpdateCharacterNameData(uint32 guid, std::string const& name, uint8
itr->second.m_race = race;
}
+void World::UpdateCharacterNameDataLevel(uint32 guid, uint8 level)
+{
+ std::map<uint32, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
+ if (itr == _characterNameDataMap.end())
+ return;
+
+ itr->second.m_level = level;
+}
+
CharacterNameData const* World::GetCharacterNameData(uint32 guid) const
{
std::map<uint32, CharacterNameData>::const_iterator itr = _characterNameDataMap.find(guid);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 90bb82f1c2e..66b52549e93 100755
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -538,6 +538,7 @@ struct CharacterNameData
uint8 m_class;
uint8 m_race;
uint8 m_gender;
+ uint8 m_level;
};
/// The World
@@ -759,8 +760,9 @@ class World
bool isEventKillStart;
CharacterNameData const* GetCharacterNameData(uint32 guid) const;
- void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass);
+ void AddCharacterNameData(uint32 guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level);
void UpdateCharacterNameData(uint32 guid, std::string const& name, uint8 gender = GENDER_NONE, uint8 race = RACE_NONE);
+ void UpdateCharacterNameDataLevel(uint32 guid, uint8 level);
void DeleteCharaceterNameData(uint32 guid) { _characterNameDataMap.erase(guid); }
uint32 GetCleaningFlags() const { return m_CleaningFlags; }
diff --git a/src/server/scripts/Commands/cs_character.cpp b/src/server/scripts/Commands/cs_character.cpp
index f5fbfa33cae..080b2416c9a 100644
--- a/src/server/scripts/Commands/cs_character.cpp
+++ b/src/server/scripts/Commands/cs_character.cpp
@@ -224,7 +224,7 @@ public:
stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_NAME_DATA);
stmt->setUInt32(0, delInfo.lowGuid);
if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
- sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8());
+ sWorld->AddCharacterNameData(delInfo.lowGuid, delInfo.name, (*result)[2].GetUInt8(), (*result)[0].GetUInt8(), (*result)[1].GetUInt8(), (*result)[2].GetUInt8());
}
static void HandleCharacterLevel(Player* player, uint64 playerGuid, uint32 oldLevel, uint32 newLevel, ChatHandler* handler)
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index add782cf517..c29d8313c20 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -49,7 +49,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_CHAR_RACE, "SELECT race FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_LEVEL, "SELECT level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_ZONE, "SELECT zone FROM characters WHERE guid = ?", CONNECTION_SYNCH);
- PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender FROM characters WHERE guid = ?", CONNECTION_SYNCH);
+ PREPARE_STATEMENT(CHAR_SEL_CHARACTER_NAME_DATA, "SELECT race, class, gender, level FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION_XYZ, "SELECT map, position_x, position_y, position_z FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_POSITION, "SELECT position_x, position_y, position_z, orientation, map, taxi_path FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_DEL_QUEST_STATUS_DAILY, "DELETE FROM character_queststatus_daily", CONNECTION_ASYNC);
@@ -421,6 +421,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_SEL_POOL_QUEST_SAVE, "SELECT quest_id FROM pool_quest_save WHERE pool_id = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHARACTER_AT_LOGIN, "SELECT at_login FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN, "SELECT class, level, at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
+ PREPARE_STATEMENT(CHAR_SEL_CHAR_AT_LOGIN_TITLES, "SELECT at_login, knownTitles FROM characters WHERE guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_INSTANCE, "SELECT data, completedEncounters FROM instance WHERE map = ? AND id = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_PET_SPELL_LIST, "SELECT DISTINCT pet_spell.spell FROM pet_spell, character_pet WHERE character_pet.owner = ? AND character_pet.id = pet_spell.guid AND character_pet.id <> ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_SEL_CHAR_PET, "SELECT id FROM character_pet WHERE owner = ? AND id <> ?", CONNECTION_SYNCH);
@@ -497,8 +498,9 @@ void CharacterDatabaseConnection::DoPrepareStatements()
PREPARE_STATEMENT(CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE, "UPDATE item_instance ii, character_inventory ci SET ii.itemEntry = ? WHERE ii.itemEntry = ? AND ci.guid = ? AND ci.item = ii.guid", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_BY_SPELL, "DELETE FROM character_spell WHERE spell = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_SPELL_FACTION_CHANGE, "UPDATE character_spell SET spell = ? where spell = ? AND guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_SEL_CHAR_REP_BY_FACTION, "SELECT standing FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_SYNCH);
PREPARE_STATEMENT(CHAR_DEL_CHAR_REP_BY_FACTION, "DELETE FROM character_reputation WHERE faction = ? AND guid = ?", CONNECTION_ASYNC);
- PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ? where faction = ? AND guid = ?", CONNECTION_ASYNC);
+ PREPARE_STATEMENT(CHAR_UPD_CHAR_REP_FACTION_CHANGE, "UPDATE character_reputation SET faction = ?, standing = ? WHERE faction = ? AND guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_UPD_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET knownTitles = ? WHERE guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_RES_CHAR_TITLES_FACTION_CHANGE, "UPDATE characters SET chosenTitle = 0 WHERE guid = ?", CONNECTION_ASYNC);
PREPARE_STATEMENT(CHAR_DEL_CHAR_SPELL_COOLDOWN, "DELETE FROM character_spell_cooldown WHERE guid = ?", CONNECTION_ASYNC);
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/shared/Database/Implementation/CharacterDatabase.h
index fedf0022fcc..88018997e4b 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -384,6 +384,7 @@ enum CharacterDatabaseStatements
CHAR_SEL_POOL_QUEST_SAVE,
CHAR_SEL_CHARACTER_AT_LOGIN,
CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN,
+ CHAR_SEL_CHAR_AT_LOGIN_TITLES,
CHAR_SEL_INSTANCE,
CHAR_SEL_PET_SPELL_LIST,
CHAR_SEL_CHAR_PET,
@@ -460,6 +461,7 @@ enum CharacterDatabaseStatements
CHAR_UPD_CHAR_INVENTORY_FACTION_CHANGE,
CHAR_DEL_CHAR_SPELL_BY_SPELL,
CHAR_UPD_CHAR_SPELL_FACTION_CHANGE,
+ CHAR_SEL_CHAR_REP_BY_FACTION,
CHAR_DEL_CHAR_REP_BY_FACTION,
CHAR_UPD_CHAR_REP_FACTION_CHANGE,
CHAR_UPD_CHAR_TITLES_FACTION_CHANGE,