Guest User

Yet Another Banking System

a guest
Sep 6th, 2016
279
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Pawn 65.15 KB | None | 0 0
  1. /*
  2.     Yet Another Banking System by rootcause
  3.    
  4.     Optional Robbable ATM Version (MySQL R39)
  5.     Topic: http://forum.sa-mp.com/showthread.php?t=606450
  6. */
  7.  
  8. #define     FILTERSCRIPT
  9. #include    <a_samp>
  10. #include    <a_mysql>           // by BlueG & maddinat0r - http://forum.sa-mp.com/showthread.php?t=56564
  11. #include    <izcmd>             // by Yashas - http://forum.sa-mp.com/showthread.php?t=576114
  12. #include    <sscanf2>           // by Y_Less - http://forum.sa-mp.com/showthread.php?t=602923
  13. #include    <streamer>          // by Incognito - http://forum.sa-mp.com/showthread.php?t=102865
  14. #include    <WeaponData>        // by Southclaw - https://github.com/Southclaw/AdvancedWeaponData
  15. #include    <YSI\y_iterate>     // by Y_Less - http://forum.sa-mp.com/showthread.php?t=570884
  16.  
  17. #define     MYSQL_HOST      "host"
  18. #define     MYSQL_USER      "user"
  19. #define     MYSQL_PASS      "password"
  20. #define     MYSQL_DBNAME    "dbname"
  21.  
  22. #define     MAX_BANKERS     (20)
  23. #define     MAX_ATMS        (100)
  24.  
  25. #define     BANKER_USE_MAPICON                  // comment or remove this line if you don't want bankers to have mapicons
  26. #define     ATM_USE_MAPICON                     // comment or remove this line if you don't want atms to have mapicons
  27. #define     BANKER_ICON_RANGE       (10.0)      // banker mapicon stream distance, you can remove this if you're not using banker icons (default: 10.0)
  28. #define     ATM_ICON_RANGE          (100.0)     // atm mapicon stream distance, you can remove this if you're not using banker icons (default: 100.0)
  29. #define     ACCOUNT_PRICE           (100)       // amount of money required to create a new bank account (default: 100)
  30. #define     ACCOUNT_CLIMIT          (5)         // a player can create x accounts, you can comment or remove this line if you don't want an account limit (default: 5)
  31. #define     ACCOUNT_LIMIT           (500000000) // how much money can a bank account have (default: 500,000,000)
  32.  
  33. // ATM Robbery Config
  34. #define     ATM_HEALTH              (350.0)     // health of an atm (Default: 350.0)
  35. #define     ATM_REGEN               (120)       // a robbed atm will start working after x seconds (Default: 120)
  36. #define     ATM_ROB_MIN             (1500)      // min. amount of money stolen from an atm (Default: 1500)
  37. #define     ATM_ROB_MAX             (3500)      // max. amount of money stolen from an atm (Default: 3500)
  38.  
  39. enum    _:E_BANK_DIALOG
  40. {
  41.     DIALOG_BANK_MENU_NOLOGIN = 12450,
  42.     DIALOG_BANK_MENU,
  43.     DIALOG_BANK_CREATE_ACCOUNT,
  44.     DIALOG_BANK_ACCOUNTS,
  45.     DIALOG_BANK_LOGIN_ID,
  46.     DIALOG_BANK_LOGIN_PASS,
  47.     DIALOG_BANK_DEPOSIT,
  48.     DIALOG_BANK_WITHDRAW,
  49.     DIALOG_BANK_TRANSFER_1,
  50.     DIALOG_BANK_TRANSFER_2,
  51.     DIALOG_BANK_PASSWORD,
  52.     DIALOG_BANK_REMOVE,
  53.     DIALOG_BANK_LOGS,
  54.     DIALOG_BANK_LOG_PAGE
  55. }
  56.  
  57. enum    _:E_BANK_LOGTYPE
  58. {
  59.     TYPE_NONE,
  60.     TYPE_LOGIN,
  61.     TYPE_DEPOSIT,
  62.     TYPE_WITHDRAW,
  63.     TYPE_TRANSFER,
  64.     TYPE_PASSCHANGE
  65. }
  66.  
  67. enum    _:E_ATMDATA
  68. {
  69.     IDString[8],
  70.     refID
  71. }
  72.  
  73. enum    E_BANKER
  74. {
  75.     // saved
  76.     Skin,
  77.     Float: bankerX,
  78.     Float: bankerY,
  79.     Float: bankerZ,
  80.     Float: bankerA,
  81.     // temp
  82.     bankerActorID,
  83.     #if defined BANKER_USE_MAPICON
  84.     bankerIconID,
  85.     #endif
  86.     Text3D: bankerLabel
  87. }
  88.  
  89. enum    E_ATM
  90. {
  91.     // saved
  92.     Float: atmX,
  93.     Float: atmY,
  94.     Float: atmZ,
  95.     Float: atmRX,
  96.     Float: atmRY,
  97.     Float: atmRZ,
  98.     // temp
  99.     atmObjID,
  100.     #if defined ATM_USE_MAPICON
  101.     atmIconID,
  102.     #endif
  103.     Text3D: atmLabel,
  104.     // atm robbing
  105.     Float: atmHealth,
  106.     atmRegen,
  107.     atmTimer,
  108.     atmPickup
  109. }
  110.  
  111. new
  112.     BankSQLHandle = -1;
  113.    
  114. new
  115.     BankerData[MAX_BANKERS][E_BANKER],
  116.     ATMData[MAX_ATMS][E_ATM];
  117.    
  118. new
  119.     Iterator: Bankers<MAX_BANKERS>,
  120.     Iterator: ATMs<MAX_ATMS>;
  121.    
  122. new
  123.     CurrentAccountID[MAX_PLAYERS] = {-1, ...},
  124.     LogListType[MAX_PLAYERS] = {TYPE_NONE, ...},
  125.     LogListPage[MAX_PLAYERS],
  126.     EditingATMID[MAX_PLAYERS] = {-1, ...};
  127.  
  128. formatInt(intVariable, iThousandSeparator = ',', iCurrencyChar = '$')
  129. {
  130.     /*
  131.         By Kar
  132.         https://gist.github.com/Kar2k/bfb0eafb2caf71a1237b349684e091b9/8849dad7baa863afb1048f40badd103567c005a5#file-formatint-function
  133.     */
  134.     static
  135.         s_szReturn[ 32 ],
  136.         s_szThousandSeparator[ 2 ] = { ' ', EOS },
  137.         s_szCurrencyChar[ 2 ] = { ' ', EOS },
  138.         s_iVariableLen,
  139.         s_iChar,
  140.         s_iSepPos,
  141.         bool:s_isNegative
  142.     ;
  143.  
  144.     format( s_szReturn, sizeof( s_szReturn ), "%d", intVariable );
  145.  
  146.     if(s_szReturn[0] == '-')
  147.         s_isNegative = true;
  148.     else
  149.         s_isNegative = false;
  150.  
  151.     s_iVariableLen = strlen( s_szReturn );
  152.  
  153.     if ( s_iVariableLen >= 4 && iThousandSeparator)
  154.     {
  155.         s_szThousandSeparator[ 0 ] = iThousandSeparator;
  156.  
  157.         s_iChar = s_iVariableLen;
  158.         s_iSepPos = 0;
  159.  
  160.         while ( --s_iChar > _:s_isNegative )
  161.         {
  162.             if ( ++s_iSepPos == 3 )
  163.             {
  164.                 strins( s_szReturn, s_szThousandSeparator, s_iChar );
  165.  
  166.                 s_iSepPos = 0;
  167.             }
  168.         }
  169.     }
  170.     if(iCurrencyChar) {
  171.         s_szCurrencyChar[ 0 ] = iCurrencyChar;
  172.         strins( s_szReturn, s_szCurrencyChar, _:s_isNegative );
  173.     }
  174.     return s_szReturn;
  175. }
  176.  
  177. RandomEx(min, max) //Y_Less
  178.     return random(max - min) + min;
  179.  
  180. ConvertToMinutes(time)
  181. {
  182.     // http://forum.sa-mp.com/showpost.php?p=3223897&postcount=11
  183.     new string[15];//-2000000000:00 could happen, so make the string 15 chars to avoid any errors
  184.     format(string, sizeof(string), "%02d:%02d", time / 60, time % 60);
  185.     return string;
  186. }
  187.  
  188. IsPlayerNearBanker(playerid)
  189. {
  190.     foreach(new i : Bankers)
  191.     {
  192.         if(IsPlayerInRangeOfPoint(playerid, 3.0, BankerData[i][bankerX], BankerData[i][bankerY], BankerData[i][bankerZ])) return 1;
  193.     }
  194.    
  195.     return 0;
  196. }
  197.  
  198. GetClosestATM(playerid, Float: range = 3.0)
  199. {
  200.     new id = -1, Float: dist = range, Float: tempdist;
  201.     foreach(new i : ATMs)
  202.     {
  203.         tempdist = GetPlayerDistanceFromPoint(playerid, ATMData[i][atmX], ATMData[i][atmY], ATMData[i][atmZ]);
  204.  
  205.         if(tempdist > range) continue;
  206.         if(tempdist <= dist)
  207.         {
  208.             dist = tempdist;
  209.             id = i;
  210.         }
  211.     }
  212.  
  213.     return id;
  214. }
  215.  
  216. Bank_SaveLog(playerid, type, accid, toaccid, amount)
  217. {
  218.     if(type == TYPE_NONE) return 1;
  219.     new query[256];
  220.    
  221.     switch(type)
  222.     {
  223.         case TYPE_LOGIN, TYPE_PASSCHANGE: mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bank_logs SET AccountID=%d, Type=%d, Player='%e', Date=UNIX_TIMESTAMP()", accid, type, Player_GetName(playerid));
  224.         case TYPE_DEPOSIT, TYPE_WITHDRAW: mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bank_logs SET AccountID=%d, Type=%d, Player='%e', Amount=%d, Date=UNIX_TIMESTAMP()", accid, type, Player_GetName(playerid), amount);
  225.         case TYPE_TRANSFER: mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bank_logs SET AccountID=%d, ToAccountID=%d, Type=%d, Player='%e', Amount=%d, Date=UNIX_TIMESTAMP()", accid, toaccid, type, Player_GetName(playerid), amount);
  226.     }
  227.    
  228.     mysql_tquery(BankSQLHandle, query);
  229.     return 1;
  230. }
  231.  
  232. Bank_ShowMenu(playerid)
  233. {
  234.     new string[256], using_atm = GetPVarInt(playerid, "usingATM");
  235.     if(CurrentAccountID[playerid] == -1) {
  236.         format(string, sizeof(string), "{%06x}Create Account\t{2ECC71}%s\nMy Accounts\t{F1C40F}%d\nAccount Login", (using_atm ? 0xE74C3CFF >>> 8 : 0xFFFFFFFF >>> 8), (using_atm ? ("") : formatInt(ACCOUNT_PRICE)), Bank_AccountCount(playerid));
  237.         ShowPlayerDialog(playerid, DIALOG_BANK_MENU_NOLOGIN, DIALOG_STYLE_TABLIST, "{F1C40F}Bank: {FFFFFF}Menu", string, "Choose", "Close");
  238.     }else{
  239.         new balance = Bank_GetBalance(CurrentAccountID[playerid]), menu_title[64];
  240.         format(menu_title, sizeof(menu_title), "{F1C40F}Bank: {FFFFFF}Menu (Account ID: {F1C40F}%d{FFFFFF})", CurrentAccountID[playerid]);
  241.        
  242.         format(
  243.             string,
  244.             sizeof(string),
  245.             "{%06x}Create Account\t{2ECC71}%s\nMy Accounts\t{F1C40F}%d\nDeposit\t{2ECC71}%s\nWithdraw\t{2ECC71}%s\nTransfer\t{2ECC71}%s\n{%06x}Account Logs\n{%06x}Change Password\n{%06x}Remove Account\nLogout",
  246.             (using_atm ? 0xE74C3CFF >>> 8 : 0xFFFFFFFF >>> 8),
  247.             (using_atm ? ("") : formatInt(ACCOUNT_PRICE)),
  248.             Bank_AccountCount(playerid),
  249.             formatInt(GetPlayerMoney(playerid)),
  250.             formatInt(balance),
  251.             formatInt(balance),
  252.             (using_atm ? 0xE74C3CFF >>> 8 : 0xFFFFFFFF >>> 8),
  253.             (using_atm ? 0xE74C3CFF >>> 8 : 0xFFFFFFFF >>> 8),
  254.             (using_atm ? 0xE74C3CFF >>> 8 : 0xFFFFFFFF >>> 8)
  255.         );
  256.  
  257.         ShowPlayerDialog(playerid, DIALOG_BANK_MENU, DIALOG_STYLE_TABLIST, menu_title, string, "Choose", "Close");
  258.     }
  259.    
  260.     DeletePVar(playerid, "bankLoginAccount");
  261.     DeletePVar(playerid, "bankTransferAccount");
  262.     return 1;
  263. }
  264.  
  265. Bank_ShowLogMenu(playerid)
  266. {
  267.     LogListType[playerid] = TYPE_NONE;
  268.     LogListPage[playerid] = 0;
  269.     ShowPlayerDialog(playerid, DIALOG_BANK_LOGS, DIALOG_STYLE_LIST, "{F1C40F}Bank: {FFFFFF}Logs", "Deposited Money\nWithdrawn Money\nTransfers\nLogins\nPassword Changes", "Show", "Back");
  270.     return 1;
  271. }
  272.  
  273. Player_GetName(playerid)
  274. {
  275.     new name[MAX_PLAYER_NAME];
  276.     GetPlayerName(playerid, name, MAX_PLAYER_NAME);
  277.     return name;
  278. }
  279.  
  280. Bank_AccountCount(playerid)
  281. {
  282.     new query[144], Cache: find_accounts;
  283.     mysql_format(BankSQLHandle, query, sizeof(query), "SELECT null FROM bank_accounts WHERE Owner='%e' && Disabled=0", Player_GetName(playerid));
  284.     find_accounts = mysql_query(BankSQLHandle, query);
  285.    
  286.     new count = cache_num_rows();
  287.     cache_delete(find_accounts);
  288.     return count;
  289. }
  290.  
  291. Bank_GetBalance(accountid)
  292. {
  293.     new query[144], Cache: get_balance;
  294.     mysql_format(BankSQLHandle, query, sizeof(query), "SELECT Balance FROM bank_accounts WHERE ID=%d && Disabled=0", accountid);
  295.     get_balance = mysql_query(BankSQLHandle, query);
  296.  
  297.     new balance = cache_get_field_content_int(0, "Balance");
  298.     cache_delete(get_balance);
  299.     return balance;
  300. }
  301.  
  302. Bank_GetOwner(accountid)
  303. {
  304.     new query[144], owner[MAX_PLAYER_NAME], Cache: get_owner;
  305.     mysql_format(BankSQLHandle, query, sizeof(query), "SELECT Owner FROM bank_accounts WHERE ID=%d && Disabled=0", accountid);
  306.     get_owner = mysql_query(BankSQLHandle, query);
  307.  
  308.     cache_get_field_content(0, "Owner", owner);
  309.     cache_delete(get_owner);
  310.     return owner;
  311. }
  312.  
  313. Bank_ListAccounts(playerid)
  314. {
  315.     new query[256], Cache: get_accounts;
  316.     mysql_format(BankSQLHandle, query, sizeof(query), "SELECT ID, Balance, LastAccess, FROM_UNIXTIME(CreatedOn, '%%d/%%m/%%Y %%H:%%i:%%s') AS Created, FROM_UNIXTIME(LastAccess, '%%d/%%m/%%Y %%H:%%i:%%s') AS Last FROM bank_accounts WHERE Owner='%e' && Disabled=0 ORDER BY CreatedOn DESC", Player_GetName(playerid));
  317.     get_accounts = mysql_query(BankSQLHandle, query);
  318.     new rows = cache_num_rows();
  319.  
  320.     if(rows) {
  321.         new string[1024], cdate[24], ldate[24];
  322.         format(string, sizeof(string), "ID\tBalance\tCreated On\tLast Access\n");
  323.         for(new i; i < rows; ++i)
  324.         {
  325.             cache_get_field_content(i, "Created", cdate);
  326.             cache_get_field_content(i, "Last", ldate);
  327.             format(string, sizeof(string), "%s{FFFFFF}%d\t{2ECC71}%s\t{FFFFFF}%s\t%s\n", string, cache_get_field_content_int(i, "ID"), formatInt(cache_get_field_content_int(i, "Balance")), cdate, (cache_get_field_content_int(i, "LastAccess") == 0) ? ("Never") : ldate);
  328.         }
  329.  
  330.         ShowPlayerDialog(playerid, DIALOG_BANK_ACCOUNTS, DIALOG_STYLE_TABLIST_HEADERS, "{F1C40F}Bank: {FFFFFF}My Accounts", string, "Login", "Back");
  331.     }else{
  332.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You don't have any bank accounts.");
  333.         Bank_ShowMenu(playerid);
  334.     }
  335.  
  336.     cache_delete(get_accounts);
  337.     return 1;
  338. }
  339.  
  340. Bank_ShowLogs(playerid)
  341. {
  342.     new query[196], type = LogListType[playerid], Cache: bank_logs;
  343.     mysql_format(BankSQLHandle, query, sizeof(query), "SELECT *, FROM_UNIXTIME(Date, '%%d/%%m/%%Y %%H:%%i:%%s') as ActionDate FROM bank_logs WHERE AccountID=%d && Type=%d ORDER BY Date DESC LIMIT %d, 15", CurrentAccountID[playerid], type, LogListPage[playerid] * 15);
  344.     bank_logs = mysql_query(BankSQLHandle, query);
  345.    
  346.     new rows = cache_num_rows();
  347.     if(rows) {
  348.         new list[1512], title[96], name[MAX_PLAYER_NAME], date[24];
  349.         switch(type)
  350.         {
  351.             case TYPE_LOGIN:
  352.             {
  353.                 format(list, sizeof(list), "By\tAction Date\n");
  354.                 format(title, sizeof(title), "{F1C40F}Bank: {FFFFFF}Login History (Page %d)", LogListPage[playerid] + 1);
  355.             }
  356.            
  357.             case TYPE_DEPOSIT:
  358.             {
  359.                 format(list, sizeof(list), "By\tAmount\tDeposit Date\n");
  360.                 format(title, sizeof(title), "{F1C40F}Bank: {FFFFFF}Deposit History (Page %d)", LogListPage[playerid] + 1);
  361.             }
  362.  
  363.             case TYPE_WITHDRAW:
  364.             {
  365.                 format(list, sizeof(list), "By\tAmount\tWithdraw Date\n");
  366.                 format(title, sizeof(title), "{F1C40F}Bank: {FFFFFF}Withdraw History (Page %d)", LogListPage[playerid] + 1);
  367.             }
  368.            
  369.             case TYPE_TRANSFER:
  370.             {
  371.                 format(list, sizeof(list), "By\tTo Account\tAmount\tTransfer Date\n");
  372.                 format(title, sizeof(title), "{F1C40F}Bank: {FFFFFF}Transfer History (Page %d)", LogListPage[playerid] + 1);
  373.             }
  374.            
  375.             case TYPE_PASSCHANGE:
  376.             {
  377.                 format(list, sizeof(list), "By\tAction Date\n");
  378.                 format(title, sizeof(title), "{F1C40F}Bank: {FFFFFF}Password Changes (Page %d)", LogListPage[playerid] + 1);
  379.             }
  380.         }
  381.        
  382.         for(new i; i < rows; ++i)
  383.         {
  384.             cache_get_field_content(i, "Player", name);
  385.             cache_get_field_content(i, "ActionDate", date);
  386.  
  387.             switch(type)
  388.             {
  389.                 case TYPE_LOGIN:
  390.                 {
  391.                     format(list, sizeof(list), "%s%s\t%s\n", list, name, date);
  392.                 }
  393.  
  394.                 case TYPE_DEPOSIT:
  395.                 {
  396.                     format(list, sizeof(list), "%s%s\t{2ECC71}%s\t%s\n", list, name, formatInt(cache_get_field_content_int(i, "Amount")), date);
  397.                 }
  398.  
  399.                 case TYPE_WITHDRAW:
  400.                 {
  401.                     format(list, sizeof(list), "%s%s\t{2ECC71}%s\t%s\n", list, name, formatInt(cache_get_field_content_int(i, "Amount")), date);
  402.                 }
  403.  
  404.                 case TYPE_TRANSFER:
  405.                 {
  406.                     format(list, sizeof(list), "%s%s\t%d\t{2ECC71}%s\t%s\n", list, name, cache_get_field_content_int(i, "ToAccountID"), formatInt(cache_get_field_content_int(i, "Amount")), date);
  407.                 }
  408.  
  409.                 case TYPE_PASSCHANGE:
  410.                 {
  411.                     format(list, sizeof(list), "%s%s\t%s\n", list, name, date);
  412.                 }
  413.             }
  414.         }
  415.  
  416.         ShowPlayerDialog(playerid, DIALOG_BANK_LOG_PAGE, DIALOG_STYLE_TABLIST_HEADERS, title, list, "Next", "Previous");
  417.     }else{
  418.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't find any more records.");
  419.         Bank_ShowLogMenu(playerid);
  420.     }
  421.  
  422.     cache_delete(bank_logs);
  423.     return 1;
  424. }
  425.  
  426. ATM_ReturnDmgText(id)
  427. {
  428.     new Float: health = ATMData[id][atmHealth], color, string[16];
  429.  
  430.     if(health < (ATM_HEALTH / 4)) {
  431.         color = 0xE74C3CFF;
  432.     }else if(health < (ATM_HEALTH / 2)) {
  433.         color = 0xF39C12FF;
  434.     }else{
  435.         color = 0x2ECC71FF;
  436.     }
  437.  
  438.     format(string, sizeof(string), "{%06x}%.2f%%", color >>> 8, (health * 100 / ATM_HEALTH));
  439.     return string;
  440. }
  441.  
  442. public OnFilterScriptInit()
  443. {
  444.     print("  [Bank System] Initializing...");
  445.    
  446.     for(new i; i < MAX_BANKERS; i++)
  447.     {
  448.         BankerData[i][bankerActorID] = -1;
  449.        
  450.         #if defined BANKER_USE_MAPICON
  451.         BankerData[i][bankerIconID] = -1;
  452.         #endif
  453.        
  454.         BankerData[i][bankerLabel] = Text3D: -1;
  455.     }
  456.    
  457.     for(new i; i < MAX_ATMS; i++)
  458.     {
  459.         ATMData[i][atmObjID] = ATMData[i][atmTimer] = ATMData[i][atmPickup] = -1;
  460.  
  461.         #if defined ATM_USE_MAPICON
  462.         ATMData[i][atmIconID] = -1;
  463.         #endif
  464.  
  465.         ATMData[i][atmLabel] = Text3D: -1;
  466.         ATMData[i][atmHealth] = ATM_HEALTH;
  467.     }
  468.    
  469.     BankSQLHandle = mysql_connect(MYSQL_HOST, MYSQL_USER, MYSQL_DBNAME, MYSQL_PASS);
  470.     mysql_log(LOG_ERROR | LOG_WARNING, LOG_TYPE_HTML);
  471.     if(mysql_errno()) return printf("  [Bank System] Can't connect to MySQL. (Error #%d)", mysql_errno());
  472.  
  473.     // create tables if they don't exist
  474.     mysql_tquery(BankSQLHandle, "CREATE TABLE IF NOT EXISTS `bankers` (\
  475.       `ID` int(11) NOT NULL,\
  476.       `Skin` smallint(3) NOT NULL,\
  477.       `PosX` float NOT NULL,\
  478.       `PosY` float NOT NULL,\
  479.       `PosZ` float NOT NULL,\
  480.       `PosA` float NOT NULL\
  481.     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
  482.    
  483.     mysql_tquery(BankSQLHandle, "CREATE TABLE IF NOT EXISTS `bank_atms` (\
  484.       `ID` int(11) NOT NULL,\
  485.       `PosX` float NOT NULL,\
  486.       `PosY` float NOT NULL,\
  487.       `PosZ` float NOT NULL,\
  488.       `RotX` float NOT NULL,\
  489.       `RotY` float NOT NULL,\
  490.       `RotZ` float NOT NULL\
  491.     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
  492.    
  493.     mysql_tquery(BankSQLHandle, "CREATE TABLE IF NOT EXISTS `bank_accounts` (\
  494.       `ID` int(11) NOT NULL auto_increment,\
  495.       `Owner` varchar(24) NOT NULL,\
  496.       `Password` varchar(32) NOT NULL,\
  497.       `Balance` int(11) NOT NULL,\
  498.       `CreatedOn` int(11) NOT NULL,\
  499.       `LastAccess` int(11) NOT NULL,\
  500.       `Disabled` smallint(1) NOT NULL,\
  501.       PRIMARY KEY  (`ID`)\
  502.     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;");
  503.    
  504.     new query[512];
  505.     mysql_format(BankSQLHandle, query, sizeof(query), "CREATE TABLE IF NOT EXISTS `bank_logs` (\
  506.         `ID` int(11) NOT NULL auto_increment,\
  507.         `AccountID` int(11) NOT NULL,\
  508.         `ToAccountID` int(11) NOT NULL default '-1',\
  509.         `Type` smallint(1) NOT NULL,\
  510.         `Player` varchar(24) NOT NULL,\
  511.         `Amount` int(11) NOT NULL,\
  512.         `Date` int(11) NOT NULL,");
  513.    
  514.     mysql_format(BankSQLHandle, query, sizeof(query), "%s\
  515.         PRIMARY KEY  (`ID`),\
  516.         KEY `bank_logs_ibfk_1` (`AccountID`),\
  517.         CONSTRAINT `bank_logs_ibfk_1` FOREIGN KEY (`AccountID`) REFERENCES `bank_accounts` (`ID`) ON DELETE CASCADE ON UPDATE CASCADE\
  518.         ) ENGINE=InnoDB DEFAULT CHARSET=utf8;", query);
  519.    
  520.     mysql_tquery(BankSQLHandle, query);
  521.    
  522.     print("  [Bank System] Connected to MySQL, loading data...");
  523.     mysql_tquery(BankSQLHandle, "SELECT * FROM bankers", "LoadBankers");
  524.     mysql_tquery(BankSQLHandle, "SELECT * FROM bank_atms", "LoadATMs");
  525.     return 1;
  526. }
  527.  
  528. public OnFilterScriptExit()
  529. {
  530.     foreach(new i : Bankers)
  531.     {
  532.         if(IsValidActor(BankerData[i][bankerActorID])) DestroyActor(BankerData[i][bankerActorID]);
  533.     }
  534.    
  535.     print("  [Bank System] Unloaded.");
  536.     mysql_close(BankSQLHandle);
  537.     return 1;
  538. }
  539.  
  540. public OnPlayerConnect(playerid)
  541. {
  542.     CurrentAccountID[playerid] = -1;
  543.     LogListType[playerid] = TYPE_NONE;
  544.     LogListPage[playerid] = 0;
  545.    
  546.     EditingATMID[playerid] = -1;
  547.     return 1;
  548. }
  549.  
  550. public OnDialogResponse(playerid, dialogid, response, listitem, inputtext[])
  551. {
  552.     switch(dialogid)
  553.     {
  554.         /* ---------------------------------------------------------------------- */
  555.         case DIALOG_BANK_MENU_NOLOGIN:
  556.         {
  557.             if(!response) return 1;
  558.             if(listitem == 0)
  559.             {
  560.                 if(GetPVarInt(playerid, "usingATM"))
  561.                 {
  562.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't do this at an ATM, visit a banker.");
  563.                     return Bank_ShowMenu(playerid);
  564.                 }
  565.                
  566.                 if(ACCOUNT_PRICE > GetPlayerMoney(playerid))
  567.                 {
  568.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You don't have enough money to create a bank account.");
  569.                     return Bank_ShowMenu(playerid);
  570.                 }
  571.                
  572.                 #if defined ACCOUNT_CLIMIT
  573.                 if(Bank_AccountCount(playerid) >= ACCOUNT_CLIMIT)
  574.                 {
  575.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't create any more bank accounts.");
  576.                     return Bank_ShowMenu(playerid);
  577.                 }
  578.                 #endif
  579.                
  580.                 ShowPlayerDialog(playerid, DIALOG_BANK_CREATE_ACCOUNT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Create Account", "Choose a password for your new bank account:", "Create", "Back");
  581.             }
  582.            
  583.             if(listitem == 1) Bank_ListAccounts(playerid);
  584.             if(listitem == 2) ShowPlayerDialog(playerid, DIALOG_BANK_LOGIN_ID, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Login", "Account ID:", "Continue", "Cancel");
  585.             return 1;
  586.         }
  587.         /* ---------------------------------------------------------------------- */
  588.         case DIALOG_BANK_MENU:
  589.         {
  590.             if(!response) return 1;
  591.             if(listitem == 0)
  592.             {
  593.                 if(GetPVarInt(playerid, "usingATM"))
  594.                 {
  595.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't do this at an ATM, visit a banker.");
  596.                     return Bank_ShowMenu(playerid);
  597.                 }
  598.                
  599.                 if(ACCOUNT_PRICE > GetPlayerMoney(playerid))
  600.                 {
  601.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You don't have enough money to create a bank account.");
  602.                     return Bank_ShowMenu(playerid);
  603.                 }
  604.  
  605.                 #if defined ACCOUNT_CLIMIT
  606.                 if(Bank_AccountCount(playerid) >= ACCOUNT_CLIMIT)
  607.                 {
  608.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't create any more bank accounts.");
  609.                     return Bank_ShowMenu(playerid);
  610.                 }
  611.                 #endif
  612.  
  613.                 ShowPlayerDialog(playerid, DIALOG_BANK_CREATE_ACCOUNT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Create Account", "Choose a password for your new bank account:", "Create", "Back");
  614.             }
  615.  
  616.             if(listitem == 1) Bank_ListAccounts(playerid);
  617.             if(listitem == 2) ShowPlayerDialog(playerid, DIALOG_BANK_DEPOSIT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Deposit", "How much money do you want to deposit?", "Deposit", "Back");
  618.             if(listitem == 3) ShowPlayerDialog(playerid, DIALOG_BANK_WITHDRAW, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Withdraw", "How much money do you want to withdraw?", "Withdraw", "Back");
  619.             if(listitem == 4) ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_1, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "Specify an account ID:", "Continue", "Back");
  620.             if(listitem == 5)
  621.             {
  622.                 if(GetPVarInt(playerid, "usingATM"))
  623.                 {
  624.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't do this at an ATM, visit a banker.");
  625.                     return Bank_ShowMenu(playerid);
  626.                 }
  627.                
  628.                 Bank_ShowLogMenu(playerid);
  629.             }
  630.            
  631.             if(listitem == 6)
  632.             {
  633.                 if(GetPVarInt(playerid, "usingATM"))
  634.                 {
  635.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't do this at an ATM, visit a banker.");
  636.                     return Bank_ShowMenu(playerid);
  637.                 }
  638.                
  639.                 if(strcmp(Bank_GetOwner(CurrentAccountID[playerid]), Player_GetName(playerid)))
  640.                 {
  641.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only the account owner can do this.");
  642.                     return Bank_ShowMenu(playerid);
  643.                 }
  644.                
  645.                 ShowPlayerDialog(playerid, DIALOG_BANK_PASSWORD, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Change Password", "Write a new password:", "Change", "Back");
  646.             }
  647.            
  648.             if(listitem == 7)
  649.             {
  650.                 if(GetPVarInt(playerid, "usingATM"))
  651.                 {
  652.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't do this at an ATM, visit a banker.");
  653.                     return Bank_ShowMenu(playerid);
  654.                 }
  655.                
  656.                 if(strcmp(Bank_GetOwner(CurrentAccountID[playerid]), Player_GetName(playerid)))
  657.                 {
  658.                     SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only the account owner can do this.");
  659.                     return Bank_ShowMenu(playerid);
  660.                 }
  661.                
  662.                 ShowPlayerDialog(playerid, DIALOG_BANK_REMOVE, DIALOG_STYLE_MSGBOX, "{F1C40F}Bank: {FFFFFF}Remove Account", "Are you sure? This account will get deleted {E74C3C}permanently.", "Yes", "Back");
  663.                 // https://youtu.be/rcjpags7JT8 - because it doesn't get deleted actually
  664.             }
  665.            
  666.             if(listitem == 8)
  667.             {
  668.                 SendClientMessage(playerid, 0x3498DBFF, "BANK: {FFFFFF}Successfully logged out.");
  669.                
  670.                 CurrentAccountID[playerid] = -1;
  671.                 Bank_ShowMenu(playerid);
  672.             }
  673.         }
  674.         /* ---------------------------------------------------------------------- */
  675.         case DIALOG_BANK_CREATE_ACCOUNT:
  676.         {
  677.             if(!response) return Bank_ShowMenu(playerid);
  678.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_CREATE_ACCOUNT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Create Account", "{E74C3C}You can't leave your account password empty.\n\n{FFFFFF}Choose a password for your new bank account:", "Create", "Back");
  679.             if(strlen(inputtext) > 16) return ShowPlayerDialog(playerid, DIALOG_BANK_CREATE_ACCOUNT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Create Account", "{E74C3C}Account password can't be more than 16 characters.\n\n{FFFFFF}Choose a password for your new bank account:", "Create", "Back");
  680.             if(ACCOUNT_PRICE > GetPlayerMoney(playerid))
  681.             {
  682.                 SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You don't have enough money to create a bank account.");
  683.                 return Bank_ShowMenu(playerid);
  684.             }
  685.  
  686.             #if defined ACCOUNT_CLIMIT
  687.             if(Bank_AccountCount(playerid) >= ACCOUNT_CLIMIT)
  688.             {
  689.                 SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't create any more bank accounts.");
  690.                 return Bank_ShowMenu(playerid);
  691.             }
  692.             #endif
  693.  
  694.             new query[144];
  695.             mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bank_accounts SET Owner='%e', Password=md5('%e'), CreatedOn=UNIX_TIMESTAMP()", Player_GetName(playerid), inputtext);
  696.             mysql_tquery(BankSQLHandle, query, "OnBankAccountCreated", "is", playerid, inputtext);
  697.             return 1;
  698.         }
  699.         /* ---------------------------------------------------------------------- */
  700.         case DIALOG_BANK_ACCOUNTS:
  701.         {
  702.             if(!response) return Bank_ShowMenu(playerid);
  703.            
  704.             SetPVarInt(playerid, "bankLoginAccount", strval(inputtext));
  705.             ShowPlayerDialog(playerid, DIALOG_BANK_LOGIN_PASS, DIALOG_STYLE_PASSWORD, "{F1C40F}Bank: {FFFFFF}Login", "Account Password:", "Login", "Cancel");
  706.             return 1;
  707.         }
  708.         /* ---------------------------------------------------------------------- */
  709.         case DIALOG_BANK_LOGIN_ID:
  710.         {
  711.             if(!response) return Bank_ShowMenu(playerid);
  712.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_LOGIN_ID, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Login", "{E74C3C}You can't leave the ID empty.\n\n{FFFFFF}Account ID:", "Continue", "Cancel");
  713.  
  714.             SetPVarInt(playerid, "bankLoginAccount", strval(inputtext));
  715.             ShowPlayerDialog(playerid, DIALOG_BANK_LOGIN_PASS, DIALOG_STYLE_PASSWORD, "{F1C40F}Bank: {FFFFFF}Login", "Account Password:", "Login", "Cancel");
  716.             return 1;
  717.         }
  718.         /* ---------------------------------------------------------------------- */
  719.         case DIALOG_BANK_LOGIN_PASS:
  720.         {
  721.             if(!response) return Bank_ShowMenu(playerid);
  722.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_LOGIN_PASS, DIALOG_STYLE_PASSWORD, "{F1C40F}Bank: {FFFFFF}Login", "{E74C3C}You can't leave the password empty.\n\n{FFFFFF}Account Password:", "Login", "Cancel");
  723.  
  724.             new query[200], id = GetPVarInt(playerid, "bankLoginAccount");
  725.             mysql_format(BankSQLHandle, query, sizeof(query), "SELECT Owner, LastAccess, FROM_UNIXTIME(LastAccess, '%%d/%%m/%%Y %%H:%%i:%%s') AS Last FROM bank_accounts WHERE ID=%d && Password=md5('%e') && Disabled=0 LIMIT 1", id, inputtext);
  726.             mysql_tquery(BankSQLHandle, query, "OnBankAccountLogin", "ii", playerid, id);
  727.             return 1;
  728.         }
  729.         /* ---------------------------------------------------------------------- */
  730.         case DIALOG_BANK_DEPOSIT:
  731.         {
  732.             if(!response) return Bank_ShowMenu(playerid);
  733.             if(CurrentAccountID[playerid] == -1) return 1;
  734.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_DEPOSIT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Deposit", "{E74C3C}You can't leave the input empty.\n\n{FFFFFF}How much money do you want to deposit?", "Deposit", "Back");
  735.             new amount = strval(inputtext);
  736.             if(!(1 <= amount <= (GetPVarInt(playerid, "usingATM") ? 5000000 : 250000000))) return ShowPlayerDialog(playerid, DIALOG_BANK_DEPOSIT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Deposit", "{E74C3C}You can't deposit less than $1 or more than $250,000,000 at once. ($5,000,000 at once on ATMs)\n\n{FFFFFF}How much money do you want to deposit?", "Deposit", "Back");
  737.             if(amount > GetPlayerMoney(playerid)) return ShowPlayerDialog(playerid, DIALOG_BANK_DEPOSIT, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Deposit", "{E74C3C}You don't have enough money.\n\n{FFFFFF}How much money do you want to deposit?", "Deposit", "Back");
  738.             if((amount + Bank_GetBalance(CurrentAccountID[playerid])) > ACCOUNT_LIMIT)
  739.             {
  740.                 SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You can't deposit any more money to this account.");
  741.                 return Bank_ShowMenu(playerid);
  742.             }
  743.            
  744.             new query[96];
  745.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Balance=Balance+%d WHERE ID=%d && Disabled=0", amount, CurrentAccountID[playerid]);
  746.             mysql_tquery(BankSQLHandle, query, "OnBankAccountDeposit", "ii", playerid, amount);
  747.             return 1;
  748.         }
  749.         /* ---------------------------------------------------------------------- */
  750.         case DIALOG_BANK_WITHDRAW:
  751.         {
  752.             if(!response) return Bank_ShowMenu(playerid);
  753.             if(CurrentAccountID[playerid] == -1) return 1;
  754.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_WITHDRAW, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Withdraw", "{E74C3C}You can't leave the input empty.\n\n{FFFFFF}How much money do you want to withdraw?", "Withdraw", "Back");
  755.             new amount = strval(inputtext);
  756.             if(!(1 <= amount <= (GetPVarInt(playerid, "usingATM") ? 5000000 : 250000000))) return ShowPlayerDialog(playerid, DIALOG_BANK_WITHDRAW, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Withdraw", "{E74C3C}You can't withdraw less than $1 or more than $250,000,000 at once. ($5,000,000 at once on ATMs)\n\n{FFFFFF}How much money do you want to withdraw?", "Withdraw", "Back");
  757.             if(amount > Bank_GetBalance(CurrentAccountID[playerid])) return ShowPlayerDialog(playerid, DIALOG_BANK_WITHDRAW, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Withdraw", "{E74C3C}Account doesn't have enough money.\n\n{FFFFFF}How much money do you want to withdraw?", "Withdraw", "Back");
  758.            
  759.             new query[96];
  760.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Balance=Balance-%d WHERE ID=%d && Disabled=0", amount, CurrentAccountID[playerid]);
  761.             mysql_tquery(BankSQLHandle, query, "OnBankAccountWithdraw", "ii", playerid, amount);
  762.             return 1;
  763.         }
  764.         /* ---------------------------------------------------------------------- */
  765.         case DIALOG_BANK_TRANSFER_1:
  766.         {
  767.             if(!response) return Bank_ShowMenu(playerid);
  768.             if(CurrentAccountID[playerid] == -1) return 1;
  769.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_1, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "{E74C3C}You can't leave the input empty.\n\n{FFFFFF}Specify an account ID:", "Continue", "Back");
  770.             if(strval(inputtext) == CurrentAccountID[playerid]) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_1, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "{E74C3C}You can't transfer money to your current account.\n\n{FFFFFF}Specify an account ID:", "Continue", "Back");
  771.             SetPVarInt(playerid, "bankTransferAccount", strval(inputtext));
  772.             ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_2, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "Specify an amount:", "Transfer", "Back");
  773.             return 1;
  774.         }
  775.         /* ---------------------------------------------------------------------- */
  776.         case DIALOG_BANK_TRANSFER_2:
  777.         {
  778.             if(!response) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_1, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "Specify an account ID:", "Continue", "Back");
  779.             if(CurrentAccountID[playerid] == -1) return 1;
  780.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_2, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "{E74C3C}You can't leave the input empty.\n\n{FFFFFF}Specify an amount:", "Transfer", "Back");
  781.             new amount = strval(inputtext);
  782.             if(!(1 <= amount <= (GetPVarInt(playerid, "usingATM") ? 5000000 : 250000000))) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_2, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "{E74C3C}You can't transfer less than $1 or more than $250,000,000 at once. ($5,000,000 on ATMs)\n\n{FFFFFF}Specify an amount:", "Transfer", "Back");
  783.             if(amount > Bank_GetBalance(CurrentAccountID[playerid])) return ShowPlayerDialog(playerid, DIALOG_BANK_TRANSFER_2, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Transfer", "{E74C3C}Account doesn't have enough money.\n\n{FFFFFF}Specify an amount:", "Transfer", "Back");
  784.             new id = GetPVarInt(playerid, "bankTransferAccount");
  785.             if((amount + Bank_GetBalance(id)) > ACCOUNT_LIMIT)
  786.             {
  787.                 SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't deposit any more money to the account you specified.");
  788.                 return Bank_ShowMenu(playerid);
  789.             }
  790.            
  791.             new query[96];
  792.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Balance=Balance+%d WHERE ID=%d && Disabled=0", amount, id);
  793.             mysql_tquery(BankSQLHandle, query, "OnBankAccountTransfer", "iii", playerid, id, amount);
  794.             return 1;
  795.         }
  796.         /* ---------------------------------------------------------------------- */
  797.         case DIALOG_BANK_PASSWORD:
  798.         {
  799.             if(!response) return Bank_ShowMenu(playerid);
  800.             if(CurrentAccountID[playerid] == -1) return 1;
  801.             if(isnull(inputtext)) return ShowPlayerDialog(playerid, DIALOG_BANK_PASSWORD, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Change Password", "{E74C3C}You can't leave the input empty.\n\n{FFFFFF}Write a new password:", "Change", "Back");
  802.             if(strlen(inputtext) > 16) return ShowPlayerDialog(playerid, DIALOG_BANK_PASSWORD, DIALOG_STYLE_INPUT, "{F1C40F}Bank: {FFFFFF}Change Password", "{E74C3C}New password can't be more than 16 characters.\n\n{FFFFFF}Write a new password:", "Change", "Back");
  803.            
  804.             new query[128];
  805.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Password=md5('%e') WHERE ID=%d && Disabled=0", inputtext, CurrentAccountID[playerid]);
  806.             mysql_tquery(BankSQLHandle, query, "OnBankAccountPassChange", "is", playerid, inputtext);
  807.             return 1;
  808.         }
  809.         /* ---------------------------------------------------------------------- */
  810.         case DIALOG_BANK_REMOVE:
  811.         {
  812.             if(!response) return Bank_ShowMenu(playerid);
  813.             if(CurrentAccountID[playerid] == -1) return 1;
  814.            
  815.             new query[96], amount = Bank_GetBalance(CurrentAccountID[playerid]);
  816.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Disabled=1 WHERE ID=%d", CurrentAccountID[playerid]);
  817.             mysql_tquery(BankSQLHandle, query, "OnBankAccountDeleted", "iii", playerid, CurrentAccountID[playerid], amount);
  818.             return 1;
  819.         }
  820.         /* ---------------------------------------------------------------------- */
  821.         case DIALOG_BANK_LOGS:
  822.         {
  823.             if(!response) return Bank_ShowMenu(playerid);
  824.             if(CurrentAccountID[playerid] == -1) return 1;
  825.            
  826.             new typelist[6] = {TYPE_NONE, TYPE_DEPOSIT, TYPE_WITHDRAW, TYPE_TRANSFER, TYPE_LOGIN, TYPE_PASSCHANGE};
  827.             LogListType[playerid] = typelist[listitem + 1];
  828.             LogListPage[playerid] = 0;
  829.             Bank_ShowLogs(playerid);
  830.             return 1;
  831.         }
  832.         /* ---------------------------------------------------------------------- */
  833.         case DIALOG_BANK_LOG_PAGE:
  834.         {
  835.             if(CurrentAccountID[playerid] == -1 || LogListType[playerid] == TYPE_NONE) return 1;
  836.             if(!response) {
  837.                 LogListPage[playerid]--;
  838.                 if(LogListPage[playerid] < 0) return Bank_ShowLogMenu(playerid);
  839.             }else{
  840.                 LogListPage[playerid]++;
  841.             }
  842.            
  843.             Bank_ShowLogs(playerid);
  844.             return 1;
  845.         }
  846.         /* ---------------------------------------------------------------------- */
  847.     }
  848.    
  849.     return 0;
  850. }
  851.  
  852. public OnPlayerEditDynamicObject(playerid, STREAMER_TAG_OBJECT objectid, response, Float:x, Float:y, Float:z, Float:rx, Float:ry, Float:rz)
  853. {
  854.     if(Iter_Contains(ATMs, EditingATMID[playerid]))
  855.     {
  856.         if(response == EDIT_RESPONSE_FINAL)
  857.         {
  858.             new id = EditingATMID[playerid];
  859.             ATMData[id][atmX] = x;
  860.             ATMData[id][atmY] = y;
  861.             ATMData[id][atmZ] = z;
  862.             ATMData[id][atmRX] = rx;
  863.             ATMData[id][atmRY] = ry;
  864.             ATMData[id][atmRZ] = rz;
  865.            
  866.             SetDynamicObjectPos(objectid, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ]);
  867.             SetDynamicObjectRot(objectid, ATMData[id][atmRX], ATMData[id][atmRY], ATMData[id][atmRZ]);
  868.            
  869.             #if defined ATM_USE_MAPICON
  870.             Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, ATMData[id][atmIconID], E_STREAMER_X, ATMData[id][atmX]);
  871.             Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, ATMData[id][atmIconID], E_STREAMER_Y, ATMData[id][atmY]);
  872.             Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, ATMData[id][atmIconID], E_STREAMER_Z, ATMData[id][atmZ]);
  873.             #endif
  874.  
  875.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, ATMData[id][atmLabel], E_STREAMER_X, ATMData[id][atmX]);
  876.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, ATMData[id][atmLabel], E_STREAMER_Y, ATMData[id][atmY]);
  877.             Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, ATMData[id][atmLabel], E_STREAMER_Z, ATMData[id][atmZ] + 0.85);
  878.  
  879.             new query[144];
  880.             mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_atms SET PosX='%f', PosY='%f', PosZ='%f', RotX='%f', RotY='%f', RotZ='%f' WHERE ID=%d", x, y, z, rx, ry, rz, id);
  881.             mysql_tquery(BankSQLHandle, query);
  882.            
  883.             EditingATMID[playerid] = -1;
  884.         }
  885.        
  886.         if(response == EDIT_RESPONSE_CANCEL)
  887.         {
  888.             new id = EditingATMID[playerid];
  889.             SetDynamicObjectPos(objectid, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ]);
  890.             SetDynamicObjectRot(objectid, ATMData[id][atmRX], ATMData[id][atmRY], ATMData[id][atmRZ]);
  891.             EditingATMID[playerid] = -1;
  892.         }
  893.     }
  894.    
  895.     return 1;
  896. }
  897.  
  898. public OnPlayerShootDynamicObject(playerid, weaponid, STREAMER_TAG_OBJECT objectid, Float:x, Float:y, Float:z)
  899. {
  900.     if(Streamer_GetIntData(STREAMER_TYPE_OBJECT, objectid, E_STREAMER_MODEL_ID) == 19324)
  901.     {
  902.         new dataArray[E_ATMDATA];
  903.         Streamer_GetArrayData(STREAMER_TYPE_OBJECT, objectid, E_STREAMER_EXTRA_ID, dataArray);
  904.  
  905.         if(strlen(dataArray[IDString]) && !strcmp(dataArray[IDString], "atm_sys") && Iter_Contains(ATMs, dataArray[refID]) && ATMData[ dataArray[refID] ][atmRegen] == 0)
  906.         {
  907.             new id = dataArray[refID], string[64], Float: damage = GetWeaponDamageFromDistance(weaponid, GetPlayerDistanceFromPoint(playerid, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ])) / 1.5;
  908.             ATMData[id][atmHealth] -= damage;
  909.  
  910.             if(ATMData[id][atmHealth] < 0.0) {
  911.                 ATMData[id][atmHealth] = 0.0;
  912.                
  913.                 format(string, sizeof(string), "ATM (%d)\n\n{FFFFFF}Out of Service\n{E74C3C}%s", id, ConvertToMinutes(ATM_REGEN));
  914.                 UpdateDynamic3DTextLabelText(ATMData[id][atmLabel], 0x1ABC9CFF, string);
  915.                
  916.                 ATMData[id][atmRegen] = ATM_REGEN;
  917.                 ATMData[id][atmTimer] = SetTimerEx("ATM_Regen", 1000, true, "i", id);
  918.                 Streamer_SetIntData(STREAMER_TYPE_OBJECT, objectid, E_STREAMER_MODEL_ID, 2943);
  919.                
  920.                 new Float: a = ATMData[id][atmRZ] + 180.0;
  921.                 ATMData[id][atmPickup] = CreateDynamicPickup(1212, 1, ATMData[id][atmX] + (1.25 * floatsin(-a, degrees)), ATMData[id][atmY] + (1.25 * floatcos(-a, degrees)), ATMData[id][atmZ] - 0.25);
  922.  
  923.                 if(IsValidDynamicPickup(ATMData[id][atmPickup]))
  924.                 {
  925.                     new pickupDataArray[E_ATMDATA];
  926.                     format(pickupDataArray[IDString], 8, "atm_sys");
  927.                     pickupDataArray[refID] = id;
  928.                     Streamer_SetArrayData(STREAMER_TYPE_PICKUP, ATMData[id][atmPickup], E_STREAMER_EXTRA_ID, pickupDataArray);
  929.                 }
  930.                
  931.                 Streamer_Update(playerid);
  932.             }else{
  933.                 format(string, sizeof(string), "ATM (%d)\n\n{FFFFFF}Use {F1C40F}/atm!\n%s", id, ATM_ReturnDmgText(id));
  934.                 UpdateDynamic3DTextLabelText(ATMData[id][atmLabel], 0x1ABC9CFF, string);
  935.             }
  936.            
  937.             PlayerPlaySound(playerid, 17802, 0.0, 0.0, 0.0);
  938.         }
  939.     }
  940.    
  941.     return 1;
  942. }
  943.  
  944. public OnPlayerPickUpDynamicPickup(playerid, pickupid)
  945. {
  946.     if(Streamer_GetIntData(STREAMER_TYPE_PICKUP, pickupid, E_STREAMER_MODEL_ID) == 1212)
  947.     {
  948.         new dataArray[E_ATMDATA];
  949.         Streamer_GetArrayData(STREAMER_TYPE_PICKUP, pickupid, E_STREAMER_EXTRA_ID, dataArray);
  950.  
  951.         if(strlen(dataArray[IDString]) && !strcmp(dataArray[IDString], "atm_sys"))
  952.         {
  953.             new money = RandomEx(ATM_ROB_MIN, ATM_ROB_MAX), string[64];
  954.             format(string, sizeof(string), "ATM: {FFFFFF}You stole {2ECC71}%s {FFFFFF}from the ATM.", formatInt(money));
  955.             SendClientMessage(playerid, 0x3498DBFF, string);
  956.             GivePlayerMoney(playerid, money);
  957.  
  958.             ATMData[ dataArray[refID] ][atmPickup] = -1;
  959.             DestroyDynamicPickup(pickupid);
  960.         }
  961.     }
  962.  
  963.     return 1;
  964. }
  965.  
  966. forward LoadBankers();
  967. public LoadBankers()
  968. {
  969.     new rows = cache_num_rows();
  970.     if(rows)
  971.     {
  972.         new id, label_string[64];
  973.         for(new i; i < rows; i++)
  974.         {
  975.             id = cache_get_field_content_int(i, "ID");
  976.             BankerData[id][Skin] = cache_get_field_content_int(i, "Skin");
  977.             BankerData[id][bankerX] = cache_get_field_content_float(i, "PosX");
  978.             BankerData[id][bankerY] = cache_get_field_content_float(i, "PosY");
  979.             BankerData[id][bankerZ] = cache_get_field_content_float(i, "PosZ");
  980.             BankerData[id][bankerA] = cache_get_field_content_float(i, "PosA");
  981.            
  982.             BankerData[id][bankerActorID] = CreateActor(BankerData[id][Skin], BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA]);
  983.             if(!IsValidActor(BankerData[id][bankerActorID])) {
  984.                 printf("  [Bank System] Couldn't create an actor for banker ID %d.", id);
  985.             }else{
  986.                 SetActorInvulnerable(BankerData[id][bankerActorID], true); // people may use a version where actors aren't invulnerable by default
  987.             }
  988.            
  989.             #if defined BANKER_USE_MAPICON
  990.             BankerData[id][bankerIconID] = CreateDynamicMapIcon(BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], 58, 0, .streamdistance = BANKER_ICON_RANGE);
  991.             #endif
  992.            
  993.             format(label_string, sizeof(label_string), "Banker (%d)\n\n{FFFFFF}Use {F1C40F}/bank!", id);
  994.             BankerData[id][bankerLabel] = CreateDynamic3DTextLabel(label_string, 0x1ABC9CFF, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ] + 0.25, 5.0, .testlos = 1);
  995.  
  996.             Iter_Add(Bankers, id);
  997.         }
  998.     }
  999.    
  1000.     printf("  [Bank System] Loaded %d bankers.", Iter_Count(Bankers));
  1001.     return 1;
  1002. }
  1003.  
  1004. forward LoadATMs();
  1005. public LoadATMs()
  1006. {
  1007.     new rows = cache_num_rows();
  1008.     if(rows)
  1009.     {
  1010.         new id, label_string[64], dataArray[E_ATMDATA];
  1011.         for(new i; i < rows; i++)
  1012.         {
  1013.             id = cache_get_field_content_int(i, "ID");
  1014.             ATMData[id][atmX] = cache_get_field_content_float(i, "PosX");
  1015.             ATMData[id][atmY] = cache_get_field_content_float(i, "PosY");
  1016.             ATMData[id][atmZ] = cache_get_field_content_float(i, "PosZ");
  1017.             ATMData[id][atmRX] = cache_get_field_content_float(i, "RotX");
  1018.             ATMData[id][atmRY] = cache_get_field_content_float(i, "RotY");
  1019.             ATMData[id][atmRZ] = cache_get_field_content_float(i, "RotZ");
  1020.  
  1021.             ATMData[id][atmObjID] = CreateDynamicObject(19324, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ], ATMData[id][atmRX], ATMData[id][atmRY], ATMData[id][atmRZ]);
  1022.            
  1023.             if(IsValidDynamicObject(ATMData[id][atmObjID])) {
  1024.                 format(dataArray[IDString], 8, "atm_sys");
  1025.                 dataArray[refID] = id;
  1026.                
  1027.                 Streamer_SetArrayData(STREAMER_TYPE_OBJECT, ATMData[id][atmObjID], E_STREAMER_EXTRA_ID, dataArray);
  1028.             }else{
  1029.                 printf("  [Bank System] Couldn't create an ATM object for ATM ID %d.", id);
  1030.             }
  1031.            
  1032.             #if defined ATM_USE_MAPICON
  1033.             ATMData[id][atmIconID] = CreateDynamicMapIcon(ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ], 52, 0, .streamdistance = ATM_ICON_RANGE);
  1034.             #endif
  1035.  
  1036.             format(label_string, sizeof(label_string), "ATM (%d)\n\n{FFFFFF}Use {F1C40F}/atm!", id);
  1037.             ATMData[id][atmLabel] = CreateDynamic3DTextLabel(label_string, 0x1ABC9CFF, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ] + 0.85, 5.0, .testlos = 1);
  1038.  
  1039.             Iter_Add(ATMs, id);
  1040.         }
  1041.     }
  1042.  
  1043.     printf("  [Bank System] Loaded %d ATMs.", Iter_Count(ATMs));
  1044.     return 1;
  1045. }
  1046.  
  1047. forward OnBankAccountCreated(playerid, pass[]);
  1048. public OnBankAccountCreated(playerid, pass[])
  1049. {
  1050.     GivePlayerMoney(playerid, -ACCOUNT_PRICE);
  1051.    
  1052.     new id = cache_insert_id(), string[64];
  1053.     SendClientMessage(playerid, 0x3498DBFF, "BANK: {FFFFFF}Successfully created an account for you!");
  1054.    
  1055.     format(string, sizeof(string), "BANK: {FFFFFF}Your account ID: {F1C40F}%d", id);
  1056.     SendClientMessage(playerid, 0x3498DBFF, string);
  1057.    
  1058.     format(string, sizeof(string), "BANK: {FFFFFF}Your account password: {F1C40F}%s", pass);
  1059.     SendClientMessage(playerid, 0x3498DBFF, string);
  1060.     return 1;
  1061. }
  1062.  
  1063. forward OnBankAccountLogin(playerid, id);
  1064. public OnBankAccountLogin(playerid, id)
  1065. {
  1066.     if(cache_num_rows() > 0) {
  1067.         new string[128], owner[MAX_PLAYER_NAME], ldate[24];
  1068.         cache_get_field_content(0, "Owner", owner);
  1069.         cache_get_field_content(0, "Last", ldate);
  1070.        
  1071.         format(string, sizeof(string), "BANK: {FFFFFF}This account is owned by {F1C40F}%s.", owner);
  1072.         SendClientMessage(playerid, 0x3498DBFF, string);
  1073.         format(string, sizeof(string), "BANK: {FFFFFF}Last Accessed On: {F1C40F}%s", (cache_get_field_content_int(0, "LastAccess") == 0) ? ("Never") : ldate);
  1074.         SendClientMessage(playerid, 0x3498DBFF, string);
  1075.        
  1076.         CurrentAccountID[playerid] = id;
  1077.         Bank_ShowMenu(playerid);
  1078.        
  1079.         new query[96];
  1080.         mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET LastAccess=UNIX_TIMESTAMP() WHERE ID=%d && Disabled=0", id);
  1081.         mysql_tquery(BankSQLHandle, query);
  1082.        
  1083.         Bank_SaveLog(playerid, TYPE_LOGIN, id, -1, 0);
  1084.     }else{
  1085.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid credentials.");
  1086.         Bank_ShowMenu(playerid);
  1087.     }
  1088.    
  1089.     return 1;
  1090. }
  1091.  
  1092. forward OnBankAccountDeposit(playerid, amount);
  1093. public OnBankAccountDeposit(playerid, amount)
  1094. {
  1095.     if(cache_affected_rows() > 0) {
  1096.         new string[64];
  1097.         format(string, sizeof(string), "BANK: {FFFFFF}Successfully deposited {2ECC71}%s.", formatInt(amount));
  1098.         SendClientMessage(playerid, 0x3498DBFF, string);
  1099.        
  1100.         GivePlayerMoney(playerid, -amount);
  1101.         Bank_SaveLog(playerid, TYPE_DEPOSIT, CurrentAccountID[playerid], -1, amount);
  1102.     }else{
  1103.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Transaction failed.");
  1104.     }
  1105.    
  1106.     Bank_ShowMenu(playerid);
  1107.     return 1;
  1108. }
  1109.  
  1110. forward OnBankAccountWithdraw(playerid, amount);
  1111. public OnBankAccountWithdraw(playerid, amount)
  1112. {
  1113.     if(cache_affected_rows() > 0) {
  1114.         new string[64];
  1115.         format(string, sizeof(string), "BANK: {FFFFFF}Successfully withdrawn {2ECC71}%s.", formatInt(amount));
  1116.         SendClientMessage(playerid, 0x3498DBFF, string);
  1117.  
  1118.         GivePlayerMoney(playerid, amount);
  1119.         Bank_SaveLog(playerid, TYPE_WITHDRAW, CurrentAccountID[playerid], -1, amount);
  1120.     }else{
  1121.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Transaction failed.");
  1122.     }
  1123.  
  1124.     Bank_ShowMenu(playerid);
  1125.     return 1;
  1126. }
  1127.  
  1128. forward OnBankAccountTransfer(playerid, id, amount);
  1129. public OnBankAccountTransfer(playerid, id, amount)
  1130. {
  1131.     if(cache_affected_rows() > 0) {
  1132.         new query[144];
  1133.         mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Balance=Balance-%d WHERE ID=%d && Disabled=0", amount, CurrentAccountID[playerid]);
  1134.         mysql_tquery(BankSQLHandle, query, "OnBankAccountTransferDone", "iii", playerid, id, amount);
  1135.     }else{
  1136.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Transaction failed.");
  1137.         Bank_ShowMenu(playerid);
  1138.     }
  1139.  
  1140.     return 1;
  1141. }
  1142.  
  1143. forward OnBankAccountTransferDone(playerid, id, amount);
  1144. public OnBankAccountTransferDone(playerid, id, amount)
  1145. {
  1146.     if(cache_affected_rows() > 0) {
  1147.         new string[128];
  1148.         format(string, sizeof(string), "BANK: {FFFFFF}Successfully transferred {2ECC71}%s {FFFFFF}to account ID {F1C40F}%d.", formatInt(amount), id);
  1149.         SendClientMessage(playerid, 0x3498DBFF, string);
  1150.        
  1151.         Bank_SaveLog(playerid, TYPE_TRANSFER, CurrentAccountID[playerid], id, amount);
  1152.     }else{
  1153.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Transaction failed.");
  1154.        
  1155.     }
  1156.  
  1157.     Bank_ShowMenu(playerid);
  1158.     return 1;
  1159. }
  1160.  
  1161. forward OnBankAccountPassChange(playerid, newpass[]);
  1162. public OnBankAccountPassChange(playerid, newpass[])
  1163. {
  1164.     if(cache_affected_rows() > 0) {
  1165.         new string[128];
  1166.         format(string, sizeof(string), "BANK: {FFFFFF}Account password set to {F1C40F}%s.", newpass);
  1167.         SendClientMessage(playerid, 0x3498DBFF, string);
  1168.        
  1169.         Bank_SaveLog(playerid, TYPE_PASSCHANGE, CurrentAccountID[playerid], -1, 0);
  1170.     }else{
  1171.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Password change failed.");
  1172.     }
  1173.  
  1174.     Bank_ShowMenu(playerid);
  1175.     return 1;
  1176. }
  1177.  
  1178. forward OnBankAccountDeleted(playerid, id, amount);
  1179. public OnBankAccountDeleted(playerid, id, amount)
  1180. {
  1181.     if(cache_affected_rows() > 0) {
  1182.         GivePlayerMoney(playerid, amount);
  1183.        
  1184.         foreach(new i : Player)
  1185.         {
  1186.             if(i == playerid) continue;
  1187.             if(CurrentAccountID[i] == id) CurrentAccountID[i] = -1;
  1188.         }
  1189.        
  1190.         new string[128];
  1191.         format(string, sizeof(string), "BANK: {FFFFFF}Account removed, you got the {2ECC71}%s {FFFFFF}left in the account.", formatInt(amount));
  1192.         SendClientMessage(playerid, 0x3498DBFF, string);
  1193.     }else{
  1194.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Account removal failed.");
  1195.     }
  1196.  
  1197.     CurrentAccountID[playerid] = -1;
  1198.     Bank_ShowMenu(playerid);
  1199.     return 1;
  1200. }
  1201.  
  1202. forward OnBankAccountAdminEdit(playerid);
  1203. public OnBankAccountAdminEdit(playerid)
  1204. {
  1205.     if(cache_affected_rows() > 0) {
  1206.         SendClientMessage(playerid, 0x3498DBFF, "BANK: {FFFFFF}Account edited.");
  1207.     }else{
  1208.         SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Account editing failed. (No affected rows)");
  1209.     }
  1210.    
  1211.     return 1;
  1212. }
  1213.  
  1214. forward ATM_Regen(id);
  1215. public ATM_Regen(id)
  1216. {
  1217.     new string[64];
  1218.    
  1219.     if(ATMData[id][atmRegen] > 1) {
  1220.         ATMData[id][atmRegen]--;
  1221.        
  1222.         format(string, sizeof(string), "ATM (%d)\n\n{FFFFFF}Out of Service\n{E74C3C}%s", id, ConvertToMinutes(ATMData[id][atmRegen]));
  1223.         UpdateDynamic3DTextLabelText(ATMData[id][atmLabel], 0x1ABC9CFF, string);
  1224.     }else if(ATMData[id][atmRegen] == 1) {
  1225.         if(IsValidDynamicPickup(ATMData[id][atmPickup])) DestroyDynamicPickup(ATMData[id][atmPickup]);
  1226.         KillTimer(ATMData[id][atmTimer]);
  1227.        
  1228.         ATMData[id][atmHealth] = ATM_HEALTH;
  1229.         ATMData[id][atmRegen] = 0;
  1230.         ATMData[id][atmTimer] = ATMData[id][atmPickup] = -1;
  1231.        
  1232.         Streamer_SetIntData(STREAMER_TYPE_OBJECT, ATMData[id][atmObjID], E_STREAMER_MODEL_ID, 19324);
  1233.        
  1234.         format(string, sizeof(string), "ATM (%d)\n\n{FFFFFF}Use {F1C40F}/atm!", id);
  1235.         UpdateDynamic3DTextLabelText(ATMData[id][atmLabel], 0x1ABC9CFF, string);
  1236.     }
  1237.    
  1238.     return 1;
  1239. }
  1240.  
  1241. // Player Commands
  1242. CMD:bank(playerid, params[])
  1243. {
  1244.     if(!IsPlayerNearBanker(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near a banker.");
  1245.     SetPVarInt(playerid, "usingATM", 0);
  1246.     Bank_ShowMenu(playerid);
  1247.     return 1;
  1248. }
  1249.  
  1250. CMD:atm(playerid, params[])
  1251. {
  1252.     new id = GetClosestATM(playerid);
  1253.     if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near an ATM.");
  1254.     if(ATMData[id][atmRegen] > 0) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}This ATM is out of service.");
  1255.     SetPVarInt(playerid, "usingATM", 1);
  1256.     Bank_ShowMenu(playerid);
  1257.     return 1;
  1258. }
  1259.  
  1260. // Admin Commands
  1261. CMD:asetowner(playerid, params[])
  1262. {
  1263.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1264.     new id, owner[MAX_PLAYER_NAME];
  1265.     if(sscanf(params, "is[24]", id, owner)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/asetowner [account id] [new owner]");
  1266.     new query[128];
  1267.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Owner='%e' WHERE ID=%d", owner, id);
  1268.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1269.     return 1;
  1270. }
  1271.  
  1272. CMD:asetpassword(playerid, params[])
  1273. {
  1274.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1275.     new id, password[16];
  1276.     if(sscanf(params, "is[16]", id, password)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/asetpassword [account id] [new password]");
  1277.     new query[128];
  1278.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Password=md5('%e') WHERE ID=%d", password, id);
  1279.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1280.     return 1;
  1281. }
  1282.  
  1283. CMD:asetbalance(playerid, params[])
  1284. {
  1285.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1286.     new id, balance;
  1287.     if(sscanf(params, "ii", id, balance)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/asetbalance [account id] [balance]");
  1288.     if(balance > ACCOUNT_LIMIT) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Balance you specified exceeds account money limit.");
  1289.     new query[128];
  1290.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Balance=%d WHERE ID=%d", balance, id);
  1291.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1292.     return 1;
  1293. }
  1294.  
  1295. CMD:aclearlogs(playerid, params[])
  1296. {
  1297.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1298.     new id, type;
  1299.     if(sscanf(params, "iI(0)", id, type))
  1300.     {
  1301.         SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/aclearlogs [account id] [log type (optional)]");
  1302.         SendClientMessage(playerid, 0xE88732FF, "TYPES: {FFFFFF}0- All | 1- Logins | 2- Deposits | 3- Withdraws | 4- Transfers | 5- Password Changes");
  1303.         return 1;
  1304.     }
  1305.  
  1306.     new query[128];
  1307.     if(type > 0) {
  1308.         mysql_format(BankSQLHandle, query, sizeof(query), "DELETE FROM bank_logs WHERE AccountID=%d && Type=%d", id, type);
  1309.     }else{
  1310.         mysql_format(BankSQLHandle, query, sizeof(query), "DELETE FROM bank_logs WHERE AccountID=%d", id);
  1311.     }
  1312.  
  1313.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1314.     return 1;
  1315. }
  1316.  
  1317. CMD:aremoveaccount(playerid, params[])
  1318. {
  1319.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1320.     new id;
  1321.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/aremoveaccount [account id]");
  1322.     foreach(new i : Player)
  1323.     {
  1324.         if(CurrentAccountID[i] == id) CurrentAccountID[i] = -1;
  1325.     }
  1326.    
  1327.     new query[128];
  1328.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Disabled=1 WHERE ID=%d", id);
  1329.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1330.     return 1;
  1331. }
  1332.  
  1333. CMD:areturnaccount(playerid, params[])
  1334. {
  1335.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1336.     new id;
  1337.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/areturnaccount [account id]");
  1338.     new query[128];
  1339.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bank_accounts SET Disabled=0 WHERE ID=%d", id);
  1340.     mysql_tquery(BankSQLHandle, query, "OnBankAccountAdminEdit", "i", playerid);
  1341.     return 1;
  1342. }
  1343.  
  1344. // Admin Commands for Bankers
  1345. CMD:createbanker(playerid, params[])
  1346. {
  1347.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1348.     new id = Iter_Free(Bankers);
  1349.     if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't create any more bankers.");
  1350.     new skin;
  1351.     if(sscanf(params, "i", skin)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/createbanker [skin id]");
  1352.     if(!(0 <= skin <= 311)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid skin ID.");
  1353.     BankerData[id][Skin] = skin;
  1354.     GetPlayerPos(playerid, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ]);
  1355.     GetPlayerFacingAngle(playerid, BankerData[id][bankerA]);
  1356.     SetPlayerPos(playerid, BankerData[id][bankerX] + (1.0 * floatsin(-BankerData[id][bankerA], degrees)), BankerData[id][bankerY] + (1.0 * floatcos(-BankerData[id][bankerA], degrees)), BankerData[id][bankerZ]);
  1357.  
  1358.     BankerData[id][bankerActorID] = CreateActor(skin, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA]);
  1359.     if(IsValidActor(BankerData[id][bankerActorID])) SetActorInvulnerable(BankerData[id][bankerActorID], true);
  1360.    
  1361.     #if defined BANKER_USE_MAPICON
  1362.     BankerData[id][bankerIconID] = CreateDynamicMapIcon(BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], 58, 0, .streamdistance = BANKER_ICON_RANGE);
  1363.     #endif
  1364.  
  1365.     new label_string[64];
  1366.     format(label_string, sizeof(label_string), "Banker (%d)\n\n{FFFFFF}Use {F1C40F}/bank!", id);
  1367.     BankerData[id][bankerLabel] = CreateDynamic3DTextLabel(label_string, 0x1ABC9CFF, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ] + 0.25, 5.0, .testlos = 1);
  1368.  
  1369.     new query[144];
  1370.     mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bankers SET ID=%d, Skin=%d, PosX='%f', PosY='%f', PosZ='%f', PosA='%f'", id, skin, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA]);
  1371.     mysql_tquery(BankSQLHandle, query);
  1372.    
  1373.     Iter_Add(Bankers, id);
  1374.     return 1;
  1375. }
  1376.  
  1377. CMD:setbankerpos(playerid, params[])
  1378. {
  1379.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1380.     new id;
  1381.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/setbankerpos [banker id]");
  1382.     if(!Iter_Contains(Bankers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid banker ID.");
  1383.     GetPlayerPos(playerid, BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ]);
  1384.     GetPlayerFacingAngle(playerid, BankerData[id][bankerA]);
  1385.  
  1386.     DestroyActor(BankerData[id][bankerActorID]);
  1387.     BankerData[id][bankerActorID] = CreateActor(BankerData[id][Skin], BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA]);
  1388.     if(IsValidActor(BankerData[id][bankerActorID])) SetActorInvulnerable(BankerData[id][bankerActorID], true);
  1389.  
  1390.     #if defined BANKER_USE_MAPICON
  1391.     Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, BankerData[id][bankerIconID], E_STREAMER_X, BankerData[id][bankerX]);
  1392.     Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, BankerData[id][bankerIconID], E_STREAMER_Y, BankerData[id][bankerY]);
  1393.     Streamer_SetFloatData(STREAMER_TYPE_MAP_ICON, BankerData[id][bankerIconID], E_STREAMER_Z, BankerData[id][bankerZ]);
  1394.     #endif
  1395.  
  1396.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BankerData[id][bankerLabel], E_STREAMER_X, BankerData[id][bankerX]);
  1397.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BankerData[id][bankerLabel], E_STREAMER_Y, BankerData[id][bankerY]);
  1398.     Streamer_SetFloatData(STREAMER_TYPE_3D_TEXT_LABEL, BankerData[id][bankerLabel], E_STREAMER_Z, BankerData[id][bankerZ]);
  1399.    
  1400.     SetPlayerPos(playerid, BankerData[id][bankerX] + (1.0 * floatsin(-BankerData[id][bankerA], degrees)), BankerData[id][bankerY] + (1.0 * floatcos(-BankerData[id][bankerA], degrees)), BankerData[id][bankerZ]);
  1401.    
  1402.     new query[144];
  1403.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bankers SET PosX='%f', PosY='%f', PosZ='%f', PosA='%f' WHERE ID=%d", BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA], id);
  1404.     mysql_tquery(BankSQLHandle, query);
  1405.     return 1;
  1406. }
  1407.  
  1408. CMD:setbankerskin(playerid, params[])
  1409. {
  1410.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1411.     new id, skin;
  1412.     if(sscanf(params, "ii", id, skin)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/setbankerskin [banker id] [skin id]");
  1413.     if(!Iter_Contains(Bankers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid banker ID.");
  1414.     if(!(0 <= skin <= 311)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid skin ID.");
  1415.     BankerData[id][Skin] = skin;
  1416.    
  1417.     if(IsValidActor(BankerData[id][bankerActorID])) DestroyActor(BankerData[id][bankerActorID]);
  1418.     BankerData[id][bankerActorID] = CreateActor(BankerData[id][Skin], BankerData[id][bankerX], BankerData[id][bankerY], BankerData[id][bankerZ], BankerData[id][bankerA]);
  1419.     if(IsValidActor(BankerData[id][bankerActorID])) SetActorInvulnerable(BankerData[id][bankerActorID], true);
  1420.  
  1421.     new query[48];
  1422.     mysql_format(BankSQLHandle, query, sizeof(query), "UPDATE bankers SET Skin=%d WHERE ID=%d", BankerData[id][Skin], id);
  1423.     mysql_tquery(BankSQLHandle, query);
  1424.     return 1;
  1425. }
  1426.  
  1427. CMD:removebanker(playerid, params[])
  1428. {
  1429.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1430.     new id;
  1431.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/removebanker [banker id]");
  1432.     if(!Iter_Contains(Bankers, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid banker ID.");
  1433.     if(IsValidActor(BankerData[id][bankerActorID])) DestroyActor(BankerData[id][bankerActorID]);
  1434.     BankerData[id][bankerActorID] = -1;
  1435.    
  1436.     #if defined BANKER_USE_MAPICON
  1437.     if(IsValidDynamicMapIcon(BankerData[id][bankerIconID])) DestroyDynamicMapIcon(BankerData[id][bankerIconID]);
  1438.     BankerData[id][bankerIconID] = -1;
  1439.     #endif
  1440.  
  1441.     if(IsValidDynamic3DTextLabel(BankerData[id][bankerLabel])) DestroyDynamic3DTextLabel(BankerData[id][bankerLabel]);
  1442.     BankerData[id][bankerLabel] = Text3D: -1;
  1443.    
  1444.     Iter_Remove(Bankers, id);
  1445.    
  1446.     new query[48];
  1447.     mysql_format(BankSQLHandle, query, sizeof(query), "DELETE FROM bankers WHERE ID=%d", id);
  1448.     mysql_tquery(BankSQLHandle, query);
  1449.     return 1;
  1450. }
  1451.  
  1452. // Admin Commands for ATMs
  1453. CMD:createatm(playerid, params[])
  1454. {
  1455.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1456.     new id = Iter_Free(ATMs);
  1457.     if(id == -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Can't create any more ATMs.");
  1458.     ATMData[id][atmRX] = ATMData[id][atmRY] = 0.0;
  1459.    
  1460.     GetPlayerPos(playerid, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ]);
  1461.     GetPlayerFacingAngle(playerid, ATMData[id][atmRZ]);
  1462.  
  1463.     ATMData[id][atmX] += (2.0 * floatsin(-ATMData[id][atmRZ], degrees));
  1464.     ATMData[id][atmY] += (2.0 * floatcos(-ATMData[id][atmRZ], degrees));
  1465.     ATMData[id][atmZ] -= 0.3;
  1466.    
  1467.     ATMData[id][atmObjID] = CreateDynamicObject(19324, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ], ATMData[id][atmRX], ATMData[id][atmRY], ATMData[id][atmRZ]);
  1468.     if(IsValidDynamicObject(ATMData[id][atmObjID]))
  1469.     {
  1470.         new dataArray[E_ATMDATA];
  1471.         format(dataArray[IDString], 8, "atm_sys");
  1472.         dataArray[refID] = id;
  1473.         Streamer_SetArrayData(STREAMER_TYPE_OBJECT, ATMData[id][atmObjID], E_STREAMER_EXTRA_ID, dataArray);
  1474.        
  1475.         EditingATMID[playerid] = id;
  1476.         EditDynamicObject(playerid, ATMData[id][atmObjID]);
  1477.     }
  1478.    
  1479.     #if defined ATM_USE_MAPICON
  1480.     ATMData[id][atmIconID] = CreateDynamicMapIcon(ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ], 52, 0, .streamdistance = ATM_ICON_RANGE);
  1481.     #endif
  1482.  
  1483.     new label_string[64];
  1484.     format(label_string, sizeof(label_string), "ATM (%d)\n\n{FFFFFF}Use {F1C40F}/atm!", id);
  1485.     ATMData[id][atmLabel] = CreateDynamic3DTextLabel(label_string, 0x1ABC9CFF, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ] + 0.85, 5.0, .testlos = 1);
  1486.  
  1487.     new query[144];
  1488.     mysql_format(BankSQLHandle, query, sizeof(query), "INSERT INTO bank_atms SET ID=%d, PosX='%f', PosY='%f', PosZ='%f', RotX='%f', RotY='%f', RotZ='%f'", id, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ], ATMData[id][atmRX], ATMData[id][atmRY], ATMData[id][atmRZ]);
  1489.     mysql_tquery(BankSQLHandle, query);
  1490.  
  1491.     Iter_Add(ATMs, id);
  1492.     return 1;
  1493. }
  1494.  
  1495. CMD:editatm(playerid, params[])
  1496. {
  1497.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1498.     new id;
  1499.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/editatm [ATM id]");
  1500.     if(!Iter_Contains(ATMs, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ATM ID.");
  1501.     if(!IsPlayerInRangeOfPoint(playerid, 30.0, ATMData[id][atmX], ATMData[id][atmY], ATMData[id][atmZ])) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're not near the ATM you want to edit.");
  1502.     if(EditingATMID[playerid] != -1) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}You're already editing an ATM.");
  1503.     EditingATMID[playerid] = id;
  1504.     EditDynamicObject(playerid, ATMData[id][atmObjID]);
  1505.     return 1;
  1506. }
  1507.  
  1508. CMD:removeatm(playerid, params[])
  1509. {
  1510.     if(!IsPlayerAdmin(playerid)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Only RCON admins can use this command.");
  1511.     new id;
  1512.     if(sscanf(params, "i", id)) return SendClientMessage(playerid, 0xE88732FF, "SYNTAX: {FFFFFF}/removeatm [ATM id]");
  1513.     if(!Iter_Contains(ATMs, id)) return SendClientMessage(playerid, 0xE74C3CFF, "ERROR: {FFFFFF}Invalid ATM ID.");
  1514.     if(IsValidDynamicObject(ATMData[id][atmObjID])) DestroyDynamicObject(ATMData[id][atmObjID]);
  1515.     ATMData[id][atmObjID] = -1;
  1516.  
  1517.     #if defined ATM_USE_MAPICON
  1518.     if(IsValidDynamicMapIcon(ATMData[id][atmIconID])) DestroyDynamicMapIcon(ATMData[id][atmIconID]);
  1519.     ATMData[id][atmIconID] = -1;
  1520.     #endif
  1521.  
  1522.     if(IsValidDynamic3DTextLabel(ATMData[id][atmLabel])) DestroyDynamic3DTextLabel(ATMData[id][atmLabel]);
  1523.     ATMData[id][atmLabel] = Text3D: -1;
  1524.    
  1525.     if(ATMData[id][atmTimer] != -1) KillTimer(ATMData[id][atmTimer]);
  1526.     ATMData[id][atmTimer] = -1;
  1527.    
  1528.     if(IsValidDynamicPickup(ATMData[id][atmPickup])) DestroyDynamicPickup(ATMData[id][atmPickup]);
  1529.     ATMData[id][atmPickup] = -1;
  1530.    
  1531.     ATMData[id][atmHealth] = ATM_HEALTH;
  1532.     ATMData[id][atmRegen] = 0;
  1533.  
  1534.     Iter_Remove(ATMs, id);
  1535.    
  1536.     new query[48];
  1537.     mysql_format(BankSQLHandle, query, sizeof(query), "DELETE FROM bank_atms WHERE ID=%d", id);
  1538.     mysql_tquery(BankSQLHandle, query);
  1539.     return 1;
  1540. }
Add Comment
Please, Sign In to add comment