aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/base/world_database.sql30
-rw-r--r--src/server/game/Chat/Chat.cpp1
-rw-r--r--src/server/game/Chat/Chat.h1
-rw-r--r--src/server/game/Chat/Commands/Level3.cpp8
-rw-r--r--src/server/game/DataStores/DBCStores.cpp4
-rw-r--r--src/server/game/DataStores/DBCStores.h2
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp118
-rw-r--r--src/server/game/Globals/ObjectMgr.h19
-rw-r--r--src/server/game/Miscellaneous/SharedDefines.h2
-rw-r--r--src/server/game/Reputation/ReputationMgr.cpp128
-rw-r--r--src/server/game/World/World.cpp3
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();