diff --git a/sql/updates/world/4.3.4/custom_2017_12_19_04_world.sql b/sql/updates/world/4.3.4/custom_2017_12_19_04_world.sql new file mode 100644 index 00000000000..7e3079adcff --- /dev/null +++ b/sql/updates/world/4.3.4/custom_2017_12_19_04_world.sql @@ -0,0 +1,11 @@ +UPDATE `command` SET +`name`= "reload creature_onkill_reward", +`help`= "Syntax: .reload creature_onkill_reward \nReload creature_onkill_reward table." WHERE `permission`= 635; + +ALTER TABLE `creature_onkill_reputation` ADD COLUMN `CurrencyId1` MEDIUMINT(8) DEFAULT 0 NULL AFTER `TeamDependent`, +ADD COLUMN `CurrencyId2` MEDIUMINT(8) DEFAULT 0 NULL AFTER `CurrencyId1`, +ADD COLUMN `CurrencyId3` MEDIUMINT(8) DEFAULT 0 NULL AFTER `CurrencyId2`, +ADD COLUMN `CurrencyCount1` MEDIUMINT(8) DEFAULT 0 NULL AFTER `CurrencyId3`, +ADD COLUMN `CurrencyCount2` MEDIUMINT(8) DEFAULT 0 NULL AFTER `CurrencyCount1`, +ADD COLUMN `CurrencyCount3` MEDIUMINT(8) DEFAULT 0 NULL AFTER `CurrencyCount2`; +RENAME TABLE`creature_onkill_reputation` TO `creature_onkill_reward`; diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index c4b49321796..d18caf838a2 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -539,7 +539,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_MUTEHISTORY = 632, RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN = 633, RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE = 634, - RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION = 635, + RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REWARD = 635, RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER = 636, RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER = 637, RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS = 638, diff --git a/src/server/game/Entities/Player/KillRewarder.cpp b/src/server/game/Entities/Player/KillRewarder.cpp index 773319728eb..82791382b42 100644 --- a/src/server/game/Entities/Player/KillRewarder.cpp +++ b/src/server/game/Entities/Player/KillRewarder.cpp @@ -163,11 +163,11 @@ inline void KillRewarder::_RewardXP(Player* player, float rate) } } -inline void KillRewarder::_RewardReputation(Player* player, float rate) +inline void KillRewarder::_RewardOnKill(Player* player, float rate) { - // 4.3. Give reputation (player must not be on BG). + // 4.3. Give reputation and currency (player must not be on BG). // Even dead players and corpses are rewarded. - player->RewardReputation(_victim, rate); + player->RewardOnKill(_victim, rate); } inline void KillRewarder::_RewardKillCredit(Player* player) @@ -204,8 +204,8 @@ void KillRewarder::_RewardPlayer(Player* player, bool isDungeon) _RewardXP(player, rate); if (!_isBattleGround) { - // If killer is in dungeon then all members receive full reputation at kill. - _RewardReputation(player, isDungeon ? 1.0f : rate); + // If killer is in dungeon then all members receive full reward at kill. + _RewardOnKill(player, isDungeon ? 1.0f : rate); _RewardKillCredit(player); } } diff --git a/src/server/game/Entities/Player/KillRewarder.h b/src/server/game/Entities/Player/KillRewarder.h index a67014a2403..e441f50462d 100644 --- a/src/server/game/Entities/Player/KillRewarder.h +++ b/src/server/game/Entities/Player/KillRewarder.h @@ -37,7 +37,7 @@ private: void _RewardHonor(Player* player); void _RewardXP(Player* player, float rate); - void _RewardReputation(Player* player, float rate); + void _RewardOnKill(Player* player, float rate); void _RewardKillCredit(Player* player); void _RewardPlayer(Player* player, bool isDungeon); void _RewardGroup(); diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index e818a48ab06..12ae46684cf 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -6618,8 +6618,8 @@ int32 Player::CalculateReputationGain(ReputationSource source, uint32 creatureOr return CalculatePct(rep, percent); } -// Calculates how many reputation points player gains in victim's enemy factions -void Player::RewardReputation(Unit* victim, float rate) +// Calculates how many reputation and currency the player gets uppon killing an creature +void Player::RewardOnKill(Unit* victim, float rate) { if (!victim || victim->GetTypeId() == TYPEID_PLAYER) return; @@ -6627,8 +6627,9 @@ void Player::RewardReputation(Unit* victim, float rate) if (victim->ToCreature()->IsReputationGainDisabled()) return; - ReputationOnKillEntry const* Rep = sObjectMgr->GetReputationOnKilEntry(victim->ToCreature()->GetCreatureTemplate()->Entry); - if (!Rep) + RewardOnKillEntry const* Rew = sObjectMgr->GetRewardOnKillEntry(victim->GetEntry()); + + if (!Rew) return; uint32 ChampioningFaction = 0; @@ -6639,32 +6640,53 @@ void Player::RewardReputation(Unit* victim, float rate) Map const* map = GetMap(); if (map->IsNonRaidDungeon()) if (LFGDungeonEntry const* dungeon = GetLFGDungeon(map->GetId(), map->GetDifficulty())) - if (dungeon->reclevel == 80) + if (dungeon->reclevel == GetMaxLevelForExpansion(dungeon->expansion)) ChampioningFaction = GetChampioningFaction(); } uint32 team = GetTeam(); - if (Rep->RepFaction1 && (!Rep->TeamDependent || team == ALLIANCE)) + if (Rew->RepFaction1 && (!Rew->TeamDependent || team == ALLIANCE)) { - int32 donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue1, ChampioningFaction ? ChampioningFaction : Rep->RepFaction1); + int32 donerep1 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rew->RepValue1, ChampioningFaction ? ChampioningFaction : Rew->RepFaction1); donerep1 = int32(donerep1 * rate); - FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction1); + FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rew->RepFaction1); uint32 current_reputation_rank1 = GetReputationMgr().GetRank(factionEntry1); if (factionEntry1) - GetReputationMgr().ModifyReputation(factionEntry1, donerep1, current_reputation_rank1 > Rep->ReputationMaxCap1); + GetReputationMgr().ModifyReputation(factionEntry1, donerep1, current_reputation_rank1 > Rew->ReputationMaxCap1); } - if (Rep->RepFaction2 && (!Rep->TeamDependent || team == HORDE)) + if (Rew->RepFaction2 && (!Rew->TeamDependent || team == HORDE)) { - int32 donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rep->RepValue2, ChampioningFaction ? ChampioningFaction : Rep->RepFaction2); + int32 donerep2 = CalculateReputationGain(REPUTATION_SOURCE_KILL, victim->getLevel(), Rew->RepValue2, ChampioningFaction ? ChampioningFaction : Rew->RepFaction2); donerep2 = int32(donerep2 * rate); - FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rep->RepFaction2); + FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(ChampioningFaction ? ChampioningFaction : Rew->RepFaction2); uint32 current_reputation_rank2 = GetReputationMgr().GetRank(factionEntry2); if (factionEntry2) - GetReputationMgr().ModifyReputation(factionEntry2, donerep2, current_reputation_rank2 > Rep->ReputationMaxCap2); + GetReputationMgr().ModifyReputation(factionEntry2, donerep2, current_reputation_rank2 > Rew->ReputationMaxCap2); + } + + if (Rew->CurrencyId1 && Rew->CurrencyCount1) + { + CurrencyTypesEntry const* currencyId1 = sCurrencyTypesStore.LookupEntry(Rew->CurrencyId1); + if (!currencyId1) + ModifyCurrency(Rew->CurrencyId1, Rew->CurrencyCount1); + } + + if (Rew->CurrencyId2 && Rew->CurrencyCount2) + { + CurrencyTypesEntry const* currencyId2 = sCurrencyTypesStore.LookupEntry(Rew->CurrencyId2); + if (!currencyId2) + ModifyCurrency(Rew->CurrencyId2, Rew->CurrencyCount2); + } + + if (Rew->CurrencyId3 && Rew->CurrencyCount3) + { + CurrencyTypesEntry const* currencyId3 = sCurrencyTypesStore.LookupEntry(Rew->CurrencyId3); + if (!currencyId3) + ModifyCurrency(Rew->CurrencyId3, Rew->CurrencyCount3); } } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index ea47b62bd82..295f79d403c 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -2132,7 +2132,7 @@ class TC_GAME_API Player : public Unit, public GridObject ReputationMgr& GetReputationMgr() { return *m_reputationMgr; } ReputationMgr const& GetReputationMgr() const { return *m_reputationMgr; } ReputationRank GetReputationRank(uint32 faction_id) const; - void RewardReputation(Unit* victim, float rate); + void RewardOnKill(Unit* victim, float rate); void RewardReputation(Quest const* quest); int32 CalculateReputationGain(ReputationSource source, uint32 creatureOrQuestLevel, int32 rep, int32 faction, bool noQuestBonus = false); diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp index 5a5192107b4..1c482facb97 100644 --- a/src/server/game/Globals/ObjectMgr.cpp +++ b/src/server/game/Globals/ObjectMgr.cpp @@ -7328,24 +7328,26 @@ void ObjectMgr::LoadReputationRewardRate() TC_LOG_INFO("server.loading", ">> Loaded %u reputation_reward_rate in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void ObjectMgr::LoadReputationOnKill() +void ObjectMgr::LoadRewardOnKill() { uint32 oldMSTime = getMSTime(); // For reload case - _repOnKillStore.clear(); + _rewOnKillStore.clear(); uint32 count = 0; // 0 1 2 QueryResult result = WorldDatabase.Query("SELECT creature_id, RewOnKillRepFaction1, RewOnKillRepFaction2, " // 3 4 5 6 7 8 9 - "IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent " - "FROM creature_onkill_reputation"); + "IsTeamAward1, MaxStanding1, RewOnKillRepValue1, IsTeamAward2, MaxStanding2, RewOnKillRepValue2, TeamDependent, " + // 10 11 12 13 14 15 + "CurrencyId1, CurrencyId2, CurrencyId3, CurrencyCount1, CurrencyCount2, CurrencyCount3 " + "FROM creature_onkill_reward"); if (!result) { - TC_LOG_ERROR("server.loading", ">> Loaded 0 creature award reputation definitions. DB table `creature_onkill_reputation` is empty."); + TC_LOG_ERROR("server.loading", ">> Loaded 0 creature reward definitions. DB table `creature_onkill_reputation` is empty."); return; } @@ -7355,44 +7357,80 @@ void ObjectMgr::LoadReputationOnKill() uint32 creature_id = fields[0].GetUInt32(); - ReputationOnKillEntry repOnKill; - repOnKill.RepFaction1 = fields[1].GetInt16(); - repOnKill.RepFaction2 = fields[2].GetInt16(); - repOnKill.IsTeamAward1 = fields[3].GetBool(); - repOnKill.ReputationMaxCap1 = fields[4].GetUInt8(); - repOnKill.RepValue1 = fields[5].GetInt32(); - repOnKill.IsTeamAward2 = fields[6].GetBool(); - repOnKill.ReputationMaxCap2 = fields[7].GetUInt8(); - repOnKill.RepValue2 = fields[8].GetInt32(); - repOnKill.TeamDependent = fields[9].GetBool(); + RewardOnKillEntry rewOnKill; + rewOnKill.RepFaction1 = fields[1].GetUInt32(); + rewOnKill.RepFaction2 = fields[2].GetUInt32(); + rewOnKill.IsTeamAward1 = fields[3].GetBool(); + rewOnKill.ReputationMaxCap1 = fields[4].GetUInt32(); + rewOnKill.RepValue1 = fields[5].GetInt32(); + rewOnKill.IsTeamAward2 = fields[6].GetBool(); + rewOnKill.ReputationMaxCap2 = fields[7].GetUInt32(); + rewOnKill.RepValue2 = fields[8].GetInt32(); + rewOnKill.TeamDependent = fields[9].GetUInt8(); + rewOnKill.CurrencyId1 = fields[10].GetUInt32(); + rewOnKill.CurrencyId2 = fields[11].GetUInt32(); + rewOnKill.CurrencyId3 = fields[12].GetUInt32(); + rewOnKill.CurrencyCount1 = fields[13].GetInt32(); + rewOnKill.CurrencyCount2 = fields[14].GetInt32(); + rewOnKill.CurrencyCount3 = fields[15].GetInt32(); if (!GetCreatureTemplate(creature_id)) { - TC_LOG_ERROR("sql.sql", "Table `creature_onkill_reputation` has data for nonexistent creature entry (%u), skipped", creature_id); + TC_LOG_ERROR("sql.sql", "Table `creature_onkill_reward` has data for nonexistent creature entry (%u), skipped", creature_id); continue; } - if (repOnKill.RepFaction1) + if (rewOnKill.RepFaction1) { - FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(repOnKill.RepFaction1); + FactionEntry const* factionEntry1 = sFactionStore.LookupEntry(rewOnKill.RepFaction1); if (!factionEntry1) { - TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.RepFaction1); + TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", rewOnKill.RepFaction1); continue; } } - if (repOnKill.RepFaction2) + if (rewOnKill.RepFaction2) { - FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(repOnKill.RepFaction2); + FactionEntry const* factionEntry2 = sFactionStore.LookupEntry(rewOnKill.RepFaction2); if (!factionEntry2) { - TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", repOnKill.RepFaction2); + TC_LOG_ERROR("sql.sql", "Faction (faction.dbc) %u does not exist but is used in `creature_onkill_reputation`", rewOnKill.RepFaction2); continue; } } - _repOnKillStore[creature_id] = repOnKill; + if (rewOnKill.CurrencyId1) + { + CurrencyTypesEntry const* currencyId1 = sCurrencyTypesStore.LookupEntry(rewOnKill.CurrencyId1); + if (!currencyId1) + { + TC_LOG_ERROR("sql.sql", "CurrencyType (CurrenctTypes.dbc) %u does not exist but is used in `creature_onkill_reward`", rewOnKill.CurrencyId1); + continue; + } + } + + if (rewOnKill.CurrencyId2) + { + CurrencyTypesEntry const* currencyId2 = sCurrencyTypesStore.LookupEntry(rewOnKill.CurrencyId2); + if (!currencyId2) + { + TC_LOG_ERROR("sql.sql", "CurrencyType (CurrenctTypes.dbc) %u does not exist but is used in `creature_onkill_reward`", rewOnKill.CurrencyId2); + continue; + } + } + + if (rewOnKill.CurrencyId3) + { + CurrencyTypesEntry const* currencyId3 = sCurrencyTypesStore.LookupEntry(rewOnKill.CurrencyId3); + if (!currencyId3) + { + TC_LOG_ERROR("sql.sql", "CurrencyType (CurrenctTypes.dbc) %u does not exist but is used in `creature_onkill_reward`", rewOnKill.CurrencyId3); + continue; + } + } + + _rewOnKillStore[creature_id] = rewOnKill; ++count; } while (result->NextRow()); diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h index 307e5b9d11f..3459db6eed4 100644 --- a/src/server/game/Globals/ObjectMgr.h +++ b/src/server/game/Globals/ObjectMgr.h @@ -536,7 +536,7 @@ struct RepRewardRate float spellRate; }; -struct ReputationOnKillEntry +struct RewardOnKillEntry { uint32 RepFaction1; uint32 RepFaction2; @@ -547,6 +547,12 @@ struct ReputationOnKillEntry bool IsTeamAward1; bool IsTeamAward2; bool TeamDependent; + uint32 CurrencyId1; + uint32 CurrencyId2; + uint32 CurrencyId3; + int32 CurrencyCount1; + int32 CurrencyCount2; + int32 CurrencyCount3; }; struct RepSpilloverTemplate @@ -750,7 +756,7 @@ class TC_GAME_API ObjectMgr typedef std::unordered_map AccessRequirementContainer; typedef std::unordered_map RepRewardRateContainer; - typedef std::unordered_map RepOnKillContainer; + typedef std::unordered_map RewOnKillContainer; typedef std::unordered_map RepSpilloverTemplateContainer; typedef std::unordered_map PointOfInterestContainer; @@ -880,10 +886,10 @@ class TC_GAME_API ObjectMgr return nullptr; } - ReputationOnKillEntry const* GetReputationOnKilEntry(uint32 id) const + RewardOnKillEntry const* GetRewardOnKillEntry(uint32 id) const { - RepOnKillContainer::const_iterator itr = _repOnKillStore.find(id); - if (itr != _repOnKillStore.end()) + RewOnKillContainer::const_iterator itr = _rewOnKillStore.find(id); + if (itr != _rewOnKillStore.end()) return &itr->second; return nullptr; } @@ -1049,7 +1055,7 @@ class TC_GAME_API ObjectMgr void LoadFishingBaseSkillLevel(); void LoadReputationRewardRate(); - void LoadReputationOnKill(); + void LoadRewardOnKill(); void LoadReputationSpilloverTemplate(); void LoadPointsOfInterest(); @@ -1450,7 +1456,7 @@ class TC_GAME_API ObjectMgr DungeonEncounterContainer _dungeonEncounterStore; RepRewardRateContainer _repRewardRateStore; - RepOnKillContainer _repOnKillStore; + RewOnKillContainer _rewOnKillStore; RepSpilloverTemplateContainer _repSpilloverTemplateStore; GossipMenusContainer _gossipMenusStore; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 544b5555f26..7215f3842a4 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1671,8 +1671,8 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Reputation Reward Rates..."); sObjectMgr->LoadReputationRewardRate(); - TC_LOG_INFO("server.loading", "Loading Creature Reputation OnKill Data..."); - sObjectMgr->LoadReputationOnKill(); + TC_LOG_INFO("server.loading", "Loading Creature Reward OnKill Data..."); + sObjectMgr->LoadRewardOnKill(); TC_LOG_INFO("server.loading", "Loading Reputation Spillover Data..."); sObjectMgr->LoadReputationSpilloverTemplate(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 72e7f986d4a..e32149a6861 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -83,7 +83,7 @@ public: { "creature_questender", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTENDER, true, &HandleReloadCreatureQuestEnderCommand, "" }, { "creature_linked_respawn", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LINKED_RESPAWN, true, &HandleReloadLinkedRespawnCommand, "" }, { "creature_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesCreatureCommand, "" }, - { "creature_onkill_reputation", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REPUTATION, true, &HandleReloadOnKillReputationCommand, "" }, + { "creature_onkill_reward", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_ONKILL_REWARD, true, &HandleReloadOnKillRewardCommand, "" }, { "creature_queststarter", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_QUESTSTARTER, true, &HandleReloadCreatureQuestStarterCommand, "" }, { "creature_summon_groups", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_SUMMON_GROUPS, true, &HandleReloadCreatureSummonGroupsCommand, "" }, { "creature_template", rbac::RBAC_PERM_COMMAND_RELOAD_CREATURE_TEMPLATE, true, &HandleReloadCreatureTemplateCommand, "" }, @@ -398,11 +398,11 @@ public: return true; } - static bool HandleReloadOnKillReputationCommand(ChatHandler* handler, const char* /*args*/) + static bool HandleReloadOnKillRewardCommand(ChatHandler* handler, const char* /*args*/) { TC_LOG_INFO("misc", "Re-Loading creature award reputation definitions..."); - sObjectMgr->LoadReputationOnKill(); - handler->SendGlobalGMSysMessage("DB table `creature_onkill_reputation` reloaded."); + sObjectMgr->LoadRewardOnKill(); + handler->SendGlobalGMSysMessage("DB table `creature_onkill_reward` reloaded."); return true; }