diff options
-rwxr-xr-x | src/server/game/Globals/ObjectMgr.cpp | 22 | ||||
-rwxr-xr-x | src/server/game/Globals/ObjectMgr.h | 2 | ||||
-rw-r--r-- | src/server/game/Handlers/CharacterHandler.cpp | 55 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.cpp | 3 | ||||
-rw-r--r-- | src/server/shared/Database/Implementation/CharacterDatabase.h | 1 |
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, |