aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.cpp22
-rwxr-xr-xsrc/server/game/Globals/ObjectMgr.h2
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp55
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.cpp3
-rw-r--r--src/server/shared/Database/Implementation/CharacterDatabase.h1
5 files changed, 75 insertions, 8 deletions
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 95a27fd14e1..ea4386c4d41 100755
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -7590,6 +7590,28 @@ 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, uint32 playerClass)
+{
+ if (!factionEntry)
+ return 0;
+
+ uint32 raceMask = (1 << (race - 1));
+ uint32 classMask = (1 << (playerClass-1));
+
+ for (int i=0; i < 4; i++)
+ {
+ if ((factionEntry->BaseRepRaceMask[i] & raceMask ||
+ (factionEntry->BaseRepRaceMask[i] == 0 &&
+ factionEntry->BaseRepClassMask[i] != 0)) &&
+ (factionEntry->BaseRepClassMask[i] & classMask ||
+ factionEntry->BaseRepClassMask[i] == 0))
+ 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..81ca02af5d9 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, uint32 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..30bc6df0539 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1625,11 +1625,23 @@ 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
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_RACE);
+ stmt->setUInt32(0, guid);
+ 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();
+ uint8 oldRace = fields[0].GetUInt8();
+ stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_CLASS_LVL_AT_LOGIN);
stmt->setUInt32(0, lowGuid);
-
- PreparedQueryResult result = CharacterDatabase.Query(stmt);
+ result = CharacterDatabase.Query(stmt);
if (!result)
{
@@ -1639,7 +1651,7 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
return;
}
- Field* fields = result->Fetch();
+ fields = result->Fetch();
uint32 playerClass = uint32(fields[0].GetUInt8());
uint32 level = uint32(fields[1].GetUInt8());
uint32 at_loginFlags = fields[2].GetUInt16();
@@ -2004,15 +2016,44 @@ void WorldSession::HandleCharFactionOrRaceChange(WorldPacket& recv_data)
uint32 reputation_alliance = it->first;
uint32 reputation_horde = it->second;
- PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_REP_BY_FACTION);
+ // select old standing set in db
+ PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHAR_REP_BY_FACTION);
+ stmt->setUInt32(0, team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance);
+ 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(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance);
+
+ // old base reputation
+ int32 oldBaseRep = sObjectMgr->GetBaseReputation(factionEntry, oldRace, playerClass);
+
+ // new base reputation
+ int32 newBaseRep = sObjectMgr->GetBaseReputation(sFactionStore.LookupEntry(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde), 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, uint16(team == TEAM_ALLIANCE ? reputation_alliance : reputation_horde));
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->setInt32(1, newDBRep);
+ stmt->setUInt16(2, uint16(team == TEAM_ALLIANCE ? reputation_horde : reputation_alliance));
+ stmt->setUInt32(3, lowGuid);
trans->Append(stmt);
}
diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
index add782cf517..4396f67244a 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.cpp
@@ -497,8 +497,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..95b059de95c 100644
--- a/src/server/shared/Database/Implementation/CharacterDatabase.h
+++ b/src/server/shared/Database/Implementation/CharacterDatabase.h
@@ -460,6 +460,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,