Sign in to follow this  
Roarl

wotlk
[TC 3.3.5] Stockmarket NPC

Sharing this here as well (copy/paste from Modcraft)

Hi guys!

Took me some time to post this because I couldn't find any fan for my laptop.... But I did some days ago so... Here you go!

As I said before, I acknowledge this is not much. But I just wanna play my part in Modcraft  as best as I can even if it doesn't mean a lot. :)

First you will need the tables and rows which the script uses : SQL File

Then the Creature Script : StockExchange.cpp

/*
1.0.0
StockExchange NPC Script
Description
-----------
The script uses data from DB to define 5 different stocks (Name, Worth (in gold coins), Scale (scale of the stock's variations), OwnedRatio(so that players can't acquire more than its worth)).
Players can buy and sell shares of those stocks, provided they have bought a licence first.

Thanks to Rochet2 for the nice menu look and for helping me clean this script up!
 
*/
#include "ScriptPCH.h"
#include "Config.h"
#include "ScriptedCreature.h"
#include "Language.h"
#include "time.h"
#define STOCKNUMBER 5
#define GOLDTOCOPPER 10000
namespace
{
    class CS_StockExchange : public CreatureScript
    {
    public:
        CS_StockExchange() : CreatureScript("Creature_StockExchange") { }
        
        uint32 stock = 0;
        void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) override
        {
        }
        bool OnGossipHello(Player* plr, Creature* creature) override //MAIN MENU
        {
            //StockUpdate every 2 minutes
            QueryResult result = WorldDatabase.PQuery("SELECT `UpdateTime`   FROM `stocks` WHERE iD = 0");
            if (!result)
                return false;
            Field* field = result->Fetch();
            uint32 stockPrevTime = field[0].GetUInt32();
            uint32 realCurrTime = getMSTime();
            uint32 stockDiff = getMSTimeDiff(stockPrevTime, realCurrTime);
            if (stockDiff >= 120000)
            {
                uint32 timeMult;
                timeMult = stockDiff / 120000;
                if (StockUpdate(timeMult))
                    TC_LOG_INFO("server.worldserver", "Stocks have been updated (%u)", realCurrTime);
                else
                {
                    TC_LOG_INFO("server.worldserver", "Error while updating stocks...");
                }
                stockPrevTime = realCurrTime;
                WorldDatabase.PExecute("UPDATE `stocks` SET `UpdateTime` = %u WHERE `iD` = 0", getMSTime());
            }
            WorldSession* session = plr->GetSession();
            QueryResult licencetest = CharacterDatabase.PQuery("SELECT `1`, `2`, `3`, `4`, `5`  FROM `character_stockdata` WHERE iD = %u", plr->GetGUIDLow());
            plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Scroll_08:30:30:-18:0|tWhat are the current exchange rates?", GOSSIP_SENDER_MAIN, 2);
            plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tHow many unsold shares are there left?", GOSSIP_SENDER_MAIN, 1);
            if (!licencetest)
            {
            plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_MISC_NOTE_02:30:30:-18:0|tI'd like to acquire a trade licence.", GOSSIP_SENDER_MAIN, 12, "This will cost you", 400000, false);
            }
            else //Player can invest if he has a licence
            {
            plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_02:30:30:-18:0|tI'd like to manage my portfolio.", GOSSIP_SENDER_MAIN, 3);
            }
            plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tIt was a pleasure to make business with you.", GOSSIP_SENDER_MAIN, 4);
            plr->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());
            return true;
        }
        bool OnGossipSelect(Player* plr, Creature* creature, uint32 sender, uint32 uiAction) override
        {
            
            int32 amount = 0;
            plr->PlayerTalkClass->ClearMenus();
            WorldSession* session = plr->GetSession();
            std::ostringstream message;
            float ownedratio[5];
            int worth[5];
            for (int iter = 1; iter < 6; iter++)
            {
            QueryResult result = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`   FROM `stocks` WHERE iD = %u", iter);
            if (!result)
                return false;
            Field* field = result->Fetch();
            ownedratio[iter-1]= field[0].GetFloat();
            worth[iter-1] = field[1].GetInt32();
            }
            switch (uiAction)
            {
            case 1: //REMAINING SHARES
                message << "REMAINING SHARES (in gold coins)$BRavenholdt Manor : " << worth[0] * (1 - ownedratio[0]) << "$BBloodsail : " << worth[1] * (1 - ownedratio[1]) << "$BSteamwheedle Cartel : " << worth[2] * (1 - ownedratio[2]) << "$BTheramore Silk Traders : " << worth[3] * (1 - ownedratio[3]) << "$BEldoar'norore : " << worth[4] * (1 - ownedratio[4]);
                creature->Whisper(message.str(), LANG_UNIVERSAL, plr);
                plr->PlayerTalkClass->SendCloseGossip();
                OnGossipHello(plr, creature);
                break;
            case 2: //CURRENT EXCHANGE RATES
                message << "CURRENT EXCHANGE RATES (in gold coins)$BRavenholdt Manor : " << worth[0] << "$BBloodsail : " << worth[1] << "$BSteamwheedle Cartel : " << worth[2] << "$BTheramore Silk Traders : " << worth[3] << "$BEldoar'norore : " << worth[4];
                creature->Whisper(message.str(), LANG_UNIVERSAL, plr);
                plr->PlayerTalkClass->SendCloseGossip();
                OnGossipHello(plr, creature);
                break;
            case 3: //MANAGE PORTFOLIO MENU (5-10)
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Helmet_30:30:30:-18:0|tRavenholdt Manor", GOSSIP_SENDER_MAIN, 5);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Helmet_66:30:30:-18:0|tBloodsail", GOSSIP_SENDER_MAIN, 6);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Bomb_03:30:30:-18:0|tSteamwheedle Cartel", GOSSIP_SENDER_MAIN, 7);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Chest_Cloth_56:30:30:-18:0|tTheramore Silk Traders", GOSSIP_SENDER_MAIN, 8);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_FireDancer_01:30:30:-18:0|tEldoar'norore", GOSSIP_SENDER_MAIN, 9);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack", GOSSIP_SENDER_MAIN, 10);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                break;
            case 4: //CLOSE GOSSIP
                plr->PlayerTalkClass->SendCloseGossip();
                break;
            case 5: //MANAGE RAVENHOLDT STOCK
                stock = 1;
                plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                return true;
                break;
            case 6: //MANAGE BLOODSAIL STOCK
                stock = 2;
                plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                break;
            case 7: //MANAGE GOBLIN STOCK
                stock = 3;
                plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                break;
            case 8: //MANAGE SILKTRADERS STOCK
                stock = 4;
                plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                break;
            case 9: //MANAGE ELDOAR'NORORE STOCK
                stock = 5;
                plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);
                plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);
                plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());
                return true;
                break;
            case 11: //TRANSACTION = SELL
                if (!SellStock(plr, stock, creature))
                    plr->GetSession()->SendNotification("Error while selling shares... Please contact the administrator.");
                else
                {
                    
                }
                plr->PlayerTalkClass->SendCloseGossip();
                OnGossipHello(plr, creature);
                    
                break;
            case 12: //CREATE PLAYER LICENCE ( = ROW IN CHARACTER_STOCKDATA )
                if (plr->GetMoney() >= 40*GOLDTOCOPPER)
                {
                if (CreateLicence(plr))
                {
                    amount = 40*GOLDTOCOPPER;
                    plr->ModifyMoney(-amount);
                    message << "Your licence has been acquired successfully, " << plr->GetName() << "!";
                    creature->Say(message.str(), LANG_UNIVERSAL, plr);
                }
                else
                    plr->GetSession()->SendNotification("Error while registering your licence. Please contact the administrator.");
                }
                else
                {
                    message << "I am afraid you do not have these 40 gold coins, " << plr->GetName() << "...";
                    creature->Say(message.str().c_str(), LANG_UNIVERSAL, plr);
                }
                plr->PlayerTalkClass->SendCloseGossip();
                OnGossipHello(plr, creature);
                break;
            default:
                OnGossipHello(plr, creature);
                break;
            }
            return true;
        }
        bool OnGossipSelectCode(Player* plr, Creature* creature, uint32 stock, uint32 uiAction, const char* code) override
        {
            plr->PlayerTalkClass->ClearMenus();
            std::ostringstream message;
            int32 amount = 0;
            std::string investment = code;
            static const char* allowedcharacters = "1234567890";
            if (!investment.length() || investment.find_first_not_of(allowedcharacters) != std::string::npos) //If investment was specified incorrectly
            {
                plr->GetSession()->SendNotification("Your investment bust be declared using figures.(0123456789)");
            }
            else //If investment was specified properly
            {
                //Statements
                uint32 investmentI = uint32(atol(code));
                if (investmentI*GOLDTOCOPPER <= plr->GetMoney())
                {
                QueryResult result1 = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`  FROM `stocks` WHERE iD = %u", stock);
                if (!result1)
                    return false;
                Field* field = result1->Fetch();
                float ownedratio = field[0].GetFloat();
                int worth = field[1].GetInt32();
                QueryResult result2 = CharacterDatabase.PQuery("SELECT `%u` FROM `character_stockdata` WHERE iD = %u", stock, plr->GetGUIDLow());
                if (!result2)
                    return false;
                field = result2->Fetch();
                float initialratio = field[0].GetFloat();
                float ratio = static_cast<float>(investmentI) / worth;
                if (ratio <= (1-ownedratio)) //If enough stocks left
                {
                int amount = investmentI*GOLDTOCOPPER;
                plr->ModifyMoney(-amount);  // substract it from player money
                CharacterDatabase.PExecute("UPDATE `character_stockdata` SET `%u` = %f WHERE `iD` = %u", stock, initialratio + ratio, plr->GetGUIDLow());
                WorldDatabase.PExecute("UPDATE `stocks` SET `OwnedRatio` = %f WHERE `iD` = %u", ownedratio + ratio, stock);
                }
                else
                {
                    plr->GetSession()->SendNotification("There are not so many shares for you to acquire, check the remaining shares before trying to invest.");
                }
                }
                else
                {
                    message << "You do not have so much money, " << plr->GetName() << ".";
                    creature->Say(message.str().c_str(), LANG_UNIVERSAL, plr);
                }
            }
            plr->PlayerTalkClass->SendCloseGossip();
            OnGossipHello(plr, creature);
            return true;
        }
        
        private :
            bool SendMoneyByMail(ObjectGuid player, uint64 money, int32 stock)
            {
                MailSender sender(MAIL_CREATURE, 50038, MAIL_STATIONERY_DEFAULT);
                std::string stockName;
                switch (stock)
                {
                case 1:
                    stockName = "Ravenholdt Manor";
                    break;
                case 2:
                    stockName = "Bloodsail";
                    break;
                case 3:
                    stockName = "Steamwheedle Cartel";
                    break;
                case 4:
                    stockName = "Theramore Silk Traders";
                    break;
                case 5:
                    stockName = "Eldoar'norore";
                    break;
                default:
                    return false;
                }
                std::ostringstream text;
                text << "You have requested the General Exchange Hall to sell your shares of the " << stockName << " stock. This has yielded some " << money/GOLDTOCOPPER << " gold coins from which I have deducted " <<  money/10/GOLDTOCOPPER << " in the sake of various sale and accountancy costs. Enclosed to this letter are " << 9* money/10/GOLDTOCOPPER << " gold coins which come down to you.";
                MailDraft draft("Share Sale", text.str().c_str());
                draft.AddMoney(money * 9 / 10);
                SQLTransaction letter = CharacterDatabase.BeginTransaction();
                draft.SendMailTo(letter, MailReceiver(NULL, player.GetCounter()), sender);
                CharacterDatabase.CommitTransaction(letter);
                return true;
            }
            bool SellStock(Player* plr, int32 stock, Creature* creature) /*SELL ALL THE SHARES OF THE SPECIFIED STOCK */
            {
                QueryResult result2 = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`   FROM `stocks` WHERE iD = %u", stock);
                if (!result2)
                    return false;
                QueryResult result1 = CharacterDatabase.PQuery("SELECT `1`, `2`, `3`, `4`, `5`  FROM `character_stockdata` WHERE iD = %u", plr->GetGUIDLow());
                if (!result1)
                    return false;
                Field* field = result1->Fetch();
                float ratio = field[stock - 1].GetFloat();
                if (ratio == 0)
                {
                    plr->GetSession()->SendNotification("You don't own any share of this stock...");
                }
                else //ONLY IF PLAYER OWNS SOMETHING
                {
                    Field* field = result2->Fetch();
                    float newownedratio = field[0].GetFloat()-ratio;
                    int worth = field[1].GetInt32();
                    if (!SendMoneyByMail(plr->GetGUID(), worth*GOLDTOCOPPER*ratio, stock))
                        return false;
                    std::ostringstream text;
                    text << "I shall make the arragement for the sale, " << plr->GetName() << ", you will receive your money by mail soon enough.";
                    creature->Say(text.str().c_str(), LANG_UNIVERSAL);
                    CharacterDatabase.PExecute("UPDATE `character_stockdata` SET `%u` = 0 WHERE `iD` = %u", stock, plr->GetGUIDLow());
                    WorldDatabase.PExecute("UPDATE `stocks` SET `OwnedRatio` = %f WHERE `iD` = %u", newownedratio, stock);
                }
                return true;
            }
            bool CreateLicence(Player* plr)
            {
                SQLTransaction trans = CharacterDatabase.BeginTransaction();
                trans->PAppend("REPLACE INTO `character_stockdata` (`iD`, `1`, `2`, `3`, `4`, `5`) VALUES (%u, 0, 0, 0, 0, 0)", plr->GetGUIDLow());
                CharacterDatabase.CommitTransaction(trans);
                return true;
            }
            bool StockUpdate(int timeMult)
            {
                int32 stockWorth[STOCKNUMBER], newStockWorth[STOCKNUMBER];
                int32 stockScale[STOCKNUMBER];
                float stockOwnedRatio[STOCKNUMBER];
                srand(time(NULL));
                // Load stock values from DB
                for (int itr = 0; itr < STOCKNUMBER; itr++)
                {
                    QueryResult result = WorldDatabase.PQuery("SELECT `Scale`,`OwnedRatio`,`Worth`  FROM `stocks` WHERE iD = %u", itr + 1);
                    if (!result)
                        return false;
                    Field* field = result->Fetch();
                    stockScale[itr] = field[0].GetInt32();
                    stockOwnedRatio[itr] = field[1].GetFloat();
                    stockWorth[itr] = field[2].GetInt32();
                }
                // Dicethrows and Upload values to DB
                for (int itr = 0; itr < STOCKNUMBER; itr++)
                {
                    char sign;
                    if (stockWorth[itr] + stockScale[itr]*timeMult > 200000) //Don't go over 200.000 gold coins
                        sign = -1;
                    else if (stockWorth[itr] - stockScale[itr]*timeMult < 0) //Nor below 0
                        sign = 1;
                    else
                    {
                        int dice = (rand() % 101) + floor(10 * stockOwnedRatio[itr]) - 55;
                        sign = dice / abs(dice);
                    }
                    newStockWorth[itr] = stockWorth[itr] + sign*stockScale[itr]*timeMult;
                    WorldDatabase.PExecute("UPDATE `stocks` SET `worth` = %u WHERE `iD` = %u", newStockWorth[itr], itr + 1);
                }
                return true;
                }
    };
}
    void AddSC_Stock()
    {
        new CS_StockExchange();
    }

I know this code ain't perfect but I'm still open for suggestions and critics. :)

Have a nice day.

Edited by Roarl
  • Like 2

Share this post


Link to post
Share on other sites
On 2015/11/26 at PM8点12分, Roarl said:

也可以在此处共享(从Modcraft复制/粘贴)

嗨,大家好!

花了我一些时间发布此消息,因为我找不到笔记本电脑的风扇。...但是几天前我这样做了,所以...来了!

如我之前所说,我承认这一点并不多。但是我只是想尽我最大的努力在Modcraft中发挥作用,即使这并不意味着什么。:)

首先,您将需要脚本使用的表和行:SQL File

然后创建生物脚本:StockExchange.cpp

/* 1.0.0 StockExchange NPC Script Description ----------- The script uses data from DB to define 5 different stocks (Name, Worth (in gold coins), Scale (scale of the stock's variations), OwnedRatio(so that players can't acquire more than its worth)). Players can buy and sell shares of those stocks, provided they have bought a licence first. Thanks to Rochet2 for the nice menu look and for helping me clean this script up!   */ #include "ScriptPCH.h" #include "Config.h" #include "ScriptedCreature.h" #include "Language.h" #include "time.h" #define STOCKNUMBER 5 #define GOLDTOCOPPER 10000 namespace {     class CS_StockExchange : public CreatureScript     {     public:         CS_StockExchange() : CreatureScript("Creature_StockExchange") { }                  uint32 stock = 0;         void OnPlayerTextEmote(Player* player, uint32 textEmote, uint32 emoteNum, ObjectGuid guid) override         {         }         bool OnGossipHello(Player* plr, Creature* creature) override //MAIN MENU         {             //StockUpdate every 2 minutes             QueryResult result = WorldDatabase.PQuery("SELECT `UpdateTime`   FROM `stocks` WHERE iD = 0");             if (!result)                 return false;             Field* field = result->Fetch();             uint32 stockPrevTime = field[0].GetUInt32();             uint32 realCurrTime = getMSTime();             uint32 stockDiff = getMSTimeDiff(stockPrevTime, realCurrTime);             if (stockDiff >= 120000)             {                 uint32 timeMult;                 timeMult = stockDiff / 120000;                 if (StockUpdate(timeMult))                     TC_LOG_INFO("server.worldserver", "Stocks have been updated (%u)", realCurrTime);                 else                 {                     TC_LOG_INFO("server.worldserver", "Error while updating stocks...");                 }                 stockPrevTime = realCurrTime;                 WorldDatabase.PExecute("UPDATE `stocks` SET `UpdateTime` = %u WHERE `iD` = 0", getMSTime());             }             WorldSession* session = plr->GetSession();             QueryResult licencetest = CharacterDatabase.PQuery("SELECT `1`, `2`, `3`, `4`, `5`  FROM `character_stockdata` WHERE iD = %u", plr->GetGUIDLow());             plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Scroll_08:30:30:-18:0|tWhat are the current exchange rates?", GOSSIP_SENDER_MAIN, 2);             plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Book_11:30:30:-18:0|tHow many unsold shares are there left?", GOSSIP_SENDER_MAIN, 1);             if (!licencetest)             {             plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_MISC_NOTE_02:30:30:-18:0|tI'd like to acquire a trade licence.", GOSSIP_SENDER_MAIN, 12, "This will cost you", 400000, false);             }             else //Player can invest if he has a licence             {             plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_02:30:30:-18:0|tI'd like to manage my portfolio.", GOSSIP_SENDER_MAIN, 3);             }             plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tIt was a pleasure to make business with you.", GOSSIP_SENDER_MAIN, 4);             plr->SEND_GOSSIP_MENU(DEFAULT_GOSSIP_MESSAGE, creature->GetGUID());             return true;         }         bool OnGossipSelect(Player* plr, Creature* creature, uint32 sender, uint32 uiAction) override         {                          int32 amount = 0;             plr->PlayerTalkClass->ClearMenus();             WorldSession* session = plr->GetSession();             std::ostringstream message;             float ownedratio[5];             int worth[5];             for (int iter = 1; iter < 6; iter++)             {             QueryResult result = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`   FROM `stocks` WHERE iD = %u", iter);             if (!result)                 return false;             Field* field = result->Fetch();             ownedratio[iter-1]= field[0].GetFloat();             worth[iter-1] = field[1].GetInt32();             }             switch (uiAction)             {             case 1: //REMAINING SHARES                 message << "REMAINING SHARES (in gold coins)$BRavenholdt Manor : " << worth[0] * (1 - ownedratio[0]) << "$BBloodsail : " << worth[1] * (1 - ownedratio[1]) << "$BSteamwheedle Cartel : " << worth[2] * (1 - ownedratio[2]) << "$BTheramore Silk Traders : " << worth[3] * (1 - ownedratio[3]) << "$BEldoar'norore : " << worth[4] * (1 - ownedratio[4]);                 creature->Whisper(message.str(), LANG_UNIVERSAL, plr);                 plr->PlayerTalkClass->SendCloseGossip();                 OnGossipHello(plr, creature);                 break;             case 2: //CURRENT EXCHANGE RATES                 message << "CURRENT EXCHANGE RATES (in gold coins)$BRavenholdt Manor : " << worth[0] << "$BBloodsail : " << worth[1] << "$BSteamwheedle Cartel : " << worth[2] << "$BTheramore Silk Traders : " << worth[3] << "$BEldoar'norore : " << worth[4];                 creature->Whisper(message.str(), LANG_UNIVERSAL, plr);                 plr->PlayerTalkClass->SendCloseGossip();                 OnGossipHello(plr, creature);                 break;             case 3: //MANAGE PORTFOLIO MENU (5-10)                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Helmet_30:30:30:-18:0|tRavenholdt Manor", GOSSIP_SENDER_MAIN, 5);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Helmet_66:30:30:-18:0|tBloodsail", GOSSIP_SENDER_MAIN, 6);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Bomb_03:30:30:-18:0|tSteamwheedle Cartel", GOSSIP_SENDER_MAIN, 7);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Chest_Cloth_56:30:30:-18:0|tTheramore Silk Traders", GOSSIP_SENDER_MAIN, 8);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_FireDancer_01:30:30:-18:0|tEldoar'norore", GOSSIP_SENDER_MAIN, 9);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack", GOSSIP_SENDER_MAIN, 10);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 break;             case 4: //CLOSE GOSSIP                 plr->PlayerTalkClass->SendCloseGossip();                 break;             case 5: //MANAGE RAVENHOLDT STOCK                 stock = 1;                 plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 return true;                 break;             case 6: //MANAGE BLOODSAIL STOCK                 stock = 2;                 plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 break;             case 7: //MANAGE GOBLIN STOCK                 stock = 3;                 plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 break;             case 8: //MANAGE SILKTRADERS STOCK                 stock = 4;                 plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 break;             case 9: //MANAGE ELDOAR'NORORE STOCK                 stock = 5;                 plr->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Letter_03:30:30:-18:0|tBuy shares", stock, 0, "How much gold would you like to invest?", 0, true);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/INV_Misc_Coin_16:30:30:-18:0|tSell all shares", stock, 11);                 plr->ADD_GOSSIP_ITEM(GOSSIP_ICON_MONEY_BAG, "|TInterface/ICONS/Ability_Spy:30:30:-18:0|tBack...", GOSSIP_SENDER_MAIN, 3);                 plr->SEND_GOSSIP_MENU(50002, creature->GetGUID());                 return true;                 break;             case 11: //TRANSACTION = SELL                 if (!SellStock(plr, stock, creature))                     plr->GetSession()->SendNotification("Error while selling shares... Please contact the administrator.");                 else                 {                                      }                 plr->PlayerTalkClass->SendCloseGossip();                 OnGossipHello(plr, creature);                                      break;             case 12: //CREATE PLAYER LICENCE ( = ROW IN CHARACTER_STOCKDATA )                 if (plr->GetMoney() >= 40*GOLDTOCOPPER)                 {                 if (CreateLicence(plr))                 {                     amount = 40*GOLDTOCOPPER;                     plr->ModifyMoney(-amount);                     message << "Your licence has been acquired successfully, " << plr->GetName() << "!";                     creature->Say(message.str(), LANG_UNIVERSAL, plr);                 }                 else                     plr->GetSession()->SendNotification("Error while registering your licence. Please contact the administrator.");                 }                 else                 {                     message << "I am afraid you do not have these 40 gold coins, " << plr->GetName() << "...";                     creature->Say(message.str().c_str(), LANG_UNIVERSAL, plr);                 }                 plr->PlayerTalkClass->SendCloseGossip();                 OnGossipHello(plr, creature);                 break;             default:                 OnGossipHello(plr, creature);                 break;             }             return true;         }         bool OnGossipSelectCode(Player* plr, Creature* creature, uint32 stock, uint32 uiAction, const char* code) override         {             plr->PlayerTalkClass->ClearMenus();             std::ostringstream message;             int32 amount = 0;             std::string investment = code;             static const char* allowedcharacters = "1234567890";             if (!investment.length() || investment.find_first_not_of(allowedcharacters) != std::string::npos) //If investment was specified incorrectly             {                 plr->GetSession()->SendNotification("Your investment bust be declared using figures.(0123456789)");             }             else //If investment was specified properly             {                 //Statements                 uint32 investmentI = uint32(atol(code));                 if (investmentI*GOLDTOCOPPER <= plr->GetMoney())                 {                 QueryResult result1 = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`  FROM `stocks` WHERE iD = %u", stock);                 if (!result1)                     return false;                 Field* field = result1->Fetch();                 float ownedratio = field[0].GetFloat();                 int worth = field[1].GetInt32();                 QueryResult result2 = CharacterDatabase.PQuery("SELECT `%u` FROM `character_stockdata` WHERE iD = %u", stock, plr->GetGUIDLow());                 if (!result2)                     return false;                 field = result2->Fetch();                 float initialratio = field[0].GetFloat();                 float ratio = static_cast<float>(investmentI) / worth;                 if (ratio <= (1-ownedratio)) //If enough stocks left                 {                 int amount = investmentI*GOLDTOCOPPER;                 plr->ModifyMoney(-amount);  // substract it from player money                 CharacterDatabase.PExecute("UPDATE `character_stockdata` SET `%u` = %f WHERE `iD` = %u", stock, initialratio + ratio, plr->GetGUIDLow());                 WorldDatabase.PExecute("UPDATE `stocks` SET `OwnedRatio` = %f WHERE `iD` = %u", ownedratio + ratio, stock);                 }                 else                 {                     plr->GetSession()->SendNotification("There are not so many shares for you to acquire, check the remaining shares before trying to invest.");                 }                 }                 else                 {                     message << "You do not have so much money, " << plr->GetName() << ".";                     creature->Say(message.str().c_str(), LANG_UNIVERSAL, plr);                 }             }             plr->PlayerTalkClass->SendCloseGossip();             OnGossipHello(plr, creature);             return true;         }                  private :             bool SendMoneyByMail(ObjectGuid player, uint64 money, int32 stock)             {                 MailSender sender(MAIL_CREATURE, 50038, MAIL_STATIONERY_DEFAULT);                 std::string stockName;                 switch (stock)                 {                 case 1:                     stockName = "Ravenholdt Manor";                     break;                 case 2:                     stockName = "Bloodsail";                     break;                 case 3:                     stockName = "Steamwheedle Cartel";                     break;                 case 4:                     stockName = "Theramore Silk Traders";                     break;                 case 5:                     stockName = "Eldoar'norore";                     break;                 default:                     return false;                 }                 std::ostringstream text;                 text << "You have requested the General Exchange Hall to sell your shares of the " << stockName << " stock. This has yielded some " << money/GOLDTOCOPPER << " gold coins from which I have deducted " <<  money/10/GOLDTOCOPPER << " in the sake of various sale and accountancy costs. Enclosed to this letter are " << 9* money/10/GOLDTOCOPPER << " gold coins which come down to you.";                 MailDraft draft("Share Sale", text.str().c_str());                 draft.AddMoney(money * 9 / 10);                 SQLTransaction letter = CharacterDatabase.BeginTransaction();                 draft.SendMailTo(letter, MailReceiver(NULL, player.GetCounter()), sender);                 CharacterDatabase.CommitTransaction(letter);                 return true;             }             bool SellStock(Player* plr, int32 stock, Creature* creature) /*SELL ALL THE SHARES OF THE SPECIFIED STOCK */             {                 QueryResult result2 = WorldDatabase.PQuery("SELECT `OwnedRatio`,`Worth`   FROM `stocks` WHERE iD = %u", stock);                 if (!result2)                     return false;                 QueryResult result1 = CharacterDatabase.PQuery("SELECT `1`, `2`, `3`, `4`, `5`  FROM `character_stockdata` WHERE iD = %u", plr->GetGUIDLow());                 if (!result1)                     return false;                 Field* field = result1->Fetch();                 float ratio = field[stock - 1].GetFloat();                 if (ratio == 0)                 {                     plr->GetSession()->SendNotification("You don't own any share of this stock...");                 }                 else //ONLY IF PLAYER OWNS SOMETHING                 {                     Field* field = result2->Fetch();                     float newownedratio = field[0].GetFloat()-ratio;                     int worth = field[1].GetInt32();                     if (!SendMoneyByMail(plr->GetGUID(), worth*GOLDTOCOPPER*ratio, stock))                         return false;                     std::ostringstream text;                     text << "I shall make the arragement for the sale, " << plr->GetName() << ", you will receive your money by mail soon enough.";                     creature->Say(text.str().c_str(), LANG_UNIVERSAL);                     CharacterDatabase.PExecute("UPDATE `character_stockdata` SET `%u` = 0 WHERE `iD` = %u", stock, plr->GetGUIDLow());                     WorldDatabase.PExecute("UPDATE `stocks` SET `OwnedRatio` = %f WHERE `iD` = %u", newownedratio, stock);                 }                 return true;             }             bool CreateLicence(Player* plr)             {                 SQLTransaction trans = CharacterDatabase.BeginTransaction();                 trans->PAppend("REPLACE INTO `character_stockdata` (`iD`, `1`, `2`, `3`, `4`, `5`) VALUES (%u, 0, 0, 0, 0, 0)", plr->GetGUIDLow());                 CharacterDatabase.CommitTransaction(trans);                 return true;             }             bool StockUpdate(int timeMult)             {                 int32 stockWorth[STOCKNUMBER], newStockWorth[STOCKNUMBER];                 int32 stockScale[STOCKNUMBER];                 float stockOwnedRatio[STOCKNUMBER];                 srand(time(NULL));                 // Load stock values from DB                 for (int itr = 0; itr < STOCKNUMBER; itr++)                 {                     QueryResult result = WorldDatabase.PQuery("SELECT `Scale`,`OwnedRatio`,`Worth`  FROM `stocks` WHERE iD = %u", itr + 1);                     if (!result)                         return false;                     Field* field = result->Fetch();                     stockScale[itr] = field[0].GetInt32();                     stockOwnedRatio[itr] = field[1].GetFloat();                     stockWorth[itr] = field[2].GetInt32();                 }                 // Dicethrows and Upload values to DB                 for (int itr = 0; itr < STOCKNUMBER; itr++)                 {                     char sign;                     if (stockWorth[itr] + stockScale[itr]*timeMult > 200000) //Don't go over 200.000 gold coins                         sign = -1;                     else if (stockWorth[itr] - stockScale[itr]*timeMult < 0) //Nor below 0                         sign = 1;                     else                     {                         int dice = (rand() % 101) + floor(10 * stockOwnedRatio[itr]) - 55;                         sign = dice / abs(dice);                     }                     newStockWorth[itr] = stockWorth[itr] + sign*stockScale[itr]*timeMult;                     WorldDatabase.PExecute("UPDATE `stocks` SET `worth` = %u WHERE `iD` = %u", newStockWorth[itr], itr + 1);                 }                 return true;                 }     }; }     void AddSC_Stock()     {         new CS_StockExchange();     }




 
        
            
                    
                    
        

我知道这段代码并不完美,但我仍然欢迎提出建议和提出批评。 :)

祝你今天愉快。

The download link is invalid. Can you update the link

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this