Rochet2

Gold banker

Apr 15th, 2013
392
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.53 KB | None | 0 0
  1. /*######################-> [[GOLD BANKER ]] <-#########################
  2. **************************! DEV: ak47sigh !****************************
  3. #######################################################################*/
  4.  
  5. // Rewritten by Rochet2
  6.  
  7. #include "ScriptPCH.h"
  8. #include <cstring>
  9. #include "Chat.h"
  10. #include <cctype>
  11.  
  12. // -- [[ Configs:
  13. const uint8 maxPlayerDeposits = 3;          // absolute max 30
  14. const uint8 minDepositNameLenght = 3;
  15. const uint8 maxDepositNameLenght = 255;
  16. const uint32 createDepositCost = 100000;    // default 10 gold per deposit (number in copper)
  17. const uint32 createDepositPlus = 50000;     // increase the cost by X gold for each new repository
  18.  
  19. // -- [[ DO NOT EDIT BELOW // --
  20.  
  21. struct depInfo
  22. {
  23.     uint32 gold;
  24.     std::string name;
  25.     std::string pass;
  26. };
  27.  
  28. bool cmp_by_name(const depInfo &a, const depInfo &b)
  29. {
  30.     return a.name < b.name; // c_str()?
  31. }
  32.  
  33. class gold_banker : public CreatureScript
  34. {
  35. public:
  36.     enum banker_actions
  37.     {
  38.         CREATE_DEPOSIT,
  39.         LIST_DEPOSITS,
  40.         EDIT_DEPOSIT,
  41.         CLOSE_MENU,
  42.  
  43.         DEPOSIT_WITHDRAW,
  44.         DEPOSIT_DEPOSIT,
  45.         DEPOSIT_RENAME,
  46.         DEPOSIT_DELETE,
  47.         ADD_PASSWORD,
  48.         MODIFY_PASSWORD,
  49.         REMOVE_PASSWORD,
  50.     };
  51.     UNORDERED_MAP<uint32, std::list<depInfo> > deposits; // plrGUID, info
  52.  
  53.     depInfo* getDeposit(Player* player, uint8 key = 0)
  54.     {
  55.         std::list<depInfo>::iterator it = deposits[player->GetGUIDLow()].begin();
  56.         if(key)
  57.             std::advance(it, key);
  58.         if(it == deposits[player->GetGUIDLow()].end())
  59.         {
  60.             sendError(player, "Internal error. Deposit no longer exists!");
  61.             return NULL;
  62.         }
  63.         return &(*it);
  64.     }
  65.  
  66.     void sendError(Player* player, const char* error)
  67.     {
  68.         player->GetSession()->SendNotification(error);
  69.         ChatHandler(player->GetSession()).PSendSysMessage(error);
  70.     }
  71.  
  72.     // A custom ModifyMoney that can handle up to uint32 values, which allows transactions the size of max money amount.
  73.     bool modifyMoney(Player* player, uint32 amount, bool addMoney)
  74.     {
  75.         if (!amount)
  76.             return true;
  77.  
  78.         if (!addMoney)
  79.             player->SetMoney(player->GetMoney() > amount ? player->GetMoney() - amount : 0);
  80.         else
  81.         {
  82.             if (player->GetMoney() < uint32(MAX_MONEY_AMOUNT - amount))
  83.                 player->SetMoney(player->GetMoney() + amount);
  84.             else
  85.             {
  86.                 player->SendEquipError(EQUIP_ERR_TOO_MUCH_GOLD, NULL, NULL);
  87.                 return false;
  88.             }
  89.         }
  90.         return true;
  91.     }
  92.  
  93.     bool checkName(Player* player, std::string nameStr)
  94.     {
  95.         if(nameStr.length() < minDepositNameLenght)
  96.         {
  97.             sendError(player, ("You inserted too short name: "+nameStr).c_str());
  98.             return false;
  99.         }
  100.         if(nameStr.length() > maxDepositNameLenght)
  101.         {
  102.             sendError(player, ("You inserted too long name: "+nameStr).c_str());
  103.             return false;
  104.         }
  105.  
  106.         std::list<depInfo> infos = deposits[player->GetGUIDLow()];
  107.         std::list<depInfo>::iterator it = infos.begin();
  108.         while(it != infos.end())
  109.         {
  110.             if(it->name == nameStr)
  111.             {
  112.                 sendError(player, ("You already have a deposit with name "+nameStr).c_str());
  113.                 return false;
  114.             }
  115.             ++it;
  116.         }
  117.         return true;
  118.     }
  119.  
  120.     gold_banker() : CreatureScript("Gold_Banker")
  121.     {
  122.         CharacterDatabase.DirectExecute("DELETE FROM gold_bank_data WHERE NOT EXISTS(SELECT 1 FROM characters WHERE characters.guid = gold_bank_data.plrGUID)");
  123.         QueryResult result = CharacterDatabase.Query("SELECT `plrGUID`, `name`, `gold`, `password` FROM `gold_bank_data` ORDER BY `name` ASC");
  124.         if(result)
  125.         {
  126.             Field* fields = result->Fetch();
  127.             do
  128.             {
  129.                 uint32 plrGUID = fields[0].GetUInt32();
  130.                 std::string name = fields[1].GetString();
  131.                 uint32 gold = fields[2].GetUInt32();
  132.                 std::string pass = fields[3].GetString();
  133.  
  134.                 depInfo info = {gold, name, pass};
  135.                 deposits[plrGUID].push_back(info);
  136.             }
  137.             while (result->NextRow());
  138.         }
  139.     }
  140.  
  141.     bool OnGossipHello(Player * player, Creature * creature)
  142.     {
  143.         ListPlayerDeposits(player, creature);
  144.         return true;
  145.     }
  146.     bool OnGossipSelect(Player * player, Creature * creature, uint32 action, uint32 deposit)
  147.     {
  148.         player->PlayerTalkClass->ClearMenus();
  149.  
  150.         switch(action)
  151.         {
  152.         case LIST_DEPOSITS:
  153.             ListPlayerDeposits(player, creature);
  154.             return true;
  155.         case EDIT_DEPOSIT:
  156.             EditDeposit(player, creature, deposit);
  157.             return true;
  158.         case CLOSE_MENU:
  159.             player->CLOSE_GOSSIP_MENU();
  160.             return true;
  161.         }
  162.         ListPlayerDeposits(player, creature);
  163.         return true;
  164.     }
  165.     bool OnGossipSelectCode(Player* player, Creature* creature, uint32 action, uint32 deposit, const char* code)
  166.     {
  167.         player->PlayerTalkClass->ClearMenus();
  168.         switch(action)
  169.         {
  170.         case CREATE_DEPOSIT:
  171.             CreateDeposit(player, code);
  172.             break;
  173.         case DEPOSIT_WITHDRAW:
  174.             WithdrawGold(player, deposit, (uint32)atol(code));
  175.             break;
  176.         case DEPOSIT_DEPOSIT:
  177.             DepositGold(player, deposit, (uint32)atol(code));
  178.             break;
  179.         case DEPOSIT_RENAME:
  180.             RenameDeposit(player, deposit, code);
  181.             break;
  182.         case DEPOSIT_DELETE:
  183.             DisbandDeposit(player, deposit, code);
  184.             break;
  185.         case ADD_PASSWORD:
  186.             AddPasswordToDeposit(player, deposit, code);
  187.             break;
  188.         case MODIFY_PASSWORD:
  189.             if(AskOldDepositPass(player, deposit, code))
  190.             {
  191.                 player->ADD_GOSSIP_ITEM(7, "|cff5C5C5C[Return]|r", LIST_DEPOSITS, 0);
  192.                 player->ADD_GOSSIP_ITEM_EXTENDED(4, "Add password", ADD_PASSWORD, deposit, "Insert new password", 0, true);
  193.                 player->SEND_GOSSIP_MENU(7777778, creature->GetGUID());
  194.                 return true;
  195.             }
  196.             break;
  197.         case REMOVE_PASSWORD:
  198.             if(AskOldDepositPass(player, deposit, code))
  199.                 RemoveDepositPass(player, deposit);
  200.             break;
  201.         case EDIT_DEPOSIT:
  202.             EditDeposit(player, creature, deposit, code);
  203.             return true;
  204.         }
  205.         ListPlayerDeposits(player, creature);
  206.         return true;
  207.     }
  208.  
  209.     // Creates a deposit
  210.     void CreateDeposit(Player* player, const char* name)
  211.     {
  212.         std::list<depInfo> infos = deposits[player->GetGUIDLow()];
  213.         if(infos.size() >= maxPlayerDeposits)
  214.         {
  215.             sendError(player, "You have too many deposits");
  216.             return;
  217.         }
  218.  
  219.         uint32 cost = createDepositCost + (infos.size() * createDepositPlus);
  220.  
  221.         if(player->GetMoney() < cost)
  222.         {
  223.             sendError(player, "You dont have enough money");
  224.             return;
  225.         }
  226.  
  227.         std::string nameStr(name);
  228.         if(!checkName(player, nameStr))
  229.             return;
  230.  
  231.         if(!modifyMoney(player, cost, false))
  232.             return;
  233.  
  234.         depInfo info = {0, nameStr, ""};
  235.         deposits[player->GetGUIDLow()].push_back(info);
  236.         CharacterDatabase.PExecute("INSERT INTO `gold_bank_data` (`plrGUID`, `name`, `gold`, `password`) VALUES (%u, \"%s\", 0, NULL)", player->GetGUIDLow(), name);
  237.         deposits[player->GetGUIDLow()].sort(cmp_by_name); // resort the deposits after adding new
  238.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit %s created and ready to use", name);
  239.     }
  240.  
  241.     // Opens a list with the player's available deposits
  242.     void ListPlayerDeposits(Player* player, WorldObject* obj)
  243.     {
  244.         std::list<depInfo> infos = deposits[player->GetGUIDLow()];
  245.         std::list<depInfo>::iterator it = infos.begin();
  246.         uint8 i = 0;
  247.         while(it != infos.end() || i >= 30)
  248.         {
  249.             std::ostringstream ss;
  250.             ss << "[Deposit: \"|cff0055FF";
  251.             ss << it->name;
  252.             ss << "|r\"]\n |cff00ff00available|r ";
  253.             ss << it->gold;
  254.             ss << "|cffFF0000 gold|r";
  255.             player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_MONEY_BAG, ss.str().c_str(), EDIT_DEPOSIT, i++, it->pass.empty() ? "" : "Insert password", 0, !it->pass.empty());
  256.             ++it;
  257.         }
  258.        
  259.         if(i < maxPlayerDeposits)
  260.             player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_INTERACT_2, "[+] Create a new Deposit", CREATE_DEPOSIT, 0, "Insert a new unique name\n\nWould you like to create a new deposit?", createDepositCost + (i * createDepositPlus), true);
  261.  
  262.         player->ADD_GOSSIP_ITEM_EXTENDED(GOSSIP_ICON_TALK, "Nevermid..", CLOSE_MENU, 0, "", 0, false);
  263.         player->SEND_GOSSIP_MENU(7777778, obj->GetGUID());
  264.     }
  265.  
  266.     // Asks for the deposit password
  267.     bool CheckPassword(Player* player, Creature* creature, uint8 deposit)
  268.     {
  269.         depInfo* info = getDeposit(player, deposit);
  270.         if(!info)
  271.         {
  272.             ListPlayerDeposits(player, creature);
  273.             return true;
  274.         }
  275.  
  276.         if(info->pass.empty())
  277.             return false;
  278.  
  279.         player->ADD_GOSSIP_ITEM(7, "|cff5C5C5C[Return]|r", LIST_DEPOSITS, 0);
  280.         player->ADD_GOSSIP_ITEM_EXTENDED(6, "Withdraw some gold", DEPOSIT_WITHDRAW, deposit, "Insert how much gold you would like to|cffFF0000 withdraw|r?", 0, true);
  281.         player->SEND_GOSSIP_MENU(7777778, creature->GetGUID());
  282.         return true;
  283.     }
  284.     // Opens a menu to edit the selected deposit
  285.     void EditDeposit(Player* player, Creature* creature, uint8 deposit, const char* pass = NULL)
  286.     {
  287.         depInfo* info = getDeposit(player, deposit);
  288.         if(!info)
  289.         {
  290.             ListPlayerDeposits(player, creature);
  291.             return;
  292.         }
  293.  
  294.         if(!info->pass.empty()) // has pass
  295.         {
  296.             if(!pass)
  297.             {
  298.                 ListPlayerDeposits(player, creature);
  299.                 return;
  300.             }
  301.  
  302.             // to String and trim it
  303.             std::string passStr(pass);
  304.  
  305.             if(passStr != info->pass)
  306.             {
  307.                 sendError(player, ("Wrong password for deposit "+info->name).c_str());
  308.                 ListPlayerDeposits(player, creature);
  309.                 return;
  310.             }
  311.         }
  312.  
  313.         player->ADD_GOSSIP_ITEM(7, "|cff5C5C5C[Return]|r", LIST_DEPOSITS, 0);
  314.         player->ADD_GOSSIP_ITEM_EXTENDED(6, "Withdraw some gold", DEPOSIT_WITHDRAW, deposit, "Insert how much gold you would like to|cffFF0000 withdraw|r?", 0, true);
  315.         player->ADD_GOSSIP_ITEM_EXTENDED(6, "Deposit some gold", DEPOSIT_DEPOSIT, deposit, "Insert how much gold you would like to|cFF00FF00 deposit|r?", 0, true);
  316.         player->ADD_GOSSIP_ITEM_EXTENDED(8, "|cff9E00FFRename deposit|r", DEPOSIT_RENAME, deposit, "|cffEBFF00Press insert a new name|r", 0, true);
  317.         player->ADD_GOSSIP_ITEM_EXTENDED(4, "|cffFF0000Disband deposit|r", DEPOSIT_DELETE, deposit, "|cffEBFF00Are you sure about disbanding this deposit?\n|cFFFF0000Once disbanded cannot be recovered!|r\n\nWrite |cFFFF0000Disband|r to the box to confirm", 0, true);
  318.         if(info->pass.empty())
  319.             player->ADD_GOSSIP_ITEM_EXTENDED(4, "Add password", ADD_PASSWORD, deposit, "Insert new password", 0, true);
  320.         else
  321.         {
  322.             player->ADD_GOSSIP_ITEM_EXTENDED(4, "Modify password", MODIFY_PASSWORD, deposit, "Insert old password", 0, true);
  323.             player->ADD_GOSSIP_ITEM_EXTENDED(4, "Delete password", REMOVE_PASSWORD, deposit, "Insert old password", 0, true);
  324.         }
  325.         player->SEND_GOSSIP_MENU(7777778, creature->GetGUID());
  326.     }
  327.  
  328.     // Withdraw gold from the deposit
  329.     void WithdrawGold(Player* player, uint8 deposit, uint32 amount)
  330.     {
  331.         if(!amount) // gave bad value to input box
  332.         {
  333.             sendError(player, "Invalid gold amount");
  334.             return;
  335.         }
  336.  
  337.         depInfo* info = getDeposit(player, deposit);
  338.         if(!info)
  339.             return;
  340.  
  341.         if(!info->gold) // empty deposit
  342.         {
  343.             sendError(player, "Deposit is empty");
  344.             return;
  345.         }
  346.  
  347.         if(amount > info->gold)
  348.             amount = info->gold;
  349.  
  350.         if(!modifyMoney(player, amount*GOLD, true))
  351.             return;
  352.         info->gold -= amount;
  353.         CharacterDatabase.PExecute("UPDATE `gold_bank_data` SET `gold`= %u WHERE `plrGUID`= %u AND `name` = \"%s\"", info->gold, player->GetGUIDLow(), info->name.c_str());
  354.  
  355.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit [%s] withdrew %u gold", info->name.c_str(), amount);
  356.     }
  357.     // Deposit gold in the deposit
  358.     void DepositGold(Player* player, uint8 deposit, uint32 amount)
  359.     {
  360.         if(!amount) // gave bad value to input box
  361.         {
  362.             sendError(player, "Invalid gold amount");
  363.             return;
  364.         }
  365.  
  366.         if(amount*GOLD > player->GetMoney())
  367.         {
  368.             sendError(player, "You dont have the amount of gold inserted!");
  369.             return;
  370.         }
  371.  
  372.         depInfo* info = getDeposit(player, deposit);
  373.         if(!info)
  374.             return;
  375.  
  376.         if(info->gold >= uint32(MAX_MONEY_AMOUNT - amount)) // can only add to max money amount
  377.             amount = MAX_MONEY_AMOUNT-info->gold;
  378.  
  379.         if(!modifyMoney(player, amount*GOLD, false))
  380.             return;
  381.         info->gold += amount;
  382.         CharacterDatabase.PExecute("UPDATE `gold_bank_data` SET `gold`= %u WHERE `plrGUID`= %u AND `name` = \"%s\"", info->gold, player->GetGUIDLow(), info->name.c_str());
  383.  
  384.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit [%s] deposited %u gold", info->name.c_str(), amount);
  385.         return;
  386.     }
  387.     // Rename the deposit
  388.     void RenameDeposit(Player* player, uint8 deposit, const char* newName)
  389.     {
  390.         std::string nameStr(newName);
  391.         if(!checkName(player, nameStr))
  392.             return;
  393.  
  394.         depInfo* info = getDeposit(player, deposit);
  395.         if(!info)
  396.             return;
  397.  
  398.         CharacterDatabase.PExecute("UPDATE `gold_bank_data` SET `name`= \"%s\" WHERE `plrGUID`= %u AND `name` = \"%s\"", newName, player->GetGUIDLow(), info->name.c_str());
  399.         info->name = nameStr;
  400.         deposits[player->GetGUIDLow()].sort(cmp_by_name); // resort the deposits after rename
  401.  
  402.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit renamed to %s", newName);
  403.     }
  404.     //Disband deposit
  405.     void DisbandDeposit(Player* player, uint8 deposit, const char* message)
  406.     {
  407.         std::string data(message);
  408.         std::transform(data.begin(), data.end(), data.begin(), ::tolower);
  409.         if(data != "disband")
  410.         {
  411.             sendError(player, "You need to insert Disband to disband the deposit");
  412.             return;
  413.         }
  414.  
  415.         depInfo* info = getDeposit(player, deposit);
  416.         if(!info)
  417.             return;
  418.  
  419.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit %s disbanded", info->name.c_str());
  420.  
  421.         CharacterDatabase.PExecute("DELETE FROM `gold_bank_data` WHERE `plrGUID`= %u AND `name` = \"%s\"", player->GetGUIDLow(), info->name.c_str());
  422.         std::list<depInfo>::iterator it = deposits[player->GetGUIDLow()].begin();
  423.         std::advance(it, deposit);
  424.         if(it != deposits[player->GetGUIDLow()].end())
  425.             deposits[player->GetGUIDLow()].erase(it);
  426.     }
  427.     //Add new password
  428.     void AddPasswordToDeposit(Player* player, uint8 deposit, const char* newPass)
  429.     {
  430.         std::string passStr(newPass);
  431.  
  432.         if(passStr.empty() || passStr.length() < 2 || passStr.length() > 255)
  433.         {
  434.             sendError(player, "Invalid password length");
  435.             return;
  436.         }
  437.  
  438.         depInfo* info = getDeposit(player, deposit);
  439.         if(!info)
  440.             return;
  441.  
  442.         info->pass = passStr;
  443.         CharacterDatabase.PExecute("UPDATE `gold_bank_data` SET `password`= \"%s\" WHERE `plrGUID`= %u AND `name` = \"%s\"", newPass, player->GetGUIDLow(), info->name.c_str());
  444.  
  445.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit %s now has a new password", info->name.c_str());
  446.     }
  447.     //Check old pass
  448.     bool AskOldDepositPass(Player* player, uint8 deposit, const char* oldPass)
  449.     {
  450.         depInfo* info = getDeposit(player, deposit);
  451.         if(!info)
  452.             return false;
  453.  
  454.         if(info->pass.empty())
  455.         {
  456.             sendError(player, "Internal error. Deposit has no password!");
  457.             return false;
  458.         }
  459.  
  460.         std::string passStr(oldPass);
  461.  
  462.         if(passStr.empty())
  463.         {
  464.             sendError(player, "Invalid password inputted");
  465.             return false;
  466.         }
  467.  
  468.         if(info->pass != passStr)
  469.         {
  470.             sendError(player, "Password inserted does not match the old password");
  471.             return false;
  472.         }
  473.  
  474.         return true;
  475.     }
  476.     void RemoveDepositPass(Player* player, uint8 deposit)
  477.     {
  478.         depInfo* info = getDeposit(player, deposit);
  479.         if(!info)
  480.             return;
  481.  
  482.         info->pass = "";
  483.         CharacterDatabase.PExecute("UPDATE `gold_bank_data` SET `password`= NULL WHERE `plrGUID`= %u AND `name` = \"%s\"", player->GetGUIDLow(), info->name.c_str());
  484.  
  485.         ChatHandler(player->GetSession()).PSendSysMessage("Deposit %s no longer has a password", info->name.c_str());
  486.     }
  487. };
  488.  
  489. void AddSC_Gold_Banker()
  490. {
  491.     new gold_banker();
  492. }
Add Comment
Please, Sign In to add comment