Loud's Magic Stone System

0 Replies, 181 Views

Recently a well known fun server dev named Loud/Luka passed away. I wanted to release this before it was lost to time. I do not know if he was the original creator but he sold it to me way back in 2018.


Known Bugs:
  • The options are out of order sometimes because of an use of std::unordered_map instead of std::map


C++ Code:
Code:
#include "Player.h"
#include "DatabaseWorker.h"
#include "WorldDatabase.h"
#include "Field.h"
#include "QueryResult.h"
#include "Chat.h"
#include "RBAC.h"
#include "Item.h"
#include "DatabaseEnv.h"
#include "Spell.h"
#include "Logger.h"
#include "ObjectMgr.h"
#include "Log.h"
#include "WorldSession.h"
#include "Player.h"
#include "ScriptedGossip.h"
#include "Pet.h"
#include "DBCStores.h"
#include "SpellMgr.h"

constexpr int factToken = 831041;
constexpr int raceToken = 831039;
constexpr int nameToken = 831037;
constexpr int clasToken = 831040;
constexpr int magicCoin = 80000;

enum MenuType
{
    MainMenu = 2,
    SubMenu = 3,
    SecondSubMenu = 4,
    ThirdSubMenu = 5,
    Teleport = 6,
    TokenSevices = 7,
    SpecialServices = 8,
    CharInformation = 9,
    FullTalents = 10,
    TitansGrip = 11,
    ChangeRace = 12,
    ChangeFaction = 13,
    ChangeName = 14,
    ChangeClass = 15,
    GoBack = 16,
    VipZone = 17,
    DualWield = 18,
    HomeBind = 19,
    ClassWarrior = 20,
    ClassPaladin = 21,
    ClassHunter = 22,
    ClassRogue = 23,
    ClassPriest = 24,
    ClassDeathKnight = 25,
    ClassShaman = 26,
    ClassMage = 27,
    ClassWarlock = 28,
    ClassDruid = 29,
    Mailbox = 30,
    Bank = 31,
    ConvertMG = 32,
    ConvertCoin = 33,

};

struct MagicStoneStruct
{
    uint32 menuId;
    uint32 menuType;
    uint32 menuParent;
    std::string menuIcon;
    std::string menuName;
    uint32 mapId;
    float pos_x;
    float pos_y;
    float pos_z;
    float orientation;
};

using StoneMap_t = std::unordered_map<uint32, MagicStoneStruct>;

std::unordered_map<uint32, StoneMap_t> MagicStoneMap;

void LoadMagicStone()
{
    MagicStoneMap.clear();
    QueryResult result = WorldDatabase.Query("SELECT menu_id, menu_type, menu_parent, menu_icon, menu_name, map, position_x, position_y, position_z, orientation FROM z_magic_stone");
    if (result)
    {
        do
        {
            Field* fields = result->Fetch();
            MagicStoneStruct mst;

            mst.menuId = fields[0].GetUInt32();
            mst.menuType = fields[1].GetUInt32();
            mst.menuParent = fields[2].GetUInt32();
            mst.menuIcon = fields[3].GetString();
            mst.menuName = fields[4].GetString();
            mst.mapId = fields[5].GetUInt32();
            mst.pos_x = fields[6].GetFloat();
            mst.pos_y = fields[7].GetFloat();
            mst.pos_z = fields[8].GetFloat();
            mst.orientation = fields[9].GetFloat();

            MagicStoneMap[mst.menuParent][mst.menuId] = mst;

        } while (result->NextRow());
    }
}

class magic_stone_loader : public WorldScript
{
public:
    magic_stone_loader() : WorldScript("magic_stone_loader") { }

    void OnStartup()
    {
        LoadMagicStone();
    }
};

class magic_stone_reload_command : public CommandScript
{
public:
    magic_stone_reload_command() : CommandScript("magic_stone_reload_command") { }

    std::vector<ChatCommand> GetCommands() const
    {
        static std::vector<ChatCommand> commandTable =
        {
            { "reload_magic_stone",  rbac::RBAC_PERM_COMMAND_RELOAD, true, &HandleReloadMagicStoneCommand,   "" },
        };
        return commandTable;
    }

    static bool HandleReloadMagicStoneCommand(ChatHandler * handler, const char * args)
    {
        handler->SendSysMessage("Reloading Magic Stone System");
        LoadMagicStone();
        handler->SendSysMessage("Magic Stone System Reloaded");
        return true;
    }
};

class magic_stone : public ItemScript
{
public:
    magic_stone() : ItemScript("magic_stone") {}

    bool LearnFullTalents(Player* player)
    {
        player->ResetTalents();
        uint32 classMask = player->getClassMask();
        Pet* pet = player->GetPet();

        for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
        {
            TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
            if (!talentInfo)
                continue;

            TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
            if (!talentTabInfo)
                continue;

            if ((classMask & talentTabInfo->ClassMask) == 0)
                continue;

            // search highest talent rank
            uint32 spellId = 0;
            for (int8 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank)
            {
                if (talentInfo->RankID[rank] != 0)
                {
                    spellId = talentInfo->RankID[rank];
                    break;
                }
            }

            if (!spellId)                                        // ??? none spells in talent
                continue;

            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
            if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player, false))
                continue;

            // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
            player->LearnSpellHighestRank(spellId);
            player->AddTalent(spellId, player->GetActiveSpec(), true);
        }

        if (!pet)
            return false;

        CreatureTemplate const* creatureInfo = pet->GetCreatureTemplate();
        if (!creatureInfo)
            return false;

        CreatureFamilyEntry const* petFamily = sCreatureFamilyStore.LookupEntry(creatureInfo->family);

        if (petFamily->petTalentType < 0)
            return false;

        for (uint32 i = 0; i < sTalentStore.GetNumRows(); ++i)
        {
            TalentEntry const* talentInfo = sTalentStore.LookupEntry(i);
            if (!talentInfo)
                continue;

            TalentTabEntry const* talentTabInfo = sTalentTabStore.LookupEntry(talentInfo->TalentTab);
            if (!talentTabInfo)
                continue;

            // prevent learn talent for different family (cheating)
            if (((1 << petFamily->petTalentType) & talentTabInfo->petTalentMask) == 0)
                continue;

            // search highest talent rank
            uint32 spellId = 0;

            for (int8 rank = MAX_TALENT_RANK - 1; rank >= 0; --rank)
            {
                if (talentInfo->RankID[rank] != 0)
                {
                    spellId = talentInfo->RankID[rank];
                    break;
                }
            }

            if (!spellId)                                        // ??? none spells in talent
                continue;

            SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId);
            if (!spellInfo || !SpellMgr::IsSpellValid(spellInfo, player, false))
                continue;

            // learn highest rank of talent and learn all non-talent spell ranks (recursive by tree)
            pet->learnSpellHighRank(spellId);
        }

        pet->SetFreeTalentPoints(0);
        player->SetFreeTalentPoints(0);
        return true;
    }

    bool OnUse(Player* player, Item* item, SpellCastTargets const& /*targets*/) override
    {
        if (player->HasAura(15007))
        {
            player->RemoveAura(15007);
        }

        if (player->IsInCombat())
        {
            player->GetSession()->SendNotification("You are in combat!");
            CloseGossipMenuFor(player);
            return false;
        }

        if (player->GetAura(8326) && !player->IsAlive())
        {
            player->ResurrectPlayer(1.0f);
            player->SpawnCorpseBones();
            player->SaveToDB();
            player->RemoveAurasDueToSpell(45322);
            return true;
        }

        player->PlayerTalkClass->ClearMenus();
        AddGossipItemFor(player, 0, "|TInterface/ICONS/achievement_character_human_male:30:30:-18:0|t|rCharacter Information", 1, 3);
        AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_08:30:30:-18:0|t|rToken Services", 1, 1);
        AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_02:30:30:-18:0|t|rSpecial Services", 1, 2);
        for (const auto& elem : MagicStoneMap[2])
        {
            const auto& info = elem.second;
            AddGossipItemFor(player, 0, info.menuIcon + info.menuName, info.menuParent, info.menuId);
        }
        SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
        return true;
    }

    void RefundFullTalents(Player* player)
    {
        if (player->m_usedTalentCount > 120)
            LoginDatabase.PQuery("UPDATE account SET dp=dp+15 WHERE id=%u", player->GetSession()->GetAccountId());
    }

    void RefundTitansGrip(Player* player)
    {
        if (player->HasSpell(46917) && player->getClass() != CLASS_WARRIOR)
            LoginDatabase.PQuery("UPDATE account SET dp=dp+50 WHERE id=%u", player->GetSession()->GetAccountId());
    }

    void OnGossipSelect(Player * player, Item * item, uint32 parentId, uint32 menuId)
    {
        const auto& menu = MagicStoneMap[parentId][menuId];
        player->PlayerTalkClass->ClearMenus();

        switch (menu.menuType)
        {
        case MenuType::SubMenu:
        {
            for (const auto& menu : MagicStoneMap[menu.menuId])
            {
                const auto& info = menu.second;
                AddGossipItemFor(player, 0, info.menuIcon + info.menuName, info.menuParent, info.menuId);
            }
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
        }break;

        case MenuType::SecondSubMenu:
        {
            for (const auto& menu : MagicStoneMap[menu.menuId])
            {
                const auto& info = menu.second;
                AddGossipItemFor(player, 0, info.menuIcon + info.menuName, info.menuParent, info.menuId);
            }
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
        }break;

        case MenuType::ThirdSubMenu:
        {
            for (const auto& menu : MagicStoneMap[menu.menuId])
            {
                const auto& info = menu.second;
                AddGossipItemFor(player, 0, info.menuIcon + info.menuName, info.menuParent, info.menuId);
            }
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
        }break;

        case MenuType::Teleport:
        {
            SpellCastTargets targets;
            player->TeleportTo(menu.mapId, menu.pos_x, menu.pos_y, menu.pos_z, menu.orientation);
            OnUse(player, item, targets);
        }
        break;


        case MenuType::TokenSevices:
            AddGossipItemFor(player, 0, "|TInterface/ICONS/achievement_character_orc_male_brn:30:30:-18:0|tRace Change", 1, 6);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/achievement_character_orc_male:30:30:-18:0|tFaction Change", 1, 7);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_book_03:30:30:-18:0|tName Change", 1, 8);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/achievement_character_nightelf_female:30:30:-18:0|tChange Class", 1, 9);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
            break;

        case MenuType::SpecialServices:
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_book_05:30:30:-18:0|tFull Talents", 1, 4);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/ability_warrior_titansgrip:30:30:-18:0|tTitans Grip", 1, 5);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/achievement_zone_alteracmountains_01:30:30:-18:0|tVIP Zone", 1, 11);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/ability_dualwield:30:30:-18:0|tDual Wield", 1, 12);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_rune_01:30:30:-18:0|tVIP Binding", 1, 13);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
            break;

        case MenuType::FullTalents:
            if (player->GetSession()->GetSecurity() < SEC_MODERATOR)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You are not VIP");
                return;
            }
            if (player->GetPlayerDP() < 15)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have enough DP to make this purchase!");
                return;
            }
            LoginDatabase.PQuery("UPDATE account SET dp=dp-15 WHERE id=%u", player->GetSession()->GetAccountId());
            ChatHandler(player->GetSession()).PSendSysMessage("Thank you for supporting the server!");
            LearnFullTalents(player);
            break;

        case MenuType::TitansGrip:
            if (player->GetSession()->GetSecurity() < SEC_MODERATOR)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You are not VIP");
                return;
            }
            if (player->GetPlayerDP() < 50)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have enough DP to make this purchase!");
                return;
            }
            LoginDatabase.PQuery("UPDATE account SET dp=dp-50 WHERE id=%u", player->GetSession()->GetAccountId());
            ChatHandler(player->GetSession()).PSendSysMessage("Thank you for supporting the server!");
            player->LearnSpell(46917, false);
            break;
        case MenuType::DualWield:
        {
            if (player->GetSession()->GetSecurity() < SEC_MODERATOR)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You are not VIP");
                return;
            }
            ChatHandler(player->GetSession()).PSendSysMessage("Thank you for supporting the server!");
            player->LearnSpell(674, false);
        }
        break;

        case MenuType::VipZone:
            if (player->GetSession()->GetSecurity() < SEC_MODERATOR)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You are not VIP");
                return;
            }
            {
            SpellCastTargets targets;
            player->TeleportTo(menu.mapId, menu.pos_x, menu.pos_y, menu.pos_z, menu.orientation);
            OnUse(player, item, targets);
            }
            break;
        break;

        case MenuType::HomeBind:
        {
            if (player->GetSession()->GetSecurity() < SEC_MODERATOR)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You are not VIP");
                return;
            }
            CloseGossipMenuFor(player);
            WorldLocation loc = player->GetWorldLocation();
            player->SetHomebind(loc, player->GetAreaId());
            ChatHandler(player->GetSession()).PSendSysMessage("Your new home has been set.");
        }
        break;

        case MenuType::CharInformation:
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_02:30:30:-18:0|tYou have " + std::to_string(player->GetPlayerDP()) + " DP", 1, 10);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_03:30:30:-18:0|tYou have " + std::to_string(player->GetPlayerVP()) + " VP", 1, 10);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_04:30:30:-18:0|tYou have " + std::to_string(player->GetPlayerMG()) + " MG", 1, 10);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_letter_01:30:30:-18:0|tMailbox", 1, 24);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_box_01:30:30:-18:0|tBank", 1, 25);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_03:30:30:-18:0|tConvert MG to Coins", 1, 26, "Enter the amount you'd like to convert", 0, true);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/inv_misc_coin_04:30:30:-18:0|tConvert Coins to MG", 1, 27, "Enter the amount you'd like to convert", 0, true);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
            break;

        case MenuType::Mailbox:
            CloseGossipMenuFor(player);
            player->GetSession()->SendShowMailBox(player->GetGUID());
            break;

        case MenuType::Bank:
            CloseGossipMenuFor(player);
            player->GetSession()->SendShowBank(player->GetGUID());
            break;

        case MenuType::ChangeFaction:
            if (!player->HasItemCount(factToken, 1))
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have the required token!");
                return;
            }
            player->DestroyItemCount(factToken, 1, true);
            player->SetAtLoginFlag(AT_LOGIN_CHANGE_FACTION);
            ChatHandler(player->GetSession()).PSendSysMessage("Please relog for the system to take effect!");
            break;

        case MenuType::ChangeRace:
            if (!player->HasItemCount(raceToken, 1))
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have the required token!");
                return;
            }
            player->DestroyItemCount(raceToken, 1, true);
            player->SetAtLoginFlag(AT_LOGIN_CHANGE_RACE);
            ChatHandler(player->GetSession()).PSendSysMessage("Please relog for the system to take effect!");
            break;

        case MenuType::ChangeName:
            if (!player->HasItemCount(nameToken, 1))
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have the required token!");
                return;
            }
            player->DestroyItemCount(nameToken, 1, true);
            player->SetAtLoginFlag(AT_LOGIN_RENAME);
            ChatHandler(player->GetSession()).PSendSysMessage("Please relog for the system to take effect!");
            break;

        case MenuType::ChangeClass:
        {
            if (!player->HasItemCount(clasToken, 1))
            {
                ChatHandler(player->GetSession()).PSendSysMessage("You do not have the required token!");
                return;
            }
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_warrior:30:30:-18:0|tWarrior", 1, 14);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_paladin:30:30:-18:0|tPaladin", 1, 15);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_hunter:30:30:-18:0|tHunter", 1, 16);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_rogue:30:30:-18:0|tRogue", 1, 17);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_priest:30:30:-18:0|tPriest", 1, 18);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_deathknight:30:30:-18:0|tDeath Knight", 1, 19);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_shaman:30:30:-18:0|tShaman", 1, 20);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_mage:30:30:-18:0|tMage", 1, 21);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_warlock:30:30:-18:0|tWarlock", 1, 22);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/classicon_druid:30:30:-18:0|tDruid", 1, 23);
            AddGossipItemFor(player, 0, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tMain Menu", 1, 10);
            SendGossipMenuFor(player, DEFAULT_GOSSIP_MESSAGE, item->GetGUID());
        }
            break;

        case MenuType::ClassWarrior:
        {
            if (player->getClass() == CLASS_WARRIOR){
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Warrior.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARRIOR);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
               
        }
        break;

        case MenuType::ClassPaladin:
        {
            if (player->getClass() == CLASS_PALADIN) {
            ChatHandler(player->GetSession()).PSendSysMessage("You are already a Paladin.");
            return;
        }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_PALADIN);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassHunter:
        {
            if (player->getClass() == CLASS_HUNTER) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Hunter.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_HUNTER);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassRogue:
        {
            if (player->getClass() == CLASS_ROGUE) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Rogue.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_ROGUE);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassPriest:
        {
            if (player->getClass() == CLASS_PRIEST) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Priest.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_PRIEST);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassDeathKnight:
        {
            if (player->getClass() == CLASS_DEATH_KNIGHT) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Death Knight.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_DEATH_KNIGHT);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassShaman:
        {
            if (player->getClass() == CLASS_SHAMAN) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Shaman.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_SHAMAN);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassMage:
        {
            if (player->getClass() == CLASS_MAGE) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Mage.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_MAGE);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassWarlock:
        {
            if (player->getClass() == CLASS_WARLOCK) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Warlock.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_WARLOCK);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;

        case MenuType::ClassDruid:
        {
            if (player->getClass() == CLASS_DRUID) {
                ChatHandler(player->GetSession()).PSendSysMessage("You are already a Druid.");
                return;
            }
            uint32 pGuid = player->GetGUID().GetCounter();
            player->ResetTalents();
            player->ResetSpells(false);
            player->DestroyItemCount(clasToken, 1, true);
            player->SetByteValue(UNIT_FIELD_BYTES_0, UNIT_BYTES_0_OFFSET_CLASS, CLASS_DRUID);
            player->GetSession()->KickPlayer();
            RefundFullTalents(player);
            RefundTitansGrip(player);
        }
        break;
        //hell wtf
        case MenuType::GoBack:
        {
            SpellCastTargets targets;
            OnUse(player, item, targets);
        }
        break;

        }

    }

    void OnGossipSelectCode(Player* player, Item* item, uint32 parentId, uint32 menuId, const char* code)
    {
        const auto& menu = MagicStoneMap[parentId][menuId];
        player->PlayerTalkClass->ClearMenus();
        uint32 mgAmount = std::atoi(code);

        switch (menu.menuType)
        {
        case MenuType::ConvertMG:
        {
            if (player->GetPlayerMG() < mgAmount)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("Not enough Magic Gold.");
                return;
            }
            player->SetPlayerMG(player->GetPlayerMG() - mgAmount);

            ChatHandler(player->GetSession()).PSendSysMessage("Successfully converted MG to Coins.");
            player->AddItem(magicCoin, mgAmount);
        }
        break;

        case MenuType::ConvertCoin:
        {
            if (player->GetItemCount(magicCoin) < mgAmount)
            {
                ChatHandler(player->GetSession()).PSendSysMessage("Not enough Magic Coins.");
                return;
            }
            player->SetPlayerMG(player->GetPlayerMG() + mgAmount);
            player->DestroyItemCount(magicCoin, mgAmount, true, false);
            ChatHandler(player->GetSession()).PSendSysMessage("Successfully converted MG to Coins.");
        }
            break;
        }

    }
};

// Add to script loader
void AddSC_magic_stone()
{
    new magic_stone();
    new magic_stone_reload_command();
    new magic_stone_loader();
}

SQL
Code:
-- Dumping structure for table world_moonlight.z_magic_stone
CREATE TABLE IF NOT EXISTS `z_magic_stone` (
  `menu_id` int(10) unsigned NOT NULL DEFAULT '0',
  `menu_type` int(10) unsigned NOT NULL DEFAULT '0',
  `menu_parent` int(10) unsigned NOT NULL DEFAULT '0',
  `menu_icon` varchar(50) DEFAULT NULL,
  `menu_name` varchar(50) DEFAULT NULL,
  `map` int(10) unsigned DEFAULT '0',
  `position_x` float NOT NULL DEFAULT '0',
  `position_y` float NOT NULL DEFAULT '0',
  `position_z` float NOT NULL DEFAULT '0',
  `orientation` float NOT NULL DEFAULT '0',
  `comment` varchar(50) NOT NULL DEFAULT '0',
  `locked` int(3) DEFAULT NULL,
  `isEvent` int(3) DEFAULT NULL,
  UNIQUE KEY `menu_id` (`menu_id`,`menu_parent`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- Dumping data for table world_moonlight.z_magic_stone: ~46 rows (approximately)
/*!40000 ALTER TABLE `z_magic_stone` DISABLE KEYS */;
INSERT INTO `z_magic_stone` (`menu_id`, `menu_type`, `menu_parent`, `menu_icon`, `menu_name`, `map`, `position_x`, `position_y`, `position_z`, `orientation`, `comment`, `locked`, `isEvent`) VALUES
    (1, 7, 1, 'TOKEN SERVICES DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (2, 8, 1, 'SPECIAL SERVICES DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (3, 9, 1, 'CHAR INFO DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (4, 10, 1, 'FULL TALENTS DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (5, 11, 1, 'TITAN\'S GRIP DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (6, 12, 1, 'CHANGE RACE DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (7, 13, 1, 'CHANGE FACTION DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (8, 14, 1, 'CHANGE NAME DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (9, 15, 1, 'CHANGE CLASS DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (10, 16, 1, 'GO BACK DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (11, 17, 1, 'VIP ZONE DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (12, 18, 1, 'DUAL WIELD DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (13, 19, 1, 'HOMEBIND DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (14, 20, 1, 'WARRIOR DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (15, 21, 1, 'PALADIN DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (16, 22, 1, 'HUNTER DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (17, 23, 1, 'ROGUE DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (18, 24, 1, 'PRIEST DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (19, 25, 1, 'DEATH KNIGHT DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (20, 26, 1, 'SHAMAN DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (21, 27, 1, 'MAGE DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (22, 28, 1, 'WARLOCK DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (23, 29, 1, 'DRUID DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (24, 30, 1, 'MAILBOX DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (25, 31, 1, 'BANK DON\'T TOUCH', NULL, 0, 0, 0, 0, 0, '0', NULL, NULL),
    (31, 3, 2, 'ability_creature_disease_02', 'Blizzlike Instances', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (32, 3, 2, NULL, 'Custom Instances', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (33, 3, 2, NULL, 'Main Cities', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (40, 6, 12, NULL, 'Custom Instance 1', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (41, 6, 12, NULL, 'Custom Instance 2', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (42, 6, 12, NULL, 'Custom Instance 3', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (43, 6, 12, NULL, 'Custom Instance 4', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (44, 6, 12, NULL, 'Custom Instance 5', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (45, 6, 12, NULL, 'Custom Instance 6', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (46, 6, 12, NULL, 'Custom Instance 7', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (47, 6, 12, NULL, 'Custom Instance 8', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (48, 6, 12, NULL, 'Custom Instance 9', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (49, 6, 12, NULL, 'Custom Instance 10', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (50, 6, 12, NULL, 'Custom Instance 11', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (100, 3, 11, '', 'Outland', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (101, 3, 11, '', 'Northrend', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (102, 3, 11, '', 'Kalimdor', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (103, 3, 11, '', 'Eastern Kingdoms', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (150, 6, 13, NULL, 'Stormwind', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (151, 6, 13, NULL, 'Orgrimmar', 0, 0, 0, 0, 0, '0', NULL, NULL),
    (152, 6, 13, NULL, 'Dalaran', 0, 0, 0, 0, 0, '0', NULL, NULL);
(This post was last modified: 12-08-2025, 06:01 PM by BentByte.)



Users browsing this thread: 1 Guest(s)