* 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
This commit is contained in:
@@ -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 },
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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...");
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
switch(team)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
FactionEntry const *targetFaction = NULL;
|
||||
switch(extraTarget)
|
||||
{
|
||||
case 0: // To entire team
|
||||
bool res = false;
|
||||
for (SimpleFactionsList::const_iterator itr = flist->begin();itr != flist->end();++itr)
|
||||
{
|
||||
for (SimpleFactionsList::const_iterator itr = flist->begin(); itr != flist->end(); ++itr)
|
||||
if (FactionEntry const *factionEntryCalc = sFactionStore.LookupEntry(*itr))
|
||||
{
|
||||
targetFaction = sFactionStore.LookupEntry(*itr);
|
||||
ASSERT(targetFaction != NULL);
|
||||
res = SetOneFactionReputation(targetFaction, sharedStanding, 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;
|
||||
res = SetOneFactionReputation(factionEntryCalc, standing, incremental);
|
||||
|
||||
targetFaction = sFactionStore.LookupEntry(*itr);
|
||||
ASSERT(targetFaction != NULL);
|
||||
res = SetOneFactionReputation(targetFaction, sharedStanding, incremental);
|
||||
if (res)
|
||||
{
|
||||
FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID);
|
||||
if (itr != m_factions.end())
|
||||
SendState(&itr->second);
|
||||
}
|
||||
}
|
||||
}break;
|
||||
case 2: // Extra rep to team parent.
|
||||
{
|
||||
targetFaction = sFactionStore.LookupEntry(team);
|
||||
ASSERT(targetFaction != NULL);
|
||||
res = SetOneFactionReputation(targetFaction, sharedStanding, incremental);
|
||||
}
|
||||
break;
|
||||
default: // -1 Default case, 1 faction
|
||||
return SetOneFactionReputation(factionEntry, standing, incremental);
|
||||
break;
|
||||
return res;
|
||||
}
|
||||
else
|
||||
{
|
||||
// update for the actual faction first
|
||||
bool res = SetOneFactionReputation(factionEntry, standing, incremental);
|
||||
|
||||
return (SetOneFactionReputation(factionEntry, standing, incremental) && res);
|
||||
if (res)
|
||||
{
|
||||
// then some spillover calculation here if it exist
|
||||
if (const RepSpilloverTemplate *repTemplate = objmgr.GetRepSpilloverTemplate(factionEntry->ID))
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// now we can send it
|
||||
FactionStateList::iterator itr = m_factions.find(factionEntry->reputationListID);
|
||||
if (itr != m_factions.end())
|
||||
SendState(&itr->second);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user