aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp45
-rw-r--r--src/server/game/Achievements/AchievementMgr.h4
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp22
-rw-r--r--src/server/game/Scripting/ScriptMgr.h17
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/scripts/World/achievement_scripts.cpp29
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();
}