Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "ScriptPCH.h"
- #include "DatabaseEnv.h"
- #include "Util.h"
- #include "World.h"
- #include "ObjectMgr.h"
- #include <unordered_map>
- #include <memory>
- #include <boost/any.hpp>
- #include <functional>
- constexpr bool LoadNonFreeSpells = true;
- namespace LevelUpActions
- {
- const std::unordered_map<uint32, std::array<uint32, 2>> trainers =
- {
- {CLASS_WARRIOR, {26332, 26332}},
- {CLASS_PALADIN, {20406, 20406}},
- {CLASS_DRUID, {26324, 12042}},
- {CLASS_MAGE, {26326, 28956}},
- {CLASS_WARLOCK, {23534, 16266}},
- {CLASS_PRIEST, {16660, 17510}},
- {CLASS_HUNTER, {17505, 16673}},
- {CLASS_ROGUE, {26329, 26329}},
- {CLASS_SHAMAN, {17520, 17520}},
- {CLASS_DEATH_KNIGHT, {31084, 31084}}
- };
- enum class ActionType : uint16
- {
- LearnSpell = 1,
- LearnAllSpells,
- ApplyAura,
- ModifyMoney,
- AddItem
- };
- class Action
- {
- public:
- virtual void Process(Player*) = 0;
- virtual ~Action() {};
- };
- namespace detail
- {
- template <typename D>
- class Action_Impl : public Action
- {
- public:
- Action_Impl(std::vector<boost::any>&& params) : params(params) {}
- void Process(Player* player)
- {
- static_cast<D*>(this)->Process(player);
- }
- protected:
- std::vector<boost::any> params;
- };
- #define DEFINE_TAG(x) \
- struct x {} x##_;
- DEFINE_TAG(float_tag);
- DEFINE_TAG(int32_tag);
- DEFINE_TAG(uint32_tag);
- DEFINE_TAG(vector_uint32_tag);
- #define EXTRACT_F(x) void ExtractOne(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i, x)
- EXTRACT_F(float_tag)
- {
- v.push_back(boost::any{ std::stof(tok[i]) });
- }
- EXTRACT_F(int32_tag)
- {
- v.push_back(boost::any{ std::stoi(tok[i]) });
- }
- EXTRACT_F(uint32_tag)
- {
- auto res = std::stoi(tok[i]);
- if (res < 0)
- res = 0;
- v.push_back(boost::any{ static_cast<uint32>(res) });
- }
- EXTRACT_F(vector_uint32_tag)
- {
- std::vector<uint32> vec;
- for (uint32 k = i; k < tok.size(); ++k, ++i)
- {
- vec.push_back(std::stoi(tok[k]));
- }
- v.push_back(boost::any{ vec });
- }
- template <typename Type, typename... Types>
- void Extract(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i, Type type, Types... types)
- {
- ExtractOne(v, tok, i++, type);
- Extract(v, tok, i, types...);
- }
- template <typename... Types>
- void Extract(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i) {}
- template <typename... Types>
- std::vector<boost::any> ExtractTypes(std::string params, std::size_t i, Types... types)
- {
- Tokenizer tokenizer{ params, ' ' };
- std::vector<boost::any> ret;
- if(tokenizer.size())
- Extract<Types...>(ret, tokenizer, 0, types...);
- return ret;
- }
- }
- #define CLASS_IMPL(x) class x : public detail::Action_Impl<x>
- CLASS_IMPL(LearnSpellAction)
- {
- public:
- using Action_Impl::Action_Impl;
- void Process(Player* player)
- {
- uint32 spellId = boost::any_cast<uint32>(params[0]);
- if (!player->HasSpell(spellId))
- player->LearnSpell(spellId, false);
- }
- };
- CLASS_IMPL(LearnAllSpellsAction)
- {
- public:
- using Action_Impl::Action_Impl;
- void Process(Player* player)
- {
- auto itr = trainers.find(player->getClass());
- if(itr != trainers.end())
- {
- for (const auto& trainerId : itr->second)
- {
- auto spells = sObjectMgr->GetNpcTrainerSpells(trainerId);
- if (spells)
- {
- for (const auto& spell : spells->spellList)
- {
- const auto& sp = spell.second;
- if (sp.MoneyCost && !LoadNonFreeSpells)
- continue;
- if (!sp.ReqSkillLine && !sp.ReqSkillRank && sp.ReqLevel <= player->getLevel() && !player->HasSpell(sp.SpellID))
- player->LearnSpell(sp.SpellID, false);
- }
- }
- }
- }
- }
- };
- CLASS_IMPL(ApplyAuraAction)
- {
- public:
- using Action_Impl::Action_Impl;
- void Process(Player* player)
- {
- uint32 spellId = boost::any_cast<uint32>(params[0]);
- player->AddAura(spellId, player);
- }
- };
- CLASS_IMPL(ModifyMoneyAction)
- {
- public:
- using Action_Impl::Action_Impl;
- void Process(Player* player)
- {
- int32 money = boost::any_cast<int32>(params[0]);
- player->ModifyMoney(money);
- }
- };
- CLASS_IMPL(AddItemAction)
- {
- public:
- using Action_Impl::Action_Impl;
- void Process(Player* player)
- {
- uint32 itemId = boost::any_cast<uint32>(params[0]);
- uint32 count = boost::any_cast<uint32>(params[1]);
- player->AddItem(itemId, count);
- }
- };
- const std::unordered_map<ActionType, std::function<std::unique_ptr<Action>(std::string params)>> typeFactory =
- {
- {
- ActionType::LearnSpell, [] (std::string params) {
- auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_);
- return std::unique_ptr<Action>(new LearnSpellAction(std::move(vec))); }
- },
- {
- ActionType::LearnAllSpells, [] (std::string params) {
- auto vec = detail::ExtractTypes(params, 0, detail::vector_uint32_tag_);
- return std::unique_ptr<Action>(new LearnAllSpellsAction(std::move(vec))); }
- },
- {
- ActionType::ApplyAura, [] (std::string params) {
- auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_);
- return std::unique_ptr<Action>(new ApplyAuraAction(std::move(vec))); }
- },
- {
- ActionType::ModifyMoney, [] (std::string params) {
- auto vec = detail::ExtractTypes(params, 0, detail::int32_tag_);
- return std::unique_ptr<Action>(new ModifyMoneyAction(std::move(vec))); }
- },
- {
- ActionType::AddItem, [] (std::string params) {
- auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_, detail::uint32_tag_);
- return std::unique_ptr<Action>(new AddItemAction(std::move(vec))); }
- }
- };
- std::unordered_multimap<int32, std::unique_ptr<Action>> actionHolder;
- class OnLevelupActions : public PlayerScript
- {
- public:
- OnLevelupActions() : PlayerScript("OnLevelupSpells") {}
- void OnLevelChanged(Player* player, uint8 oldLevel) override
- {
- int32 newLevel = player->getLevel();
- auto levelPairItr = actionHolder.equal_range(newLevel);
- auto autoPairItr = actionHolder.equal_range(-1);
- if (levelPairItr.first != levelPairItr.second)
- {
- while (levelPairItr.first != levelPairItr.second)
- {
- levelPairItr.first->second->Process(player);
- ++levelPairItr.first;
- }
- }
- if (autoPairItr.first != autoPairItr.second)
- {
- while (autoPairItr.first != autoPairItr.second)
- {
- autoPairItr.first->second->Process(player);
- ++autoPairItr.first;
- }
- }
- }
- };
- class LoadActions : public WorldScript
- {
- public:
- LoadActions() : WorldScript("LoadActionsLevelup") {}
- void OnStartup() override
- {
- const auto actionResult = WorldDatabase.Query("SELECT `Level`, `Action`, `Params` FROM `levelup_actions`");
- if (!actionResult)
- return;
- do {
- Field* fields = actionResult->Fetch();
- int32 level = fields[0].GetInt32();
- uint32 action = fields[1].GetUInt32();
- std::string params = fields[2].GetString();
- auto itr = typeFactory.find(static_cast<ActionType>(action));
- if (itr != typeFactory.end())
- actionHolder.insert({ level, itr->second(params) });
- } while (actionResult->NextRow());
- }
- };
- }
- void AddSC_LevelUpActions()
- {
- new LevelUpActions::OnLevelupActions;
- new LevelUpActions::LoadActions;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement