diff options
author | Brian <runningnak3d@gmail.com> | 2010-07-26 17:58:25 -0600 |
---|---|---|
committer | Brian <runningnak3d@gmail.com> | 2010-07-26 17:58:25 -0600 |
commit | 024b57bb74a664cd515cf0822d4b8e939a91fe03 (patch) | |
tree | 7a8086b28654ea23bc30348b0c58bd0486da5206 | |
parent | 3ea0f411d3be47f073232e7fc54e10f5c09de8d8 (diff) |
* Implement reputation spillover via the database
* Remove the nasty hack that we had to handle Vanguard Alliance / Horde
* Expedition, and city spillover.
* Needs DB data
* Original patch by NoFantasy
--HG--
branch : trunk
-rw-r--r-- | sql/base/world_database.sql | 30 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.cpp | 1 | ||||
-rw-r--r-- | src/server/game/Chat/Chat.h | 1 | ||||
-rw-r--r-- | src/server/game/Chat/Commands/Level3.cpp | 8 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.cpp | 4 | ||||
-rw-r--r-- | src/server/game/DataStores/DBCStores.h | 2 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.cpp | 118 | ||||
-rw-r--r-- | src/server/game/Globals/ObjectMgr.h | 19 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Reputation/ReputationMgr.cpp | 128 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 3 |
11 files changed, 242 insertions, 74 deletions
diff --git a/sql/base/world_database.sql b/sql/base/world_database.sql index ebfcb2a0cfa..fbe88688b22 100644 --- a/sql/base/world_database.sql +++ b/sql/base/world_database.sql @@ -4681,6 +4681,36 @@ LOCK TABLES `reputation_reward_rate` WRITE; /*!40000 ALTER TABLE `reputation_reward_rate` DISABLE KEYS */; /*!40000 ALTER TABLE `reputation_reward_rate` ENABLE KEYS */; UNLOCK TABLES; +-- +-- Table structure for table `reputation_spillover_template` +-- + +DROP TABLE IF EXISTS `reputation_spillover_template`; +CREATE TABLE `reputation_spillover_template` ( + `faction` smallint(6) unsigned NOT NULL default '0' COMMENT 'faction entry', + `faction1` smallint(6) unsigned NOT NULL default '0' COMMENT 'faction to give spillover for', + `rate_1` float NOT NULL default '0' COMMENT 'the given rep points * rate', + `rank_1` tinyint(3) unsigned NOT NULL default '0' COMMENT 'max rank, above this will not give any spillover', + `faction2` smallint(6) unsigned NOT NULL default '0', + `rate_2` float NOT NULL default '0', + `rank_2` tinyint(3) unsigned NOT NULL default '0', + `faction3` smallint(6) unsigned NOT NULL default '0', + `rate_3` float NOT NULL default '0', + `rank_3` tinyint(3) unsigned NOT NULL default '0', + `faction4` smallint(6) unsigned NOT NULL default '0', + `rate_4` float NOT NULL default '0', + `rank_4` tinyint(3) unsigned NOT NULL default '0', + PRIMARY KEY (`faction`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC COMMENT='Reputation spillover reputation gain'; + +-- +-- Dumping data for table `reputation_spillover_template` +-- + +LOCK TABLES `reputation_spillover_template` WRITE; +/*!40000 ALTER TABLE `reputation_spillover_template` DISABLE KEYS */; +/*!40000 ALTER TABLE `reputation_spillover_template` ENABLE KEYS */; +UNLOCK TABLES; -- -- Table structure for table `reserved_name` diff --git a/src/server/game/Chat/Chat.cpp b/src/server/game/Chat/Chat.cpp index e1480c6d637..b98633d2b1a 100644 --- a/src/server/game/Chat/Chat.cpp +++ b/src/server/game/Chat/Chat.cpp @@ -516,6 +516,7 @@ ChatCommand * ChatHandler::getCommandTable() { "reference_loot_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadLootTemplatesReferenceCommand, "", NULL }, { "reserved_name", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadReservedNameCommand, "", NULL }, { "reputation_reward_rate", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadReputationRewardRateCommand, "", NULL }, + { "reputation_spillover_template",SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadReputationRewardRateCommand, "", NULL }, { "skill_discovery_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillDiscoveryTemplateCommand, "", NULL }, { "skill_extra_item_template", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillExtraItemTemplateCommand, "", NULL }, { "skill_fishing_base_level", SEC_ADMINISTRATOR, true, &ChatHandler::HandleReloadSkillFishingBaseLevelCommand, "", NULL }, diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h index bd12e454b56..62ae51b5e0b 100644 --- a/src/server/game/Chat/Chat.h +++ b/src/server/game/Chat/Chat.h @@ -417,6 +417,7 @@ class ChatHandler bool HandleReloadQuestTemplateCommand(const char* args); bool HandleReloadReservedNameCommand(const char*); bool HandleReloadReputationRewardRateCommand(const char* args); + bool HandleReloadReputationSpilloverTemplateCommand(const char* args); bool HandleReloadSkillDiscoveryTemplateCommand(const char* args); bool HandleReloadSkillExtraItemTemplateCommand(const char* args); bool HandleReloadSkillFishingBaseLevelCommand(const char* args); diff --git a/src/server/game/Chat/Commands/Level3.cpp b/src/server/game/Chat/Commands/Level3.cpp index 72e4dfb4cfd..46083f05728 100644 --- a/src/server/game/Chat/Commands/Level3.cpp +++ b/src/server/game/Chat/Commands/Level3.cpp @@ -1160,6 +1160,14 @@ bool ChatHandler::HandleReloadReputationRewardRateCommand(const char*) return true; } +bool ChatHandler::HandleReloadReputationSpilloverTemplateCommand(const char*) +{ + sLog.outString( "Re-Loading `reputation_spillover_template` Table!" ); + objmgr.LoadReputationSpilloverTemplate(); + SendGlobalSysMessage("DB table `reputation_spillover_template` reloaded."); + return true; +} + bool ChatHandler::HandleReloadSkillDiscoveryTemplateCommand(const char* /*args*/) { sLog.outString("Re-Loading Skill Discovery Table..."); diff --git a/src/server/game/DataStores/DBCStores.cpp b/src/server/game/DataStores/DBCStores.cpp index 4ddccd735f5..3ceb6fe02ef 100644 --- a/src/server/game/DataStores/DBCStores.cpp +++ b/src/server/game/DataStores/DBCStores.cpp @@ -607,20 +607,18 @@ void LoadDBCStores(const std::string& dataPath) sLog.outString(">> Initialized %d data stores", DBCFilesCount); } -SimpleFactionsList const* GetFactionTeamList(uint32 faction, bool &isTeamMember) +SimpleFactionsList const* GetFactionTeamList(uint32 faction) { for (FactionTeamMap::const_iterator itr = sFactionTeamMap.begin(); itr != sFactionTeamMap.end(); ++itr) { if (itr->first == faction) { - isTeamMember = false; return &itr->second; } for (SimpleFactionsList::const_iterator itr2 = itr->second.begin(); itr2 != itr->second.end(); ++itr2) { if ((*itr2) == faction) { - isTeamMember = true; return &itr->second; } } diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h index 1bda56f38cc..cd08f23b9d4 100644 --- a/src/server/game/DataStores/DBCStores.h +++ b/src/server/game/DataStores/DBCStores.h @@ -27,7 +27,7 @@ typedef std::list<uint32> SimpleFactionsList; -SimpleFactionsList const* GetFactionTeamList(uint32 faction, bool &isTeamMember); +SimpleFactionsList const* GetFactionTeamList(uint32 faction); char* GetPetName(uint32 petfamily, uint32 dbclang); uint32 GetTalentSpellCost(uint32 spellId); TalentSpellPos const* GetTalentSpellPos(uint32 spellId); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 2a51d2f3273..139e3accdce 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -6889,6 +6889,124 @@ void ObjectMgr::LoadReputationOnKill() sLog.outString(">> Loaded %u creature award reputation definitions", count); } +void ObjectMgr::LoadReputationSpilloverTemplate() +{ + m_RepSpilloverTemplateMap.clear(); // for reload case + + uint32 count = 0; + QueryResult_AutoPtr result = WorldDatabase.Query("SELECT faction, faction1, rate_1, rank_1, faction2, rate_2, rank_2, faction3, rate_3, rank_3, faction4, rate_4, rank_4 FROM reputation_spillover_template"); + + if (!result) + { + barGoLink bar(1); + + bar.step(); + + sLog.outString(); + sLog.outErrorDb(">> Loaded `reputation_spillover_template`, table is empty!"); + return; + } + + barGoLink bar((int)result->GetRowCount()); + + do + { + bar.step(); + + Field *fields = result->Fetch(); + + uint32 factionId = fields[0].GetUInt32(); + + RepSpilloverTemplate repTemplate; + + repTemplate.faction[0] = fields[1].GetUInt32(); + repTemplate.faction_rate[0] = fields[2].GetFloat(); + repTemplate.faction_rank[0] = fields[3].GetUInt32(); + repTemplate.faction[1] = fields[4].GetUInt32(); + repTemplate.faction_rate[1] = fields[5].GetFloat(); + repTemplate.faction_rank[1] = fields[6].GetUInt32(); + repTemplate.faction[2] = fields[7].GetUInt32(); + repTemplate.faction_rate[2] = fields[8].GetFloat(); + repTemplate.faction_rank[2] = fields[9].GetUInt32(); + repTemplate.faction[3] = fields[10].GetUInt32(); + repTemplate.faction_rate[3] = fields[11].GetFloat(); + repTemplate.faction_rank[3] = fields[12].GetUInt32(); + + FactionEntry const *factionEntry = sFactionStore.LookupEntry(factionId); + + if (!factionEntry) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", factionId); + continue; + } + + if (factionEntry->team == 0) + { + sLog.outErrorDb("Faction (faction.dbc) %u in `reputation_spillover_template` does not belong to any team, skipping", factionId); + continue; + } + + for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i) + { + if (repTemplate.faction[i]) + { + FactionEntry const *factionSpillover = sFactionStore.LookupEntry(repTemplate.faction[i]); + + if (!factionSpillover) + { + sLog.outErrorDb("Spillover faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template` for faction %u, skipping", repTemplate.faction[i], factionId); + continue; + } + + if (factionSpillover->reputationListID < 0) + { + sLog.outErrorDb("Spillover faction (faction.dbc) %u for faction %u in `reputation_spillover_template` can not be listed for client, and then useless, skipping", repTemplate.faction[i], factionId); + continue; + } + + if (repTemplate.faction_rank[i] >= MAX_REPUTATION_RANK) + { + sLog.outErrorDb("Rank %u used in `reputation_spillover_template` for spillover faction %u is not valid, skipping", repTemplate.faction_rank[i], repTemplate.faction[i]); + continue; + } + } + } + + FactionEntry const *factionEntry0 = sFactionStore.LookupEntry(repTemplate.faction[0]); + if (repTemplate.faction[0] && !factionEntry0) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[0]); + continue; + } + FactionEntry const *factionEntry1 = sFactionStore.LookupEntry(repTemplate.faction[1]); + if (repTemplate.faction[1] && !factionEntry1) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[1]); + continue; + } + FactionEntry const *factionEntry2 = sFactionStore.LookupEntry(repTemplate.faction[2]); + if (repTemplate.faction[2] && !factionEntry2) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[2]); + continue; + } + FactionEntry const *factionEntry3 = sFactionStore.LookupEntry(repTemplate.faction[3]); + if (repTemplate.faction[3] && !factionEntry3) + { + sLog.outErrorDb("Faction (faction.dbc) %u does not exist but is used in `reputation_spillover_template`", repTemplate.faction[3]); + continue; + } + + m_RepSpilloverTemplateMap[factionId] = repTemplate; + + ++count; + } + while (result->NextRow()); + + sLog.outString(); + sLog.outString(">> Loaded %u reputation_spillover_template", count); +} + void ObjectMgr::LoadPointsOfInterest() { uint32 count = 0; diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 580034fe703..b44225dc5e6 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -219,6 +219,13 @@ struct ReputationOnKillEntry bool team_dependent; }; +struct RepSpilloverTemplate +{ + uint32 faction[MAX_SPILLOVER_FACTIONS]; + float faction_rate[MAX_SPILLOVER_FACTIONS]; + uint32 faction_rank[MAX_SPILLOVER_FACTIONS]; +}; + struct PointOfInterest { uint32 entry; @@ -387,6 +394,7 @@ class ObjectMgr typedef UNORDERED_MAP<uint32, RepRewardRate > RepRewardRateMap; typedef UNORDERED_MAP<uint32, ReputationOnKillEntry> RepOnKillMap; + typedef UNORDERED_MAP<uint32, RepSpilloverTemplate> RepSpilloverTemplateMap; typedef UNORDERED_MAP<uint32, PointOfInterest> PointOfInterestMap; @@ -552,6 +560,15 @@ class ObjectMgr return NULL; } + RepSpilloverTemplate const* GetRepSpilloverTemplate(uint32 factionId) const + { + RepSpilloverTemplateMap::const_iterator itr = m_RepSpilloverTemplateMap.find(factionId); + if (itr != m_RepSpilloverTemplateMap.end()) + return &itr->second; + + return NULL; + } + PointOfInterest const* GetPointOfInterest(uint32 id) const { PointOfInterestMap::const_iterator itr = mPointsOfInterest.find(id); @@ -664,6 +681,7 @@ class ObjectMgr void LoadReputationRewardRate(); void LoadReputationOnKill(); + void LoadReputationSpilloverTemplate(); void LoadPointsOfInterest(); void LoadQuestPOI(); @@ -1009,6 +1027,7 @@ class ObjectMgr RepRewardRateMap m_RepRewardRateMap; RepOnKillMap mRepOnKill; + RepSpilloverTemplateMap m_RepSpilloverTemplateMap; GossipMenusMap m_mGossipMenusMap; GossipMenuItemsMap m_mGossipMenuItemsMap; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index 54dfd749b66..45069ecf561 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -142,6 +142,8 @@ enum ReputationRank #define MIN_REPUTATION_RANK (REP_HATED) #define MAX_REPUTATION_RANK 8 +#define MAX_SPILLOVER_FACTIONS 4 + enum MoneyConstants { COPPER = 1, diff --git a/src/server/game/Reputation/ReputationMgr.cpp b/src/server/game/Reputation/ReputationMgr.cpp index 9d363921f4c..78952136d27 100644 --- a/src/server/game/Reputation/ReputationMgr.cpp +++ b/src/server/game/Reputation/ReputationMgr.cpp @@ -140,14 +140,29 @@ void ReputationMgr::SendState(FactionState const* faction) const { if (faction->Flags & FACTION_FLAG_VISIBLE) //If faction is visible then update it { + uint32 count = 1; + WorldPacket data(SMSG_SET_FACTION_STANDING, (16)); // last check 2.4.0 data << (float) 0; // unk 2.4.0 data << (uint8) 0; // wotlk 8634 - data << (uint32) 1; // count - // for + + size_t p_count = data.wpos(); + data << (uint32) count; // placeholder + data << (uint32) faction->ReputationListID; data << (uint32) faction->Standing; - // end for + + for(FactionStateList::const_iterator itr = m_factions.begin(); itr != m_factions.end(); ++itr) + { + if (itr->second.Changed && itr->second.ReputationListID != faction->ReputationListID) + { + data << (uint32) itr->second.ReputationListID; + data << (uint32) itr->second.Standing; + ++count; + } + } + + data.put<uint32>(p_count, count); m_player->SendDirectMessage(&data); } } @@ -235,82 +250,57 @@ void ReputationMgr::Initialize() bool ReputationMgr::SetReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) { - // Determines whether or not the faction is part of a team or the leader of a team. - bool isTeamMember = false; - - // Return variable for the function - bool res = false; - - SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID, isTeamMember); - // Determines whether reputation should be sent to team parent or other team members. - int8 extraTarget = (isTeamMember || !flist ? -1 : 0); // 0 = Give equal amount of reputation to anyone in the team (unhandled cases). - - /* When gaining reputation with some factions, you receive a reputation increase - towards other reputations for that group. - */ - uint32 team = factionEntry->team; - - int32 sharedStanding = standing; // Here we decide what the amount is to send to the others of the group. - switch(factionEntry->ID) + if (SimpleFactionsList const* flist = GetFactionTeamList(factionEntry->ID)) { - case 1037: // Alliance Vanguard - case 1052: // Horde Expedition - extraTarget = -1; // Make possible to earn rep with this two factions - break; + bool res = false; + for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr) + { + if (FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr)) + { + res = SetOneFactionReputation(factionEntryCalc, standing, incremental); + if (res) + { + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + SendState(&itr->second); + } + } + } + return res; } - switch(team) + else { - case HORDE: // When earning reputation with home city factions, 25% of the earned reputation - case ALLIANCE: // is added to others of your alliance. (http://www.wowwiki.com/Reputation) - sharedStanding *= 0.25f; - extraTarget = 1; - break; - case 1037: // Alliance Vanguard - case 1052: // Horde Expedition - sharedStanding *= 0.5f; // Half of the reputation earned by any of the four subfactions of this team will - extraTarget = 2; // be added to the main faction. (http://www.wowwiki.com/Alliance_Vanguard) - break; - } + // update for the actual faction first + bool res = SetOneFactionReputation(factionEntry, standing, incremental); - FactionEntry const *targetFaction = NULL; - switch(extraTarget) - { - case 0: // To entire team + if (res) { - for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr) + // then some spillover calculation here if it exist + if (const RepSpilloverTemplate *repTemplate = objmgr.GetRepSpilloverTemplate(factionEntry->ID)) { - targetFaction = sFactionStore.LookupEntry(*itr); - ASSERT(targetFaction != NULL); - res = SetOneFactionReputation(targetFaction, sharedStanding, incremental); + for (uint32 i = 0; i < MAX_SPILLOVER_FACTIONS; ++i) + { + if (repTemplate->faction[i]) + { + if (m_player->GetReputationRank(repTemplate->faction[i]) <= ReputationRank(repTemplate->faction_rank[i])) + { + // bonuses are already given, so just modify standing by rate + int32 spilloverRep = standing * repTemplate->faction_rate[i]; + SetOneFactionReputation(sFactionStore.LookupEntry(repTemplate->faction[i]), spilloverRep, incremental); + } + } + } } - return res; - }break; - case 1: // To other team members - { - for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr) - { - if ((*itr) == factionEntry->ID) // Not to self - continue; - targetFaction = sFactionStore.LookupEntry(*itr); - ASSERT(targetFaction != NULL); - res = SetOneFactionReputation(targetFaction, sharedStanding, incremental); - } - }break; - case 2: // Extra rep to team parent. - { - targetFaction = sFactionStore.LookupEntry(team); - ASSERT(targetFaction != NULL); - res = SetOneFactionReputation(targetFaction, sharedStanding, incremental); + // now we can send it + FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID); + if (itr != m_factions.end()) + SendState(&itr->second); } - break; - default: // -1 Default case, 1 faction - return SetOneFactionReputation(factionEntry, standing, incremental); - break; - } - return (SetOneFactionReputation(factionEntry, standing, incremental) && res); + return res; + } } bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, int32 standing, bool incremental) @@ -343,8 +333,6 @@ bool ReputationMgr::SetOneFactionReputation(FactionEntry const* factionEntry, in if (new_rank <= REP_HOSTILE) SetAtWar(&itr->second,true); - SendState(&itr->second); - UpdateRankCounters(old_rank, new_rank); m_player->ReputationChanged(factionEntry); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 2c082bbd4a6..66254e0b545 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1388,6 +1388,9 @@ void World::SetInitialWorldSettings() sLog.outString("Loading Creature Reputation OnKill Data..."); objmgr.LoadReputationOnKill(); + sLog.outString( "Loading Reputation Spillover Data..." ); + objmgr.LoadReputationSpilloverTemplate(); + sLog.outString("Loading Points Of Interest Data..."); objmgr.LoadPointsOfInterest(); |