diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Achievements/AchievementMgr.cpp | 45 | ||||
-rw-r--r-- | src/server/game/Achievements/AchievementMgr.h | 4 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.cpp | 22 | ||||
-rw-r--r-- | src/server/game/Scripting/ScriptMgr.h | 17 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 2 | ||||
-rw-r--r-- | src/server/scripts/World/achievement_scripts.cpp | 29 |
6 files changed, 119 insertions, 0 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 2444511cafc..68d84b2d9e8 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -34,6 +34,7 @@ #include "ObjectMgr.h" #include "RBAC.h" #include "StringConvert.h" +#include "ScriptMgr.h" #include "World.h" #include "WorldSession.h" #include <sstream> @@ -535,6 +536,8 @@ void PlayerAchievementMgr::CompletedAchievement(AchievementEntry const* achievem UpdateCriteria(CriteriaType::EarnAchievement, achievement->ID, 0, 0, nullptr, referencePlayer); UpdateCriteria(CriteriaType::EarnAchievementPoints, achievement->Points, 0, 0, nullptr, referencePlayer); + sScriptMgr->OnAchievementCompleted(referencePlayer, achievement); + // reward items and titles if any AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement); @@ -985,6 +988,8 @@ void GuildAchievementMgr::CompletedAchievement(AchievementEntry const* achieveme UpdateCriteria(CriteriaType::EarnAchievement, achievement->ID, 0, 0, nullptr, referencePlayer); UpdateCriteria(CriteriaType::EarnAchievementPoints, achievement->Points, 0, 0, nullptr, referencePlayer); + + sScriptMgr->OnAchievementCompleted(referencePlayer, achievement); } void GuildAchievementMgr::SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, Seconds /*timeElapsed*/, bool /*timedCompleted*/) const @@ -1140,6 +1145,39 @@ void AchievementGlobalMgr::LoadAchievementReferenceList() TC_LOG_INFO("server.loading", ">> Loaded %u achievement references in %u ms.", count, GetMSTimeDiffToNow(oldMSTime)); } +void AchievementGlobalMgr::LoadAchievementScripts() +{ + uint32 oldMSTime = getMSTime(); + + _achievementScripts.clear(); // need for reload case + + QueryResult result = WorldDatabase.Query("SELECT AchievementId, ScriptName FROM achievement_scripts"); + if (!result) + { + TC_LOG_INFO("server.loading", ">> Loaded 0 achievement scripts. DB table `achievement_scripts` is empty."); + return; + } + + do + { + Field* fields = result->Fetch(); + + uint32 achievementId = fields[0].GetUInt32(); + std::string scriptName = fields[1].GetString(); + + AchievementEntry const* achievement = sAchievementStore.LookupEntry(achievementId); + if (!achievement) + { + TC_LOG_ERROR("sql.sql", "Table `achievement_scripts` contains non-existing Achievement (ID: %u), skipped.", achievementId); + continue; + } + _achievementScripts[achievementId] = sObjectMgr->GetScriptId(scriptName); + } + while (result->NextRow()); + + TC_LOG_INFO("server.loading", ">> Loaded " SZFMTD " achievement scripts in %u ms", _achievementScripts.size(), GetMSTimeDiffToNow(oldMSTime)); +} + void AchievementGlobalMgr::LoadCompletedAchievements() { uint32 oldMSTime = getMSTime(); @@ -1338,3 +1376,10 @@ void AchievementGlobalMgr::LoadRewardLocales() TC_LOG_INFO("server.loading", ">> Loaded %u achievement reward locale strings in %u ms.", uint32(_achievementRewardLocales.size()), GetMSTimeDiffToNow(oldMSTime)); } + +uint32 AchievementGlobalMgr::GetAchievementScriptId(uint32 achievementId) const +{ + if (uint32 const* scriptId = Trinity::Containers::MapGetValuePtr(_achievementScripts, achievementId)) + return *scriptId; + return 0; +} diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index cb3a63f6803..f18194c0eee 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -160,10 +160,13 @@ public: void SetRealmCompleted(AchievementEntry const* achievement); void LoadAchievementReferenceList(); + void LoadAchievementScripts(); void LoadCompletedAchievements(); void LoadRewards(); void LoadRewardLocales(); + uint32 GetAchievementScriptId(uint32 achievementId) const; + private: // store achievements by referenced achievement id to speed up lookup std::unordered_map<uint32, std::vector<AchievementEntry const*>> _achievementListByReferencedId; @@ -175,6 +178,7 @@ private: std::unordered_map<uint32, AchievementReward> _achievementRewards; std::unordered_map<uint32, AchievementRewardLocale> _achievementRewardLocales; + std::unordered_map<uint32, uint32> _achievementScripts; }; #define sAchievementMgr AchievementGlobalMgr::Instance() diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp index 0943147095d..a439949cd26 100644 --- a/src/server/game/Scripting/ScriptMgr.cpp +++ b/src/server/game/Scripting/ScriptMgr.cpp @@ -16,6 +16,7 @@ */ #include "ScriptMgr.h" +#include "AchievementMgr.h" #include "AreaTrigger.h" #include "AreaTriggerAI.h" #include "Chat.h" @@ -109,6 +110,10 @@ struct is_script_database_bound<TransportScript> : std::true_type { }; template<> +struct is_script_database_bound<AchievementScript> + : std::true_type { }; + +template<> struct is_script_database_bound<AchievementCriteriaScript> : std::true_type { }; @@ -1938,6 +1943,16 @@ void ScriptMgr::OnShutdown() FOREACH_SCRIPT(WorldScript)->OnShutdown(); } +// Achievement +void ScriptMgr::OnAchievementCompleted(Player* player, AchievementEntry const* achievement) +{ + ASSERT(player); + ASSERT(achievement); + + GET_SCRIPT(AchievementScript, sAchievementMgr->GetAchievementScriptId(achievement->ID), tmpscript); + tmpscript->OnCompleted(player, achievement); +} + bool ScriptMgr::OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target) { ASSERT(source); @@ -2511,6 +2526,12 @@ TransportScript::TransportScript(char const* name) ScriptRegistry<TransportScript>::Instance()->AddScript(this); } +AchievementScript::AchievementScript(char const* name) + : ScriptObject(name) +{ + ScriptRegistry<AchievementScript>::Instance()->AddScript(this); +} + AchievementCriteriaScript::AchievementCriteriaScript(char const* name) : ScriptObject(name) { @@ -2587,6 +2608,7 @@ template class TC_GAME_API ScriptRegistry<ConditionScript>; template class TC_GAME_API ScriptRegistry<VehicleScript>; template class TC_GAME_API ScriptRegistry<DynamicObjectScript>; template class TC_GAME_API ScriptRegistry<TransportScript>; +template class TC_GAME_API ScriptRegistry<AchievementScript>; template class TC_GAME_API ScriptRegistry<AchievementCriteriaScript>; template class TC_GAME_API ScriptRegistry<PlayerScript>; template class TC_GAME_API ScriptRegistry<GuildScript>; diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h index 3c343d32650..7aae463cd86 100644 --- a/src/server/game/Scripting/ScriptMgr.h +++ b/src/server/game/Scripting/ScriptMgr.h @@ -66,6 +66,7 @@ class WorldSocket; class WorldObject; class WorldSession; +struct AchievementEntry; struct AreaTriggerEntry; struct AuctionPosting; struct ConditionSourceInfo; @@ -622,6 +623,18 @@ class TC_GAME_API TransportScript : public ScriptObject, public UpdatableScript< virtual void OnRelocate(Transport* /*transport*/, uint32 /*waypointId*/, uint32 /*mapId*/, float /*x*/, float /*y*/, float /*z*/) { } }; +class TC_GAME_API AchievementScript : public ScriptObject +{ + protected: + + AchievementScript(char const* name); + + public: + + // Called when an achievement is completed. + virtual void OnCompleted(Player* /*player*/, AchievementEntry const* /*achievement*/) { } +}; + class TC_GAME_API AchievementCriteriaScript : public ScriptObject { protected: @@ -1085,6 +1098,10 @@ class TC_GAME_API ScriptMgr void OnTransportUpdate(Transport* transport, uint32 diff); void OnRelocate(Transport* transport, uint32 waypointId, uint32 mapId, float x, float y, float z); + public: /* AchievementScript */ + + void OnAchievementCompleted(Player* player, AchievementEntry const* achievement); + public: /* AchievementCriteriaScript */ bool OnCriteriaCheck(uint32 scriptId, Player* source, Unit* target); diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 0fc8edc74e4..bbc979e7403 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -2149,6 +2149,8 @@ void World::SetInitialWorldSettings() sCriteriaMgr->LoadCriteriaData(); TC_LOG_INFO("server.loading", "Loading Achievements..."); sAchievementMgr->LoadAchievementReferenceList(); + TC_LOG_INFO("server.loading", "Loading Achievements Scripts..."); + sAchievementMgr->LoadAchievementScripts(); TC_LOG_INFO("server.loading", "Loading Achievement Rewards..."); sAchievementMgr->LoadRewards(); TC_LOG_INFO("server.loading", "Loading Achievement Reward Locales..."); diff --git a/src/server/scripts/World/achievement_scripts.cpp b/src/server/scripts/World/achievement_scripts.cpp index 62a7621db79..30364ac5fe6 100644 --- a/src/server/scripts/World/achievement_scripts.cpp +++ b/src/server/scripts/World/achievement_scripts.cpp @@ -18,8 +18,10 @@ #include "ScriptMgr.h" #include "BattlegroundSA.h" #include "BattlegroundIC.h" +#include "BattlePetMgr.h" #include "Creature.h" #include "Player.h" +#include "WorldSession.h" class achievement_resilient_victory : public AchievementCriteriaScript { @@ -289,6 +291,31 @@ class achievement_killed_exp_or_honor_target : public AchievementCriteriaScript } }; +// 7433 - Newbie +class achievement_newbie : public AchievementScript +{ +public: + achievement_newbie() : AchievementScript("achievement_newbie") { } + + void OnCompleted(Player* player, AchievementEntry const* /*achievement*/) override + { + player->GetSession()->GetBattlePetMgr()->UnlockSlot(BattlePets::BattlePetSlot::Slot1); + // TODO: Unlock trap + } +}; + +// 6566 - Just a Pup +class achievement_just_a_pup : public AchievementScript +{ +public: + achievement_just_a_pup() : AchievementScript("achievement_just_a_pup") { } + + void OnCompleted(Player* player, AchievementEntry const* /*achievement*/) override + { + player->GetSession()->GetBattlePetMgr()->UnlockSlot(BattlePets::BattlePetSlot::Slot2); + } +}; + void AddSC_achievement_scripts() { new achievement_resilient_victory(); @@ -309,4 +336,6 @@ void AddSC_achievement_scripts() new achievement_not_even_a_scratch(); new achievement_flirt_with_disaster_perf_check(); new achievement_killed_exp_or_honor_target(); + new achievement_newbie(); + new achievement_just_a_pup(); } |