Advertisement
xingchao

OnLevelupSpells

Dec 14th, 2019
139
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include "ScriptPCH.h"
  2. #include "DatabaseEnv.h"
  3. #include "Util.h"
  4. #include "World.h"
  5. #include "ObjectMgr.h"
  6.  
  7. #include <unordered_map>
  8. #include <memory>
  9. #include <boost/any.hpp>
  10. #include <functional>
  11.  
  12.  
  13. constexpr bool LoadNonFreeSpells = true;
  14.  
  15. namespace LevelUpActions
  16. {
  17.     const std::unordered_map<uint32, std::array<uint32, 2>> trainers =
  18.     {
  19.         {CLASS_WARRIOR, {26332, 26332}},
  20.         {CLASS_PALADIN, {20406, 20406}},
  21.         {CLASS_DRUID, {26324, 12042}},
  22.         {CLASS_MAGE, {26326, 28956}},
  23.         {CLASS_WARLOCK, {23534, 16266}},
  24.         {CLASS_PRIEST, {16660, 17510}},
  25.         {CLASS_HUNTER, {17505, 16673}},
  26.         {CLASS_ROGUE, {26329, 26329}},
  27.         {CLASS_SHAMAN, {17520, 17520}},
  28.         {CLASS_DEATH_KNIGHT, {31084, 31084}}
  29.     };
  30.  
  31.  
  32.     enum class ActionType : uint16
  33.     {
  34.         LearnSpell = 1,
  35.         LearnAllSpells,
  36.         ApplyAura,
  37.         ModifyMoney,
  38.         AddItem
  39.     };
  40.  
  41.  
  42.     class Action
  43.     {
  44.     public:
  45.         virtual void Process(Player*) = 0;
  46.         virtual ~Action() {};
  47.     };
  48.  
  49.     namespace detail
  50.     {
  51.  
  52.  
  53.         template <typename D>
  54.         class Action_Impl : public Action
  55.         {
  56.         public:
  57.             Action_Impl(std::vector<boost::any>&& params) : params(params) {}
  58.  
  59.             void Process(Player* player)
  60.             {
  61.                 static_cast<D*>(this)->Process(player);
  62.             }
  63.  
  64.         protected:
  65.             std::vector<boost::any> params;
  66.         };
  67.  
  68.  
  69. #define DEFINE_TAG(x) \
  70.         struct x {} x##_;
  71.  
  72.  
  73.         DEFINE_TAG(float_tag);
  74.         DEFINE_TAG(int32_tag);
  75.         DEFINE_TAG(uint32_tag);
  76.         DEFINE_TAG(vector_uint32_tag);
  77.  
  78.  
  79. #define EXTRACT_F(x) void ExtractOne(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i, x)
  80.  
  81.         EXTRACT_F(float_tag)
  82.         {
  83.             v.push_back(boost::any{ std::stof(tok[i]) });
  84.         }
  85.  
  86.         EXTRACT_F(int32_tag)
  87.         {
  88.             v.push_back(boost::any{ std::stoi(tok[i]) });
  89.         }
  90.  
  91.         EXTRACT_F(uint32_tag)
  92.         {
  93.             auto res = std::stoi(tok[i]);
  94.             if (res < 0)
  95.                 res = 0;
  96.             v.push_back(boost::any{ static_cast<uint32>(res) });
  97.         }
  98.  
  99.         EXTRACT_F(vector_uint32_tag)
  100.         {
  101.             std::vector<uint32> vec;
  102.             for (uint32 k = i; k < tok.size(); ++k, ++i)
  103.             {
  104.                 vec.push_back(std::stoi(tok[k]));
  105.             }
  106.             v.push_back(boost::any{ vec });
  107.         }
  108.  
  109.  
  110.         template <typename Type, typename... Types>
  111.         void Extract(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i, Type type, Types... types)
  112.         {
  113.             ExtractOne(v, tok, i++, type);
  114.             Extract(v, tok, i, types...);
  115.         }
  116.  
  117.         template <typename... Types>
  118.         void Extract(std::vector<boost::any>& v, Tokenizer& tok, std::size_t i) {}
  119.  
  120.  
  121.         template <typename... Types>
  122.         std::vector<boost::any> ExtractTypes(std::string params, std::size_t i, Types... types)
  123.         {
  124.             Tokenizer tokenizer{ params, ' ' };
  125.             std::vector<boost::any> ret;
  126.             if(tokenizer.size())
  127.                 Extract<Types...>(ret, tokenizer, 0, types...);
  128.             return ret;
  129.         }
  130.     }
  131.  
  132. #define CLASS_IMPL(x) class x : public detail::Action_Impl<x>
  133.  
  134.  
  135.     CLASS_IMPL(LearnSpellAction)
  136.     {
  137.     public:
  138.         using Action_Impl::Action_Impl;
  139.  
  140.         void Process(Player* player)
  141.         {
  142.             uint32 spellId = boost::any_cast<uint32>(params[0]);
  143.             if (!player->HasSpell(spellId))
  144.                 player->LearnSpell(spellId, false);
  145.         }
  146.     };
  147.  
  148.     CLASS_IMPL(LearnAllSpellsAction)
  149.     {
  150.     public:
  151.         using Action_Impl::Action_Impl;
  152.  
  153.         void Process(Player* player)
  154.         {
  155.             auto itr = trainers.find(player->getClass());
  156.             if(itr != trainers.end())
  157.             {
  158.                 for (const auto& trainerId : itr->second)
  159.                 {
  160.                     auto spells = sObjectMgr->GetNpcTrainerSpells(trainerId);
  161.                     if (spells)
  162.                     {
  163.                         for (const auto& spell : spells->spellList)
  164.                         {
  165.                             const auto& sp = spell.second;
  166.                             if (sp.MoneyCost && !LoadNonFreeSpells)
  167.                                 continue;
  168.  
  169.                             if (!sp.ReqSkillLine && !sp.ReqSkillRank && sp.ReqLevel <= player->getLevel() && !player->HasSpell(sp.SpellID))
  170.                                 player->LearnSpell(sp.SpellID, false);
  171.                         }
  172.                     }
  173.                 }
  174.             }
  175.         }
  176.     };
  177.  
  178.     CLASS_IMPL(ApplyAuraAction)
  179.     {
  180.     public:
  181.         using Action_Impl::Action_Impl;
  182.  
  183.         void Process(Player* player)
  184.         {
  185.             uint32 spellId = boost::any_cast<uint32>(params[0]);
  186.             player->AddAura(spellId, player);
  187.         }
  188.     };
  189.  
  190.     CLASS_IMPL(ModifyMoneyAction)
  191.     {
  192.     public:
  193.         using Action_Impl::Action_Impl;
  194.  
  195.         void Process(Player* player)
  196.         {
  197.             int32 money = boost::any_cast<int32>(params[0]);
  198.             player->ModifyMoney(money);
  199.         }
  200.     };
  201.  
  202.     CLASS_IMPL(AddItemAction)
  203.     {
  204.     public:
  205.         using Action_Impl::Action_Impl;
  206.  
  207.         void Process(Player* player)
  208.         {
  209.             uint32 itemId = boost::any_cast<uint32>(params[0]);
  210.             uint32 count = boost::any_cast<uint32>(params[1]);
  211.             player->AddItem(itemId, count);
  212.         }
  213.     };
  214.  
  215.     const std::unordered_map<ActionType, std::function<std::unique_ptr<Action>(std::string params)>> typeFactory =
  216.     {
  217.         {
  218.           ActionType::LearnSpell, [] (std::string params) {
  219.             auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_);
  220.             return std::unique_ptr<Action>(new LearnSpellAction(std::move(vec))); }
  221.         },
  222.  
  223.         {
  224.           ActionType::LearnAllSpells, [] (std::string params) {
  225.             auto vec = detail::ExtractTypes(params, 0, detail::vector_uint32_tag_);
  226.             return std::unique_ptr<Action>(new LearnAllSpellsAction(std::move(vec))); }
  227.         },
  228.  
  229.         {
  230.           ActionType::ApplyAura, [] (std::string params) {
  231.             auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_);
  232.             return std::unique_ptr<Action>(new ApplyAuraAction(std::move(vec))); }
  233.         },
  234.  
  235.         {
  236.           ActionType::ModifyMoney, [] (std::string params) {
  237.             auto vec = detail::ExtractTypes(params, 0, detail::int32_tag_);
  238.             return std::unique_ptr<Action>(new ModifyMoneyAction(std::move(vec))); }
  239.         },
  240.  
  241.         {
  242.           ActionType::AddItem, [] (std::string params) {
  243.             auto vec = detail::ExtractTypes(params, 0, detail::uint32_tag_, detail::uint32_tag_);
  244.             return std::unique_ptr<Action>(new AddItemAction(std::move(vec))); }
  245.         }
  246.     };
  247.  
  248.  
  249.  
  250.  
  251.     std::unordered_multimap<int32, std::unique_ptr<Action>> actionHolder;
  252.  
  253.     class OnLevelupActions : public PlayerScript
  254.     {
  255.     public:
  256.         OnLevelupActions() : PlayerScript("OnLevelupSpells") {}
  257.  
  258.         void OnLevelChanged(Player* player, uint8 oldLevel) override
  259.         {
  260.             int32 newLevel = player->getLevel();
  261.             auto levelPairItr = actionHolder.equal_range(newLevel);
  262.             auto autoPairItr = actionHolder.equal_range(-1);
  263.  
  264.             if (levelPairItr.first != levelPairItr.second)
  265.             {
  266.                 while (levelPairItr.first != levelPairItr.second)
  267.                 {
  268.                     levelPairItr.first->second->Process(player);
  269.                     ++levelPairItr.first;
  270.                 }
  271.             }
  272.  
  273.             if (autoPairItr.first != autoPairItr.second)
  274.             {
  275.                 while (autoPairItr.first != autoPairItr.second)
  276.                 {
  277.                     autoPairItr.first->second->Process(player);
  278.                     ++autoPairItr.first;
  279.                 }
  280.             }
  281.         }
  282.     };
  283.  
  284.     class LoadActions : public WorldScript
  285.     {
  286.     public:
  287.         LoadActions() : WorldScript("LoadActionsLevelup") {}
  288.  
  289.  
  290.         void OnStartup() override
  291.         {
  292.             const auto actionResult = WorldDatabase.Query("SELECT `Level`, `Action`, `Params` FROM `levelup_actions`");
  293.  
  294.             if (!actionResult)
  295.                 return;
  296.  
  297.  
  298.             do {
  299.                 Field* fields = actionResult->Fetch();
  300.  
  301.                 int32 level = fields[0].GetInt32();
  302.                 uint32 action = fields[1].GetUInt32();
  303.                 std::string params = fields[2].GetString();
  304.  
  305.  
  306.                 auto itr = typeFactory.find(static_cast<ActionType>(action));
  307.                 if (itr != typeFactory.end())
  308.                     actionHolder.insert({ level, itr->second(params) });
  309.  
  310.             } while (actionResult->NextRow());
  311.         }
  312.  
  313.     };
  314. }
  315.  
  316. void AddSC_LevelUpActions()
  317. {
  318.     new LevelUpActions::OnLevelupActions;
  319.     new LevelUpActions::LoadActions;
  320. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement