root/trunk/twcore/src/twcore/bots/elim/elim.java

Revision 3972, 76.3 KB (checked in by subby, 3 weeks ago)

changed sqlbackgroundquery identifiers into null since bot doesn't care about them

Line 
1package twcore.bots.elim;
2
3import java.text.DecimalFormat;
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.Iterator;
9import java.util.List;
10import java.util.Random;
11import java.util.TreeMap;
12import java.util.TimerTask;
13
14import java.sql.ResultSet;
15import java.sql.SQLException;
16
17import javax.swing.text.NumberFormatter;
18
19import twcore.core.BotAction;
20import twcore.core.SubspaceBot;
21import twcore.core.BotSettings;
22import twcore.core.EventRequester;
23import twcore.core.OperatorList;
24import twcore.core.events.Message;
25import twcore.core.events.ArenaJoined;
26import twcore.core.events.LoggedOn;
27import twcore.core.events.SQLResultEvent;
28import twcore.core.events.WeaponFired;
29import twcore.core.events.PlayerDeath;
30import twcore.core.events.PlayerEntered;
31import twcore.core.events.PlayerPosition;
32import twcore.core.events.PlayerLeft;
33import twcore.core.events.FrequencyShipChange;
34import twcore.core.events.FrequencyChange;
35import twcore.core.game.Player;
36import twcore.core.util.Tools;
37import twcore.core.util.Spy;
38
39public class elim extends SubspaceBot {
40       
41        public OperatorList opList;
42        public Spy racismWatcher;
43        public String db = "website";
44        public Random rand = new Random();
45        public static DecimalFormat decForm = new DecimalFormat("0.##");
46        public static NumberFormatter format = new NumberFormatter(decForm);
47       
48        //Class variables
49        public int botMode = 1;
50        public int gameStyle = 1;
51        public int shipType = -1;
52        public int deaths = -1;
53        public int kills = -1;
54        public int shrap = 0;
55        public int avg_rating = 0;
56        public String lastWinner = "-anonymous-";
57        public int winStreak = 0;
58        public long lastZoner = 0;
59        public ElimPlayer winner;
60       
61        //Game collections
62        public GameStatus game = new GameStatus();
63        public TreeMap<String, CasualPlayer> casualPlayers = new TreeMap<String, CasualPlayer>();
64        public TreeMap<String, ElimPlayer> elimPlayers = new TreeMap<String, ElimPlayer>();
65        public TreeMap<String, ElimPlayer> lagouts = new TreeMap<String, ElimPlayer>();
66        public TreeMap<String, ElimPlayer> losers = new TreeMap<String, ElimPlayer>();
67        public TreeMap<Integer, Integer> votes = new TreeMap<Integer, Integer>();
68        public ArrayList<String> enabled = new ArrayList<String>();
69        public ArrayList<String> classicMode = new ArrayList<String>();
70
71       
72        //BotSettings variables
73        BotSettings cfg;
74        public int cfg_minPlayers, cfg_maxDeaths, cfg_maxKills, cfg_defaultShip, cfg_gameType;
75        public int cfg_votingLength, cfg_waitLength, cfg_zone, cfg_border, cfg_casualAllowed;
76        public int[] cfg_safe, cfg_competitive, cfg_casual, cfg_barY;
77        public int[][] cfg_barspots;
78        public String cfg_arena, cfg_chats, cfg_gameName;
79        public ArrayList<Integer> cfg_shipTypes = new ArrayList<Integer>();
80       
81        //Defaults
82        public int[] defaultElimTypes = {1,3,4,7,9};
83        public int[] defaultBelimTypes = {2,5,6,8,9};
84        public String[]  sMessages = {
85                        "On Fire!",
86                        "Killing Spree!",
87                        "Rampage!",
88                        "Dominating!",
89                        "Unstoppable!",
90                        "God-like!",
91                        "Cheater!",
92                        "Juggernaut!",
93                        "Kill Frenzy!",
94                        "Running Riot!",
95                        "Utter Chaos!",
96                        "Grim Reaper!",
97                        "Bulletproof!",
98                        "Invincible!",
99                        "Certified Veteran!",
100                        "Trench Wars Most Wanted!",
101                        "Unforeseeable paradoxes have ripped a hole in the fabric of the universe!"
102                };
103       
104        //Enums
105        public static final int ELIM = 1;          //Game type and game style
106        public static final int BASEELIM = 2;      //Game type
107        public static final int KILLRACE = 2;      //Game style
108        public static final int OFF = 0;           //Simple boolean used for int variables
109        public static final int ON = 1;            //Simple boolean used for int variables
110        public static final int DISCONNECT = 2;    //Bot mode... bot will disconnect after game finishes
111        public static final int SPAWN_TIME = 5005; //Time to wait before warping a player after a death in milliseconds
112        public static final int SPAWN_NC = 1;      //Time that a spawn kill won't count after spawning in seconds
113        public static final int LAGOUT_TIME = 30;  //Time you must wait before returning from a lagout in seconds
114        public static final int LAGOUT_RETURN = 60;//Time you must return before when returning from a lagout in seconds
115        public static final int MAX_LAGOUT = 2;    //Maximum number of lagouts allowed
116        public static final int DOUBLE_KILL = 5;   //Number of seconds after a kill for another kill to be considered duplicate
117        public static final int MIN_ZONER = 15;    //The minimum amount of minutes that another zoner can be sent
118        public static final int BOUNDARY_TIME = 30;//The maximum amount of time you can be outside of base in seconds
119        public static final int STREAK_INIT = 5;   //The number of kills needed for the first streak
120        public static final int STREAK_REPEAT = 2; //The number of kills needed for streak messages after the initial streak
121        public static final int SAFE_HEIGHT = 14;  //The height of the safety area in tiles
122        public static final int ANY_SHIP = 9;      //A ship type... all ships within the cfg_shipTypes are allowed
123        public static final int SPEC_FREQ = 9999;  //The spec frequency
124        public static final int MAX_FREQ = 99;     //The maximum frequency casual players can be on
125        public static final int LIMIT_STREAK = 3;  //The amount of consecutive game wins to limit minimum kill/death voting
126        public static final int MIN_FOR_STREAK = 5;//The minimum kills/deaths allowable to vote on during a game winning streak
127        public static final int INIT_RATING = 300; //The initial rating that players begin at.
128        public static final int INIT_RANKING = 500;//The number of combined kills and deaths needed to be ranked.
129       
130        //LVZ
131        public static final int CASUAL_SPLASH_LVZ = 1;    //Displays temporary image below energy bar that says "This is casual play"
132        public static final int CASUAL_LOGO_LVZ = 2;      //Displays casual logo above radar.
133       
134    public elim(BotAction botAction) {
135        super(botAction);
136        requestEvents();
137        racismWatcher = new Spy(botAction);
138        opList = m_botAction.getOperatorList();
139        reinstantiateCFG();       
140    }
141   
142    public void reinstantiateCFG(){
143        cfg = m_botAction.getBotSettings();
144        int botnum = getBotNumber(cfg);
145        cfg_minPlayers = cfg.getInt("MinPlayers");
146        cfg_maxDeaths = cfg.getInt("MaxDeaths");
147        cfg_maxKills = cfg.getInt("MaxKills");
148        cfg_votingLength = cfg.getInt("VotingLength");
149        cfg_waitLength = (cfg.getInt("WaitLength") - 10);
150        cfg_zone = cfg.getInt("SendZoner");
151        cfg_border = cfg.getInt("Border");
152        cfg_arena = cfg.getString("Arena" + botnum);       
153        cfg_gameType = cfg.getInt("GameType" + botnum);
154        cfg_defaultShip = cfg.getInt("DefaultShip" + cfg_gameType);
155        cfg_chats = cfg.getString("Chats" + cfg_gameType);
156        cfg_safe = cfg.getIntArray("Safe" + cfg_gameType, ",");
157        cfg_competitive = cfg.getIntArray("Competitive" + cfg_gameType, ",");
158        cfg_casualAllowed = cfg.getInt("CasualAllowed");
159        cfg_casual = cfg.getIntArray("Casual" + cfg_gameType, ",");
160        if(cfg_gameType == ELIM) cfg_gameName = "elim";
161        else{
162                cfg_gameName = "belim";
163                cfg_barY = cfg.getIntArray("BarwarpY", ",");
164                cfg_barspots = new int[cfg.getInt("Barspots")][4];
165                for(int i=0;i<cfg_barspots.length;i++)
166                        cfg_barspots[i] = cfg.getIntArray("Barspot" + (i+1), ",");
167        }
168        String[] types = cfg.getString("ShipTypes" + cfg_gameType).split(",");
169        cfg_shipTypes.clear();
170        try{
171                for(int i=0;i<types.length;i++)
172                        cfg_shipTypes.add(Integer.parseInt(types[i]));         
173        }catch(NumberFormatException e){
174                if(cfg_gameType == ELIM){
175                        for(int i=0;i<defaultElimTypes.length;i++)
176                        cfg_shipTypes.add(defaultElimTypes[i]);   
177                } else {
178                        for(int i=0;i<defaultBelimTypes.length;i++)
179                        cfg_shipTypes.add(defaultBelimTypes[i]); 
180                }       
181        }
182    }
183       
184        public String[] getHelpMsg(String name){
185                ArrayList<String> help = new ArrayList<String>();
186                String[] reghelp = {
187                                "+=============================== HELP MENU ==================================+",
188                                "| !help         - Displays this menu. (?)                                    |",
189                                "| !play         - Toggles whether or not you wish to play. (!p)              |",
190                                "| !lagout       - Puts you back into the game if you've lagged out. (!l)     |",
191                                "| !status       - Displays the game status. (!s)                             |",
192                                "| !mvp          - Shows the three players with the best and worst recs.      |",
193                                "| !wl           - Shows the three players with the most and least losses.    |",
194                                "| !who          - Shows all remaining players in the game.                   |",
195                                "| !rank <#>     - Returns the player at rank <#>.                            |",
196                                "| !stats        - Shows your statistics including your rank.                 |",
197                                "| !stats <name> - Shows statistics of <name>.                                |",
198                                "| !rec          - Shows your wins and losses. (!r)                           |",
199                                "| !rec <name>   - Shows the wins and losses of <name>.                       |",
200                                "| !classic      - Toggles whether or not you'd like to be spec'd when out.   |",
201                                "| !warp         - Warps you out of the safe if you're stuck.                 |",
202                                "| !scorereset   - Resets all of your stats to zero. No going back. (!sr)     |",
203
204                };List<String> reg = Arrays.asList(reghelp);
205                String[] modHelp = {
206                        "+=============================== MOD MENU ===================================+",
207                        "| !remove <name> - Removes <name> from the game                              |",
208                };List<String> mod = Arrays.asList(modHelp);
209                String[] smodhelp = {
210                                "+=============================== SMOD MENU ==================================+",
211                                "| !zone         - Toggles whether or not the bot should zone for games.      |",
212                                "| !stop         - Ends the current game and prevents new games from starting.|",
213                                "| !off          - Prevents new games from starting once the current one ends.|",
214                                "| !on           - Turns off !off mode and allows new games to begin          |",
215                                "| !shutdown     - Causes the bot to disconnect once the current game ends.   |",
216                                "| !die          - Causes the bot to disconnect.                              |",
217                };List<String> smod = Arrays.asList(smodhelp);                         
218                help.addAll(reg);
219                if(opList.isModerator(name))
220                    help.addAll(mod);
221                if(opList.isSmod(name))
222                        help.addAll(smod);
223                if(opList.isSysop(name)) {
224                        help.add("| !updatecfg    - Updates the bot to the most current CFG file.              |");
225                        help.add("| !greetmsg <m> - Sets arena greet message(Sysop only).                      |");
226                }
227                help.add("+============================================================================+");
228                return help.toArray(new String[help.size()]);
229
230        }
231       
232        public String getStatusMsg(){
233                switch(game.state){
234                        case GameStatus.OFF_MODE:
235                                return "Elimination is temporarily disabled.";
236                        case GameStatus.WAITING_FOR_PLAYERS:
237                                return "A new elimination match will begin when " + (cfg_minPlayers - elimPlayers.size()) + " more player(s) enter.";
238                        case GameStatus.VOTING_ON_SHIP:
239                                return "We are currently voting on ship type.";
240                        case GameStatus.VOTING_ON_DEATHS:
241                                if(gameStyle == ELIM)
242                                        return "We are playing " + Tools.shipName(shipType) + " elim. We are currently voting on number of deaths.";
243                                else return "We are playing " + Tools.shipName(shipType) + " kill race. We are currently voting on number of kills.";
244                        case GameStatus.VOTING_ON_SHRAP:
245                                if(gameStyle == ELIM)
246                                        return "We are playing " + Tools.shipName(shipType) + " elim to " + deaths + ". We are currently voting on shrap.";
247                                else return "We are playing " + Tools.shipName(shipType) + " kill race to " + kills + ". We are currently voting on shrap.";
248                        case GameStatus.WAITING_TO_START:
249                                if(gameStyle == ELIM)
250                                        return "We are playing " + Tools.shipName(shipType) + " elim to " + deaths + ". The game will start soon. Enter to play!";
251                                else return "We are playing " + Tools.shipName(shipType) + " kill race to " + kills + ". The game will start soon. Enter to play!";
252                        case GameStatus.TEN_SECONDS:
253                                return "The game will begin in less than ten seconds. No more entries";
254                        case GameStatus.GAME_IN_PROGRESS:
255                                if(gameStyle == ELIM)
256                                        return "We are currently playing " + Tools.shipName(shipType) + " elim to " + deaths + ". " + elimPlayers.size() + " players left.";
257                                else return "We are currently playing " + Tools.shipName(shipType) + " kill race to " + kills + ". " + elimPlayers.size() + " players playing.";
258                        case GameStatus.GAME_OVER:
259                                return "A new elimination match will begin shortly.";
260                        default: return null;
261                }
262        }
263       
264    public void handleEvent(Message event) {
265        String message = event.getMessage();
266                String name = event.getMessager() == null ? m_botAction.getPlayerName(event.getPlayerID()) : event.getMessager();
267                int messageType = event.getMessageType();
268               
269                if(messageType == Message.PUBLIC_MESSAGE        ||
270                                messageType == Message.TEAM_MESSAGE          ||
271                                messageType == Message.OPPOSING_TEAM_MESSAGE ||
272                                messageType == Message.PUBLIC_MACRO_MESSAGE)
273                                        racismWatcher.handleEvent(event);
274               
275                if(messageType == Message.PRIVATE_MESSAGE || messageType == Message.REMOTE_PRIVATE_MESSAGE){
276                        handleCommands(name, message);
277                        if (opList.isModerator(name))
278                            handleModeratorCommands(name, message);
279                        if(opList.isSmod(name))
280                                handleSmodCommands(name, message);
281                        if(opList.isSysop(name))
282                                handleSysopCommands(name, message);
283                }
284                else if(messageType == Message.ARENA_MESSAGE && message.contains("UserId:"))
285                        doEInfo(message);
286                else if(messageType == Message.PUBLIC_MESSAGE &&
287                                game.isVoting()                       &&
288                                Tools.isAllDigits(message)            &&
289                                message.length() <= 2)
290                        vote(name, message);
291    }
292   
293    public void handleCommands(String name, String cmd){
294        if(cmd.equalsIgnoreCase("!help") || cmd.equals("?"))
295                m_botAction.smartPrivateMessageSpam(name, getHelpMsg(name));
296        else if(cmd.equalsIgnoreCase("!play") || cmd.equalsIgnoreCase("!p") || cmd.equals(""))
297                cmd_play(name);
298        else if(cmd.equalsIgnoreCase("!status") || cmd.equalsIgnoreCase("!s"))
299                m_botAction.sendSmartPrivateMessage( name, getStatusMsg());
300        else if(cmd.equalsIgnoreCase("!mvp"))
301                cmd_mvp(name);
302        else if(cmd.equalsIgnoreCase("!wl"))
303                cmd_wl(name);
304        else if(cmd.equalsIgnoreCase("!who"))
305                cmd_who(name);
306        else if(cmd.equalsIgnoreCase("!rec") || cmd.equalsIgnoreCase("!r"))
307                cmd_rec(name, name);
308        else if(cmd.startsWith("!rec "))
309                cmd_rec(name, cmd.substring(5));
310        else if(cmd.equalsIgnoreCase("!classic") || cmd.equalsIgnoreCase("!c"))
311                cmd_classic(name);
312        else if(cmd.equalsIgnoreCase("!warp") || cmd.equalsIgnoreCase("!w"))
313                cmd_warp(name);
314        else if(cmd.equalsIgnoreCase("!lagout") || cmd.equalsIgnoreCase("!l"))
315                cmd_lagout(name);
316        else if(cmd.equalsIgnoreCase("!scorereset") || cmd.equalsIgnoreCase("!sr"))
317                cmd_scorereset(name);
318        else if(cmd.equalsIgnoreCase("!stats"))
319                cmd_stats(name, name);
320        else if(cmd.startsWith("!stats "))
321                cmd_stats(name, cmd.substring(7));
322        else if(cmd.startsWith("!rank "))
323                cmd_rank(name, cmd.substring(6));
324    }
325   
326    public void handleModeratorCommands(String name, String cmd) {
327        if(cmd.startsWith("!remove "))
328            cmd_remove(name, cmd.substring(8));
329    }
330   
331    public void handleSmodCommands(String name, String cmd){
332        if(cmd.equalsIgnoreCase("!zone"))
333                cmd_zone(name);
334        else if(cmd.equalsIgnoreCase("!stop"))
335                cmd_stop(name);
336        else if(cmd.equalsIgnoreCase("!off"))
337                cmd_off(name, false);
338        else if(cmd.equalsIgnoreCase("!on"))
339                cmd_on(name);
340        else if(cmd.equalsIgnoreCase("!shutdown"))
341                cmd_off(name, true);
342        else if(cmd.equalsIgnoreCase("!die")){
343                try{
344                        m_botAction.scheduleTask(new DieTask(name), 500);
345                }catch(Exception e){}
346        }
347    }
348   
349    public void handleSysopCommands(String name, String cmd){
350        if(cmd.startsWith("!greetmsg "))
351                        m_botAction.sendUnfilteredPublicMessage( "?set misc:greetmessage:"+cmd.substring(10) );
352        else if(cmd.equalsIgnoreCase("!updatecfg"))
353                reinstantiateCFG();
354    }
355   
356    public void cmd_play(String name){
357        if(name == null)return;
358        if(enabled.remove(name)){
359            if( cfg_casualAllowed == 1 )
360                m_botAction.sendSmartPrivateMessage( name, "You have disabled !play. Type !play again to compete.");
361            else
362                m_botAction.sendSmartPrivateMessage( name, "You have disabled !play. Because casual is not enabled, you have been removed from the game. Type !play again to compete.");
363                if(elimPlayers.containsKey(name) && game.state == GameStatus.GAME_IN_PROGRESS){
364                        m_botAction.sendArenaMessage(name + " is out. " + elimPlayers.get(name).wins + " wins " + elimPlayers.get(name).losses + " losses (Resigned)");
365                        losers.put(name, elimPlayers.remove(name));                     
366                }
367                else if(elimPlayers.containsKey(name))
368                        elimPlayers.remove(name);
369                doWarpIntoCasual(name);
370        }else {
371            if( cfg_casualAllowed == 1 )
372                m_botAction.sendSmartPrivateMessage( name, "You have enabled !play. Type !play again to play casually.");
373            else
374                m_botAction.sendSmartPrivateMessage( name, "You have enabled !play, and can now play in the next elimination.");
375                enabled.add(name);
376                Player p = m_botAction.getPlayer(name);
377                if(p == null)return;
378                if(p.getShipType() > 0 && !game.isInProgress()){
379                        elimPlayers.put(name, new ElimPlayer(name));
380                        doWarpIntoElim(name);
381                        if(elimPlayers.size() >= cfg_minPlayers && game.state == GameStatus.WAITING_FOR_PLAYERS)
382                                game.moveOn();
383                }               
384        }
385    }
386   
387    public void cmd_mvp(String name){
388        CompareByWinsLossesAccuracy byMVP = new CompareByWinsLossesAccuracy();
389        List<ElimPlayer> l = Arrays.asList(elimPlayers.values().toArray(new ElimPlayer[elimPlayers.values().size()]));
390        Collections.sort(l, Collections.reverseOrder(byMVP));
391        int index = 1;
392        Iterator<ElimPlayer> i = l.iterator();
393        m_botAction.sendSmartPrivateMessage( name, "------------- Best Records ------------");
394        while( i.hasNext() && index <= 3){
395                ElimPlayer p = i.next();
396                m_botAction.sendSmartPrivateMessage( name, index + ") " + p.name + " (" + p.wins + "-" + p.losses + ")");
397                index++;
398        }
399        Collections.sort(l, byMVP);
400        i = l.iterator();
401        index = 1;
402        m_botAction.sendSmartPrivateMessage( name, "------------ Worst Records ------------");
403        while( i.hasNext() && index <= 3){
404                ElimPlayer p = i.next();
405                m_botAction.sendSmartPrivateMessage( name, index + ") " + p.name + " (" + p.wins + "-" + p.losses + ")");
406                index++;
407        }
408    }
409   
410    public void cmd_wl(String name){
411        CompareByLosses byLosses = new CompareByLosses();
412        List<ElimPlayer> l = Arrays.asList(elimPlayers.values().toArray(new ElimPlayer[elimPlayers.values().size()]));
413        Collections.sort(l, Collections.reverseOrder(byLosses));
414        int index = 1;
415        Iterator<ElimPlayer> i = l.iterator();
416        m_botAction.sendSmartPrivateMessage( name, "------- Most Deaths ---- Limit: " + deaths + "-------");
417        while( i.hasNext() && index <= 3){
418                ElimPlayer p = i.next();
419                m_botAction.sendSmartPrivateMessage( name, index + ") " + p.name + " (" + p.wins + "-" + p.losses + ")");
420                index++;
421        }
422        Collections.sort(l, byLosses);
423        i = l.iterator();
424        index = 1;
425        m_botAction.sendSmartPrivateMessage( name, "------ Least Deaths --- Players: " + elimPlayers.size() + "------");
426        while( i.hasNext() && index <= 3){
427                ElimPlayer p = i.next();
428                m_botAction.sendSmartPrivateMessage( name, index + ") " + p.name + " (" + p.wins + "-" + p.losses + ")");
429                index++;
430        }
431    }
432   
433    public void cmd_who(String name){
434        if(!game.isInProgress()){
435                m_botAction.sendSmartPrivateMessage( name, "There is no game in progress.");
436                return;
437        }
438        m_botAction.sendSmartPrivateMessage( name, elimPlayers.size() + " players remaining:");
439        ArrayList<String> pNames = new ArrayList<String>();
440        CompareAlphabetical byName = new CompareAlphabetical();
441        List<ElimPlayer> l = Arrays.asList(elimPlayers.values().toArray(new ElimPlayer[elimPlayers.values().size()]));
442        Collections.sort(l, byName);
443        Iterator<ElimPlayer> i = l.iterator();         
444        while( i.hasNext() ){
445                ElimPlayer ep = i.next();
446                pNames.add(ep.name + "(" + ep.wins + "-" + ep.losses + ")");
447                if(pNames.size() == 5){
448                        String message = pNames.toString();
449                        m_botAction.sendSmartPrivateMessage( name, message.substring(1, message.indexOf("]")));
450                        pNames.clear();
451                }
452        }
453        if(!pNames.isEmpty()){
454                String message = pNames.toString();
455                        m_botAction.sendSmartPrivateMessage( name, message.substring(1, message.indexOf("]")));
456        }
457    }
458   
459    public void cmd_rec(String name, String target){
460        String clone = m_botAction.getFuzzyPlayerName(target);
461        if(clone == null)clone = target;
462        try{
463                ResultSet rs = m_botAction.SQLQuery(db, "SELECT fnKills, fnDeaths FROM tblElimCasualRecs WHERE fcUserName = '" + Tools.addSlashesToString(clone.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
464                if(rs != null && rs.next()){
465                        int kills = rs.getInt("fnKills");
466                        int deaths = rs.getInt("fnDeaths");
467                        m_botAction.SQLClose(rs);
468                        if(casualPlayers.containsKey(clone)){
469                                kills += casualPlayers.get(clone).wins;
470                                deaths += casualPlayers.get(clone).losses;
471                        }
472                        m_botAction.sendSmartPrivateMessage( name, "'" + clone + "' (" + kills + "-" + deaths + ")");
473                } else {
474                        m_botAction.SQLClose(rs);
475                        m_botAction.sendSmartPrivateMessage( name, "No record was found for '" + clone + "'.");
476                }
477        }catch(SQLException e){
478                m_botAction.sendSmartPrivateMessage( name, "Error retrieving record. Please try again later. If problem persists contact a staff member.");
479        }
480    }
481   
482    public void cmd_remove(String name, String target) {
483        boolean spec = true;
484        String clone = m_botAction.getFuzzyPlayerName(target);
485       
486        if (clone == null) {
487            clone = target;
488            spec = false;
489        }
490       
491        if(!elimPlayers.containsKey(clone) && !lagouts.containsKey(clone)) {
492            m_botAction.sendPrivateMessage(name, clone + " could not be found in the playing players list.");
493            return;
494        }
495       
496        if (elimPlayers.containsKey(clone))
497            losers.put(clone, elimPlayers.remove(clone));
498        else if (lagouts.containsKey(clone))
499            losers.put(clone, lagouts.remove(clone));
500       
501        if (spec)
502            m_botAction.specWithoutLock(clone);
503       
504        m_botAction.sendPrivateMessage(name, clone + " has been removed from the game.");
505    }
506   
507    public void cmd_lagout(String name){
508        if(game.state != GameStatus.GAME_IN_PROGRESS)return;
509        if(lagouts.containsKey(name)){
510                if(System.currentTimeMillis() - lagouts.get(name).lagTime > LAGOUT_TIME * Tools.TimeInMillis.SECOND){
511                        if(System.currentTimeMillis() - lagouts.get(name).lagTime < LAGOUT_RETURN * Tools.TimeInMillis.SECOND) {
512                                elimPlayers.put(name, lagouts.remove(name));
513                                if(!enabled.contains(name))
514                                        enabled.add(name);
515                                m_botAction.sendSmartPrivateMessage( name, "You have been put back into the game. You have " + (MAX_LAGOUT-elimPlayers.get(name).lagouts) + " lagouts left.");
516                                elimPlayers.get(name).clearBorderInfo();
517                                m_botAction.setShip(name, elimPlayers.get(name).shiptype);
518                                m_botAction.setFreq(name, elimPlayers.get(name).frequency);
519                                doWarpIntoElim(name);
520                        } else
521                                m_botAction.sendSmartPrivateMessage( name, "You have taken too long to return. Please wait for the next game to begin.");
522                } else
523                        m_botAction.sendSmartPrivateMessage( name, "You must wait for " + (LAGOUT_TIME-((System.currentTimeMillis() - lagouts.get(name).lagTime)/Tools.TimeInMillis.SECOND)) + " more seconds.");
524        } else
525                m_botAction.sendSmartPrivateMessage( name, "You aren't in the game!");                 
526    }
527   
528    public void cmd_scorereset(String name){
529                m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimCasualRecs SET fnKills = 0, fnDeaths = 0 WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
530                m_botAction.SQLBackgroundQuery(db, null, "DELETE FROM tblElimPlayer WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
531                m_botAction.sendSmartPrivateMessage( name, "Your wins and losses have been reset to zero.");
532    }
533   
534    public void cmd_classic(String name){
535        if( cfg_casualAllowed == 1 ) {
536            int wantsClassic = 0;
537            if(classicMode.remove(name))
538                m_botAction.sendSmartPrivateMessage( name, "You will be moved to the casual arena when you are out.");
539            else {
540                wantsClassic = 1;
541                classicMode.add(name);
542                m_botAction.sendSmartPrivateMessage( name, "You will be specced when you are out.");
543            }
544           
545            m_botAction.SQLBackgroundQuery(db, null,"UPDATE tblElimPlayer SET fnSpecWhenOut = " + wantsClassic + " WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
546        } else {
547            m_botAction.sendSmartPrivateMessage( name, "Casual play has been disabled.");
548        }
549    }
550   
551    public void cmd_warp(String name){
552        Player p = m_botAction.getPlayer(name);
553        if(p == null)return;
554        if((p.getYTileLocation() > (cfg_safe[1]-SAFE_HEIGHT) && p.getYTileLocation() < (cfg_safe[1]+SAFE_HEIGHT) && cfg_gameType == BASEELIM) ||
555           (p.getYTileLocation() > (cfg_safe[1]-SAFE_HEIGHT) && p.getYTileLocation() < (cfg_safe[1]+SAFE_HEIGHT) && cfg_gameType == ELIM))
556                m_botAction.specificPrize(name, Tools.Prize.WARP);
557        else
558                m_botAction.sendSmartPrivateMessage( name, "This command is for players in the safe.");
559    }
560   
561    public void cmd_stats(String name, String target){
562        String t = m_botAction.getFuzzyPlayerName(target);
563        if(t != null)
564                target = t;
565        try{
566                ResultSet rs = m_botAction.SQLQuery(db, "SELECT * FROM tblElimPlayer WHERE fcUserName = '" + Tools.addSlashesToString(target.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
567                if( rs != null && rs.next() ){
568                        int ranking = rs.getInt("fnRank");
569                        int rating = rs.getInt("fnRating");
570                        int kills = rs.getInt("fnKills");
571                        int deaths = rs.getInt("fnDeaths");
572                        float ave = rs.getFloat("fnAve");
573                        double aimNum = rs.getDouble("fnAim");
574                        int cks = rs.getInt("fnCKS");
575                        int cls = rs.getInt("fnCLS");
576                        int bks = rs.getInt("fnBKS");
577                        int wls = rs.getInt("fnWLS");
578                        int bws = rs.getInt("fnBWS");
579                        int pe = rs.getInt("fnPe");
580                        int dk = rs.getInt("fnDK");
581                        int sb = rs.getInt("fnSB");
582                        int gamesWon = rs.getInt("fnGamesWon");
583                        int gamesPlayed = rs.getInt("fnGamesPlayed");
584                        m_botAction.SQLClose(rs);
585                        String aim = format.valueToString(aimNum);
586                        String rank;
587                        if(ranking == 0)
588                                rank = "Not ranked";
589                        else
590                                rank = "#" + ranking;
591                        m_botAction.sendSmartPrivateMessage( name, "=== Player: '" + target + "' Rank: " + rank + " Rating: " + rating + " ===");
592                        m_botAction.sendSmartPrivateMessage( name, "Kills: " + kills + " Deaths: " + deaths + " Ave: " + Math.round(ave) + " AIM:" + aim + "% CKS:" + cks + " BKS:" + bks + " CLS:" + cls + " WLS:" + wls + " BWS:" + bws);
593                        m_botAction.sendSmartPrivateMessage( name, "Games Won: " + gamesWon + " Games Played: " + gamesPlayed + " PE:" + pe + " DK:" + dk + " SB:" + sb);
594                } else {
595                        m_botAction.SQLClose(rs);
596                        m_botAction.sendSmartPrivateMessage( name, "User '" + target + "' not found."); 
597                }
598        } catch(Exception e){
599                m_botAction.sendSmartPrivateMessage( name, "There was a problem handling your request. Please try again in a minute.");
600        }
601    }
602   
603    public void cmd_rank(String name, String message){
604        int rank;
605        try{
606                rank = Integer.parseInt(message);
607        }catch(NumberFormatException e){
608                m_botAction.sendSmartPrivateMessage( name, "Incorrect usage. Example: !rank 1");
609                return;
610        }
611        try{
612                if(rank < 3)rank = 3;
613                ResultSet rs = m_botAction.SQLQuery(db, "SELECT fnRank, fnRating, fcUserName FROM tblElimPlayer WHERE fnGameType = " + cfg_gameType + " AND fnRank BETWEEN " + (rank - 2) + " AND " + (rank + 2) + " ORDER BY fnRank ASC");
614                while(rs != null && rs.next()){
615                        int rsRank = rs.getInt("fnRank");
616                        int rsRating = rs.getInt("fnRating");
617                        String rsName = rs.getString("fcUserName");
618                        m_botAction.sendSmartPrivateMessage( name, "#" + rsRank + ") " + rsName + " - " + rsRating);
619                }
620                m_botAction.SQLClose(rs);
621        }catch(Exception e){
622                Tools.printStackTrace(e);
623        }
624    }
625   
626    public void cmd_zone(String name){
627        if(cfg_zone == ON){
628                cfg_zone = OFF;
629                m_botAction.sendSmartPrivateMessage( name, "The bot will no longer zone at the start of elimination matches.");
630        }else{
631                cfg_zone = ON;
632                m_botAction.sendSmartPrivateMessage( name, "The bot will now zone at the start of elimination matches.");
633        }
634    }
635   
636    public void cmd_stop(String name){
637        if(game.state != GameStatus.OFF_MODE){
638                m_botAction.sendArenaMessage("This game has been brutally killed by " + name);
639                game.state = GameStatus.OFF_MODE;
640                lastWinner = "-anonymous-";
641                winStreak = 0;
642                Iterator<String> i = elimPlayers.keySet().iterator();
643                while( i.hasNext() ){
644                        doWarpIntoCasual(i.next());
645                        i.remove();
646                }
647                lagouts.clear();
648                losers.clear();
649                votes.clear();
650                m_botAction.cancelTasks();
651        }
652        else
653                m_botAction.sendSmartPrivateMessage( name, "There is currently no game in progress.");
654    }
655   
656    public void cmd_off(String name, boolean shouldDisconnect){
657        if((botMode == OFF && !shouldDisconnect) || (botMode == DISCONNECT && shouldDisconnect)){
658                m_botAction.sendSmartPrivateMessage( name, "The bot is already set for that task.");
659                return;
660        }
661        if(!shouldDisconnect){
662                botMode = OFF;
663                m_botAction.sendSmartPrivateMessage( name, "New games will be prevented from starting once the current game ends.");
664        }else{
665                botMode = DISCONNECT;
666                if(game.state == GameStatus.OFF_MODE || game.state == GameStatus.WAITING_FOR_PLAYERS)
667                        try{
668                                m_botAction.scheduleTask(new DieTask(name), 500);
669                        }catch(Exception e){}
670                else
671                        m_botAction.sendSmartPrivateMessage( name, "The bot will disconnect once the current game ends.");
672        }
673    }
674   
675    public void cmd_on(String name){
676        if(botMode == ON){
677                m_botAction.sendSmartPrivateMessage( name, "The bot is already on.");
678                return;
679        }
680        if(botMode == OFF)
681                m_botAction.sendSmartPrivateMessage( name, "Off mode disabled. New games will be allowed to start.");
682        else
683                m_botAction.sendSmartPrivateMessage( name, "Shutdown mode disabled. New games will be allowed to start.");
684        botMode = ON;
685        if(game.state == GameStatus.OFF_MODE)
686                game.moveOn();
687    }
688   
689    public void doEInfo(String message){
690        String name, userid;
691        int IDindex, ID;
692        IDindex = message.indexOf("UserId:");
693        name = message.substring(0,IDindex-2);
694        userid = message.substring(IDindex + 8, message.indexOf("  Res:"));
695        try{
696                ID = Integer.parseInt(userid);
697                ResultSet rs = m_botAction.SQLQuery(db, "SELECT * FROM tblElimJavsRecs WHERE fnUserID = " + ID);
698                if(rs != null && rs.next()){
699                        int kills = rs.getInt("fnKills"), deaths = rs.getInt("fnDeaths");
700                        m_botAction.SQLClose(rs);
701                        m_botAction.SQLBackgroundQuery(db, null, "DELETE FROM tblElimJavsRecs WHERE fnUserID = " + ID);
702                        casualPlayers.get(name).wins += kills;
703                        casualPlayers.get(name).losses += deaths;                       
704                        m_botAction.sendSmartPrivateMessage( name, "Your record has been updated from ?go javs. PM me with !rec to view your wins and losses.");
705                }
706                else m_botAction.SQLClose(rs);
707        }catch(Exception e){}
708    }
709   
710    public void doWaitingForPlayers(){
711        game.state = GameStatus.WAITING_FOR_PLAYERS;
712        int neededPlayers = cfg_minPlayers - elimPlayers.size();
713        if(neededPlayers <= 0) {
714            if(cfg_zone == ON)doElimZoner();
715            for(int i=1;i<=10;i++)
716                m_botAction.sendChatMessage(i, "Next " + cfg_gameName + " is starting. Type ?go " + cfg_arena + " to play");
717            TimerTask wait10Seconds = new TimerTask() {
718                public void run() {
719                    game.moveOn();
720                }
721            };
722            try{
723                m_botAction.scheduleTask(wait10Seconds, 10 * Tools.TimeInMillis.SECOND);
724            }catch(Exception e){}
725        } else
726                m_botAction.sendArenaMessage("A new elimination match will begin when " + neededPlayers + " more player(s) enter.");
727    }
728   
729    public void doVotingOnShip(){
730        game.state = GameStatus.VOTING_ON_SHIP;
731        shipType = cfg_defaultShip;
732        shrap = OFF;
733        Iterator<String> it = enabled.iterator();
734        while( it.hasNext() )
735                doWarpIntoElim(it.next());
736        String s = "Vote: ";
737        for(int i=0;i<cfg_shipTypes.size();i++){
738                s += Tools.shipName(cfg_shipTypes.get(i)) + " - " + cfg_shipTypes.get(i) + ", ";
739                votes.put(cfg_shipTypes.get(i),0);
740                votes.put(cfg_shipTypes.get(i) * 10, 0);
741        }
742        s = s.substring(0, s.length()-2);
743        m_botAction.sendArenaMessage(s);
744        m_botAction.sendArenaMessage("NOTICE: To vote for a kill race add a 0 on the end of your vote.");
745        game.moveOn(cfg_votingLength * Tools.TimeInMillis.SECOND);
746       
747    }
748   
749    public void doVotingOnDeaths(){
750        game.state = GameStatus.VOTING_ON_DEATHS;
751        deaths = -1;
752        kills = -1;
753        int min = 1;
754        if(winStreak >= LIMIT_STREAK)
755                min = MIN_FOR_STREAK;
756        if(gameStyle == ELIM)
757                for(int i=min;i<=cfg_maxDeaths;i++)
758                        votes.put(i, 0);
759        else
760                for(int i=min;i<=cfg_maxKills;i++)
761                        votes.put(i, 0);
762        game.moveOn(cfg_votingLength * Tools.TimeInMillis.SECOND);
763    }
764   
765    public void doVotingOnShrap(){
766        game.state = GameStatus.VOTING_ON_SHRAP;
767        votes.put(0,0);
768        votes.put(1,0);
769        game.moveOn(cfg_votingLength * Tools.TimeInMillis.SECOND);
770    }
771   
772    public void doWaitingToStart(){
773        game.state = GameStatus.WAITING_TO_START;
774        m_botAction.sendArenaMessage("Enter to play. Game will begin in " + (cfg_waitLength + 10) + " seconds");
775        if(deaths == 1 && gameStyle == ELIM)
776                m_botAction.sendArenaMessage("Rules: All on own freq, no teaming! Die "+ deaths + " time and you are out");
777        else if(gameStyle == ELIM)
778                m_botAction.sendArenaMessage("Rules: All on own freq, no teaming! Die "+ deaths + " times and you are out");
779        else if(kills == 1 && gameStyle == KILLRACE)
780                m_botAction.sendArenaMessage("Rules: All on own freq, no teaming! Get "+ kills + " kill to win");
781        else
782                m_botAction.sendArenaMessage("Rules: All on own freq, no teaming! Get "+ kills + " kills to win");
783        game.moveOn(cfg_waitLength * Tools.TimeInMillis.SECOND);
784    }
785   
786    public void doTenSeconds(){
787        game.state = GameStatus.TEN_SECONDS;
788        m_botAction.sendArenaMessage("Get ready. Game will start in 10 seconds");//No new entries
789        int freq = 600;
790        Iterator<ElimPlayer> i = elimPlayers.values().iterator();
791        while(i.hasNext()){
792                ElimPlayer ep = i.next();
793                Player p = m_botAction.getPlayer(ep.name);
794                if(p == null || p.getShipType() == 0){
795                        i.remove();
796                        continue;
797                }
798                ep.frequency = freq;
799                if(p.getFrequency() != ep.frequency)
800                        m_botAction.setFreq(ep.name, freq);
801                ep.shiptype = p.getShipType();
802                if(shipType == ANY_SHIP){
803                        if(!cfg_shipTypes.contains(p.getShipType())){
804                                m_botAction.setShip(p.getPlayerName(), cfg_defaultShip);
805                                ep.shiptype = cfg_defaultShip;
806                        }
807                }
808                else if(p.getShipType() != shipType){
809                        ep.shiptype = shipType;
810                        m_botAction.setShip(p.getPlayerName(), shipType);
811                }
812                freq++;
813        }
814        if(elimPlayers.size() >= 15)
815                m_botAction.setDoors("00001000");
816        else
817                m_botAction.setDoors(255);
818        game.moveOn(10 * Tools.TimeInMillis.SECOND);
819    }
820   
821    public void doGameInProgress(){
822        game.state = GameStatus.GAME_IN_PROGRESS;
823        lagouts.clear();
824        losers.clear();
825        m_botAction.sendArenaMessage("GO! GO! GO!", Tools.Sound.GOGOGO);
826        Iterator<ElimPlayer> i = elimPlayers.values().iterator();
827        while(i.hasNext()){
828                ElimPlayer ep = i.next();
829                ep.gotChangeWarning = false;
830                if(shrap == ON)
831                        m_botAction.specificPrize(ep.name, Tools.Prize.SHRAPNEL);
832                m_botAction.specificPrize(ep.name, Tools.Prize.MULTIFIRE);
833                ep.resetScore();
834                m_botAction.scoreReset(ep.name);
835                try{
836                        boolean newPlayer = false;
837                        ResultSet rs = m_botAction.SQLQuery(db, "SELECT * FROM tblElimPlayer WHERE fcUserName = '" + Tools.addSlashesToString(ep.name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
838                        if(rs != null && rs.next()){
839                                ep.ave = rs.getFloat("fnAve");
840                                ep.BDK = rs.getInt("fnBDK");
841                                ep.streak = rs.getInt("fnCKS");
842                                ep.BKS = rs.getInt("fnBKS");
843                                ep.lstreak = rs.getInt("fnCLS");
844                                ep.WLS = rs.getInt("fnWLS");
845                                ep.initWins = rs.getInt("fnKills");
846                                ep.initLosses = rs.getInt("fnDeaths");
847                                ep.initRating = rs.getInt("fnRating");
848                        }
849                        else newPlayer = true;
850                        m_botAction.SQLClose(rs);
851                        if(newPlayer){
852                                ep.initRating = INIT_RATING;
853                                ep.ave = INIT_RATING;
854                                m_botAction.SQLBackgroundQuery(db, null, "INSERT INTO tblElimPlayer (fcUserName, fnGameType, fnRating, fnElim, ftUpdated) VALUES ('" + Tools.addSlashesToString(ep.name.toLowerCase()) + "'," + cfg_gameType + "," + INIT_RATING + ",1,NOW())");
855                        }
856                }catch(SQLException e){
857                        Tools.printStackTrace(e);
858                }
859        }
860    }
861   
862    public void doGameOver(){
863        game.state = GameStatus.GAME_OVER;
864        CompareByWinsLossesAccuracy byMVP = new CompareByWinsLossesAccuracy();
865        Iterator<ElimPlayer> i = lagouts.values().iterator();
866        while( i.hasNext() ){
867                ElimPlayer ep = i.next();
868                if(((((float)ep.getTotalWins()/(float)ep.getTotalLosses())*ep.ave) - ep.initRating) < 0)
869                        losers.put(ep.name, ep);
870        }
871        lagouts.clear();
872        losers.put(winner.name, winner);
873        i = losers.values().iterator();
874        while( i.hasNext() ){
875                ElimPlayer ep = i.next();
876                avg_rating += ep.initRating;
877               
878                        if(ep.name.equalsIgnoreCase(winner.name)){
879                                if(lastWinner.equalsIgnoreCase(ep.name)){
880                                        winStreak++;
881                                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnGamesWon = fnGamesWon + 1, " + 
882                                                        "fnGamesPlayed = fnGamesPlayed + 1, fnKills = fnKills + " + ep.wins + 
883                                                        ", fnDeaths = fnDeaths + " + ep.losses + ", fnShots = fnShots + " + ep.shots +
884                                                        ", fnPE = fnPE + " + ep.eliminations + 
885                                                        ", fnSB = fnSB + " + ep.streakBreaks + 
886                                                        ", fnDK = fnDK + " + ep.doublekills +
887                                                        ", fnAve = " + ep.ave + ", fnAim = (CASE WHEN (fnAim = 0 OR fnShots = 0) THEN " + ep.hitRatio + 
888                                                        " ELSE ((fnKills/fnShots)*100) END), " + 
889                                                        "fnCKS = " + ep.streak + ", fnCLS = " + ep.lstreak + 
890                                                        ", fnCWS = fnCWS + 1, fnBWS = (CASE WHEN (fnCWS > fnBWS) THEN fnCWS ELSE fnBWS END), " + 
891                                                        "fnRating = (CASE WHEN (fnDeaths = 0) THEN 0 ELSE ((fnKills/fnDeaths)*fnAve) END) " + 
892                                                        "WHERE fcUserName = '" + Tools.addSlashesToString(ep.name.toLowerCase()) + 
893                                                        "' AND fnGameType = " + cfg_gameType);
894                                } else {
895                                        winStreak = 1;
896                                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnGamesWon = fnGamesWon + 1, " + 
897                                                        "fnGamesPlayed = fnGamesPlayed + 1, fnKills = fnKills + " + ep.wins + 
898                                                        ", fnDeaths = fnDeaths + " + ep.losses + ", fnShots = fnShots + " + ep.shots +
899                                                        ", fnPE = fnPE + " + ep.eliminations + 
900                                                        ", fnSB = fnSB + " + ep.streakBreaks + 
901                                                        ", fnDK = fnDK + " + ep.doublekills +
902                                                        ", fnAve = " + ep.ave + ", fnAim = (CASE WHEN (fnAim = 0 OR fnShots = 0) THEN " + ep.hitRatio + 
903                                                        " ELSE ((fnKills/fnShots)*100) END), " + 
904                                                        "fnCKS = " + ep.streak + ", fnCLS = " + ep.lstreak + 
905                                                        ", fnCWS = 1, fnRating = (CASE WHEN (fnDeaths = 0) THEN 0 ELSE ((fnKills/fnDeaths)*fnAve) END) " + 
906                                                        "WHERE fcUserName = '" + Tools.addSlashesToString(ep.name.toLowerCase()) + 
907                                                        "' AND fnGameType = " + cfg_gameType);
908                                }
909                        } else {
910                                m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnGamesPlayed = fnGamesPlayed + 1, " + 
911                                                "fnKills = fnKills + " + ep.wins + ", fnDeaths = fnDeaths + " + ep.losses + 
912                                                ", fnShots = fnShots + " + ep.shots +
913                                                ", fnPE = fnPE + " + ep.eliminations + 
914                                                ", fnSB = fnSB + " + ep.streakBreaks +
915                                                ", fnDK = fnDK + " + ep.doublekills +
916                                                ", fnAve = " + ep.ave + ", fnAim = (CASE WHEN (fnAim = 0 OR fnShots = 0) THEN " + ep.hitRatio + 
917                                                " ELSE ((fnKills/fnShots)*100) END), " + 
918                                                "fnCKS = " + ep.streak + ", fnCLS = " + ep.lstreak + 
919                                                ", fnCWS = 0, fnRating = (CASE WHEN (fnDeaths = 0) THEN 0 ELSE ((fnKills/fnDeaths)*fnAve) END) " + 
920                                                "WHERE fcUserName = '" + Tools.addSlashesToString(ep.name.toLowerCase()) + 
921                                                "' AND fnGameType = " + cfg_gameType);
922                        }
923        }
924        avg_rating /= losers.size();
925            List<ElimPlayer> l = Arrays.asList(losers.values().toArray(new ElimPlayer[losers.values().size()]));
926            Collections.sort(l, Collections.reverseOrder(byMVP));//Best record
927            new MVPTimer(l.get(0).name);
928            m_botAction.sendArenaMessage("GAME OVER. Winner: " + winner.name + "!", Tools.Sound.HALLELUJAH);
929            lastWinner = winner.name;
930        Iterator<String> s = enabled.iterator();
931        while( s.hasNext() ){
932                String playerName = s.next();
933                Player p = m_botAction.getPlayer(playerName);
934                if(p == null)continue;
935                elimPlayers.put(playerName, new ElimPlayer(playerName));
936                doWarpIntoElim(playerName);
937        }
938       
939        try{
940                m_botAction.SQLQueryAndClose(db, "INSERT INTO tblElimGame (fnGameType, fcWinnerName, fnWinnerKills, fnWinnerDeaths, fnShipType, fnDeaths, fnNumPlayers, fnAvgRating, fdPlayed) VALUES( " + cfg_gameType + ", '" + Tools.addSlashesToString(winner.name.toLowerCase()) + "', " + winner.wins + ", " + winner.losses + ", " + shipType + ", " + deaths + ", " + losers.size() + ", " + avg_rating + ", NOW())");
941                ResultSet rs = m_botAction.SQLQuery(db, "SELECT fcUserName FROM tblElimPlayer WHERE fnGameType = " + cfg_gameType + " AND (fnKills + fnDeaths) > " + INIT_RANKING + " ORDER BY fnRating DESC");
942                TreeMap<String, Integer> rankings = new TreeMap<String, Integer>();
943                int rank = 1;
944                while( rs != null && rs.next() ){
945                        rankings.put(rs.getString("fcUserName"), rank);
946                        rank++;
947                }
948                m_botAction.SQLClose(rs);
949                Iterator<String> r = rankings.keySet().iterator();
950                while( r.hasNext() ){
951                        String name = r.next();
952                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnRank = " + rankings.get(name) + " WHERE fnGameType = " + cfg_gameType + " AND fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "'");
953                }               
954        }catch(SQLException e){
955                Tools.printStackTrace(e);
956        }
957        game.moveOn(20 * Tools.TimeInMillis.SECOND);
958    }
959   
960    public void vote(String name, String message){
961        if(!elimPlayers.containsKey(name)){
962                m_botAction.sendSmartPrivateMessage( name, "You must be playing to vote!");
963                return;
964        }
965        int vote = 0;
966        ElimPlayer player;
967        try{
968                vote = Integer.parseInt(message);
969        } catch(NumberFormatException e){
970                Tools.printStackTrace(e);//This should never happen
971        }
972        player = elimPlayers.get(name);
973        if(votes.containsKey(vote)){
974                if(player.vote != -1)
975                        votes.put(player.vote, votes.get(player.vote) - 1);
976                player.vote = vote;
977                        votes.put(vote, votes.get(vote) + 1);
978        }       
979    }
980   
981    public void countVotes(){
982        int max = 0;
983                ArrayList<Integer> winners = new ArrayList<Integer>();         
984                Iterator<Integer> i = votes.keySet().iterator();
985                while( i.hasNext() ){
986                        int x = i.next();
987                        if( votes.get(x) > max ){
988                                max = votes.get(x);
989                                winners.clear();
990                                winners.add(x);
991                        }
992                        else if( votes.get(x) == max && max != 0) winners.add(x);
993                }
994                if(game.state == GameStatus.VOTING_ON_SHIP){//The ship vote
995                        if(winners.isEmpty()){
996                                shipType = cfg_defaultShip;
997                        }else if(winners.size() > 1){
998                                shipType = winners.get(rand.nextInt(winners.size()-1));
999                        }else
1000                                shipType = winners.get(0);
1001                        gameStyle = ELIM;
1002                        if(shipType > 10){
1003                                shipType /= 10;
1004                                gameStyle = KILLRACE;
1005                        }
1006                        int min = 1;
1007                if(winStreak >= LIMIT_STREAK)
1008                        min = MIN_FOR_STREAK;
1009                        if(gameStyle == ELIM)
1010                                m_botAction.sendArenaMessage("This will be " + Tools.shipName(shipType) + " elim. VOTE: How many deaths? (" + min + "-" + cfg_maxDeaths + ")");
1011                        else
1012                                m_botAction.sendArenaMessage("This will be " + Tools.shipName(shipType) + " kill race. VOTE: How many kills? (" + min + "-" + cfg_maxKills + ")");
1013                } else if(game.state == GameStatus.VOTING_ON_DEATHS){//The deaths vote
1014                        if(gameStyle == ELIM){
1015                                if(winners.isEmpty())
1016                                        deaths = cfg_maxDeaths;
1017                                else if(winners.size() > 1)
1018                                        deaths = winners.get(rand.nextInt(winners.size()-1));
1019                                else
1020                                        deaths = winners.get(0);
1021                                if(cfg_gameType == ELIM || shipType != 2)
1022                                        m_botAction.sendArenaMessage(Tools.shipName(shipType) + " elim to " + deaths);
1023                                else
1024                                        m_botAction.sendArenaMessage(Tools.shipName(shipType) + " elim to " + deaths + ". VOTE: Shrap on or off? (1-on, 0-off)");
1025                        } else {
1026                                if(winners.isEmpty())
1027                                        kills = cfg_maxKills;
1028                                else if(winners.size() > 1)
1029                                        kills = winners.get(rand.nextInt(winners.size()-1));
1030                                else
1031                                        kills = winners.get(0);
1032                                if(cfg_gameType == ELIM || shipType != 2)
1033                                        m_botAction.sendArenaMessage(Tools.shipName(shipType) + " kill race to " + kills);
1034                                else
1035                                        m_botAction.sendArenaMessage(Tools.shipName(shipType) + " kill race to " + kills + ". VOTE: Shrap on or off? (1-on, 0-off)");
1036                        }
1037                } else if(game.state == GameStatus.VOTING_ON_SHRAP){//Shrap vote(Only for baseelim)
1038                        if(winners.isEmpty() || winners.size() > 1)
1039                                shrap = OFF;
1040                        else
1041                                shrap = winners.get(0);
1042                        if(shrap == OFF)
1043                                m_botAction.sendArenaMessage(Tools.shipName(shipType) + " elim to " + deaths + ". Shrap: [OFF]");
1044                        else
1045                                m_botAction.sendArenaMessage(Tools.shipName(shipType) + " elim to " + deaths + ". Shrap: [ON]");
1046                }
1047                //Clear votes
1048                votes = new TreeMap<Integer,Integer>();
1049                Iterator<ElimPlayer> it = elimPlayers.values().iterator();
1050                while( it.hasNext() )
1051                        it.next().vote = -1;
1052    }
1053   
1054    public void doElimZoner(){
1055        if((System.currentTimeMillis() - lastZoner) < (MIN_ZONER * Tools.TimeInMillis.MINUTE))return;
1056        if(winStreak == 1)
1057                m_botAction.sendZoneMessage("Next " + cfg_gameName + " is starting. Last round's winner was " + lastWinner + "! Type ?go " + cfg_arena + " to play");
1058        else if(winStreak > 1)
1059                switch(winStreak){
1060                        case 2:m_botAction.sendZoneMessage("Next " + cfg_gameName + " is starting. " + lastWinner + " has won 2 back to back! Type ?go " + cfg_arena + " to play");
1061                                break;
1062                        case 3:m_botAction.sendZoneMessage(cfg_gameName.toUpperCase() + ": " + lastWinner + " is on fire with a triple win! Type ?go " + cfg_arena + " to end the streak!", Tools.Sound.CROWD_OOO);
1063                                break;
1064                        case 4:m_botAction.sendZoneMessage(cfg_gameName.toUpperCase() + ": " + lastWinner + " is on a rampage! 4 wins in a row! Type ?go " + cfg_arena + " to put a stop to the carnage!", Tools.Sound.CROWD_GEE);
1065                                break;
1066                        case 5:m_botAction.sendZoneMessage(cfg_gameName.toUpperCase() + ": " + lastWinner + " is dominating with a 5 game streak! Type ?go " + cfg_arena + " to end this madness!", Tools.Sound.SCREAM);
1067                                break;
1068                        default:m_botAction.sendZoneMessage(cfg_gameName.toUpperCase() + ": " + lastWinner + " is bringing the zone to shame with " + winStreak + " consecutive wins! Type ?go " + cfg_arena + " to redeem yourselves!", Tools.Sound.INCONCEIVABLE);
1069                                break;
1070                }
1071        else
1072                m_botAction.sendZoneMessage("Next " + cfg_gameName + " is starting. Type ?go " + cfg_arena + " to play");
1073        lastZoner = System.currentTimeMillis();
1074    }
1075   
1076    public void doWarpIntoElim(String name){
1077        if( cfg_casualAllowed == 1 )
1078            m_botAction.sendUnfilteredPrivateMessage(name, "*objoff " + CASUAL_LOGO_LVZ);
1079        if(shipType == 6 && cfg_gameType == BASEELIM){
1080                int[] xarena = cfg.getIntArray("XArena" + rand.nextInt(3), ",");
1081                m_botAction.warpTo(name, xarena[0], xarena[1], xarena[2]);
1082        }
1083    }
1084   
1085    public void doWarpIntoCasual(String name){
1086        if( cfg_casualAllowed == 1 ) {
1087            m_botAction.sendUnfilteredPrivateMessage(name, "*objon " + CASUAL_LOGO_LVZ);
1088            m_botAction.warpTo(name, cfg_casual[0], cfg_casual[1], cfg_casual[2]);
1089        } else {
1090            m_botAction.specWithoutLock(name);           
1091        }
1092    }
1093   
1094    public void doWarpIntoCasualSafe(String name){
1095        if(cfg_casualAllowed != 1 || classicMode.contains(name))
1096                m_botAction.specWithoutLock(name);
1097        else{
1098                for(int i=0;i<9999;i++){
1099                        if(m_botAction.getFrequencySize(i) == 0){
1100                                m_botAction.setFreq(name, i);
1101                                break;
1102                        }                       
1103                }
1104                m_botAction.warpTo(name, cfg_safe[0], cfg_safe[1], cfg_safe[2]);
1105                m_botAction.sendUnfilteredPrivateMessage(name, "*objon " + CASUAL_SPLASH_LVZ);
1106                m_botAction.sendUnfilteredPrivateMessage(name, "*objon " + CASUAL_LOGO_LVZ);
1107        }
1108    }
1109   
1110
1111private class CasualPlayer{
1112        private int wins = 0, losses = 0;
1113        private String name;
1114       
1115        private CasualPlayer(String name){
1116                this.name = name;
1117                try{
1118                        ResultSet rs = m_botAction.SQLQuery(db, "SELECT fcUserName FROM tblElimCasualRecs WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
1119                        if(rs == null || !rs.next()){
1120                                m_botAction.SQLClose(rs);
1121                                m_botAction.SQLBackgroundQuery(db, null, "INSERT INTO tblElimCasualRecs (fcUserName, fnKills, fnDeaths, fnGameType) VALUES ('" + Tools.addSlashesToString(name.toLowerCase()) + "', 0, 0, " + cfg_gameType + ")");
1122                        }else m_botAction.SQLClose(rs);
1123                }catch(SQLException e){
1124                        Tools.printStackTrace(e);
1125                }
1126        }
1127       
1128        private void gotWin(){
1129                wins += 1;
1130        }
1131       
1132        private void gotLoss(){
1133                losses += 1;
1134        }
1135       
1136        private void storeStats(){
1137                // avoid unnecessary updates to the database
1138                if (wins != 0 || losses != 0)
1139                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimCasualRecs SET fnKills = fnKills + " + wins + ", fnDeaths = fnDeaths + " + losses + " WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType );
1140        }
1141}
1142   
1143private class ElimPlayer{
1144        private String name;
1145        //========================================================================
1146        //Bot variables
1147        //========================================================================
1148        private int shiptype = -1, vote = -1, frequency = -1, lagouts = 0;
1149        private long outOfBounds = 0, lagTime = -1, spawnTime = -1, killTime = -1;
1150        private boolean gotBorderWarning = false, gotChangeWarning = false;
1151        //========================================================================
1152        //Database variables
1153        //========================================================================
1154        private int initRating = 0, initWins = 0, initLosses = 0, BKS = 0, WLS = 0, BDK = 0;
1155        private float ave = 0;
1156        //========================================================================
1157        //Game statistic variables
1158        //========================================================================
1159        private int wins = 0, losses = 0;       
1160        private int shots = 0, quickKills = 0, streak = 0, lstreak = 0;
1161        private int streakBreaks = 0, eliminations = 0, doublekills = 0;
1162        private double hitRatio = 0;
1163       
1164        private ElimPlayer(String name){
1165                this.name = name;       
1166        }
1167       
1168        private void resetScore(){
1169                wins = 0;
1170                losses = 0;
1171                lagouts = 0;
1172        }
1173       
1174        private void gotWin(int enemyRating){
1175                if(System.currentTimeMillis() - killTime < (DOUBLE_KILL * Tools.TimeInMillis.SECOND)){
1176                        quickKills++;
1177                        doQuickKill();
1178                }
1179                else quickKills = 0;
1180                lstreak = 0;
1181                killTime = System.currentTimeMillis();
1182                wins += 1;
1183                ave = ((ave * (float)getTotalWins()) + (float)enemyRating)/((float)getTotalWins() + 1f);       
1184                streak += 1;
1185                if(streak >= STREAK_INIT && (streak - STREAK_INIT)%STREAK_REPEAT == 0){
1186                        int i = (streak-STREAK_INIT)/STREAK_REPEAT;
1187                        if(i>=sMessages.length)
1188                                i = sMessages.length - 1;
1189                        m_botAction.sendArenaMessage(name + " - " + sMessages[i] + "(" + streak + ":0)");
1190                }
1191                if(streak > BKS){
1192                        BKS = streak;
1193                        m_botAction.SQLBackgroundQuery(db, null,"UPDATE tblElimPlayer SET fnBKS = " + streak + " WHERE fnGameType = " + cfg_gameType + " AND fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "'");
1194                }
1195        }
1196       
1197        private int getTotalWins(){
1198                return (wins + initWins);
1199        }
1200       
1201        private void gotLoss(boolean resetStreak){
1202                losses += 1;
1203                lstreak += 1;
1204                if(resetStreak)
1205                        streak = 0;
1206                if(lstreak > WLS){
1207                        WLS = lstreak;
1208                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnWLS = " + lstreak + " WHERE fnGameType = " + cfg_gameType + " AND fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "'");
1209                }
1210        }
1211       
1212        private int getTotalLosses(){
1213                return (losses + initLosses) == 0 ? 1 : (losses + initLosses);
1214        }
1215       
1216        private void doQuickKill(){
1217                doublekills++;
1218                switch(quickKills){
1219                        case 1:m_botAction.sendArenaMessage(name + " - Double kill!", Tools.Sound.CROWD_OHH);break;
1220                        case 2:m_botAction.sendArenaMessage(name + " - Triple kill!", Tools.Sound.CROWD_GEE);break;
1221                        case 3:m_botAction.sendArenaMessage(name + " - Quadruple kill!", Tools.Sound.INCONCEIVABLE);break;
1222                        case 4:m_botAction.sendArenaMessage(name + " - Quintuple kill!", Tools.Sound.SCREAM);break;
1223                        case 5:m_botAction.sendArenaMessage(name + " - Sextuple kill!", Tools.Sound.CRYING);break;
1224                        case 6:m_botAction.sendArenaMessage(name + " - Septuple kill!", Tools.Sound.GAME_SUCKS);break;         
1225                }
1226               
1227                if(quickKills > BDK){
1228                        BDK = quickKills;
1229                        m_botAction.SQLBackgroundQuery(db, null, "UPDATE tblElimPlayer SET fnBDK = " + BDK + " WHERE fnGameType = " + cfg_gameType + " AND fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "'");
1230                }
1231        }
1232       
1233        private void calculateRatios(){
1234                if(shots != 0)
1235                        hitRatio = (((double)wins / shots) * 100);
1236                else
1237                        hitRatio = (((double)wins / 1) * 100);
1238                if(hitRatio > 100) 
1239                        hitRatio = 100;
1240        }
1241       
1242        private void clearBorderInfo(){
1243                outOfBounds = 0;
1244                gotBorderWarning = false;
1245        }
1246
1247}
1248
1249public class CompareByLosses implements Comparator<ElimPlayer> {
1250        public int compare(ElimPlayer a, ElimPlayer b){
1251                if(a.losses > b.losses)return 1;
1252                else if(a.losses == b.losses)return 0;
1253                else return -1;
1254        }
1255}
1256
1257public class CompareAlphabetical implements Comparator<ElimPlayer> {
1258        public int compare(ElimPlayer a, ElimPlayer b){
1259                return a.name.compareToIgnoreCase(b.name);
1260        }
1261}
1262
1263public class CompareByWinsLossesAccuracy implements Comparator<ElimPlayer> {
1264        public int compare(ElimPlayer a,ElimPlayer b) {
1265                // compare by wins first
1266                if (a.wins > b.wins)return 1;
1267                else if(a.wins < b.wins)return -1;
1268                // least losses
1269                else if(a.losses < b.losses)return 1;
1270                else if(a.losses > b.losses)return -1;
1271                // try accuracy
1272                a.calculateRatios();
1273                b.calculateRatios();
1274                if(a.hitRatio > b.hitRatio)return 1;
1275                else if(a.hitRatio < b.hitRatio)return -1;
1276                // they did equally well...we leave it to the underlying implementation of Collections.sort for a pseudorandom pick
1277                return 0;
1278        }
1279}
1280private class GameStatus{
1281        private static final int OFF_MODE = -1;
1282        private static final int WAITING_FOR_PLAYERS = 0;
1283        private static final int VOTING_ON_SHIP = 1;
1284        private static final int VOTING_ON_DEATHS = 2;
1285        private static final int VOTING_ON_SHRAP = 3;
1286        private static final int WAITING_TO_START = 4;
1287        private static final int TEN_SECONDS = 5;
1288        private static final int GAME_IN_PROGRESS = 6;
1289        private static final int GAME_OVER = 7;
1290        private int state = 0;
1291        private TimerTask task;
1292       
1293        private GameStatus(){}
1294       
1295        private void moveOn(long millis){
1296                m_botAction.cancelTask(task);
1297                task = new TimerTask(){
1298                        public void run(){
1299                                moveOn();
1300                                this.cancel();
1301                        }
1302                };
1303                try{ 
1304                        m_botAction.scheduleTask(task, millis);
1305                }catch(Exception e){}
1306        }
1307       
1308        private void moveOn(){
1309                if(elimPlayers.size() < cfg_minPlayers && state < GAME_IN_PROGRESS){
1310                        state = OFF_MODE;
1311                        lastWinner = "-anonymous-";
1312                        winStreak = 0;
1313                }
1314                switch(state){
1315                        case OFF_MODE:
1316                                doWaitingForPlayers();
1317                                break;
1318                        case WAITING_FOR_PLAYERS:
1319                                doVotingOnShip();
1320                                break;
1321                        case VOTING_ON_SHIP:
1322                                countVotes();
1323                                doVotingOnDeaths();
1324                                break;
1325                        case VOTING_ON_DEATHS:
1326                                countVotes();
1327                                if(cfg_gameType == ELIM || shipType != 2){
1328                                        doWaitingToStart();
1329                                } else {
1330                                        doVotingOnShrap();
1331                                }
1332                                break;
1333                        case VOTING_ON_SHRAP:
1334                                countVotes();
1335                                doWaitingToStart();
1336                                break;
1337                        case WAITING_TO_START:
1338                                doTenSeconds();
1339                                break;
1340                        case TEN_SECONDS:
1341                                doGameInProgress();
1342                                break;
1343                        case GAME_IN_PROGRESS:
1344                                doGameOver();
1345                                break;
1346                        case GAME_OVER:
1347                                if(botMode == ON)
1348                                        doWaitingForPlayers();
1349                                else if(botMode == OFF){
1350                                        state = OFF_MODE;
1351                                        lastWinner = "-anonymous-";
1352                                        winStreak = 0;
1353                                }
1354                                else if(botMode == DISCONNECT){
1355                                        try{
1356                                                m_botAction.scheduleTask(new DieTask(m_botAction.getBotName()), 500);
1357                                        }catch( Exception e ){}
1358                                }
1359                                break;
1360                }       
1361        }
1362       
1363        public boolean isVoting(){
1364                if(state == VOTING_ON_SHIP || state == VOTING_ON_DEATHS || state == VOTING_ON_SHRAP)
1365                        return true;
1366                else return false;
1367        }
1368       
1369        public boolean isInProgress(){
1370                if(state == TEN_SECONDS || state == GAME_IN_PROGRESS)
1371                        return true;
1372                else return false;
1373        }
1374       
1375}
1376
1377private class SpawnTimer {
1378    private String name;
1379    private boolean casual;
1380    private TimerTask runIt = new TimerTask() {
1381        public void run() {
1382                if(!casual){
1383                        if(shrap == ON)
1384                                m_botAction.specificPrize(name, Tools.Prize.SHRAPNEL);
1385                        m_botAction.specificPrize(name, Tools.Prize.MULTIFIRE);
1386                        doWarpIntoElim(name);
1387                        if(elimPlayers.containsKey(name)){
1388                                elimPlayers.get(name).spawnTime = System.currentTimeMillis();
1389                                if(elimPlayers.get(name).shiptype == 8){
1390                                        m_botAction.specificPrize(name, Tools.Prize.SHRAPNEL);
1391                                        m_botAction.specificPrize(name, Tools.Prize.SHRAPNEL);
1392                                }
1393                        }
1394                }else
1395                        doWarpIntoCasual(name);
1396        }
1397    };
1398       
1399    public SpawnTimer(String name, boolean casual) {
1400        this.name = name;
1401        if( cfg_casualAllowed == 1 )
1402            this.casual = casual;
1403        else
1404            this.casual = false;
1405        try {
1406            m_botAction.scheduleTask(runIt, SPAWN_TIME);
1407        } catch( Exception e) {}
1408    }
1409}
1410
1411private class MVPTimer {
1412    private String name;
1413    private TimerTask runIt = new TimerTask() {
1414        public void run() {
1415                m_botAction.sendArenaMessage("MVP: " + name, Tools.Sound.INCONCEIVABLE);
1416        }
1417    };
1418       
1419    public MVPTimer(String name) {
1420        this.name = name;
1421        try{
1422                m_botAction.scheduleTask(runIt, 5 * Tools.TimeInMillis.SECOND);
1423        } catch( Exception e){}
1424    }
1425}
1426
1427////////////////////////////////////////////////////
1428//                    EVENTS                      //
1429////////////////////////////////////////////////////
1430
1431    public void handleEvent(LoggedOn event) {                 
1432        m_botAction.joinArena(cfg_arena);
1433        m_botAction.specAll();
1434        m_botAction.receiveAllPlayerDeaths();
1435        m_botAction.setPlayerPositionUpdating( 400 );
1436        m_botAction.sendUnfilteredPublicMessage("?chat=" + cfg_chats);
1437    }
1438   
1439    public void handleEvent(ArenaJoined event) {
1440        for(int z=0;z<4;z++){
1441                m_botAction.sendUnfilteredPublicMessage( "?set spawn:team" + z + "-x:" + cfg_competitive[0]);
1442                m_botAction.sendUnfilteredPublicMessage( "?set spawn:team" + z + "-y:" + cfg_competitive[1]);
1443                m_botAction.sendUnfilteredPublicMessage( "?set spawn:team" + z + "-radius:" + cfg_competitive[2]);
1444        }
1445        Iterator<Player> i = m_botAction.getPlayerIterator();
1446        while( i.hasNext() ){
1447                Player p = i.next();
1448                String name = p.getPlayerName();
1449                if(!opList.isBotExact(name)){
1450                    if( cfg_casualAllowed == 1 ) {
1451                        casualPlayers.put(name, new CasualPlayer(name));
1452                        if(cfg_gameType == BASEELIM)
1453                            m_botAction.sendUnfilteredPrivateMessage(name, "*einfo");
1454                        enabled.add(name);
1455                    } else {
1456                    if(p.getShipType() > 0){
1457                        elimPlayers.put(name, new ElimPlayer(name));
1458                        doWarpIntoElim(name);
1459                    }
1460                    }
1461                }
1462                try{
1463                        ResultSet rs = m_botAction.SQLQuery(db, "SELECT fnSpecWhenOut, fnElim FROM tblElimPlayer WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
1464                        if(rs != null && rs.next()){
1465                                if(rs.getInt("fnElim") == 0)
1466                                        enabled.remove(name);
1467                                if(cfg_casualAllowed != 1 || rs.getInt("fnSpecWhenOut") == 1)
1468                                        classicMode.add(name);
1469                        }
1470                        m_botAction.SQLClose(rs);
1471                }catch(SQLException e){
1472                        Tools.printStackTrace(e);
1473                }
1474        }
1475        game.moveOn();
1476    }
1477   
1478    public void handleEvent(WeaponFired event) {
1479        String name = m_botAction.getPlayerName(event.getPlayerID());
1480        if(name == null)return;
1481        else if(!game.isInProgress() || !elimPlayers.containsKey(name))return;
1482        elimPlayers.get(name).shots += 1;       
1483    }
1484   
1485    public void handleEvent(PlayerDeath event) {
1486        String win = m_botAction.getPlayerName(event.getKillerID());
1487        String loss = m_botAction.getPlayerName(event.getKilleeID());
1488        if(win == null || loss == null)return;
1489        Player winp = m_botAction.getPlayer(win);
1490        Player lossp = m_botAction.getPlayer(loss);
1491        if(opList.isBotExact(win) || opList.isBotExact(loss) || winp == null || lossp == null)return;
1492        casualPlayers.get(win).gotWin();
1493        casualPlayers.get(loss).gotLoss();
1494        ElimPlayer w = findCollection(win);
1495        ElimPlayer l = findCollection(loss);
1496        if(!(game.state == GameStatus.GAME_IN_PROGRESS) || w == null || l == null || winp.getYTileLocation() < (cfg_safe[1] + SAFE_HEIGHT)){
1497                new SpawnTimer(loss, true);
1498                return;
1499        }
1500        if((System.currentTimeMillis() - l.spawnTime) < (SPAWN_NC * Tools.TimeInMillis.SECOND)||
1501           (System.currentTimeMillis() - w.spawnTime) < (SPAWN_NC * Tools.TimeInMillis.SECOND)){
1502                m_botAction.sendSmartPrivateMessage( win, "Spawn kill(No count).");
1503                m_botAction.sendSmartPrivateMessage( loss, "Spawn kill(No count).");
1504                return;
1505        }
1506        if(winp.getShipType() == 0 || elimPlayers.containsKey(win))
1507                w.gotWin(l.initRating);
1508        if(l.streak >= 5){
1509                w.streakBreaks++;
1510                m_botAction.sendArenaMessage("Streak breaker! " + loss + "(" + l.streak + ":0) broken by " + win + "!", Tools.Sound.INCONCEIVABLE);
1511        }
1512        if(lossp.getShipType() == 0 || elimPlayers.containsKey(loss))
1513                l.gotLoss(true);
1514        if(gameStyle == ELIM && l.losses == deaths && elimPlayers.containsKey(loss)){
1515                w.eliminations++;
1516                m_botAction.sendArenaMessage(loss + " is out. " + l.wins + " wins " + l.losses + " losses");
1517                losers.put(loss, elimPlayers.remove(loss));
1518                doWarpIntoCasualSafe(loss);
1519        }else if(gameStyle == KILLRACE && w.wins == kills && elimPlayers.containsKey(win)){
1520                Iterator<ElimPlayer> i = elimPlayers.values().iterator();
1521                while( i.hasNext() ){
1522                        ElimPlayer ep = i.next();
1523                        if(!ep.name.equalsIgnoreCase(w.name)){
1524                                losers.put(ep.name, ep);
1525                                doWarpIntoCasualSafe(ep.name);
1526                                i.remove();                             
1527                        }
1528                }
1529        }else if(elimPlayers.containsKey(loss)){
1530                l.clearBorderInfo();
1531                new SpawnTimer(loss, false);
1532        }else
1533                new SpawnTimer(loss, true);
1534        if(elimPlayers.size() == 1){
1535                winner = elimPlayers.get(elimPlayers.firstKey());
1536                game.moveOn();
1537        }
1538    }
1539   
1540    public void handleEvent(PlayerEntered event) {
1541        String name = m_botAction.getPlayerName(event.getPlayerID());
1542        if(name == null || opList.isBotExact(name))return;
1543        casualPlayers.put(name, new CasualPlayer(name));
1544        if(cfg_gameType == BASEELIM)
1545                m_botAction.sendUnfilteredPrivateMessage(name, "*einfo");       
1546        m_botAction.sendSmartPrivateMessage( name, "Welcome to " + cfg_arena + "! " + getStatusMsg());
1547        enabled.add(name);
1548        if(!game.isInProgress()){
1549                elimPlayers.put(name, new ElimPlayer(name));
1550                if(elimPlayers.size() >= cfg_minPlayers && game.state == GameStatus.WAITING_FOR_PLAYERS)
1551                        game.moveOn();
1552        }
1553        try{
1554                ResultSet rs = m_botAction.SQLQuery(db, "SELECT fnSpecWhenOut, fnElim FROM tblElimPlayer WHERE fcUserName = '" + Tools.addSlashesToString(name.toLowerCase()) + "' AND fnGameType = " + cfg_gameType);
1555                if(rs != null && rs.next()){
1556                        if(rs.getInt("fnElim") == 0)
1557                                enabled.remove(name);
1558                        if(cfg_casualAllowed != 1 || rs.getInt("fnSpecWhenOut") == 1)
1559                                classicMode.add(name);
1560                }
1561                m_botAction.SQLClose(rs);
1562        }catch(SQLException e){
1563                Tools.printStackTrace(e);
1564        }
1565    }
1566   
1567    public void handleEvent(PlayerLeft event) {
1568        String name = m_botAction.getPlayerName(event.getPlayerID());
1569        if(name == null || opList.isBotExact(name))return;
1570        enabled.remove(name);
1571        classicMode.remove(name);
1572        CasualPlayer c = casualPlayers.get(name);
1573        if( c != null )
1574            c.storeStats();
1575        casualPlayers.remove(name);
1576        if(game.isInProgress() && elimPlayers.containsKey(name)){
1577                lagouts.put(name, elimPlayers.remove(name));
1578                lagouts.get(name).lagTime = System.currentTimeMillis();
1579                lagouts.get(name).lagouts++;
1580                if(lagouts.get(name).lagouts >= MAX_LAGOUT){
1581                        m_botAction.sendArenaMessage(name + " is out. " + lagouts.get(name).wins + " wins " + lagouts.get(name).losses + " losses (Too many lagouts)");
1582                        losers.put(name, lagouts.remove(name));
1583                        doWarpIntoCasualSafe(name);
1584                }
1585        }
1586        else if(!game.isInProgress() && elimPlayers.containsKey(name))
1587                elimPlayers.remove(name);
1588        if(elimPlayers.size() == 1 && game.state == GameStatus.GAME_IN_PROGRESS){
1589                        winner = elimPlayers.get(elimPlayers.firstKey());
1590                game.moveOn();
1591                }
1592    }
1593   
1594    public void handleEvent(FrequencyShipChange event) {
1595        String name = m_botAction.getPlayerName(event.getPlayerID());
1596        if(game.isInProgress() && elimPlayers.containsKey(name) && event.getShipType() == 0){
1597                lagouts.put(name, elimPlayers.remove(name));
1598                lagouts.get(name).lagTime = System.currentTimeMillis();
1599                lagouts.get(name).lagouts++;
1600                if(lagouts.get(name).lagouts >= MAX_LAGOUT){
1601                        m_botAction.sendArenaMessage(name + " is out. " + lagouts.get(name).wins + " wins " + lagouts.get(name).losses + " losses (Too many lagouts)");
1602                        losers.put(name, lagouts.remove(name));
1603                        doWarpIntoCasualSafe(name);
1604                }               
1605                if(elimPlayers.size() == 1 && game.state == GameStatus.GAME_IN_PROGRESS){
1606                        winner = elimPlayers.get(elimPlayers.firstKey());
1607                        game.moveOn();
1608                }
1609        } else if(!elimPlayers.containsKey(name) && event.getShipType() != cfg_defaultShip && event.getShipType() > 0){
1610                m_botAction.setShip(name, cfg_defaultShip);
1611                doWarpIntoCasual(name);
1612        } else if(!elimPlayers.containsKey(name) && game.isInProgress() && event.getShipType() > 0){
1613            if( cfg_casualAllowed == 1 ) {
1614                m_botAction.sendUnfilteredPrivateMessage(name, "*objon " + CASUAL_LOGO_LVZ);
1615                m_botAction.sendUnfilteredPrivateMessage(name, "*objon " + CASUAL_SPLASH_LVZ);
1616                if(enabled.contains(name))
1617                    m_botAction.sendSmartPrivateMessage( name, "You have entered casual play. Please wait for the next game to begin to participate.");
1618            }
1619                doWarpIntoCasual(name);
1620        } else if(game.isInProgress() && elimPlayers.containsKey(name) && event.getShipType() > 0){
1621                ElimPlayer ep = elimPlayers.get(name);
1622                if(event.getShipType() != ep.shiptype){
1623                        m_botAction.setShip(name, ep.shiptype);
1624                        doWarpIntoElim(name);
1625                        if(game.state == GameStatus.GAME_IN_PROGRESS){
1626                                if(!ep.gotChangeWarning){
1627                                        ep.gotLoss(false);
1628                                        m_botAction.sendArenaMessage(name + " has attempted to change ships - +1 death");
1629                                        if(ep.losses == deaths && gameStyle == ELIM){
1630                                        m_botAction.sendArenaMessage(ep.name + " is out. " + ep.wins + " wins " + ep.losses + " losses");
1631                                        losers.put(ep.name, elimPlayers.remove(ep.name));
1632                                        doWarpIntoCasualSafe(ep.name);
1633                                }else{
1634                                        m_botAction.sendSmartPrivateMessage( name, "Attempt to change ships or frequencies again and you will be removed from the game. You have been warned.");
1635                                        ep.gotChangeWarning = true;
1636                                }
1637                                }else{
1638                                        m_botAction.sendArenaMessage(name + " is out. " + ep.wins + " wins " + ep.losses + " losses (Disqualified)");
1639                                        losers.put(name, elimPlayers.remove(name));
1640                                        doWarpIntoCasualSafe(name);
1641                                }
1642                                if(elimPlayers.size() == 1 && game.state == GameStatus.GAME_IN_PROGRESS){
1643                                        winner = elimPlayers.get(elimPlayers.firstKey());
1644                                        game.moveOn();
1645                                }
1646                        }
1647                }
1648        } else if(enabled.contains(name) && !elimPlayers.containsKey(name) && !game.isInProgress() && event.getShipType() > 0){
1649                doWarpIntoElim(name);
1650                elimPlayers.put(name, new ElimPlayer(name));
1651                if(elimPlayers.size() >= cfg_minPlayers && game.state == GameStatus.WAITING_FOR_PLAYERS)
1652                        game.moveOn();
1653        }
1654    }
1655   
1656    public void handleEvent(FrequencyChange event){
1657        String name = m_botAction.getPlayerName(event.getPlayerID());
1658        if(game.isInProgress() && elimPlayers.containsKey(name)){
1659                if(event.getFrequency() != elimPlayers.get(name).frequency  && event.getFrequency() != SPEC_FREQ){
1660                        ElimPlayer ep = elimPlayers.get(name);
1661                        m_botAction.setFreq(name, ep.frequency);
1662                        doWarpIntoElim(name);
1663                        if(!ep.gotChangeWarning){
1664                                ep.gotLoss(false);
1665                                m_botAction.sendArenaMessage(name + " has attempted to change frequencies - +1 death");
1666                                if(ep.losses == deaths && gameStyle == ELIM){
1667                                m_botAction.sendArenaMessage(ep.name + " is out. " + ep.wins + " wins " + ep.losses + " losses");
1668                                losers.put(ep.name, elimPlayers.remove(ep.name));
1669                                doWarpIntoCasualSafe(ep.name);
1670                        }else{
1671                                m_botAction.sendSmartPrivateMessage( name, "Attempt to change ships or frequencies again and you will be removed from the game. You have been warned.");
1672                                        ep.gotChangeWarning = true;
1673                        }
1674                        } else {               
1675                                m_botAction.sendArenaMessage(name + " is out. " + ep.wins + " wins " + ep.losses + " losses (Disqualified)");
1676                                losers.put(name, elimPlayers.remove(name));
1677                                doWarpIntoCasualSafe(name);
1678                        }
1679                }
1680        } else if(!elimPlayers.containsKey(name) && event.getFrequency() > MAX_FREQ){
1681                m_botAction.sendSmartPrivateMessage( name, "Please choose a private frequency under " + (MAX_FREQ+1) + ".");
1682                doWarpIntoCasual(name);
1683        }
1684    }
1685   
1686    public void handleEvent(PlayerPosition event){
1687        Player p = m_botAction.getPlayer(event.getPlayerID());
1688        if(p == null)return;
1689        if(p.getYTileLocation() < (cfg_safe[1]+SAFE_HEIGHT) && elimPlayers.containsKey(p.getPlayerName())){
1690                m_botAction.specificPrize(p.getPlayerName(), Tools.Prize.WARP);
1691                doWarpIntoElim(p.getPlayerName()); 
1692        }
1693        else if(p.getYTileLocation() > (cfg_safe[1]+SAFE_HEIGHT) && !elimPlayers.containsKey(p.getPlayerName())){
1694                doWarpIntoCasual(p.getPlayerName());
1695        }
1696        if(cfg_gameType == ELIM)return;
1697        ElimPlayer ep = elimPlayers.get(p.getPlayerName());
1698            if(ep != null && game.isInProgress()){
1699                if(p.getYTileLocation() < cfg_border)
1700                        ep.clearBorderInfo();
1701                    else if(p.getYTileLocation() > cfg_border){                 
1702                        if(ep.outOfBounds == 0)
1703                                ep.outOfBounds = System.currentTimeMillis();
1704                        else if((System.currentTimeMillis() - ep.outOfBounds) > BOUNDARY_TIME * Tools.TimeInMillis.SECOND){
1705                                m_botAction.sendArenaMessage(ep.name + " is out. " + ep.wins + " wins " + ep.losses + " losses (Too long outside base)");
1706                                losers.put(ep.name, elimPlayers.remove(ep.name));
1707                                doWarpIntoCasualSafe(ep.name);
1708                        }
1709                        else if((System.currentTimeMillis() - ep.outOfBounds) > (BOUNDARY_TIME/2) * Tools.TimeInMillis.SECOND && !ep.gotBorderWarning){
1710                                m_botAction.sendSmartPrivateMessage( ep.name, "Get in the base!");
1711                                ep.gotBorderWarning = true;
1712                        }               
1713                    }
1714                    if(elimPlayers.size() == 1 && game.state == GameStatus.GAME_IN_PROGRESS){
1715                        winner = elimPlayers.get(elimPlayers.firstKey());
1716                        game.moveOn();
1717                    }
1718        } else {
1719                //Barwarp
1720                if(p.getYTileLocation() > cfg_barY[0] && p.getYTileLocation() < cfg_barY[1]){
1721                        for(int i=0;i<cfg_barspots.length;i++){
1722                                if(p.getXTileLocation() > cfg_barspots[i][0] && p.getXTileLocation() < cfg_barspots[i][1])
1723                                        m_botAction.warpTo(p.getPlayerName(), cfg_barspots[i][2], cfg_barspots[i][3]);
1724                        }
1725                }
1726        }
1727    }
1728   
1729   
1730    /* (non-Javadoc)
1731     * @see twcore.core.SubspaceBot#handleEvent(twcore.core.events.SQLResultEvent)
1732     */
1733    @Override
1734    public void handleEvent(SQLResultEvent event) {
1735        if(event.getResultSet() != null) {
1736                // Just close any background queries that were done, all background queries are INSERT / UPDATE that we don't care about the result
1737                try {
1738                        event.getResultSet().close();
1739                } catch(SQLException sqle) {
1740                        Tools.printStackTrace(sqle);
1741                }
1742        }
1743       
1744    }
1745
1746        public void requestEvents() {
1747        EventRequester req = m_botAction.getEventRequester();
1748        req.request(EventRequester.MESSAGE);
1749        req.request(EventRequester.LOGGED_ON);
1750        req.request(EventRequester.PLAYER_ENTERED);
1751        req.request(EventRequester.PLAYER_LEFT);
1752        req.request(EventRequester.WEAPON_FIRED);
1753        req.request(EventRequester.FREQUENCY_SHIP_CHANGE);
1754        req.request(EventRequester.FREQUENCY_CHANGE);
1755        req.request(EventRequester.PLAYER_DEATH);
1756        req.request(EventRequester.PLAYER_POSITION);
1757        req.request(EventRequester.ARENA_JOINED);
1758    }
1759
1760    public ElimPlayer findCollection(String name){
1761        if(elimPlayers.containsKey(name))
1762                return elimPlayers.get(name);
1763        else if(losers.containsKey(name))
1764                return losers.get(name);
1765        else if(lagouts.containsKey(name))
1766                return lagouts.get(name);
1767        else return null;
1768    }
1769   
1770    public String padString(String s, int length){
1771        if(s.length() == length)return s;
1772        while(s.length() < length)
1773                s += " ";
1774        return s;
1775    }
1776   
1777    public int getBotNumber(BotSettings cfg){ 
1778        for (int i = 1; i <= cfg.getInt("Max Bots"); i++){
1779            if (cfg.getString("Name" + i).equalsIgnoreCase(m_botAction.getBotName()))
1780                return i;
1781        }
1782        return 1;
1783    }
1784   
1785    private class DieTask extends TimerTask {
1786        String m_initiator;
1787
1788        public DieTask( String name ) {
1789            super();
1790            m_initiator = name;
1791        }
1792
1793        public void run() {
1794            m_botAction.die( "!die initiated by " + m_initiator );
1795        }
1796    }
1797   
1798    public void handleDisconnect(){
1799        m_botAction.cancelTasks();
1800    }
1801}
Note: See TracBrowser for help on using the browser.