Guest User

Yet Another Banking System

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