Serverlands

TemplateNPC.cpp

Jan 15th, 2022 (edited)
66
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. Full credit goes to Mindsear -> https://www.ac-web.org/forums/member.php?303304-mindsear | https://github.com/mindsear
  3. Original file: https://github.com/mindsear/TemplateNPC/blob/master/TemplateNPC.cpp
  4.  
  5. Updated by Dandi, Discord: Dandi#2828
  6. https://serverlands.com
  7. */
  8.  
  9. #include "TemplateNPC.h"
  10. #include "Item.h"
  11. #include "DBCStores.h"
  12. #include "Log.h"
  13. #include "DatabaseEnv.h"
  14. #include "CharacterDatabase.h"
  15. #include "Player.h"
  16. #include "WorldSession.h"
  17. #include "ScriptedGossip.h"
  18. #include "ScriptMgr.h"
  19. #include "ScriptedCreature.h"
  20. #include "GossipDef.h"
  21. #include "Creature.h"
  22. #include "ObjectMgr.h"
  23. #include "Chat.h"
  24. #include "ChatCommand.h"
  25.  
  26. void sTemplateNPC::LearnPlateMailSpells(Player* player)
  27. {
  28.     switch (player->GetClass())
  29.     {
  30.     case CLASS_WARRIOR:
  31.     case CLASS_PALADIN:
  32.     case CLASS_DEATH_KNIGHT:
  33.         player->LearnSpell(PLATE_MAIL, true);
  34.         break;
  35.     case CLASS_SHAMAN:
  36.     case CLASS_HUNTER:
  37.         player->LearnSpell(MAIL, true);
  38.         break;
  39.     default:
  40.         break;
  41.     }
  42. }
  43.  
  44. void sTemplateNPC::ApplyBonus(Player* player, Item* item, EnchantmentSlot slot, uint32 bonusEntry)
  45. {
  46.     if (!item)
  47.         return;
  48.  
  49.     if (!bonusEntry || bonusEntry == 0)
  50.         return;
  51.  
  52.     player->ApplyEnchantment(item, slot, false);
  53.     item->SetEnchantment(slot, bonusEntry, 0, 0);
  54.     player->ApplyEnchantment(item, slot, true);
  55. }
  56.  
  57. void sTemplateNPC::ApplyGlyph(Player* player, uint8 slot, uint32 glyphID)
  58. {
  59.     if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyphID))
  60.     {
  61.         if (uint32 oldGlyph = player->GetGlyph(slot))
  62.         {
  63.             player->RemoveAurasDueToSpell(sGlyphPropertiesStore.LookupEntry(oldGlyph)->SpellID);
  64.             player->SetGlyph(slot, 0);
  65.         }
  66.         player->CastSpell(player, gp->SpellID, true);
  67.         player->SetGlyph(slot, glyphID);
  68.     }
  69. }
  70.  
  71. void sTemplateNPC::RemoveAllGlyphs(Player* player)
  72. {
  73.     for (uint8 i = 0; i < MAX_GLYPH_SLOT_INDEX; ++i)
  74.     {
  75.         if (uint32 glyph = player->GetGlyph(i))
  76.         {
  77.             if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyph))
  78.             {
  79.                 if (GlyphSlotEntry const* gs = sGlyphSlotStore.LookupEntry(player->GetGlyphSlot(i)))
  80.                 {
  81.                     player->RemoveAurasDueToSpell(sGlyphPropertiesStore.LookupEntry(glyph)->SpellID);
  82.                     player->SetGlyph(i, 0);
  83.                     player->SendTalentsInfoData(false); // this is somewhat an in-game glyph realtime update (apply/remove)
  84.                 }
  85.             }
  86.         }
  87.     }
  88. }
  89.  
  90. void sTemplateNPC::LearnTemplateTalents(Player* player)
  91. {
  92.     for (TalentContainer::const_iterator itr = m_TalentContainer.begin(); itr != m_TalentContainer.end(); ++itr)
  93.     {
  94.         if ((*itr)->playerClass == GetClassString(player).c_str() && (*itr)->playerSpec == sTalentsSpec)
  95.         {
  96.             player->LearnSpell((*itr)->talentId, false);
  97.             player->AddTalent((*itr)->talentId, player->GetActiveSpec(), true);
  98.         }
  99.     }
  100.     player->SetFreeTalentPoints(0);
  101.     player->SendTalentsInfoData(false);
  102. }
  103.  
  104. void sTemplateNPC::LearnTemplateGlyphs(Player* player)
  105. {
  106.     for (GlyphContainer::const_iterator itr = m_GlyphContainer.begin(); itr != m_GlyphContainer.end(); ++itr)
  107.     {
  108.         if ((*itr)->playerClass == GetClassString(player).c_str() && (*itr)->playerSpec == sTalentsSpec)
  109.             ApplyGlyph(player, (*itr)->slot, (*itr)->glyph);
  110.     }
  111.     player->SendTalentsInfoData(false);
  112. }
  113.  
  114. void sTemplateNPC::EquipTemplateGear(Player* player)
  115. {
  116.     if (player->GetRace() == RACE_HUMAN)
  117.     {
  118.         for (HumanGearContainer::const_iterator itr = m_HumanGearContainer.begin(); itr != m_HumanGearContainer.end(); ++itr)
  119.         {
  120.             if ((*itr)->playerClass == GetClassString(player).c_str() && (*itr)->playerSpec == sTalentsSpec)
  121.             {
  122.                 player->EquipNewItem((*itr)->pos, (*itr)->itemEntry, true); // Equip the item and apply enchants and gems
  123.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PERM_ENCHANTMENT_SLOT, (*itr)->enchant);
  124.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT, (*itr)->socket1);
  125.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_2, (*itr)->socket2);
  126.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_3, (*itr)->socket3);
  127.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), BONUS_ENCHANTMENT_SLOT, (*itr)->bonusEnchant);
  128.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PRISMATIC_ENCHANTMENT_SLOT, (*itr)->prismaticEnchant);
  129.             }
  130.         }
  131.     }
  132.     else if (player->GetTeam() == ALLIANCE && player->GetRace() != RACE_HUMAN)
  133.     {
  134.         for (AllianceGearContainer::const_iterator itr = m_AllianceGearContainer.begin(); itr != m_AllianceGearContainer.end(); ++itr)
  135.         {
  136.             if ((*itr)->playerClass == GetClassString(player).c_str() && (*itr)->playerSpec == sTalentsSpec)
  137.             {
  138.                 player->EquipNewItem((*itr)->pos, (*itr)->itemEntry, true); // Equip the item and apply enchants and gems
  139.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PERM_ENCHANTMENT_SLOT, (*itr)->enchant);
  140.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT, (*itr)->socket1);
  141.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_2, (*itr)->socket2);
  142.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_3, (*itr)->socket3);
  143.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), BONUS_ENCHANTMENT_SLOT, (*itr)->bonusEnchant);
  144.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PRISMATIC_ENCHANTMENT_SLOT, (*itr)->prismaticEnchant);
  145.             }
  146.         }
  147.     }
  148.     else if (player->GetTeam() == HORDE)
  149.     {
  150.         for (HordeGearContainer::const_iterator itr = m_HordeGearContainer.begin(); itr != m_HordeGearContainer.end(); ++itr)
  151.         {
  152.             if ((*itr)->playerClass == GetClassString(player).c_str() && (*itr)->playerSpec == sTalentsSpec)
  153.             {
  154.                 player->EquipNewItem((*itr)->pos, (*itr)->itemEntry, true); // Equip the item and apply enchants and gems
  155.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PERM_ENCHANTMENT_SLOT, (*itr)->enchant);
  156.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT, (*itr)->socket1);
  157.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_2, (*itr)->socket2);
  158.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), SOCK_ENCHANTMENT_SLOT_3, (*itr)->socket3);
  159.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), BONUS_ENCHANTMENT_SLOT, (*itr)->bonusEnchant);
  160.                 ApplyBonus(player, player->GetItemByPos(INVENTORY_SLOT_BAG_0, (*itr)->pos), PRISMATIC_ENCHANTMENT_SLOT, (*itr)->prismaticEnchant);
  161.             }
  162.         }
  163.     }
  164. }
  165.  
  166. void sTemplateNPC::LoadTalentsContainer()
  167. {
  168.     for (TalentContainer::const_iterator itr = m_TalentContainer.begin(); itr != m_TalentContainer.end(); ++itr)
  169.         delete* itr;
  170.  
  171.     m_TalentContainer.clear();
  172.  
  173.     uint32 oldMSTime = getMSTime();
  174.     uint32 count = 0;
  175.  
  176.     QueryResult result = CharacterDatabase.Query("SELECT playerClass, playerSpec, talentId FROM template_npc_talents;");
  177.  
  178.     if (!result)
  179.     {
  180.         TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded 0 talent templates. DB table `template_npc_talents` is empty!");
  181.         return;
  182.     }
  183.  
  184.     do
  185.     {
  186.         Field* fields = result->Fetch();
  187.  
  188.         TalentTemplate* pTalent = new TalentTemplate;
  189.  
  190.         pTalent->playerClass = fields[0].GetString();
  191.         pTalent->playerSpec = fields[1].GetString();
  192.         pTalent->talentId = fields[2].GetUInt32();
  193.  
  194.         m_TalentContainer.push_back(pTalent);
  195.         ++count;
  196.     } while (result->NextRow());
  197.     TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded %u talent templates in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
  198. }
  199.  
  200. void sTemplateNPC::LoadGlyphsContainer()
  201. {
  202.     for (GlyphContainer::const_iterator itr = m_GlyphContainer.begin(); itr != m_GlyphContainer.end(); ++itr)
  203.         delete* itr;
  204.  
  205.     m_GlyphContainer.clear();
  206.  
  207.     QueryResult result = CharacterDatabase.Query("SELECT playerClass, playerSpec, slot, glyph FROM template_npc_glyphs;");
  208.  
  209.     uint32 oldMSTime = getMSTime();
  210.     uint32 count = 0;
  211.  
  212.     if (!result)
  213.     {
  214.         TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded 0 glyph templates. DB table `template_npc_glyphs` is empty!");
  215.         return;
  216.     }
  217.  
  218.     do
  219.     {
  220.         Field* fields = result->Fetch();
  221.  
  222.         GlyphTemplate* pGlyph = new GlyphTemplate;
  223.  
  224.         pGlyph->playerClass = fields[0].GetString();
  225.         pGlyph->playerSpec = fields[1].GetString();
  226.         pGlyph->slot = fields[2].GetUInt8();
  227.         pGlyph->glyph = fields[3].GetUInt32();
  228.  
  229.         m_GlyphContainer.push_back(pGlyph);
  230.         ++count;
  231.     } while (result->NextRow());
  232.     TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded %u glyph templates in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
  233. }
  234.  
  235. void sTemplateNPC::LoadHumanGearContainer()
  236. {
  237.     for (HumanGearContainer::const_iterator itr = m_HumanGearContainer.begin(); itr != m_HumanGearContainer.end(); ++itr)
  238.         delete* itr;
  239.  
  240.     m_HumanGearContainer.clear();
  241.  
  242.     QueryResult result = CharacterDatabase.Query("SELECT playerClass, playerSpec, pos, itemEntry, enchant, socket1, socket2, socket3, bonusEnchant, prismaticEnchant FROM template_npc_human;");
  243.  
  244.     uint32 oldMSTime = getMSTime();
  245.     uint32 count = 0;
  246.  
  247.     if (!result)
  248.     {
  249.         TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded 0 'gear templates. DB table `template_npc_human` is empty!");
  250.         return;
  251.     }
  252.  
  253.     do
  254.     {
  255.         Field* fields = result->Fetch();
  256.  
  257.         HumanGearTemplate* pItem = new HumanGearTemplate;
  258.  
  259.         pItem->playerClass = fields[0].GetString();
  260.         pItem->playerSpec = fields[1].GetString();
  261.         pItem->pos = fields[2].GetUInt8();
  262.         pItem->itemEntry = fields[3].GetUInt32();
  263.         pItem->enchant = fields[4].GetUInt32();
  264.         pItem->socket1 = fields[5].GetUInt32();
  265.         pItem->socket2 = fields[6].GetUInt32();
  266.         pItem->socket3 = fields[7].GetUInt32();
  267.         pItem->bonusEnchant = fields[8].GetUInt32();
  268.         pItem->prismaticEnchant = fields[9].GetUInt32();
  269.  
  270.         m_HumanGearContainer.push_back(pItem);
  271.         ++count;
  272.     } while (result->NextRow());
  273.     TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded %u gear templates for Humans in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
  274. }
  275.  
  276. void sTemplateNPC::LoadAllianceGearContainer()
  277. {
  278.     for (AllianceGearContainer::const_iterator itr = m_AllianceGearContainer.begin(); itr != m_AllianceGearContainer.end(); ++itr)
  279.         delete* itr;
  280.  
  281.     m_AllianceGearContainer.clear();
  282.  
  283.     QueryResult result = CharacterDatabase.Query("SELECT playerClass, playerSpec, pos, itemEntry, enchant, socket1, socket2, socket3, bonusEnchant, prismaticEnchant FROM template_npc_alliance;");
  284.  
  285.     uint32 oldMSTime = getMSTime();
  286.     uint32 count = 0;
  287.  
  288.     if (!result)
  289.     {
  290.         TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded 0 'gear templates. DB table `template_npc_alliance` is empty!");
  291.         return;
  292.     }
  293.  
  294.     do
  295.     {
  296.         Field* fields = result->Fetch();
  297.  
  298.         AllianceGearTemplate* pItem = new AllianceGearTemplate;
  299.  
  300.         pItem->playerClass = fields[0].GetString();
  301.         pItem->playerSpec = fields[1].GetString();
  302.         pItem->pos = fields[2].GetUInt8();
  303.         pItem->itemEntry = fields[3].GetUInt32();
  304.         pItem->enchant = fields[4].GetUInt32();
  305.         pItem->socket1 = fields[5].GetUInt32();
  306.         pItem->socket2 = fields[6].GetUInt32();
  307.         pItem->socket3 = fields[7].GetUInt32();
  308.         pItem->bonusEnchant = fields[8].GetUInt32();
  309.         pItem->prismaticEnchant = fields[9].GetUInt32();
  310.  
  311.         m_AllianceGearContainer.push_back(pItem);
  312.         ++count;
  313.     } while (result->NextRow());
  314.     TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded %u gear templates for Alliances in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
  315. }
  316.  
  317. void sTemplateNPC::LoadHordeGearContainer()
  318. {
  319.     for (HordeGearContainer::const_iterator itr = m_HordeGearContainer.begin(); itr != m_HordeGearContainer.end(); ++itr)
  320.         delete* itr;
  321.  
  322.     m_HordeGearContainer.clear();
  323.  
  324.     QueryResult result = CharacterDatabase.Query("SELECT playerClass, playerSpec, pos, itemEntry, enchant, socket1, socket2, socket3, bonusEnchant, prismaticEnchant FROM template_npc_horde;");
  325.  
  326.     uint32 oldMSTime = getMSTime();
  327.     uint32 count = 0;
  328.  
  329.     if (!result)
  330.     {
  331.         TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded 0 'gear templates. DB table `template_npc_horde` is empty!");
  332.         return;
  333.     }
  334.  
  335.     do
  336.     {
  337.         Field* fields = result->Fetch();
  338.  
  339.         HordeGearTemplate* pItem = new HordeGearTemplate;
  340.  
  341.         pItem->playerClass = fields[0].GetString();
  342.         pItem->playerSpec = fields[1].GetString();
  343.         pItem->pos = fields[2].GetUInt8();
  344.         pItem->itemEntry = fields[3].GetUInt32();
  345.         pItem->enchant = fields[4].GetUInt32();
  346.         pItem->socket1 = fields[5].GetUInt32();
  347.         pItem->socket2 = fields[6].GetUInt32();
  348.         pItem->socket3 = fields[7].GetUInt32();
  349.         pItem->bonusEnchant = fields[8].GetUInt32();
  350.         pItem->prismaticEnchant = fields[9].GetUInt32();
  351.  
  352.         m_HordeGearContainer.push_back(pItem);
  353.         ++count;
  354.     } while (result->NextRow());
  355.     TC_LOG_INFO("server.worldserver", ">>TEMPLATE NPC: Loaded %u gear templates for Hordes in %u ms.", count, GetMSTimeDiffToNow(oldMSTime));
  356. }
  357.  
  358. std::string sTemplateNPC::GetClassString(Player* player)
  359. {
  360.     switch (player->GetClass())
  361.     {
  362.     case CLASS_PRIEST:       return "Priest";      break;
  363.     case CLASS_PALADIN:      return "Paladin";     break;
  364.     case CLASS_WARRIOR:      return "Warrior";     break;
  365.     case CLASS_MAGE:         return "Mage";        break;
  366.     case CLASS_WARLOCK:      return "Warlock";     break;
  367.     case CLASS_SHAMAN:       return "Shaman";      break;
  368.     case CLASS_DRUID:        return "Druid";       break;
  369.     case CLASS_HUNTER:       return "Hunter";      break;
  370.     case CLASS_ROGUE:        return "Rogue";       break;
  371.     case CLASS_DEATH_KNIGHT: return "DeathKnight"; break;
  372.     default:
  373.         break;
  374.     }
  375.     return "Unknown"; // Fix warning, this should never happen
  376. }
  377.  
  378. bool sTemplateNPC::OverwriteTemplate(Player* player, std::string& playerSpecStr)
  379. {
  380.     // Delete old talent and glyph templates before extracting new ones
  381.     CharacterDatabase.PExecute("DELETE FROM template_npc_talents WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  382.     CharacterDatabase.PExecute("DELETE FROM template_npc_glyphs WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  383.  
  384.     // Delete old gear templates before extracting new ones
  385.     if (player->GetRace() == RACE_HUMAN)
  386.     {
  387.         CharacterDatabase.PExecute("DELETE FROM template_npc_human WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  388.         player->GetSession()->SendAreaTriggerMessage("Template successfuly created!");
  389.         return false;
  390.     }
  391.     else if (player->GetTeam() == ALLIANCE && player->GetRace() != RACE_HUMAN)
  392.     {
  393.         CharacterDatabase.PExecute("DELETE FROM template_npc_alliance WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  394.         player->GetSession()->SendAreaTriggerMessage("Template successfuly created!");
  395.         return false;
  396.     }
  397.     else if (player->GetTeam() == HORDE)
  398.     {                                                                                                        // ????????????? sTemplateNpcMgr here??
  399.         CharacterDatabase.PExecute("DELETE FROM template_npc_horde WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  400.         player->GetSession()->SendAreaTriggerMessage("Template successfuly created!");
  401.         return false;
  402.     }
  403.     return true;
  404. }
  405.  
  406. void sTemplateNPC::ExtractGearTemplateToDB(Player* player, std::string& playerSpecStr)
  407. {
  408.     for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
  409.     {
  410.         Item* equippedItem = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i);
  411.  
  412.         if (equippedItem)
  413.         {
  414.             if (player->GetRace() == RACE_HUMAN)
  415.             {
  416.                 CharacterDatabase.PExecute("INSERT INTO template_npc_human (`playerClass`, `playerSpec`, `pos`, `itemEntry`, `enchant`, `socket1`, `socket2`, `socket3`, `bonusEnchant`, `prismaticEnchant`) VALUES ('%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u');"
  417.                     , GetClassString(player).c_str(), playerSpecStr.c_str(), equippedItem->GetSlot(), equippedItem->GetEntry(), equippedItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT),
  418.                     equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3),
  419.                     equippedItem->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
  420.             }
  421.             else if (player->GetTeam() == ALLIANCE && player->GetRace() != RACE_HUMAN)
  422.             {
  423.                 CharacterDatabase.PExecute("INSERT INTO template_npc_alliance (`playerClass`, `playerSpec`, `pos`, `itemEntry`, `enchant`, `socket1`, `socket2`, `socket3`, `bonusEnchant`, `prismaticEnchant`) VALUES ('%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u');"
  424.                     , GetClassString(player).c_str(), playerSpecStr.c_str(), equippedItem->GetSlot(), equippedItem->GetEntry(), equippedItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT),
  425.                     equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3),
  426.                     equippedItem->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
  427.             }
  428.             else if (player->GetTeam() == HORDE)
  429.             {
  430.                 CharacterDatabase.PExecute("INSERT INTO template_npc_horde (`playerClass`, `playerSpec`, `pos`, `itemEntry`, `enchant`, `socket1`, `socket2`, `socket3`, `bonusEnchant`, `prismaticEnchant`) VALUES ('%s', '%s', '%u', '%u', '%u', '%u', '%u', '%u', '%u', '%u');"
  431.                     , GetClassString(player).c_str(), playerSpecStr.c_str(), equippedItem->GetSlot(), equippedItem->GetEntry(), equippedItem->GetEnchantmentId(PERM_ENCHANTMENT_SLOT),
  432.                     equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_2), equippedItem->GetEnchantmentId(SOCK_ENCHANTMENT_SLOT_3),
  433.                     equippedItem->GetEnchantmentId(BONUS_ENCHANTMENT_SLOT), equippedItem->GetEnchantmentId(PRISMATIC_ENCHANTMENT_SLOT));
  434.             }
  435.         }
  436.     }
  437. }
  438.  
  439. void sTemplateNPC::ExtractTalentTemplateToDB(Player* player, std::string& playerSpecStr)
  440. {
  441.     QueryResult result = CharacterDatabase.PQuery("SELECT spell FROM character_talent WHERE guid = '%u' "
  442.         "AND talentGroup = '%u';", player->GetGUID(), player->GetActiveSpec());
  443.  
  444.     if (!result)
  445.     {
  446.         return;
  447.     }
  448.     else if (player->GetFreeTalentPoints() > 0)
  449.     {
  450.         player->GetSession()->SendAreaTriggerMessage("You have unspend talent points. Please spend all your talent points and re-extract the template.");
  451.         return;
  452.     }
  453.     else
  454.     {
  455.         do
  456.         {
  457.             Field* fields = result->Fetch();
  458.             uint32 spell = fields[0].GetUInt32();
  459.  
  460.             CharacterDatabase.PExecute("INSERT INTO template_npc_talents (playerClass, playerSpec, talentId) "
  461.                 "VALUES ('%s', '%s', '%u');", GetClassString(player).c_str(), playerSpecStr.c_str(), spell);
  462.         } while (result->NextRow());
  463.     }
  464. }
  465.  
  466. void sTemplateNPC::ExtractGlyphsTemplateToDB(Player* player, std::string& playerSpecStr)
  467. {
  468.     QueryResult result = CharacterDatabase.PQuery("SELECT glyph1, glyph2, glyph3, glyph4, glyph5, glyph6 "
  469.         "FROM character_glyphs WHERE guid = '%u' AND talentGroup = '%u';", player->GetGUID(), player->GetActiveSpec());
  470.  
  471.     for (uint8 slot = 0; slot < MAX_GLYPH_SLOT_INDEX; ++slot)
  472.     {
  473.         if (!result)
  474.         {
  475.             player->GetSession()->SendAreaTriggerMessage("Get glyphs and re-extract the template!");
  476.             continue;
  477.         }
  478.  
  479.         Field* fields = result->Fetch();
  480.         uint32 glyph1 = fields[0].GetUInt32();
  481.         uint32 glyph2 = fields[1].GetUInt32();
  482.         uint32 glyph3 = fields[2].GetUInt32();
  483.         uint32 glyph4 = fields[3].GetUInt32();
  484.         uint32 glyph5 = fields[4].GetUInt32();
  485.         uint32 glyph6 = fields[5].GetUInt32();
  486.  
  487.         uint32 storedGlyph;
  488.  
  489.         switch (slot)
  490.         {
  491.         case 0:
  492.             storedGlyph = glyph1;
  493.             break;
  494.         case 1:
  495.             storedGlyph = glyph2;
  496.             break;
  497.         case 2:
  498.             storedGlyph = glyph3;
  499.             break;
  500.         case 3:
  501.             storedGlyph = glyph4;
  502.             break;
  503.         case 4:
  504.             storedGlyph = glyph5;
  505.             break;
  506.         case 5:
  507.             storedGlyph = glyph6;
  508.             break;
  509.         default:
  510.             break;
  511.         }
  512.  
  513.         CharacterDatabase.PExecute("INSERT INTO template_npc_glyphs (playerClass, playerSpec, slot, glyph) "
  514.             "VALUES ('%s', '%s', '%u', '%u');", GetClassString(player).c_str(), playerSpecStr.c_str(), slot, storedGlyph);
  515.     }
  516. }
  517.  
  518. bool sTemplateNPC::CanEquipTemplate(Player* player, std::string& playerSpecStr)
  519. {
  520.     if (player->GetRace() == RACE_HUMAN)
  521.     {
  522.         QueryResult result = CharacterDatabase.PQuery("SELECT playerClass, playerSpec FROM template_npc_human "
  523.             "WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  524.  
  525.         if (!result)
  526.             return false;
  527.     }
  528.     else if (player->GetTeam() == ALLIANCE && player->GetRace() != RACE_HUMAN)
  529.     {
  530.         QueryResult result = CharacterDatabase.PQuery("SELECT playerClass, playerSpec FROM template_npc_alliance "
  531.             "WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  532.  
  533.         if (!result)
  534.             return false;
  535.     }
  536.     else if (player->GetTeam() == HORDE)
  537.     {
  538.         QueryResult result = CharacterDatabase.PQuery("SELECT playerClass, playerSpec FROM template_npc_horde "
  539.             "WHERE playerClass = '%s' AND playerSpec = '%s';", GetClassString(player).c_str(), playerSpecStr.c_str());
  540.  
  541.         if (!result)
  542.             return false;
  543.     }
  544.     return true;
  545. }
  546.  
  547. class TemplateNPC : public CreatureScript
  548. {
  549. public:
  550.     TemplateNPC() : CreatureScript("TemplateNPC") { }
  551.  
  552.     struct TemplateNPC_AI : public ScriptedAI
  553.     {
  554.         TemplateNPC_AI(Creature* creature) : ScriptedAI(creature) { }
  555.  
  556.         bool OnGossipHello(Player* player) override
  557.         {
  558.             switch (player->GetClass())
  559.             {
  560.             case CLASS_PRIEST:
  561.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_wordfortitude:30|t|r Use Discipline Spec", GOSSIP_SENDER_MAIN, 0);
  562.                 /*AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_wordfortitude:30|t|r Use Discipline Spec (Talents Only)", GOSSIP_SENDER_MAIN, 100);*/
  563.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_holybolt:30|t|r Use Holy Spec", GOSSIP_SENDER_MAIN, 1);
  564.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_shadow_shadowwordpain:30|t|r Use Shadow Spec", GOSSIP_SENDER_MAIN, 2);
  565.                 break;
  566.             case CLASS_PALADIN:
  567.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_holybolt:30|t|r Use Holy Spec", GOSSIP_SENDER_MAIN, 3);
  568.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_devotionaura:30|t|r Use Protection Spec", GOSSIP_SENDER_MAIN, 4);
  569.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_auraoflight:30|t|r Use Retribution Spec", GOSSIP_SENDER_MAIN, 5);
  570.                 break;
  571.             case CLASS_WARRIOR:
  572.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_warrior_innerrage:30|t|r Use Fury Spec", GOSSIP_SENDER_MAIN, 6);
  573.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_rogue_eviscerate:30|t|r Use Arms Spec", GOSSIP_SENDER_MAIN, 7);
  574.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_warrior_defensivestance:30|t|r Use Protection Spec", GOSSIP_SENDER_MAIN, 8);
  575.                 break;
  576.             case CLASS_MAGE:
  577.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_holy_magicalsentry:30|t|r Use Arcane Spec", GOSSIP_SENDER_MAIN, 9);
  578.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_fire_flamebolt:30|t|r Use Fire Spec", GOSSIP_SENDER_MAIN, 10);
  579.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_frost_frostbolt02:30|t|r Use Frost Spec", GOSSIP_SENDER_MAIN, 11);
  580.                 break;
  581.             case CLASS_WARLOCK:
  582.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_shadow_deathcoil:30|t|r Use Affliction Spec", GOSSIP_SENDER_MAIN, 12);
  583.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_shadow_metamorphosis:30|t|r Use Demonology Spec", GOSSIP_SENDER_MAIN, 13);
  584.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_shadow_rainoffire:30|t|r Use Destruction Spec", GOSSIP_SENDER_MAIN, 14);
  585.                 break;
  586.             case CLASS_SHAMAN:
  587.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_nature_lightning:30|t|r Use Elemental Spec", GOSSIP_SENDER_MAIN, 15);
  588.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_nature_lightningshield:30|t|r Use Enhancement Spec", GOSSIP_SENDER_MAIN, 16);
  589.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_nature_magicimmunity:30|t|r Use Restoration Spec", GOSSIP_SENDER_MAIN, 17);
  590.                 break;
  591.             case CLASS_DRUID:
  592.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_nature_starfall:30|t|r Use Ballance Spec", GOSSIP_SENDER_MAIN, 18);
  593.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_racial_bearform:30|t|r Use Feral Spec", GOSSIP_SENDER_MAIN, 19);
  594.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_nature_healingtouch:30|t|r Use Restoration Spec", GOSSIP_SENDER_MAIN, 20);
  595.                 break;
  596.             case CLASS_HUNTER:
  597.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_marksmanship:30|t|r Use Markmanship Spec", GOSSIP_SENDER_MAIN, 21);
  598.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_hunter_beasttaming:30|t|r Use Beastmastery Spec", GOSSIP_SENDER_MAIN, 22);
  599.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_Hunter_swiftstrike:30|t|r Use Survival Spec", GOSSIP_SENDER_MAIN, 23);
  600.                 break;
  601.             case CLASS_ROGUE:
  602.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_rogue_eviscerate:30|t|r Use Assasination Spec", GOSSIP_SENDER_MAIN, 24);
  603.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_backstab:30|t|r Use Combat Spec", GOSSIP_SENDER_MAIN, 25);
  604.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\ability_stealth:30|t|r Use Subtlety Spec", GOSSIP_SENDER_MAIN, 26);
  605.                 break;
  606.             case CLASS_DEATH_KNIGHT:
  607.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_deathknight_bloodpresence:30|t|r Use Blood Spec", GOSSIP_SENDER_MAIN, 27);
  608.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_deathknight_frostpresence:30|t|r Use Frost Spec", GOSSIP_SENDER_MAIN, 28);
  609.                 AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\spell_deathknight_unholypresence:30|t|r Use Unholy Spec", GOSSIP_SENDER_MAIN, 29);
  610.                 break;
  611.             }
  612.  
  613.             /*AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\Spell_ChargeNegative:30|t|r Remove all glyphs", GOSSIP_SENDER_MAIN, 30);
  614.             AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\Spell_ChargeNegative:30|t|r Reset Talents", GOSSIP_SENDER_MAIN, 31);
  615.             AddGossipItemFor(player, GOSSIP_ICON_INTERACT_1, "|cff00ff00|TInterface\\icons\\Spell_ChargeNegative:30|t|r Destroy my equipped gear", GOSSIP_SENDER_MAIN, 32);*/
  616.             SendGossipMenuFor(player, 55002, me->GetGUID());
  617.             return true;
  618.         }
  619.  
  620.         static void EquipFullTemplateGear(Player* player, std::string& playerSpecStr) // Merge
  621.         {
  622.             if (sTemplateNpcMgr->CanEquipTemplate(player, playerSpecStr) == false)
  623.             {
  624.                 player->GetSession()->SendAreaTriggerMessage("There's no templates for %s specialization yet.", playerSpecStr.c_str());
  625.                 return;
  626.             }
  627.  
  628.             // Don't let players to use Template feature while wearing some gear
  629.             for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
  630.             {
  631.                 if (Item* haveItemEquipped = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
  632.                 {
  633.                     if (haveItemEquipped)
  634.                     {
  635.                         player->GetSession()->SendAreaTriggerMessage("You need to remove all your equipped items in order to use this feature!");
  636.                         CloseGossipMenuFor(player);
  637.                         return;
  638.                     }
  639.                 }
  640.             }
  641.  
  642.             // Don't let players to use Template feature after spending some talent points
  643.             if (player->GetFreeTalentPoints() < 71)
  644.             {
  645.                 player->GetSession()->SendAreaTriggerMessage("You have already spent some talent points. You need to reset your talents first!");
  646.                 CloseGossipMenuFor(player);
  647.                 return;
  648.             }
  649.  
  650.             sTemplateNpcMgr->LearnTemplateTalents(player);
  651.             sTemplateNpcMgr->LearnTemplateGlyphs(player);
  652.             sTemplateNpcMgr->EquipTemplateGear(player);
  653.             sTemplateNpcMgr->LearnPlateMailSpells(player);
  654.  
  655.             LearnWeaponSkills(player);
  656.  
  657.             player->GetSession()->SendAreaTriggerMessage("Successfuly equipped %s %s template!", playerSpecStr.c_str(), sTemplateNpcMgr->GetClassString(player).c_str());
  658.  
  659.             if (player->GetPowerType() == POWER_MANA)
  660.                 player->SetFullPower(POWER_MANA);
  661.  
  662.             player->SetFullHealth();
  663.  
  664.             // Learn Riding/Flying
  665.             if (player->HasSpell(Artisan_Riding) ||
  666.                 player->HasSpell(Cold_Weather_Flying) ||
  667.                 player->HasSpell(Amani_War_Bear) ||
  668.                 player->HasSpell(Teach_Learn_Talent_Specialization_Switches) ||
  669.                 player->HasSpell(Learn_a_Second_Talent_Specialization))
  670.                 return;
  671.  
  672.             // Cast spells that teach dual spec
  673.             // Both are also ImplicitTarget self and must be cast by player
  674.             player->CastSpell(player, Teach_Learn_Talent_Specialization_Switches, player->GetGUID());
  675.             player->CastSpell(player, Learn_a_Second_Talent_Specialization, player->GetGUID());
  676.  
  677.             player->LearnSpell(Artisan_Riding, false);
  678.             player->LearnSpell(Cold_Weather_Flying, false);
  679.             player->LearnSpell(Amani_War_Bear, false);
  680.  
  681.         }
  682.  
  683.         static void LearnOnlyTalentsAndGlyphs(Player* player, std::string& playerSpecStr) // Merge
  684.         {
  685.             if (sTemplateNpcMgr->CanEquipTemplate(player, playerSpecStr) == false)
  686.             {
  687.                 player->GetSession()->SendAreaTriggerMessage("There's no templates for %s specialization yet.", playerSpecStr.c_str());
  688.                 return;
  689.             }
  690.  
  691.             // Don't let players to use Template feature after spending some talent points
  692.             if (player->GetFreeTalentPoints() < 71)
  693.             {
  694.                 player->GetSession()->SendAreaTriggerMessage("You have already spent some talent points. You need to reset your talents first!");
  695.                 CloseGossipMenuFor(player);
  696.                 return;
  697.             }
  698.  
  699.             sTemplateNpcMgr->LearnTemplateTalents(player);
  700.             sTemplateNpcMgr->LearnTemplateGlyphs(player);
  701.             //sTemplateNpcMgr->EquipTemplateGear(player);
  702.             sTemplateNpcMgr->LearnPlateMailSpells(player);
  703.  
  704.             LearnWeaponSkills(player);
  705.  
  706.             player->GetSession()->SendAreaTriggerMessage("Successfuly learned talent spec %s!", playerSpecStr.c_str());
  707.  
  708.             // Learn Riding/Flying
  709.             if (player->HasSpell(Artisan_Riding) ||
  710.                 player->HasSpell(Cold_Weather_Flying) ||
  711.                 player->HasSpell(Amani_War_Bear) ||
  712.                 player->HasSpell(Teach_Learn_Talent_Specialization_Switches) ||
  713.                 player->HasSpell(Learn_a_Second_Talent_Specialization))
  714.                 return;
  715.  
  716.             // Cast spells that teach dual spec
  717.             // Both are also ImplicitTarget self and must be cast by player
  718.             player->CastSpell(player, Teach_Learn_Talent_Specialization_Switches, player->GetGUID());
  719.             player->CastSpell(player, Learn_a_Second_Talent_Specialization, player->GetGUID());
  720.  
  721.             player->LearnSpell(Artisan_Riding, false);
  722.             player->LearnSpell(Cold_Weather_Flying, false);
  723.             player->LearnSpell(Amani_War_Bear, false);
  724.         }
  725.  
  726.         bool OnGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
  727.         {
  728.             uint32 const sender = player->PlayerTalkClass->GetGossipOptionSender(gossipListId);
  729.             uint32 const action = player->PlayerTalkClass->GetGossipOptionAction(gossipListId);
  730.  
  731.             if (!player || !me)
  732.                 return true;
  733.  
  734.             ClearGossipMenuFor(player);
  735.  
  736.             if (!player || !me)
  737.                 return false;
  738.  
  739.             switch (action)
  740.             {
  741.             case 0: // Use Discipline Priest Spec
  742.                 sTemplateNpcMgr->sTalentsSpec = "Discipline";
  743.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  744.                 CloseGossipMenuFor(player);
  745.                 break;
  746.  
  747.             case 1: // Use Holy Priest Spec
  748.                 sTemplateNpcMgr->sTalentsSpec = "Holy";
  749.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  750.                 CloseGossipMenuFor(player);
  751.                 break;
  752.  
  753.             case 2: // Use Shadow Priest Spec
  754.                 sTemplateNpcMgr->sTalentsSpec = "Shadow";
  755.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  756.                 CloseGossipMenuFor(player);
  757.                 break;
  758.  
  759.             case 3: // Use Holy Paladin Spec
  760.                 sTemplateNpcMgr->sTalentsSpec = "Holy";
  761.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  762.                 CloseGossipMenuFor(player);
  763.                 break;
  764.  
  765.             case 4: // Use Protection Paladin Spec
  766.                 sTemplateNpcMgr->sTalentsSpec = "Protection";
  767.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  768.                 CloseGossipMenuFor(player);
  769.                 break;
  770.  
  771.             case 5: // Use Retribution Paladin Spec
  772.                 sTemplateNpcMgr->sTalentsSpec = "Retribution";
  773.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  774.                 CloseGossipMenuFor(player);
  775.                 break;
  776.  
  777.             case 6: // Use Fury Warrior Spec
  778.                 sTemplateNpcMgr->sTalentsSpec = "Fury";
  779.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  780.                 CloseGossipMenuFor(player);
  781.                 break;
  782.  
  783.             case 7: // Use Arms Warrior Spec
  784.                 sTemplateNpcMgr->sTalentsSpec = "Arms";
  785.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  786.                 CloseGossipMenuFor(player);
  787.                 break;
  788.  
  789.             case 8: // Use Protection Warrior Spec
  790.                 sTemplateNpcMgr->sTalentsSpec = "Protection";
  791.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  792.                 CloseGossipMenuFor(player);
  793.                 break;
  794.  
  795.             case 9: // Use Arcane Mage Spec
  796.                 sTemplateNpcMgr->sTalentsSpec = "Arcane";
  797.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  798.                 CloseGossipMenuFor(player);
  799.                 break;
  800.  
  801.             case 10: // Use Fire Mage Spec
  802.                 sTemplateNpcMgr->sTalentsSpec = "Fire";
  803.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  804.                 CloseGossipMenuFor(player);
  805.                 break;
  806.  
  807.             case 11: // Use Frost Mage Spec
  808.                 sTemplateNpcMgr->sTalentsSpec = "Frost";
  809.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  810.                 CloseGossipMenuFor(player);
  811.                 break;
  812.  
  813.             case 12: // Use Affliction Warlock Spec
  814.                 sTemplateNpcMgr->sTalentsSpec = "Affliction";
  815.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  816.                 CloseGossipMenuFor(player);
  817.                 break;
  818.  
  819.             case 13: // Use Demonology Warlock Spec
  820.                 sTemplateNpcMgr->sTalentsSpec = "Demonology";
  821.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  822.                 CloseGossipMenuFor(player);
  823.                 break;
  824.  
  825.             case 14: // Use Destruction Warlock Spec
  826.                 sTemplateNpcMgr->sTalentsSpec = "Destruction";
  827.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  828.                 CloseGossipMenuFor(player);
  829.                 break;
  830.  
  831.             case 15: // Use Elemental Shaman Spec
  832.                 sTemplateNpcMgr->sTalentsSpec = "Elemental";
  833.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  834.                 CloseGossipMenuFor(player);
  835.                 break;
  836.  
  837.             case 16: // Use Enhancement Shaman Spec
  838.                 sTemplateNpcMgr->sTalentsSpec = "Enhancement";
  839.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  840.                 CloseGossipMenuFor(player);
  841.                 break;
  842.  
  843.             case 17: // Use Restoration Shaman Spec
  844.                 sTemplateNpcMgr->sTalentsSpec = "Restoration";
  845.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  846.                 CloseGossipMenuFor(player);
  847.                 break;
  848.  
  849.             case 18: // Use Ballance Druid Spec
  850.                 sTemplateNpcMgr->sTalentsSpec = "Ballance";
  851.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  852.                 CloseGossipMenuFor(player);
  853.                 break;
  854.  
  855.             case 19: // Use Feral Druid Spec
  856.                 sTemplateNpcMgr->sTalentsSpec = "Feral";
  857.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  858.                 CloseGossipMenuFor(player);
  859.                 break;
  860.  
  861.             case 20: // Use Restoration Druid Spec
  862.                 sTemplateNpcMgr->sTalentsSpec = "Restoration";
  863.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  864.                 CloseGossipMenuFor(player);
  865.                 break;
  866.  
  867.             case 21: // Use Marksmanship Hunter Spec
  868.                 sTemplateNpcMgr->sTalentsSpec = "Marksmanship";
  869.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  870.                 CloseGossipMenuFor(player);
  871.                 break;
  872.  
  873.             case 22: // Use Beastmastery Hunter Spec
  874.                 sTemplateNpcMgr->sTalentsSpec = "Beastmastery";
  875.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  876.                 CloseGossipMenuFor(player);
  877.                 break;
  878.  
  879.             case 23: // Use Survival Hunter Spec
  880.                 sTemplateNpcMgr->sTalentsSpec = "Survival";
  881.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  882.                 CloseGossipMenuFor(player);
  883.                 break;
  884.  
  885.             case 24: // Use Assassination Rogue Spec
  886.                 sTemplateNpcMgr->sTalentsSpec = "Assassination";
  887.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  888.                 CloseGossipMenuFor(player);
  889.                 break;
  890.  
  891.             case 25: // Use Combat Rogue Spec
  892.                 sTemplateNpcMgr->sTalentsSpec = "Combat";
  893.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  894.                 CloseGossipMenuFor(player);
  895.                 break;
  896.  
  897.             case 26: // Use Subtlety Rogue Spec
  898.                 sTemplateNpcMgr->sTalentsSpec = "Subtlety";
  899.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  900.                 CloseGossipMenuFor(player);
  901.                 break;
  902.  
  903.             case 27: // Use Blood DK Spec
  904.                 sTemplateNpcMgr->sTalentsSpec = "Blood";
  905.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  906.                 CloseGossipMenuFor(player);
  907.                 break;
  908.  
  909.             case 28: // Use Frost DK Spec
  910.                 sTemplateNpcMgr->sTalentsSpec = "Frost";
  911.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  912.                 CloseGossipMenuFor(player);
  913.                 break;
  914.  
  915.             case 29: // Use Unholy DK Spec
  916.                 sTemplateNpcMgr->sTalentsSpec = "Unholy";
  917.                 EquipFullTemplateGear(player, sTemplateNpcMgr->sTalentsSpec);
  918.                 CloseGossipMenuFor(player);
  919.                 break;
  920.  
  921.             case 30:
  922.                 sTemplateNpcMgr->RemoveAllGlyphs(player);
  923.                 player->GetSession()->SendAreaTriggerMessage("Your glyphs have been removed.");
  924.                 //GossipHello(player);
  925.                 CloseGossipMenuFor(player);
  926.                 break;
  927.  
  928.             case 31:
  929.                 player->ResetTalents(true);
  930.                 player->SendTalentsInfoData(false);
  931.                 player->GetSession()->SendAreaTriggerMessage("Your talents have been reset.");
  932.                 CloseGossipMenuFor(player);
  933.                 break;
  934.  
  935.             case 32:
  936.                 for (uint8 i = EQUIPMENT_SLOT_START; i < EQUIPMENT_SLOT_END; ++i)
  937.                 {
  938.                     if (Item* haveItemEquipped = player->GetItemByPos(INVENTORY_SLOT_BAG_0, i))
  939.                     {
  940.                         if (haveItemEquipped)
  941.                         {
  942.                             player->DestroyItemCount(haveItemEquipped->GetEntry(), 1, true, true);
  943.  
  944.                             if (haveItemEquipped->IsInWorld())
  945.                             {
  946.                                 haveItemEquipped->RemoveFromWorld();
  947.                                 haveItemEquipped->DestroyForPlayer(player);
  948.                             }
  949.  
  950.                             haveItemEquipped->SetGuidValue(ITEM_FIELD_CONTAINED, ObjectGuid::Empty);
  951.                             haveItemEquipped->SetSlot(NULL_SLOT);
  952.                             haveItemEquipped->SetState(ITEM_REMOVED, player);
  953.                         }
  954.                     }
  955.                 }
  956.                 player->GetSession()->SendAreaTriggerMessage("Your equipped gear has been destroyed.");
  957.                 CloseGossipMenuFor(player);
  958.                 break;
  959.  
  960.             case 100: // Use Discipline Priest Spec
  961.                 sTemplateNpcMgr->sTalentsSpec = "Discipline";
  962.                 LearnOnlyTalentsAndGlyphs(player, sTemplateNpcMgr->sTalentsSpec);
  963.                 CloseGossipMenuFor(player);
  964.                 break;
  965.  
  966.             default: // Just in case
  967.                 player->GetSession()->SendAreaTriggerMessage("Something went wrong in the code. Please contact the administrator.");
  968.                 break;
  969.             }
  970.             player->UpdateSkillsForLevel();
  971.  
  972.             return true;
  973.         }
  974.     };
  975.  
  976.     CreatureAI* GetAI(Creature* creature) const override
  977.     {
  978.         return new TemplateNPC_AI(creature);
  979.     }
  980. };
  981.  
  982. class TemplateNPC_World : public WorldScript
  983. {
  984. public:
  985.     TemplateNPC_World() : WorldScript("TemplateNPC_World") { }
  986.  
  987.     void OnStartup() override
  988.     {
  989.         // Load templates for Template NPC #1
  990.         TC_LOG_INFO("server.loading", "== TEMPLATE NPC ===========================================================================");
  991.         TC_LOG_INFO("server.loading", "Loading Template Talents...");
  992.         sTemplateNpcMgr->LoadTalentsContainer();
  993.  
  994.         // Load templates for Template NPC #2
  995.         TC_LOG_INFO("server.loading", "Loading Template Glyphs...");
  996.         sTemplateNpcMgr->LoadGlyphsContainer();
  997.  
  998.         // Load templates for Template NPC #3
  999.         TC_LOG_INFO("server.loading", "Loading Template Gear for Humans...");
  1000.         sTemplateNpcMgr->LoadHumanGearContainer();
  1001.  
  1002.         // Load templates for Template NPC #4
  1003.         TC_LOG_INFO("server.loading", "Loading Template Gear for Alliances...");
  1004.         sTemplateNpcMgr->LoadAllianceGearContainer();
  1005.  
  1006.         // Load templates for Template NPC #5
  1007.         TC_LOG_INFO("server.loading", "Loading Template Gear for Hordes...");
  1008.         sTemplateNpcMgr->LoadHordeGearContainer();
  1009.         TC_LOG_INFO("server.loading", "== END TEMPLATE NPC ===========================================================================");
  1010.     }
  1011. };
  1012.  
  1013. class TemplateNPC_command : public CommandScript
  1014. {
  1015. public:
  1016.     TemplateNPC_command() : CommandScript("TemplateNPC_command") { }
  1017.  
  1018.     std::vector<ChatCommand> GetCommands() const override
  1019.     {
  1020.         static std::vector<ChatCommand> TemplateNPCTable =
  1021.         {
  1022.             //{ "reload",      SEC_ADMINISTRATOR, true , &HandleReloadTemplateNPCCommand, "" },
  1023.             { "reload", HandleReloadTemplateNPCCommand, LANG_COMMAND_ACC_SET_ADDON_HELP, rbac::RBAC_PERM_COMMAND_ACCOUNT_SET_ADDON, Trinity::ChatCommands::Console::Yes }
  1024.         };
  1025.  
  1026.         static std::vector<ChatCommand> commandTable =
  1027.         {
  1028.             { "templatenpc", TemplateNPCTable }
  1029.         };
  1030.         return commandTable;
  1031.     }
  1032.  
  1033.  
  1034.     static bool HandleReloadTemplateNPCCommand(ChatHandler* handler, const char* /*args*/)
  1035.     {
  1036.         TC_LOG_INFO("server.loading", "misc", "Reloading templates for Template NPC table...");
  1037.         sTemplateNpcMgr->LoadTalentsContainer();
  1038.         sTemplateNpcMgr->LoadGlyphsContainer();
  1039.         sTemplateNpcMgr->LoadHumanGearContainer();
  1040.         sTemplateNpcMgr->LoadAllianceGearContainer();
  1041.         sTemplateNpcMgr->LoadHordeGearContainer();
  1042.         handler->SendGlobalGMSysMessage("Template NPC templates reloaded.");
  1043.         return true;
  1044.     }
  1045. };
  1046.  
  1047. void AddSC_TemplateNPC()
  1048. {
  1049.     new TemplateNPC();
  1050.     new TemplateNPC_World();
  1051.     new TemplateNPC_command();
  1052. }
RAW Paste Data Copied