SHARE
TWEET

Untitled

a guest May 26th, 2019 210 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. /*jshint esversion: 6 */
  3. /*jslint browser: true */
  4. /*global window */
  5. /*global console */
  6. /*global HBInit */
  7.  
  8. // TODO: MOTM
  9. // red "πŸŒΏπŸ”΄[EFC Futsal] ◻️ discord.gg/jTn2ZDp"         "code": "eu", "lat": 48.1371535, "lon": 11.5761235};
  10. // bleu "πŸŒΏπŸ”΅[EFC Futsal] ◻️ Sign up & Register"       "code": "eu", "lat": 48.1371545, "lon": 11.5761245};
  11. // white "🌿βšͺ[EFC Futsal] ◻️ Play with friends"                "code": "eu", "lat": 48.1371540, "lon": 11.5761240};
  12. // black "🌿⚫[EFC Futsal] ◻️ New Season 4"           "code": "eu", "lat": 48.1371540, "lon": 11.5761240};
  13. // orange  πŸŒΏβ˜’️[EFC Futsal] ◻️ Join us !"             "code": "eu", "lat": 48.1371550, "lon": 11.5761250};
  14. var MAX_PLAYERS = 14;
  15.  
  16. let geo = {"code": "eu", "lat": 48.1371550, "lon": 11.5761250};
  17. var room = HBInit({ roomName: "🌿☒️[EFC Futsal] ◻️ Join us !",
  18.     playerName: "EFC", maxPlayers: MAX_PLAYERS, public: true, geo });
  19.  
  20. let first_stadium_loaded = false;
  21. room.setDefaultStadium("Classic");
  22. room.setScoreLimit(3);
  23. room.setTimeLimit(3);
  24. room.setTeamsLock(true);
  25.  
  26.  
  27.  
  28.  
  29. class Player {
  30.     constructor(name) {
  31.         this.name = name;
  32.         /*************************************
  33.         ************ Individual stats**********
  34.         **************************************/
  35.         this.goals = 0; /* Number of goals */
  36.         this.assists = 0; /* Number of assists */
  37.         this.cs = 0; /* Number of cleensheets */
  38.         this.ownGoals = 0; /* Number of own goals */
  39.         this.wins = 0; /* Number of wins */
  40.         this.loses = 0; /* Number of loses */
  41.         this.motm = 0; /* Number of time a player is the man of the match */
  42.         this.playedGk = 0;
  43.  
  44.         this.badPasses = 0; /* Number of passes */
  45.         this.goodPasses = 1; /* Number of passes that reached a team mate */
  46.         this.passAcc = 0; /* Pass accuracy % */
  47.         this.motmRatio = 0; /* Man of the match % */
  48.         this.winsRatio = 0; /* Wins / Loses */
  49.         this.csPG = 0; /* CS % per game */
  50.         this.goalsPG = 0; /* Number of goals per game */
  51.         this.assistsPG = 0; /* Number of assists per game */
  52.         this.elo = 1000; /* ELO */
  53.  
  54.         this.secsPlayed = 0; /* Number of mins played */
  55.         this.minsPlayed = 0; /* Number of mins played */
  56.         this.currentStreak = 0; /* Number of current matches won in a row */
  57.         this.bestStreak = 0; /* Number of maximum amount of wins in a row */
  58.         this.statsString1 = "";
  59.         this.statsString2 = "";
  60.         this.statsString3 = "";
  61.         /*************************************
  62.         ************ Haxball manager**********
  63.         **************************************/
  64.         this.price = 10;
  65.         this.money = 100;
  66.         this.currentBet = 0;
  67.         this.winPred = 0;
  68.         this.dreamTeam = {"gk": null, "dm": null, "am": null, "st": null};
  69.         this.teamScore = 0;
  70.  
  71.         /*************************************
  72.         ************ Revelant to the room*****
  73.         **************************************/
  74.         this.team = 0;
  75.         this.gotKicked = 0; /* Number of time this player got kicked by another player */
  76.         this.kickedSomeone = 0; /* Number of time this player kicked someone */
  77.         this.id = 0; /* Current player's id on the room */
  78.         this.pw = 0; /* Password for player's account */
  79.         this.isTrustedAdmin = 0; /* Whether he's a trusted admin */
  80.         this.logged = 1; /* 0 if the player is not in the room, 1 if he's */
  81.         this.isBanned = 0; /* Whether a player is banned */
  82.         this.isPermaBanned = 0; /* Whether a player is banned permanently*/
  83.         this.isRegistered = 0; /* Whether a player is registered (e.g. his stats will count) */
  84.         this.auth = 0; /* Player's last auth */
  85.         this.conn = 0; /* Player's last conn */
  86.         this.isMuted = 0; /* Whether a player is muted */
  87.         this.isAFK = false;
  88.     }
  89.  
  90.  
  91.     updateGoals(){
  92.         if (gameStats.scorers.hasOwnProperty(this.name))
  93.             this.goals += gameStats.scorers[this.name];
  94.     }
  95.     updateAssists(){
  96.         if (gameStats.assisters.hasOwnProperty(this.name))
  97.             this.assists += gameStats.assisters[this.name];
  98.     }
  99.     updateCs(){
  100.         let [team, idteam] = this.team === 1 ? ["blueScore", 1] : ["redScore", 2];
  101.         this.cs += gameStats[team] === 0 &&
  102.             this.name === gameStats.Gks[idteam - 1];
  103.     }
  104.     updateOG(){
  105.         if (gameStats.ownScorers.hasOwnProperty(this.name))
  106.             this.ownGoals += gameStats.ownScorers[this.name];
  107.     }
  108.     updatePlayedGk(){
  109.         this.playedGk += gameStats.Gks.includes(this.name);
  110.     }
  111.     updateWins(winningTeam){
  112.         this.wins += this.team === winningTeam;
  113.     }
  114.  
  115.     updateLoses(losingTeam){
  116.         this.loses += this.team === losingTeam;
  117.     }
  118.     updateWinRatio(){
  119.         this.winsRatio = ((this.wins / (this.wins + this.loses)) * 100).toFixed(2) || 0;
  120.     }
  121.     updateGoalsPG(){
  122.         this.goalsPG = (this.goals / (this.loses + this.wins)).toFixed(2) ||Β 0;
  123.     }
  124.     updateAssistsPG(){
  125.         this.assistsPG = (this.assists / (this.loses + this.wins)).toFixed(2) || 0;
  126.     }
  127.     updateCSPG(){
  128.         this.csPG = ((this.cs / this.playedGk) * 100).toFixed(2) || 0;
  129.     }
  130.     updateCurrentStreak(won){
  131.         this.currentStreak = won === this.team ? this.currentStreak + 1 : 0;
  132.     }
  133.  
  134.     updateBestStreak(){
  135.         this.bestStreak = this.currentStreak >= this.bestStreak ?
  136.             this.currentStreak : this.bestStreak;
  137.     }
  138.     updateSecsPlayed(){
  139.         this.secsPlayed += Number(((this.team !== 0) / 60).toFixed(2));
  140.     }
  141.     updateMinsPlayed(){
  142.         this.minsPlayed = Math.floor((this.secsPlayed / 60));
  143.     }
  144.  
  145.     updatePassAccuracy(){
  146.         this.passAcc = ((this.goodPasses / (this.goodPasses + this.badPasses)) * 100).toFixed(2);
  147.     }
  148.     updateKickedSomeone(){
  149.         this.kickedSomeone += this.isTrustedAdmin === 0;
  150.     }
  151.     updatePassword(m){
  152.         this.pw = m;
  153.     }
  154.     updateMoney(won){
  155.         let diff = won == this.winPred ? this.currentBet : -1 * this.currentBet;
  156.         this.money += diff;
  157.         room.sendChat("By your bet  you got " + diff + " EFCOINS", this.id);
  158.         this.currentBet = 0;
  159.         this.winPred = 0;
  160.     }
  161.     disconnect(){
  162.         this.logged = 0;
  163.         this.isTrustedAdmin = 0;
  164.         this.price = 0;
  165.     }
  166.  
  167.     statsToString(){
  168.         this.statsString1 = " | Goals: " + this.goals + " | Assists: " + this.assists +
  169.             " | Own goals: " + this.ownGoals + " | cs: " + this.cs +
  170.             " | Wins: " + this.wins + " | Losses: " + this.loses;
  171.  
  172.         this.statsString2 = " | MOTM: " + "[Soon]" +
  173.             " | MOTMR: " + "[Soon]" + " | W/L %: " + this.winsRatio +
  174.             " | Pass acc %: " + this.passAcc + " | Elo: " + this.elo;
  175.  
  176.         this.statsString3 = " | GPG: " + this.goalsPG + " | APG: " + this.assistsPG +
  177.             " | csPG %: " + this.csPG + " | Best streak: " + this.bestStreak +
  178.             " | Mins: " + this.minsPlayed + "| EFCOINS: " + this.money;
  179.     }
  180.     displayStats(query_id){
  181.         this.statsToString();
  182.         room.sendChat(this.statsString1, query_id);
  183.         room.sendChat(this.statsString2, query_id);
  184.         room.sendChat(this.statsString3, query_id);
  185.         this.statsString1 = this.statsString2 = this.statsString3 = "";
  186.     }
  187.     updateEGStats(){
  188.         let winners = gameStats.redScore > gameStats.blueScore ? 1 : 2;
  189.         let losers = 1 + (winners === 1);
  190.         this.updateGoals();
  191.         this.updateAssists();
  192.         this.updateOG();
  193.         this.updateWins(winners);
  194.         this.updateLoses(winners - 1);
  195.         this.updatePlayedGk();
  196.  
  197.  
  198.         this.updateWinRatio();
  199.         this.updateGoalsPG();
  200.         this.updateAssistsPG();
  201.         this.updateCSPG();
  202.         this.updatePassAccuracy();
  203.         this.updateCurrentStreak(winners);
  204.         this.updateBestStreak(winners);
  205.         this.updateCs();
  206.         this.updateMoney(winners);
  207.     }
  208. }
  209.  
  210.  
  211.  
  212.  
  213. class GameStats {
  214.     constructor() {
  215.         this.redScore = 0; /* Number of goals red team scored this match */
  216.         this.blueScore = 0; /* Number of goals blue team scored this match */
  217.         this.Gks = ["", ""]; /* Name of the gks */
  218.         this.scorers = {}; /* {name: number_of_goals_scored} */
  219.         this.assisters = {};  /* {name: number_of_assists} */
  220.         this.ownScorers = {};  /* {name: number_of_own_goals} */
  221.         this.redTeam = [];  /* [name of the players in red team] */
  222.         this.blueTeam = []; /* [name of the players in blue team] */
  223.         this.matchsumup = [];
  224.         this.isOvertime = false;
  225.         this.hasStarted = false;
  226.         this.rec = false;
  227.     }
  228.     updateScore(team){
  229.         this.redScore += team === 1;
  230.         this.blueScore += team === 2;
  231.     }
  232.  
  233.     updateGK(){
  234.         var players = room.getPlayerList();
  235.         var min = players[0];
  236.         min.position = {x: room.getBallPosition().x + 60};
  237.         var max = min;
  238.  
  239.         for (var i = 1; i < players.length; i++) {
  240.             if (players[i].position !== null){
  241.                 if (min.position.x > players[i].position.x) min = players[i];
  242.                 if (max.position.x < players[i].position.x) max = players[i];
  243.             }
  244.         }
  245.         this.Gks = [min.name, max.name];
  246.     }
  247.     updateScorers(p, team){
  248.         if (p !== undefined && p.team === team) updateObject(this.scorers, p);
  249.     }
  250.     updateAssisters(p, team){
  251.         if (p !== undefined && p.team === team) updateObject(this.assisters, p);
  252.     }
  253.     updateOwnScorers(p, team){
  254.         if (p.team !== team) updateObject(this.ownScorers, p);
  255.     }
  256.  
  257.     updateRedTeam(){
  258.         this.redTeam = room.getPlayerList().filter(player => player.team === 1);
  259.     }
  260.     updateBlueTeam(){
  261.         this.blueTeam = room.getPlayerList().filter(player => player.team === 2);
  262.     }
  263.     updateOvertime(){
  264.         this.isOvertime = true;
  265.     }
  266.     sumMatch(p){
  267.         if (lastMatchSumUp.length === 0) return;
  268.         let last_match = lastMatchSumUp.length - 1;
  269.         let last_match_length = lastMatchSumUp[last_match].length;
  270.         for (var i = 0; i < last_match_length; i++){
  271.             room.sendChat(lastMatchSumUp[last_match][i], p.id);
  272.         }
  273.     }
  274.  
  275. }
  276.  
  277.  
  278.  
  279. class GameControl {
  280.     constructor(radiusBall) {
  281.         this.radiusBall = radiusBall || 10;
  282.         this.triggerDistance = this.radiusBall + 15 + 0.1;
  283.         this.currentBallOwner = "";
  284.         this.lastBallOwners = ["", ""]; /* [name: name] */
  285.         this.passesInARow = {"red": 0, "blue": 0}; /* {team: max} */
  286.         this.maxPassesInARow = 0;
  287.         this.redPoss = 0;
  288.         this.bluePoss = 0;
  289.         this.smth = "";
  290.     }
  291.     resetBallOwner(){
  292.         this.currentBallOwner = "";
  293.         this.lastBallOwners = ["", ""];
  294.     }
  295.     updateBallOwner(){
  296.         var ballPosition = room.getBallPosition();
  297.         var players = room.getPlayerList();
  298.         var distanceToBall;
  299.         for (var i = 0; i < players.length; i++) {
  300.             if (players[i].position != null) {
  301.                 distanceToBall = pointDistance(players[i].position, ballPosition);
  302.                 if (distanceToBall < this.triggerDistance) {
  303.                     this.currentBallOwner = players[i].name;
  304.                 }
  305.             }
  306.         }
  307.     }
  308.     updateLastBallOwners(){
  309.         if (this.currentBallOwner !== "" &&
  310.             this.currentBallOwner !== this.lastBallOwners[0]){
  311.  
  312.             this.lastBallOwners[1] = this.lastBallOwners[0];
  313.             this.lastBallOwners[0] = this.currentBallOwner; // last player who touched the ball
  314.         }
  315.     }
  316.     updatePassesInARow(){
  317.         if (gameStats.redTeam.length !== gameStats.blueTeam.length ||
  318.             gameStats.redTeam.length < 2) return;
  319.  
  320.         if (this.lastBallOwners[1] !== "" && this.smth !== this.currentBallOwner){
  321.  
  322.             if (Stats[this.lastBallOwners[0]].team ===
  323.                 Stats[this.lastBallOwners[1]].team){
  324.  
  325.                 Stats[this.lastBallOwners[1]].goodPasses++;
  326.  
  327.  
  328.                 if (Stats[this.lastBallOwners[0]].team === 1){
  329.                     this.passesInARow.red += 1;
  330.                     this.updateMaxPassesInARow("blue");
  331.                     this.passesInARow.blue = 0;
  332.                 }
  333.                 else {
  334.                     this.passesInARow.blue += 1;
  335.                     this.updateMaxPassesInARow("red");
  336.                     this.passesInARow.red = 0;
  337.  
  338.                 }
  339.             }
  340.             else {
  341.                 Stats[this.lastBallOwners[1]].badPasses++;
  342.             }
  343.  
  344.             this.smth = this.currentBallOwner;
  345.         }
  346.     }
  347.     updateMaxPassesInARow(team){
  348.         this.maxPassesInARow = this.passesInARow[team] > this.maxPassesInARow ?
  349.             this.passesInARow[team] : this.maxPassesInARow;
  350.     }
  351. }
  352.  
  353.  
  354. class Records {
  355.     constructor() {
  356.         this.bestPassesInARow = 0;
  357.         this.bestAccuracy = "";
  358.         this.bestStreak = {}; /*{[team]: score};*/
  359.         this.fastestWin = 0;
  360.         this.longestMatch = 0;
  361.     }
  362.     updateBestPassesInARow(){
  363.         this.bestPassesInARow = this.maxPassesInARow > this.bestPassesInARow ?
  364.             this.passesInARow : this.bestPassesInARow;
  365.  
  366.     }
  367. }
  368.  
  369. class ELO {
  370.     constructor() {
  371.         this.redAverage = 0;
  372.         this.blueAverage = 0;
  373.         this.redChanceToWin = 0;
  374.         this.blueChanceToWin = 0;
  375.         this.redRating = 0;
  376.         this.blueRating = 0;
  377.     }
  378.     getAverageRank(team){
  379.         let average = 0;
  380.         for (var i = 0; i < team.length; i++) {
  381.             average += Stats[team[i].name].elo;
  382.         }
  383.         return average / team.length;
  384.     }
  385.     updateTeamAverages(){
  386.         this.redAverage = this.getAverageRank(gameStats.redTeam);
  387.         this.blueAverage = this.getAverageRank(gameStats.blueTeam);
  388.     }
  389.     updateChancesToWin(){
  390.         this.redChanceToWin = 1 / ( 1 + Math.pow(10, (this.blueAverage - this.redAverage) / 400));
  391.         this.blueChanceToWin = 1 / ( 1 + Math.pow(10, (this.redAverage - this.blueAverage) / 400));
  392.     }
  393.     updateRating(rwin, bwin){
  394.         this.redRating = Math.round(32 * (rwin - this.redChanceToWin));
  395.         this.blueRating = Math.round(32 * (bwin - this.blueChanceToWin));
  396.     }
  397.     handleEloCalc(){
  398.         this.updateTeamAverages();
  399.         this.updateChancesToWin();
  400.     }
  401.     updateElo(){
  402.         if (gameStats.redTeam.length === gameStats.blueTeam.length){
  403.             let winners = gameStats.redScore > gameStats.blueScore;
  404.             let pr, pb;
  405.             this.updateRating(winners, !winners);
  406.             for (var i = 0; i < gameStats.redTeam.length; i++) {
  407.                 pr = gameStats.redTeam[i].name;
  408.                 pb = gameStats.blueTeam[i].name;
  409.  
  410.                 Stats[pr].elo += this.redRating;
  411.                 Stats[pb].elo += this.blueRating;
  412.             }
  413.         }
  414.     }
  415. }
  416.  
  417. /**************************************************************
  418. * ************************** ADMINS    ************************
  419. ***************************************************************/
  420.  
  421. var headAdminsAuths = {
  422.     "NzfxVorXRRJsvwtJdwCOhKkdoQxvKk_e-HOXVtMkaC0": "Mona1",
  423.     "FD7dcGdmO0W4TdrP7T6m57xzcFtoDl05MOu5sxHdwx0": "Kang1",
  424.  
  425.  
  426. };
  427.  
  428. var roomAdminsAuth = {
  429.     "NzfxVorXRRJsvwtJdwCOhKkdoQxvKk_e-HOXVtMkaC0": "Mona1",
  430.     "FD7dcGdmO0W4TdrP7T6m57xzcFtoDl05MOu5sxHdwx0": "Kang1",
  431.     "dOKIGfR8z70iF3KxsXS5zNkvg1Xaj-fC4ocgX9JrtNQ": "Common",
  432.     "D2BOPzz1QJg0KOco6LHgPVwgrbZdCMjDC3AsVxswaMM": "DbK1"
  433.  
  434. };
  435.  
  436.  
  437. function getRandomInt(max) {
  438.   return Math.floor(Math.random() * Math.floor(max));
  439. }
  440.  
  441.  
  442. var adminSelect = ["goals", "assists", "cs", "wins", "elo", "bestStreak", "minsPlayed", "money"];
  443.  
  444.  
  445. function updateAdmins() {
  446.     var players = room.getPlayerList().filter((player) => player.id != 0);
  447.     var admins = room.getPlayerList().filter((player) => player.id != 0 && player.admin == false);
  448.     if (players.length == 0 || admins.length == 0 || players.length - admins.length >= 2) return;
  449.     let select = adminSelect[getRandomInt(adminSelect.length - 1)];
  450.  
  451.     admins.sort(function(a, b){
  452.         return Stats[b.name][select] - Stats[a.name][select];
  453.     });
  454.     room.setPlayerAdmin(admins[0].id, true);
  455.  
  456. }
  457.  
  458. function updateSelectedAdmins(){
  459.     var players = room.getPlayerList().filter((p) => p.id != 0 && p.admin === true);
  460.     for (var i = 0; i < players.length; i++) {
  461.         room.setPlayerAdmin(players[i].id,
  462.             Stats[players[i].name].isTrustedAdmin >= 1);
  463.     }
  464. }
  465.  
  466.  
  467. function superAdmin(p){
  468.     if (headAdminsAuths.hasOwnProperty(Stats[p.name].auth)){
  469.         var players = room.getPlayerList().filter((p) => p.admin === true);
  470.         for (var i = 0; i < players.length; i++) {
  471.             room.setPlayerAdmin(players[i].id,
  472.                 Stats[players[i].name].isTrustedAdmin >= 1);
  473.         }
  474.         room.setPlayerAdmin(p.id, true);
  475.         Stats[p.name].isTrustedAdmin = 3;
  476.         room.sendChat("You got level 3 admin ! ", p.id);
  477.     }
  478.     return false;
  479. }
  480.  
  481. function getAdmin(p, m){
  482.     if (roomAdminsAuth.hasOwnProperty(Stats[p.name].auth)){
  483.         room.setPlayerAdmin(p.id, true);
  484.         Stats[p.name].isTrustedAdmin = 1;
  485.         room.sendChat("You got level 1 admin ! ", p.id);
  486.     }
  487.     return false;
  488. }
  489.  
  490. function getAdmin2(p, m){
  491.     if (headAdminsAuths.hasOwnProperty(Stats[p.name].auth)){
  492.         room.setPlayerAdmin(p.id, true);
  493.         Stats[p.name].isTrustedAdmin = 2;
  494.         room.sendChat("You got level 2 admin ! ", p.id);
  495.     }
  496.     return false;
  497. }
  498.  
  499. function addAdmin(p, m){
  500.     if (Stats[p.name].isTrustedAdmin >= 2){
  501.         m = m.substr("!addadmin".length + 1);
  502.         roomAdminsAuth[Stats[m].auth] = m;
  503.         room.sendChat("Succes.", p.id);
  504.     }
  505.     return false;
  506. }
  507.  
  508.  
  509. /**************************************************************
  510. * ************************** ANTI SPAM ************************
  511. * Function to call: handleSpam in room.onPlayerChat with
  512. * lastWriters and player as argument.
  513. * Purpose: This will kick a player after he talks 5 times
  514. *   in a row.
  515. * Based on: player's id.
  516. * To change the number of chats allowed in a row, change the
  517. *   const MAX_CHAT_IN_A_ROW to what you want.
  518. * Global variables used:
  519. *   lastWriters (array of int)
  520. *   const int MAX_CHAT_IN_A_ROW
  521. *   const string KICK_MESSAGE_SPAM
  522. ***************************************************************/
  523. var lastWriters = [];
  524. const MAX_CHAT_IN_A_ROW = 5;
  525. const KICK_MESSAGE_SPAM = "Stop spamming! Thanks.";
  526.  
  527. /**************************************************************
  528. * Function returning how much time the last player who wrote
  529. * in chat has previously written.
  530. ***************************************************************/
  531.  
  532. function checkSpam(lastWriters, p){
  533.     let c = 0;
  534.     for (var i = 0; i < lastWriters.length; i++){
  535.         c += lastWriters[i] === p.id;
  536.     }
  537.     return c;
  538. }
  539.  
  540. /**************************************************************
  541. * Function updating the array by deleting the first element
  542. * and adding the last player who talked.
  543. ***************************************************************/
  544. function updateLastWriters(lastWriters, p){
  545.     lastWriters.splice(0, 1);
  546.     lastWriters.push(p.id);
  547.  
  548. }
  549.  
  550. /**************************************************************
  551. * Function updating the array and kicking a spammer with the
  552. * message KICK_MESSAGE_SPAM.
  553. * When the array's length is smaller than MAX_CHAT_IN_A_ROW
  554. * (so at the beginning of a room) it doesnt check spam
  555. * but simply fills it.
  556. ***************************************************************/
  557.  
  558.  
  559. function handleSpam(lastWriters, p){
  560.     if (lastWriters.length === MAX_CHAT_IN_A_ROW){
  561.         updateLastWriters(lastWriters, p);
  562.         let res = checkSpam(lastWriters, p);
  563.  
  564.         if (res === MAX_CHAT_IN_A_ROW){
  565.             room.kickPlayer(p.id, KICK_MESSAGE_SPAM, 0);
  566.         }
  567.     }
  568.     else {
  569.         lastWriters.push(p.id);
  570.     }
  571. }
  572.  
  573.  
  574. /**************************************************************
  575. * ************************** SWAP *****************************
  576. * Function to call: swap
  577. * If it's used as a command, the parameter has to be an admin player.
  578. * Otherwise this function can just be called with no param to work.
  579. * This function put the red (resp blue) team into blue (resp red).
  580. * Global variable used: None.
  581. ***************************************************************/
  582.  
  583.  
  584. function swap(player){
  585.     if (player === undefined || player.admin){
  586.         var p = room.getPlayerList().filter((player) => player.id != 0);
  587.         for (let i = 0; i < p.length; i++){
  588.             if (p[i].team !== 0){
  589.                 room.setPlayerTeam(p[i].id, 1 + (p[i].team === 1));
  590.             }
  591.         }
  592.     }
  593. }
  594.  
  595.  
  596. /**************************************************************
  597. * ************************** PM *******************************
  598. * Function to call: sendPM.
  599. * Use: @player [message]
  600. * This function will send a private message to the player.
  601. * Global variable used: None.
  602. ***************************************************************/
  603.  
  604. function sendPM(p, m){
  605.     if (m.startsWith("@") === true){
  606.         let spacePos = m.search(" ");
  607.         let name = m.substr(1, spacePos !== -1 ? spacePos - 1: m.length);
  608.         let dest = room.getPlayerList().filter((p) => p.name === name);
  609.         if (dest.length !== 0){
  610.             m = m.substr(spacePos, m.length);
  611.             room.sendChat("PM from " + p.name + ": " + m, dest[0].id);
  612.         }
  613.         return false;
  614.     }
  615.     return true;
  616. }
  617.  
  618. /**************************************************************
  619. * ************************** Resets ****************************
  620. * Functions to call: reset and resetWithSwap.
  621. * If it's used as a command, the parameter has to be an admin player.
  622. * Otherwise this function can just be called with no param to work.
  623. * These functions allow to reset the game by typing !rr
  624. * And to reset the game by switching teams by typing !rrs
  625. * Global variables used: None
  626. ***************************************************************/
  627.  
  628. function reset(p){
  629.     if (p === undefined || p.admin === true){
  630.         room.stopGame();
  631.         room.startGame();
  632.     }
  633. }
  634.  
  635. function resetWithSwap(p){
  636.     if (p === undefined || p.admin === true){
  637.         room.stopGame();
  638.         swap();
  639.         room.startGame();
  640.     }
  641. }
  642. function resetWithTop(p){
  643.     if (p === undefined || p.admin === true){
  644.         room.stopGame();
  645.         let specs = room.getPlayerList().filter((p) => p.id !== 0 && p.team === 0);
  646.         if (specs.length !== 0){
  647.             room.setPlayerTeam(specs[0], p.team === 1 ? 2 : 1);
  648.         }
  649.         room.startGame();
  650.     }
  651. }
  652.  
  653. /**************************************************************
  654. * ************************** ACCOUNT **************************
  655. * Function to call: almost all of theses are commands.
  656. * These functions will simulate a way to have an account in the room.
  657. * To further details, read the documentation of each function.
  658. * There can be only one account per nickname.
  659. * Global variables used: Stats {name: p | p € class Player }
  660. ***************************************************************/
  661. var Stats = {};
  662. const saveStatsName = "Players_stats";
  663. var saveStatsN = 0;
  664. function loadStats(){
  665.     if (localStorage.getItem(saveStatsName + saveStatsN)){
  666.         let all = JSON.parse(localStorage.getItem(saveStatsName + saveStatsN));
  667.         let noms = Object.keys(all);
  668.         for (let i = 0; i < noms.length; i++){
  669.             Stats[noms[i]] = new Player(noms[i]);
  670.             Object.assign(Stats[noms[i]], all[noms[i]]);
  671.         }
  672.     }
  673. }
  674.  
  675.  
  676. function saveStatsFun(){
  677.     var val = JSON.stringify(Stats);
  678.     window.localStorage.setItem(saveStatsName + saveStatsN, val);
  679. }
  680.  
  681.  
  682. function deleteStatsFun(){
  683.     saveStatsN++;
  684.     Stats = {};
  685. }
  686.  
  687.  
  688. /**************************************************************
  689. * Function creating a new account for the player if this nick
  690. * never been to the room.
  691. * Also logs him and get his current id.
  692. ***************************************************************/
  693. function autoConnect(p){
  694.     if (Stats.hasOwnProperty(p.name) === false){
  695.         Stats[p.name] = new Player(p.name);
  696.         Stats[p.name].auth = p.auth;
  697.     }
  698.     else {
  699.         if (Stats[p.name].auth != 0 && p.auth !== Stats[p.name].auth){
  700.             Stats[p.name].price = 1;
  701.             room.sendChat("Your stats won't count because this nick is already taken by someone with a different id", p.id);
  702.         }
  703.         else if (Stats[p.name].auth == 0){
  704.             Stats[p.name].auth = p.auth;
  705.         }
  706.     }
  707.     Stats[p.name].logged = 1;
  708.     Stats[p.name].id = p.id;
  709.     Stats[p.name].conn = p.conn;
  710. }
  711.  
  712.  
  713.  
  714. function stats(p, m){
  715.     m = m.substr("!stats".length + 1);
  716.     if (Stats.hasOwnProperty(m)){
  717.         Stats[m].displayStats(p.id);
  718.     }
  719.     else {
  720.         room.sendChat("This player is not in our database.", p.id);
  721.     }
  722.     return false;
  723. }
  724.  
  725.  
  726. var msg_to_command = {
  727.     "goals": "goals",
  728.     "assists": "assists",
  729.     "og": "ownGoals",
  730.     "cs": "cs",
  731.     "wins": "wins",
  732.     "losses": "loses",
  733.     "wl": "winsRatio",
  734.     "passacc": "passAcc",
  735.     "elo": "elo",
  736.     "gpg": "goalsPG",
  737.     "apg": "assistsPG",
  738.     "cspg": "csPG",
  739.     "streak": "bestStreak",
  740.     "mins": "minsPlayed",
  741.     "efcoins": "money",
  742. };
  743.  
  744.  
  745.  
  746.  
  747. function bestRanks(message){
  748.     if (!msg_to_command.hasOwnProperty(message))
  749.         return "This option does not exist (yet ?), sorry :(. See !rankhelp to further infos.";
  750.  
  751.     let cmd = msg_to_command[message];
  752.     let names = Object.keys(Stats);
  753.     let score;
  754.     let string = "";
  755.     let overall = [];
  756.     for (var i = 0; i < names.length; i++) {
  757.         if (!Stats.hasOwnProperty(names[i])) continue;
  758.         score = Stats[names[i]][cmd];
  759.         if (score === 1000 || score === 0 ||
  760.             (Stats[names[i]].wins + Stats[names[i]].loses) < 10) continue;
  761.  
  762.         overall.push({name: names[i], value: score});
  763.     }
  764.     overall.sort(function(a,b){
  765.         return b.value - a.value;
  766.     });
  767.     for (i = 0; i < overall.length; i++) {
  768.         string += i + 1 + ") " + overall[i].name + ": " + overall[i].value + " | ";
  769.     }
  770.     return string;
  771. }
  772.  
  773.  
  774.  
  775. function ranking(p, m){
  776.     let string = bestRanks(m.substr("!rank".length + 1));
  777.     let line1 = string.substring(0, 120);
  778.     let line2 = string.substring(120, 240);
  779.     let line3 = string.substring(240, 360);
  780.     room.sendChat(line1, p.id);
  781.     room.sendChat(line2, p.id);
  782.     room.sendChat(line3, p.id);
  783.     return false;
  784. }
  785.  
  786. /**************************************************************
  787. * Function as a command: !bb
  788. * Kicks the player from the room with disconnecting him
  789. * (the disconnect thing is pretty useless since it is caught
  790. * in the onPlayerLeave anyway).
  791. ***************************************************************/
  792. function bb(p){
  793.     Stats[p.name].disconnect();
  794.     room.kickPlayer(p.id, "rip !", false);
  795. }
  796.  
  797.  
  798. /**************************************************************
  799. * ************************** MUTE ****************************
  800. * Global variable used: None
  801. ***************************************************************/
  802. function mute(p, m){
  803.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  804.         m = m.substr("!mute".length + 1);
  805.         if (Stats.hasOwnProperty(m)) {
  806.             Stats[m].isMuted = 1;
  807.             room.sendChat(m + " has been muted by " + p.name);
  808.         }
  809.     }
  810.     return false;
  811. }
  812.  
  813. function muteById(p, m){
  814.     m = idToName(m.substr("!muteid".length + 1));
  815.     return mute(p, "!mute " + m);
  816. }
  817.  
  818.  
  819. function unmute(p, m){
  820.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  821.         m = m.substr("!unmute".length + 1);
  822.         if (Stats.hasOwnProperty(m)) {
  823.             Stats[m].isMuted = 0;
  824.             room.sendChat(m + " has been unmuted by " + p.name);
  825.             room.sendChat(m + " has been unmuted by " + p.name, Stats[m].id);
  826.         }
  827.     }
  828.     return false;
  829. }
  830.  
  831. function unmuteById(p, m){
  832.     m = idToName(m.substr("!unmuteid".length + 1));
  833.     return unmute(p, "!unmute " + m);
  834. }
  835.  
  836. function muteAll(p, m){
  837.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  838.         var players = room.getPlayerList().filter((pl) => pl.admin === false &&
  839.             pl.team === 0);
  840.         for (var i = 0; i < players.length; i++) {
  841.  
  842.             Stats[players[i].name].isMuted = 1;
  843.         }
  844.         room.sendChat("All non-admins specs have been muted");
  845.     }
  846. }
  847.  
  848. function resetMutes(p){
  849.     if (p === undefined || p.admin === true){
  850.         var players = room.getPlayerList();
  851.         for (var i = 1; i < players.length; i++) {
  852.             Stats[players[i].name].isMuted = 0;
  853.         }
  854.     }
  855.     return false;
  856. }
  857.  
  858. /**************************************************************
  859. * ************************** BANS ****************************
  860. * Function to call: almost all of theses are commands.
  861. * These functions are set in order to ban toxic people.
  862. * This includes simple bans, simple clearing bans but also
  863. * permaban that can be only disabled by the vps owner.
  864. * In order to make this last feature work, room.clearBans is
  865. * never used.
  866. * Global variables used: None.
  867. ***************************************************************/
  868.  
  869. function permaBan(p, m){
  870.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 2){
  871.  
  872.         m = m.substr("!permaban".length + 1);
  873.         if (Stats.hasOwnProperty(m) === true){
  874.             room.sendChat(m + " has been banned permanently !");
  875.             Stats[m].isBanned = true;
  876.             Stats[m].isPermaBanned = 1;
  877.             room.kickPlayer(Stats[m].id, "You have been permanently banned", 1);
  878.         }
  879.     }
  880.     else {
  881.         room.sendChat("PM from Host: Only trusted admin with the level 3 or higher are allowed to permaban.", p.id);
  882.     }
  883.     return false;
  884.  
  885. }
  886.  
  887.  
  888. function idToName(m){
  889.     if (!m.isNaN){
  890.         let player = room.getPlayer(m);
  891.         if (player !== null)
  892.             return player.name;
  893.     }
  894.     return m;
  895. }
  896.  
  897. function permaBanById(p, m){
  898.     m = idToName(m.substr("!permabanid".length + 1));
  899.     return permaBan(p, "!permaban " + m);
  900. }
  901.  
  902.  
  903. function unbanAll(player){
  904.     if (player === undefined || Stats[player.name].isTrustedAdmin >= 1){
  905.         for (var p in Stats) {
  906.             if (Stats.hasOwnProperty(p) && Stats[p].isBanned === true &&
  907.                 Stats[p].isPermaBanned === 0) {
  908.  
  909.                 room.clearBan(Stats[p].id);
  910.                 Stats[p].isBanned = 0;
  911.             }
  912.         }
  913.         room.sendChat("PM from Host: Bans have been cleared.");
  914.     }
  915.     return false;
  916. }
  917.  
  918. function unbanPlayer(p, m){
  919.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  920.         m = m.substr("!unban".length + 1);
  921.         if (Stats.hasOwnProperty(m) === true){
  922.             room.clearBan(Stats[m].id);
  923.             room.sendChat(m + " is free now !", p.id);
  924.             Stats[m].isBanned = 0;
  925.         }
  926.     }
  927.     return false;
  928. }
  929.  
  930.  
  931. var ragequitAuth = {};
  932.  
  933. function preventPlaying(p){
  934.     if (Stats[p.name].kickedSomeone > 0 && p.team != 0){
  935.         room.sendChat("This player must wait " +
  936.             Stats[p.name].kickedSomeone + " more mins to play.");
  937.         room.setPlayerTeam(p.id, 0);
  938.     }
  939.     else {
  940.         Stats[p.name].kickedSomeone = 0;
  941.     }
  942. }
  943.  
  944. function decreaseRqTime(){
  945.     let players = room.getPlayerList().filter((p) => Stats[p.name].kickedSomeone != 0);
  946.     for (var i = 0; i < players.length; i++) {
  947.         Stats[players[i].name].kickedSomeone--;
  948.     }
  949. }
  950.  
  951.  
  952.  
  953.  
  954. /**************************************************************
  955. * ********************* MISC COMMANDS *************************
  956. * Miscellaneous functions related to some pretty commands.
  957. * Global variable used: None.
  958. ***************************************************************/
  959.  
  960. /**************************************************************
  961. * Function displaying help in 2 lines in pm to the player.
  962. ***************************************************************/
  963. function helpFun(p){
  964.     var help_string1 = "| !stats [nickname] | !rank [arg] | !rankhelp | !bethelp";
  965.     var help_string2 = "| !bb | !swap | !rr | !rrs | !msup | @nickname pm | !discord | !disp";
  966.     room.sendChat(help_string1, p.id);
  967.     room.sendChat(help_string2, p.id);
  968.     return false;
  969. }
  970.  
  971.  
  972. function rankHelp(p){
  973.     room.sendChat("Type rank + one options among: ", p.id);
  974.     room.sendChat(Object.keys(msg_to_command).join(" | "), p.id);
  975.     return false;
  976. }
  977.  
  978. function betHelp(p){
  979.     room.sendChat("πŸ’°πŸ’° You can win HAXCOINS by betting on a team ! πŸ’°πŸ’°", p.id);
  980.     room.sendChat("πŸ’°πŸ’° use !betwin [team] [haxcoins], Ex: !betwin r 20 or !betwin b 20 πŸ’°πŸ’°", p.id);
  981.     room.sendChat("πŸ’°πŸ’° You can only bet when a match started and before it reaches 20s. πŸ’°πŸ’°", p.id);
  982.     room.sendChat("πŸ’°πŸ’° If your bet is correct, you earn the same ammount of efcoins you've bet, Otherwise, you lose it πŸ’°πŸ’°", p.id);
  983.     return false;
  984. }
  985.  
  986.  
  987. /**************************************************************
  988. * Function displaying the sum up of the last match in pm.
  989. ***************************************************************/
  990. function sumMatchCommand(p){
  991.     gameStats.sumMatch(p);
  992.     return false;
  993. }
  994.  
  995.  
  996. function givesDiscord(p){
  997.     room.sendChat("https://discord.gg/jTn2ZDp", p.id);
  998. }
  999.  
  1000.  
  1001. let display = {
  1002.     "admin": ["isTrustedAdmin", 1],
  1003.     "mute": ["isMuted", true]
  1004. };
  1005.  
  1006. function displayHere(p, m){
  1007.     m = m.substr("!disp".length + 1);
  1008.     if (display.hasOwnProperty(m)){
  1009.         let players = room.getPlayerList().filter((player) => player.id != 0);
  1010.         let string = "PM from Host: ";
  1011.         for (var i = 0; i < players.length; i++) {
  1012.             if (Stats[players[i].name][m[0]] >= m[1])
  1013.                 string += players[i].name + " | ";
  1014.         }
  1015.         room.sendChat(string, p.id);
  1016.     }
  1017.     else {
  1018.         room.sendChat("PM from Host: This arg does not exist, maps: " +
  1019.             Object.keys(display).join(" | "), p.id);
  1020.     }
  1021.     return false;
  1022.  
  1023. }
  1024.  
  1025.  
  1026. function disconnectAll(){
  1027.     for (let e in Stats){
  1028.         if (Stats.hasOwnProperty(e) && Stats[e].logged != 0){
  1029.             Stats[e].logged = 0;
  1030.             Stats[e].isTrustedAdmin = 0;
  1031.         }
  1032.     }
  1033.  
  1034.  
  1035. }
  1036.  
  1037. function addPassword(p, m){
  1038.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  1039.         m = m.substr("!addpw".length + 1);
  1040.         room.setPassword(m);
  1041.         room.sendChat(m + " is the new pw of the room", p.id);
  1042.     }
  1043.     return false;
  1044. }
  1045.  
  1046. function rmPassword(p){
  1047.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  1048.         room.setPassword();
  1049.         room.sendChat("The password have been cleared", p.id);
  1050.     }
  1051.     return false;
  1052. }
  1053.  
  1054.  
  1055. function changeMaps(p, m){
  1056.     if (p === undefined || p.admin === true){
  1057.         m = m.substr("!map".length + 1);
  1058.         if (maps.hasOwnProperty(m)){
  1059.             room.setCustomStadium(maps[m]);
  1060.             return false;
  1061.         }
  1062.         room.sendChat("PM from Host: This map does not exist, maps: " +
  1063.             Object.keys(maps).join(" | "), p.id);
  1064.     }
  1065. }
  1066.  
  1067. function downloadBlob(fileName) {
  1068.     let mimeType = 'application/octet-stream';
  1069.     let data = room.stopRecording();
  1070.     let blob = new Blob([data], {type: mimeType});
  1071.     let url = window.URL.createObjectURL(blob);
  1072.     downloadURL(url, fileName);
  1073.     setTimeout(function() {
  1074.         return window.URL.revokeObjectURL(url);
  1075.     }, 1000);
  1076. }
  1077.  
  1078. function downloadURL(data, fileName) {
  1079.     let elem = document.createElement('elem');
  1080.     elem.href = data;
  1081.     elem.download = fileName;
  1082.     document.body.appendChild(elem);
  1083.     elem.style = 'display: none';
  1084.     elem.click();
  1085.     elem.remove();
  1086. }
  1087.  
  1088. function recGameFun(player){
  1089.     if (gameStats.rec === true){
  1090.         room.sendChat("Last game has already been recorded by someone." +
  1091.             "Contact us to get a copy of it", player.id);
  1092.     }
  1093.     else {
  1094.         let date = new Date();
  1095.         let month = (date.getMonth + 1);
  1096.         let recname = "haxrec_" + date.getDate() + "_"  +
  1097.             "_" + date.getFullYear() + "_" + date.getHours() + "H" +
  1098.             date.getMinutes() + "m.hbr2";
  1099.  
  1100.         downloadBlob(recname);
  1101.         room.sendChat("Game saved as " + recname +
  1102.             " . Contact us on Discord to get a copy.", player.id);
  1103.         gameStats.rec = true;
  1104.     }
  1105. }
  1106.  
  1107. var Alts = {}; //{conn: [name1, ..., nameN]}
  1108.  
  1109. function getAlts(p, m){
  1110.     m = m.substr("!getalts".length + 1);
  1111.     if (Stats.hasOwnProperty(m))
  1112.         room.sendChat("PM from Host: Alts: " + Alts[Stats[m].conn].join(" | "), p.id);
  1113.     return false;
  1114. }
  1115.  
  1116. function stringBet(p, team, bet, team_msg){
  1117.     Stats[p.name].winPred = team;
  1118.     Stats[p.name].currentBet = Number(bet);
  1119.     room.sendChat("PM from Host: You've bet " + bet + " EFCOINS on " +
  1120.         team_msg +  " team ! ", p.id);
  1121. }
  1122.  
  1123. function betOnTeam(p, m){
  1124.     m = m.substr("!betwin".length + 1);
  1125.     let bet = m.substr(2);
  1126.     m = m.substr(0, 1);
  1127.     let score = room.getScores();
  1128.     let team = ["r", "b"];
  1129.     if (!isNaN(bet) && bet >= 0 && bet <= Stats[p.name].money &&
  1130.         Stats[p.name].currentBet === 0 && team.includes(m) &&
  1131.         score != null && score.time < 20 && p.team === 0 &&
  1132.         gameStats.redTeam.length >= 3 && gameStats.blueTeam.length >= 3){
  1133.  
  1134.         stringBet(p, 1 * (m == "r") || 1 + (m == "b"), bet, m == "r" ? "red" : "blue");
  1135.     }
  1136.     else {
  1137.         room.sendChat("PM from Host: You have to put this specific format: ", p.id);
  1138.         room.sendChat("PM from Host: !betwin r X or !betwin b X", p.id);
  1139.         room.sendChat("PM from Host: where r and b are the team X is the ammount of haxcoins you want to bet. ", p.id);
  1140.     }
  1141.     return false;
  1142. }
  1143.  
  1144.  
  1145. function checkFake(p, m){
  1146.     m = m.substr("!check".length + 1);
  1147.     if (Stats.hasOwnProperty(m)){
  1148.         m = Stats[m].price ? "is" : "is not";
  1149.         room.sendChat("PM From Host: This player " + msg + " a fake.");
  1150.     }
  1151. }
  1152.  
  1153. var commands = {
  1154.     "!swag": swap,
  1155.     "!rr": reset,
  1156.     "!rrz": resetWithSwap,
  1157.     //"!rrt": resetWithTop,
  1158.     "!bb": bb,
  1159.     "!msup": sumMatchCommand,
  1160.     "!discord": givesDiscord,
  1161.     "!help": helpFun,
  1162.     "!rankhelp": rankHelp,
  1163.     "!disp": displayHere,
  1164.     "!stats": stats,
  1165.     "!rank": ranking,
  1166.     //"!changepw": changePW,
  1167.  
  1168.     "!mute": mute,
  1169.     "!muteid": muteById,
  1170.     "!muteall": muteAll,
  1171.     "!unmute": unmute,
  1172.     "!unmuteid": unmuteById,
  1173.     "!unmuteall": resetMutes,
  1174.     "!unban": unbanPlayer,
  1175.     "!unbanall": unbanAll,
  1176.     "!permaban": permaBan,
  1177.     "!permabanid": permaBanById,
  1178.     "!e": superAdmin,
  1179.     "!admin": getAdmin,
  1180.     "!admin2": getAdmin2,
  1181.     "!addadmin": addAdmin,
  1182.     "!map": changeMaps,
  1183.     "!addpw": addPassword,
  1184.     "!rmpw": rmPassword,
  1185.     "!getalts": getAlts,
  1186.     "!rec": recGameFun,
  1187.     "!betwin": betOnTeam,
  1188.     "!bethelp": betHelp,
  1189.     "!banall": banall
  1190.     "!check": checkFake,
  1191. };
  1192.  
  1193.  
  1194. function handleCommands(p, m){
  1195.     let spacePos = m.search(" ");
  1196.     let command = m.substr(0, spacePos !== -1 ? spacePos : m.length);
  1197.     if (commands.hasOwnProperty(command) === true) return commands[command](p, m);
  1198.     if (m.startsWith("!") === true) {
  1199.         room.sendChat("PM from Host: This is not an existing command, write !help if needed !", p.id);
  1200.         return false;
  1201.     }
  1202.     return true;
  1203. }
  1204.  
  1205.  
  1206. function handleStart(){
  1207.     gameStats.updateRedTeam();
  1208.     gameStats.updateBlueTeam();
  1209.     handleTeams();
  1210.     elo.handleEloCalc();
  1211.     room.stopRecording();
  1212.     room.startRecording();
  1213.     room.sendChat("πŸ’°πŸ’° Who will win this game ? You have 20s to place your bet and get rich πŸ’°πŸ’°! See !bethelp for more info.");
  1214. }
  1215.  
  1216.  
  1217. function handleTimePlayed(){
  1218.     var players = room.getPlayerList();
  1219.     for (var i = 1; i < players.length; i++){
  1220.         Stats[players[i].name].updateSecsPlayed();
  1221.         Stats[players[i].name].updateMinsPlayed();
  1222.     }
  1223. }
  1224.  
  1225.  
  1226.  
  1227. function handleGoals(team){
  1228.     var time = room.getScores().time;
  1229.     var m = Math.trunc(time / 60);
  1230.     var s = Math.trunc(time % 60);
  1231.     let string;
  1232.     let assister = "";
  1233.  
  1234.     time = m + ":" + (s < 10 ? "0" + s : s); // MM:SS format
  1235.     gameStats.updateScore(team);
  1236.  
  1237.     gameStats.updateScorers(Stats[gameControl.currentBallOwner], team);
  1238.     gameStats.updateOwnScorers(Stats[gameControl.currentBallOwner], team);
  1239.     gameStats.updateAssisters(Stats[gameControl.lastBallOwners[1]], team);
  1240.  
  1241.     if (Stats.hasOwnProperty(gameControl.lastBallOwners[1]) &&
  1242.         (Stats[gameControl.lastBallOwners[1]].team ===
  1243.         Stats[gameControl.lastBallOwners[0]].team)){
  1244.  
  1245.         assister = gameControl.lastBallOwners[1];
  1246.     }
  1247.  
  1248.  
  1249.     if (team === Stats[gameControl.currentBallOwner].team){
  1250.         string = "⚽ Scorer: " + gameControl.lastBallOwners[0] + "| Assister: " +
  1251.             assister + "| at " + time;
  1252.         room.sendChat(string);
  1253.     }
  1254.     else {
  1255.         string = "Own goal from: " + gameControl.lastBallOwners[0] + "| at " + time;
  1256.         room.sendChat(string);
  1257.     }
  1258.     gameStats.matchsumup.push(string);
  1259.     gameControl.resetBallOwner();
  1260.  
  1261. }
  1262.  
  1263. function handleTeams(){
  1264.     var p = room.getPlayerList();
  1265.     for (var i = 1; i < p.length; i++) {
  1266.         Stats[p[i].name].team = p[i].team;
  1267.     }
  1268. }
  1269.  
  1270. function handleGk(){
  1271.     if (gameStats.hasStarted === false){
  1272.         if (room.getScores().time !== 0){
  1273.            gameStats.hasStarted = true;
  1274.            gameStats.updateGK();
  1275.            room.sendChat("Red GK: " + gameStats.Gks[0] + ", Blue GK: " + gameStats.Gks[1]);
  1276.        }
  1277.     }
  1278. }
  1279.  
  1280. function handleEndGame(){
  1281.     var players = room.getPlayerList().filter((p) => p.id != 0);
  1282.     records.updateBestPassesInARow();
  1283.     elo.updateElo();
  1284.     for (var i = 0; i < players.length; i++){
  1285.         if (Stats[players[i].name].price !== 1){
  1286.             Stats[players[i].name].updateEGStats();
  1287.         }
  1288.     }
  1289. }
  1290.  
  1291. function handleOvertime(){
  1292.     let scores = room.getScores();
  1293.     if (scores !== null && scores.timeLimit !== 0 &&
  1294.         scores.time >= scores.timeLimit){
  1295.  
  1296.         handleEndGame();
  1297.     }
  1298. }
  1299.  
  1300.  
  1301.  
  1302. function handleBans2(kicked, message, ban, by){
  1303.     if (by.id !== 0){
  1304.         if (Stats[by.name].isTrustedAdmin === 0){
  1305.             room.kickPlayer(by.id, "You are not allowed to kick/ban players !", ban);
  1306.             room.clearBan(kicked.id);
  1307.         }
  1308.     }
  1309. }
  1310.  
  1311. function handleBans(kicked, message, ban, by){
  1312.     Stats[kicked.name].gotKicked += by !== null;
  1313.     Stats[kicked.name].isBanned = ban === true;
  1314.     if (by.id !== 0){
  1315.         Stats[by.name].updateKickedSomeone();
  1316.         if (Stats[by.name].kickedSomeone >= 10){
  1317.             Stats[by.name].kickedSomeone = 0;
  1318.             room.kickPlayer(by.id, "You kicked too much people", 1);
  1319.         }
  1320.     }
  1321. }
  1322.  
  1323. function handleRefresh(p){
  1324.  
  1325.  
  1326.     if (Stats.hasOwnProperty(p.name) && Stats[p.name].logged !== 0){
  1327.         if (Stats[p.name].auth === p.auth){
  1328.             room.kickPlayer(Stats[p.name].id, "You just refreshed.", 0);
  1329.         }
  1330.         else {
  1331.             room.kickPlayer(p.id, "This nickname is already taken in the room.", 0);
  1332.         }
  1333.     }
  1334. }
  1335. function handleRefresh2(p){
  1336.     let players = room.getPlayerList();
  1337.     for (var i = 0; i < players.length; i++) {
  1338.         if (Stats[players[i].name].auth === p.auth && Stats[p.name].logged !== 0)
  1339.             room.kickPlayer(Stats[players[i].name].id, "You just refreshed.", 0);
  1340.     }
  1341. }
  1342.  
  1343.  
  1344.  
  1345. function updateSanction(p){
  1346.     if (room.getPlayerList().filter((pl) => pl.name === p.name &&
  1347.         pl.team === p.team).length === 0){
  1348.  
  1349.         let score = gameStats.redScore - gameStats.blueScore;
  1350.         Stats[p.name].kickedSomeone += p.team === 1 && score > 0;
  1351.         Stats[p.name].kickedSomeone += p.team === 2 && score < 0;
  1352.  
  1353.         Stats[p.name].kickedSomeone += 3 * (p.team === 1 && score < 0);
  1354.         Stats[p.name].kickedSomeone += 3 * (p.team === 2 && score > 0);
  1355.  
  1356.         Stats[p.name].kickedSomeone += 2 * (score === 0);
  1357.  
  1358.         Stats[p.name].kickedSomeone *= 5;
  1359.  
  1360.  
  1361.     }
  1362.  
  1363. }
  1364.  
  1365. function handleSanction(p){
  1366.     if (p.team !== 0){
  1367.         setTimeout(updateSanction, 1000 * 20, p);
  1368.     }
  1369. }
  1370.  
  1371. function leaveInGame(p){
  1372.     if (room.getScores() != null && p.team !== 0){
  1373.         room.pauseGame(true);
  1374.     }
  1375. }
  1376.  
  1377. function handleCSMessage(){
  1378.     let str = "";
  1379.     if (gameStats.redScore === 0)
  1380.         str = [gameStats.Gks[1] + " kept a cs for his team"].join();
  1381.     if (gameStats.blueScore === 0)
  1382.         str = [gameStats.Gks[0] + " kept a cs for his team"].join();
  1383.     return str;
  1384. }
  1385.  
  1386.  
  1387. function handleMode(){
  1388.     mode = room.getScores().timeLimit === 7;
  1389. }
  1390.  
  1391.  
  1392.  
  1393. function handleAlts(p){
  1394.     if (Alts.hasOwnProperty(p.conn)){
  1395.         if (!Alts[p.conn].includes(p.name))
  1396.             Alts[p.conn].push(p.name);
  1397.     }
  1398.     else {
  1399.         Alts[p.conn] = [p.name];
  1400.     }
  1401. }
  1402.  
  1403. function handleBans(p){
  1404.     if (Stats[p.name].isBanned != 0)
  1405.         room.kickPlayer(p.id, "You're banned permanently", 1);
  1406. }
  1407.  
  1408. function resetBettings(){
  1409.     let players = room.getPlayerList();
  1410.     for (var i = 0; i < players.length; i++) {
  1411.         Stats[players[i].name].currentBet = 0;
  1412.         Stats[players[i].name].winPred = 0;
  1413.     }
  1414.     room.sendChat("Since the game was stopped, all bets are reseted !");
  1415. }
  1416.  
  1417.  
  1418. function handleStadiumChange(name, by){
  1419.     if (first_stadium_loaded === true){
  1420.         if (by.id != 0){
  1421.             room.kickPlayer(by.id, "Please use !map [stadium] next time !", false);
  1422.             room.setCustomStadium(maps.big);
  1423.         }
  1424.     }
  1425.     else first_stadium_loaded = true;
  1426. }
  1427.  
  1428. function updateStreak(winners){
  1429.     winStreak.score = (winStreak.team == "red" && winners) ||
  1430.         !(winStreak.team == "red" || winners) ? winStreak.score + 1 : 1;
  1431.     winStreak.team = winners ? "red" : "blue";
  1432.  
  1433.     room.sendChat("The current streak is held by " + winStreak.team +
  1434.         " with " + winStreak.score + " wins ! ");
  1435. }
  1436.  
  1437.  
  1438. function banall(p){
  1439.     if (p === undefined || Stats[p.name].isTrustedAdmin >= 1){
  1440.         let players = room.getPlayerList().filter((p) => p.id != 0);
  1441.         if (players.length != 0){
  1442.             for (var i = 0; i < players.length; i++) {
  1443.                 room.kickPlayer(players[i].id, "Be active next time :-)", 0);
  1444.             }
  1445.         }
  1446.     }
  1447.     return false;
  1448. }
  1449.  
  1450. function checkfdps(){
  1451.     if (active.length == 0 && room.getPlayerList().length >= 6){
  1452.         banall();
  1453.     }
  1454.     active = [];
  1455. }
  1456.  
  1457.  
  1458. function getBestRanks(){
  1459.     let string;
  1460.     for (var rank in msg_to_command) {
  1461.         if (msg_to_command.hasOwnProperty(rank)){
  1462.             string = bestRanks(rank);
  1463.             console.log(rank + ": " + string.substring(0, 400));
  1464.         }
  1465.     }
  1466. }
  1467.  
  1468. function resetAuth(name){
  1469.     if (Stats.hasOwnProperty(name))
  1470.         Stats[name].auth = 0;
  1471. }
  1472.  
  1473. function kickLastPlayer(p){
  1474.     if (room.getPlayerList().length === MAX_PLAYERS &&
  1475.         !roomAdminsAuth.hasOwnProperty(p.auth) &&
  1476.         !headAdminsAuths.hasOwnProperty(p.auth)){
  1477.  
  1478.         room.kickPlayer(p.id, "Sorry, this slot is reserved for EFC staff !", 0);
  1479.  
  1480.     }
  1481. }
  1482.  
  1483.  
  1484. function putTeamColor(){
  1485.     room.setTeamColors(1, 45, 0xFFA41C, [0x7A1602, 0x7A1602, 0x571002]);
  1486.     room.setTeamColors(2, 135, 0xFFA41C, [0x1A164A, 0x1A164A, 0x110E30]);
  1487. }
  1488.  
  1489. function spamcolors(team, color){
  1490.     room.setTeamColors(team, 45, color, [color, color, color]);
  1491. }
  1492.  
  1493.  
  1494. function warn4def(team){
  1495.  
  1496.     room.sendChat("You are not applying the 4def rule ! Please be careful");
  1497.     spamcolors(team, 0x000000);
  1498. }
  1499.  
  1500. function check4def(){
  1501.     if (room.getScores() == null) return;
  1502.     let red4def = room.getPlayerList().filter((p) =>
  1503.         p.team == 1 && p.position.x < -386).length;
  1504.  
  1505.     let blue4def = room.getPlayerList().filter((p) =>
  1506.         p.team == 2 && p.position.x > 386).length;
  1507.  
  1508.     if (red4def == 4 || blue4def == 4){
  1509.         warn4def(1 + (blue4def == 4));
  1510.     }
  1511.     else putTeamColor();
  1512. }
  1513.  
  1514.  
  1515. /**************************************************************
  1516. * ************************** EVENTS ****************************
  1517. ***************************************************************/
  1518. var gameStats = new GameStats();
  1519. var gameControl = new GameControl(5.9);
  1520. var records = new Records();
  1521. var elo;
  1522. var mode = false;
  1523. var lastMatchSumUp = [];
  1524. var active = [];
  1525.  
  1526. var winStreak = {"team": "", "score": 1};
  1527.  
  1528. setInterval(saveStatsFun, 300000);
  1529. setInterval(checkfdps, 1000 * 60 * 4);
  1530. setInterval(deleteStatsFun, 1000 * 60 * 60 * 24 * 7);
  1531. setInterval(updateSelectedAdmins, 1000 * 60 * 4);
  1532.  
  1533. setInterval(function(){
  1534.     room.sendChat("πŸš¨πŸ† EFC Trophy will RETURN for a 4th season! Join our Discord πŸ‘‰ http://discord.gg/jTn2ZDp πŸ‘ˆ");
  1535.     room.sendChat("πŸš¨πŸ€™ Get online! Find your team! Compete in the biggest European Haxball community! πŸ†");
  1536. }, 1000 * 60 * 5);
  1537.  
  1538. setInterval(check4def, 1000);
  1539. setInterval(decreaseRqTime, 1000 * 60);
  1540.  
  1541.  
  1542. room.onPlayerChat = function(p, m){
  1543.     console.log(p.name + "#" + p.id + " : " + m );
  1544.     if (Stats[p.name].isMuted) return false;
  1545.     if (handleCommands(p, m) === false) return false;
  1546.     if (sendPM(p, m) === false) return false;
  1547.     handleSpam(lastWriters, p);
  1548. };
  1549.  
  1550.  
  1551. room.onPlayerTeamChange = function(p, by){
  1552.     preventPlaying(p);
  1553.     if (p.id === 0 && p.team != 0){
  1554.         room.setPlayerTeam(p.id, 0);
  1555.         room.sendChat("😬 Woah, hang on! I'm only a bot, you really think I'm coded to play? 😬");
  1556.     }
  1557.     handleTeams();
  1558. };
  1559.  
  1560.  
  1561.  
  1562.  
  1563. room.onPlayerJoin = function(player) {
  1564.     console.log("πŸ‘‹πŸ‘‹πŸ‘‹ " + player.name + " # " + player.id + " Joined - " + player.auth);
  1565.     handleRefresh(player);
  1566.     //handleRefresh2(player);
  1567.     autoConnect(player);
  1568.     handleBans(player);
  1569.     handleAlts(player);
  1570.     updateAdmins();
  1571.     room.sendChat("πŸ‘‹ Hey " + player.name + " ! πŸ‘‹ New season will kick off in June! Join and play with us! πŸ“£πŸ“£ https://discord.gg/jTn2ZDp", player.id);
  1572.  
  1573.     if (!active.includes(Stats[player.name].conn)) {
  1574.         active.push(Stats[player.name].conn);
  1575.     }
  1576. };
  1577.  
  1578. room.onPlayerLeave = function(player) {
  1579.     console.log("😒😒😒 " + player.name + " has left the room");
  1580.     updateAdmins();
  1581.     leaveInGame(player);
  1582.     handleSanction(player);
  1583.     Stats[player.name].disconnect();
  1584.  
  1585. };
  1586.  
  1587.  
  1588.  
  1589.  
  1590. room.onPlayerKicked = function(kicked, message, ban, by){
  1591.     handleBans2(kicked, message, ban, by);
  1592. };
  1593.  
  1594.  
  1595. room.onGameStart = function(){
  1596.     putTeamColor();
  1597.     gameStats = new GameStats();
  1598.     gameControl = new GameControl(5.9);
  1599.     elo = new ELO();
  1600.     handleStart();
  1601.     handleMode();
  1602.  
  1603. };
  1604.  
  1605.  
  1606. room.onTeamGoal = function(team){
  1607.     handleGoals(team);
  1608. };
  1609.  
  1610.  
  1611. room.onGameStop = function(){
  1612.     resetMutes();
  1613.     gameControl.resetBallOwner();
  1614.  
  1615. };
  1616.  
  1617.  
  1618.  
  1619. room.onGameTick = function(){
  1620.     gameControl.updateBallOwner();
  1621.     gameControl.updateLastBallOwners();
  1622.     gameControl.updatePassesInARow();
  1623.     handleGk();
  1624.     handleTimePlayed();
  1625.     if (mode === true) setInterval(handleOvertime, 5000);
  1626. };
  1627.  
  1628. room.onPlayerBallKick = function (player){
  1629.     gameControl.currentBallOwner = player.name;
  1630. };
  1631.  
  1632.  
  1633. room.onTeamVictory = function(){
  1634.     if (mode === false) handleEndGame();
  1635.     gameStats.matchsumup.push(handleCSMessage());
  1636.     lastMatchSumUp.push(gameStats.matchsumup);
  1637.  
  1638.  
  1639.     updateStreak(gameStats.redScore > gameStats.blueScore);
  1640.  
  1641.     room.stopGame();
  1642.  
  1643. };
  1644.  
  1645. room.onPlayerAdminChange = function(p, by){
  1646.     if (by != null && Stats[p.name].isTrustedAdmin > Stats[by.name].isTrustedAdmin){
  1647.         room.kickPlayer(by.id, "Don't try this at home, kid.", false);
  1648.         room.setPlayerAdmin(p.id, true);
  1649.     }
  1650.     updateAdmins();
  1651. };
  1652.  
  1653. room.onRoomLink = function(){
  1654.     let vide = "";
  1655.     vide.name = "";
  1656.     loadStats();
  1657.     disconnectAll();
  1658.     autoConnect(room.getPlayer(0));
  1659.     autoConnect(vide);
  1660. };
  1661.  
  1662.  
  1663. room.onStadiumChange = function(name, by){
  1664.     handleStadiumChange(name, by);
  1665. };
  1666.  
  1667.  
  1668.  
  1669.  
  1670. room.onPlayerActivity = function(p){
  1671.     if (!active.includes(Stats[p.name].conn)) {
  1672.         active.push(Stats[p.name].conn);
  1673.     }
  1674. };
  1675.  
  1676. /* EOF */
  1677.  
  1678.  
  1679. /* Python-like update dict method having at least an empty object */
  1680. function updateObject(object, p){
  1681.     if (object.hasOwnProperty(p.name)){
  1682.         object[p.name]++;
  1683.     }
  1684.     else {
  1685.         object[p.name] = 1;
  1686.     }
  1687. }
  1688.  
  1689.  
  1690. // Gives the last player who touched the ball, works only if the ball has the same
  1691. // size than in classics maps.
  1692. // Calculate the distance between 2 points
  1693. function pointDistance(p1, p2) {
  1694.     var d1 = p1.x - p2.x;
  1695.     var d2 = p1.y - p2.y;
  1696.     return Math.sqrt(d1 * d1 + d2 * d2);
  1697. }
  1698.  
  1699.  
  1700.  
  1701.  
  1702.  
  1703.  
  1704.  
  1705.  
  1706.  
  1707. var bigmap = `{
  1708.  
  1709.     "name" : "[EFC] 4v4 by Kang & Mona",
  1710.  
  1711.     "width" : 800,
  1712.  
  1713.     "height" : 350,
  1714.  
  1715.     "spawnDistance" : 350,
  1716.  
  1717.     "bg" : { "type" : "hockey", "width" : 0, "height" : 0, "kickOffRadius" : 80, "cornerRadius" : 0 },
  1718.  
  1719.     "vertexes" : [
  1720.         /* 0 */ { "x" : -700, "y" : 320, "trait" : "ballArea" },
  1721.         /* 1 */ { "x" : -700, "y" : -320, "trait" : "ballArea" },
  1722.         /* 2 */ { "x" : 700, "y" : 320, "trait" : "ballArea" },
  1723.         /* 3 */ { "x" : 700, "y" : -320, "trait" : "ballArea" },
  1724.  
  1725.         /* 4 */ { "x" : 0, "y" : 350, "trait" : "kickOffBarrier" },
  1726.         /* 5 */ { "x" : 0, "y" : 80, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  1727.         /* 6 */ { "x" : 0, "y" : -80, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  1728.         /* 7 */ { "x" : 0, "y" : -350, "trait" : "kickOffBarrier" },
  1729.  
  1730.         /* 8 */ { "x" : -700, "y" : -85, "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B" },
  1731.         /* 9 */ { "x" : -741, "y" : -85, "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "bCoef" : 0.8 },
  1732.         /* 10 */ { "x" : -741, "y" : 85, "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "bCoef" : 0.8 },
  1733.         /* 11 */ { "x" : -700, "y" : 85, "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B" },
  1734.         /* 12 */ { "x" : 700, "y" : -85, "trait" : "goalNet", "curve" : 0, "color" : "3377ae" },
  1735.         /* 13 */ { "x" : 743, "y" : -85, "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "bCoef" : 0.8 },
  1736.         /* 14 */ { "x" : 743, "y" : 84, "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "bCoef" : 0.8 },
  1737.         /* 15 */ { "x" : 700, "y" : 85, "trait" : "goalNet", "curve" : 0, "color" : "3377ae" },
  1738.  
  1739.         /* 16 */ { "x" : -700, "y" : 85, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1740.         /* 17 */ { "x" : -700, "y" : 320, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1741.         /* 18 */ { "x" : -700, "y" : -85, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1742.         /* 19 */ { "x" : -700, "y" : -320, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1743.         /* 20 */ { "x" : -700, "y" : 320, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1744.         /* 21 */ { "x" : 700, "y" : 320, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1745.         /* 22 */ { "x" : 700, "y" : 85, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1746.         /* 23 */ { "x" : 700, "y" : 320, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1747.         /* 24 */ { "x" : 700, "y" : -320, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1748.         /* 25 */ { "x" : 700, "y" : -85, "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1749.         /* 26 */ { "x" : 700, "y" : -320, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  1750.         /* 27 */ { "x" : 700, "y" : -320, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  1751.         /* 28 */ { "x" : -700, "y" : -320, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1752.         /* 29 */ { "x" : 700, "y" : -320, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1753.  
  1754.         /* 30 */ { "x" : 0, "y" : -318, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1755.         /* 31 */ { "x" : 0, "y" : -82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1756.         /* 32 */ { "x" : 0, "y" : 82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1757.         /* 33 */ { "x" : 0, "y" : 318, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1758.         /* 34 */ { "x" : 0, "y" : -82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  1759.         /* 35 */ { "x" : 0, "y" : 82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  1760.         /* 36 */ { "x" : 0, "y" : -150, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  1761.         /* 37 */ { "x" : 0, "y" : 82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  1762.         /* 38 */ { "x" : 0, "y" : -82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  1763.         /* 39 */ { "x" : 0, "y" : 82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : 0 },
  1764.  
  1765.         /* 40 */ { "x" : -707.5, "y" : 85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  1766.         /* 41 */ { "x" : -707.5, "y" : -344, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1767.         /* 42 */ { "x" : -707.5, "y" : -85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1768.         /* 43 */ { "x" : 697, "y" : -85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea" },
  1769.         /* 44 */ { "x" : 697, "y" : -87, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1770.         /* 45 */ { "x" : 696, "y" : 84, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  1771.  
  1772.         /* 46 */ { "x" : -700, "y" : -86, "bCoef" : 0.1, "cMask" : ["blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "737573" },
  1773.         /* 47 */ { "x" : -700, "y" : 81, "bCoef" : 0.1, "cMask" : ["blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "737573" },
  1774.         /* 48 */ { "x" : 700, "y" : -83, "bCoef" : 0.1, "cMask" : ["red" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "737573" },
  1775.         /* 49 */ { "x" : 700, "y" : 84, "bCoef" : 0.1, "cMask" : ["red" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "737573" },
  1776.  
  1777.         /* 50 */ { "x" : -385.5, "y" : 318, "bCoef" : 0, "cMask" : ["wall" ], "color" : "737573" },
  1778.         /* 51 */ { "x" : -385.5, "y" : -318, "bCoef" : 0, "cMask" : ["wall" ], "color" : "737573" },
  1779.         /* 52 */ { "x" : 385.5, "y" : 318, "bCoef" : 0, "cMask" : ["wall" ], "color" : "737573" },
  1780.         /* 53 */ { "x" : 385.5, "y" : -318, "bCoef" : 0, "cMask" : ["wall" ], "color" : "737573" },
  1781.         /* 54 */ { "x" : -385.5, "y" : -130, "cMask" : ["wall" ], "curve" : 90, "color" : "737573" },
  1782.         /* 55 */ { "x" : -385.5, "y" : 130, "cMask" : ["wall" ], "curve" : 90, "color" : "737573" },
  1783.         /* 56 */ { "x" : 385.5, "y" : -130, "cMask" : ["wall" ], "curve" : -90, "color" : "737573" },
  1784.         /* 57 */ { "x" : 385.5, "y" : 130, "cMask" : ["wall" ], "curve" : -90, "color" : "737573" },
  1785.         /* 58 */ { "x" : -620, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1786.         /* 59 */ { "x" : -698, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1787.         /* 60 */ { "x" : -620, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1788.         /* 61 */ { "x" : -698, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1789.         /* 62 */ { "x" : -620, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1790.         /* 63 */ { "x" : -620, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1791.         /* 64 */ { "x" : 620, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1792.         /* 65 */ { "x" : 698, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1793.         /* 66 */ { "x" : 620, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1794.         /* 67 */ { "x" : 698, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1795.         /* 68 */ { "x" : 620, "y" : -115, "cMask" : ["wall" ], "color" : "737573" },
  1796.         /* 69 */ { "x" : 620, "y" : 115, "cMask" : ["wall" ], "color" : "737573" },
  1797.         /* 70 */ { "x" : 500, "y" : -2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1798.         /* 71 */ { "x" : 500, "y" : 2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1799.         /* 72 */ { "x" : 500, "y" : -2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1800.         /* 73 */ { "x" : 500, "y" : 2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1801.         /* 74 */ { "x" : -500, "y" : -2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1802.         /* 75 */ { "x" : -500, "y" : 2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1803.         /* 76 */ { "x" : -500, "y" : -2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1804.         /* 77 */ { "x" : -500, "y" : 2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1805.         /* 78 */ { "x" : 0, "y" : -2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1806.         /* 79 */ { "x" : 0, "y" : 2, "cMask" : ["wall" ], "curve" : 180, "color" : "737573" },
  1807.         /* 80 */ { "x" : 0, "y" : -2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1808.         /* 81 */ { "x" : 0, "y" : 2, "cMask" : ["wall" ], "curve" : -180, "color" : "737573" },
  1809.  
  1810.         /* 82 */ { "x" : -707.5, "y" : 344, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1811.         /* 83 */ { "x" : -707.5, "y" : 85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1812.         /* 84 */ { "x" : 707.5, "y" : 344, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1813.         /* 85 */ { "x" : 707.5, "y" : 85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1814.         /* 86 */ { "x" : 707.5, "y" : -344, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1815.         /* 87 */ { "x" : 707.5, "y" : -85, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 }
  1816.  
  1817.     ],
  1818.  
  1819.     "segments" : [
  1820.         { "v0" : 8, "v1" : 9, "curve" : 0, "color" : "DA4D4B", "trait" : "goalNet" },
  1821.         { "v0" : 9, "v1" : 10, "curve" : -23, "color" : "DA4D4B", "trait" : "goalNet", "bCoef" : 0.8 },
  1822.         { "v0" : 10, "v1" : 11, "curve" : 0, "color" : "DA4D4B", "trait" : "goalNet" },
  1823.         { "v0" : 12, "v1" : 13, "curve" : 0, "color" : "3377ae", "trait" : "goalNet" },
  1824.         { "v0" : 13, "v1" : 14, "curve" : 23, "color" : "3377ae", "trait" : "goalNet", "bCoef" : 0.8 },
  1825.         { "v0" : 14, "v1" : 15, "curve" : 0, "color" : "3377ae", "trait" : "goalNet" },
  1826.  
  1827.         { "v0" : 4, "v1" : 5, "trait" : "kickOffBarrier" },
  1828.         { "v0" : 5, "v1" : 6, "curve" : 180, "vis" : true, "color" : "DA4D4B", "cGroup" : ["blueKO" ], "trait" : "kickOffBarrier" },
  1829.         { "v0" : 5, "v1" : 6, "curve" : -180, "vis" : true, "color" : "3377ae", "cGroup" : ["redKO" ], "trait" : "kickOffBarrier" },
  1830.         { "v0" : 6, "v1" : 7, "trait" : "kickOffBarrier" },
  1831.  
  1832.         { "v0" : 16, "v1" : 17, "vis" : true, "color" : "1e252a", "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea" },
  1833.         { "v0" : 18, "v1" : 19, "vis" : true, "color" : "1e252a", "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea" },
  1834.         { "v0" : 20, "v1" : 21, "vis" : true, "color" : "1e252a", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea" },
  1835.         { "v0" : 22, "v1" : 23, "vis" : true, "color" : "1e252a", "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea" },
  1836.         { "v0" : 24, "v1" : 25, "vis" : true, "color" : "1e252a", "bCoef" : 1.25, "cMask" : ["ball" ], "trait" : "ballArea" },
  1837.         { "v0" : 26, "v1" : 27, "vis" : true, "color" : "F8F8F8", "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  1838.         { "v0" : 28, "v1" : 29, "vis" : true, "color" : "1e252a", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea" },
  1839.  
  1840.         { "v0" : 30, "v1" : 31, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  1841.         { "v0" : 32, "v1" : 33, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  1842.  
  1843.         { "v0" : 41, "v1" : 42, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -707.5 },
  1844.  
  1845.         { "v0" : 46, "v1" : 47, "vis" : true, "color" : "737573", "bCoef" : 0.1, "cMask" : ["blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "x" : -700 },
  1846.         { "v0" : 48, "v1" : 49, "vis" : true, "color" : "737573", "bCoef" : 0.1, "cMask" : ["red" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "x" : 700 },
  1847.  
  1848.         { "v0" : 50, "v1" : 51, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "cMask" : ["wall" ], "trait" : "goalNet" },
  1849.         { "v0" : 52, "v1" : 53, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "cMask" : ["wall" ], "trait" : "goalNet", "x" : 385.5 },
  1850.  
  1851.         { "v0" : 54, "v1" : 55, "curve" : 90, "vis" : true, "color" : "737573", "cMask" : ["wall" ] },
  1852.         { "v0" : 56, "v1" : 57, "curve" : -90, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : 385.5 },
  1853.         { "v0" : 58, "v1" : 59, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ] },
  1854.         { "v0" : 60, "v1" : 61, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "y" : 115 },
  1855.         { "v0" : 62, "v1" : 63, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ] },
  1856.         { "v0" : 64, "v1" : 65, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "y" : 215 },
  1857.         { "v0" : 66, "v1" : 67, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "y" : -115 },
  1858.         { "v0" : 68, "v1" : 69, "curve" : 0, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : 620 },
  1859.         { "v0" : 70, "v1" : 71, "curve" : 180, "vis" : true, "color" : "737573", "cMask" : ["wall" ] },
  1860.         { "v0" : 72, "v1" : 73, "curve" : -180, "vis" : true, "color" : "737573", "cMask" : ["wall" ] },
  1861.         { "v0" : 74, "v1" : 75, "curve" : 180, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : -500 },
  1862.         { "v0" : 76, "v1" : 77, "curve" : -180, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : -500 },
  1863.         { "v0" : 78, "v1" : 79, "curve" : 180, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : 0 },
  1864.         { "v0" : 80, "v1" : 81, "curve" : -180, "vis" : true, "color" : "737573", "cMask" : ["wall" ], "x" : 0 },
  1865.  
  1866.         { "v0" : 82, "v1" : 83, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -707.5 },
  1867.         { "v0" : 84, "v1" : 85, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 707.5 },
  1868.         { "v0" : 86, "v1" : 87, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 707.5 }
  1869.  
  1870.     ],
  1871.  
  1872.     "goals" : [
  1873.         { "p0" : [-706,91 ], "p1" : [-706,-79 ], "team" : "red" },
  1874.         { "p0" : [706,91 ], "p1" : [706,-79 ], "team" : "blue" }
  1875.  
  1876.     ],
  1877.  
  1878.     "discs" : [
  1879.         { "radius" : 5.4, "pos" : [-700,85 ], "color" : "ce9e9e", "trait" : "goalPost" },
  1880.         { "radius" : 5.4, "pos" : [-700,-85 ], "color" : "ce9e9e", "trait" : "goalPost" },
  1881.         { "radius" : 5.4, "pos" : [699,85 ], "color" : "9eafce", "trait" : "goalPost" },
  1882.         { "radius" : 5.4, "pos" : [699,-84 ], "color" : "9eafce", "trait" : "goalPost" }
  1883.  
  1884.     ],
  1885.  
  1886.     "planes" : [
  1887.         { "normal" : [0,1 ], "dist" : -320, "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1888.         { "normal" : [0,-1 ], "dist" : -320, "trait" : "ballArea" },
  1889.  
  1890.         { "normal" : [0,1 ], "dist" : -350, "bCoef" : 0.1 },
  1891.         { "normal" : [0,-1 ], "dist" : -352, "bCoef" : 0.1 },
  1892.         { "normal" : [1,0 ], "dist" : -800, "bCoef" : 0.1 },
  1893.         { "normal" : [-1,0 ], "dist" : -800, "bCoef" : 0.1 },
  1894.  
  1895.         { "bCoef" : 0.8, "cMask" : ["ball" ], "trait" : "goalNet", "dist" : -754, "normal" : [-1,0 ] },
  1896.         { "bCoef" : 0.8, "cMask" : ["ball" ], "trait" : "goalNet", "dist" : -753.006773306292, "normal" : [0.9999309835650598,0.011748536360424984 ] }
  1897.  
  1898.     ],
  1899.  
  1900.     "traits" : {
  1901.         "ballArea" : { "vis" : false, "bCoef" : 1, "cMask" : ["ball" ] },
  1902.         "goalPost" : { "radius" : 8, "invMass" : 0, "bCoef" : 0.5 },
  1903.         "goalNet" : { "vis" : true, "bCoef" : 0.1, "cMask" : ["ball" ] },
  1904.         "kickOffBarrier" : { "vis" : false, "bCoef" : 0.1, "cGroup" : ["redKO","blueKO" ], "cMask" : ["red","blue" ] }
  1905.  
  1906.     },
  1907.  
  1908.     "playerPhysics" : {
  1909.         "bCoef" : 0,
  1910.         "acceleration" : 0.11,
  1911.         "kickingAcceleration" : 0.083,
  1912.         "kickStrength" : 4.545
  1913.  
  1914.     },
  1915.  
  1916.     "ballPhysics" : {
  1917.         "radius" : 5.8,
  1918.         "bCoef" : 0.412,
  1919.         "invMass" : 1.5,
  1920.         "damping" : 0.99,
  1921.         "color" : "ffd133"
  1922.  
  1923.     }
  1924. }`;
  1925.  
  1926. var mediummap = `{
  1927.  
  1928.     "name" : "EFC 3v3 by Kang & Oprah)",
  1929.  
  1930.     "width" : 648,
  1931.  
  1932.     "height" : 270,
  1933.  
  1934.     "spawnDistance" : 350,
  1935.  
  1936.     "bg" : { "type" : "hockey" },
  1937.  
  1938.     "vertexes" : [
  1939.         /* 0 */ { "x" : 550, "y" : 240, "trait" : "ballArea" },
  1940.         /* 1 */ { "x" : 550, "y" : -240, "trait" : "ballArea" },
  1941.  
  1942.         /* 2 */ { "x" : 0, "y" : 270, "trait" : "kickOffBarrier" },
  1943.         /* 3 */ { "x" : 0, "y" : 80, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  1944.         /* 4 */ { "x" : 0, "y" : -80, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  1945.         /* 5 */ { "x" : 0, "y" : -270, "trait" : "kickOffBarrier" },
  1946.  
  1947.         /* 6 */ { "x" : -550, "y" : -80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B", "pos" : [-700,-80 ] },
  1948.         /* 7 */ { "x" : -590, "y" : -80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "pos" : [-700,-80 ], "bCoef" : 0.8 },
  1949.         /* 8 */ { "x" : -590, "y" : 80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "pos" : [-700,80 ], "bCoef" : 0.8 },
  1950.         /* 9 */ { "x" : -550, "y" : 80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B", "pos" : [-700,80 ] },
  1951.         /* 10 */ { "x" : 550, "y" : -80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "3377ae", "pos" : [700,-80 ] },
  1952.         /* 11 */ { "x" : 590, "y" : -80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "pos" : [700,-80 ], "bCoef" : 0.8 },
  1953.         /* 12 */ { "x" : 590, "y" : 80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "pos" : [700,80 ], "bCoef" : 0.8 },
  1954.         /* 13 */ { "x" : 550, "y" : 80, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "3377ae", "pos" : [700,80 ] },
  1955.  
  1956.         /* 14 */ { "x" : -550, "y" : 80, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [-700,80 ], "_selected" : "segment" },
  1957.         /* 15 */ { "x" : -550, "y" : 240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "_selected" : "segment" },
  1958.         /* 16 */ { "x" : -550, "y" : -80, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [-700,-80 ] },
  1959.         /* 17 */ { "x" : -550, "y" : -240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1960.         /* 18 */ { "x" : -550, "y" : 240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1961.         /* 19 */ { "x" : 550, "y" : 240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1962.         /* 20 */ { "x" : 550, "y" : 80, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "pos" : [700,80 ], "color" : "1e252a" },
  1963.         /* 21 */ { "x" : 550, "y" : 240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1964.         /* 22 */ { "x" : 550, "y" : -240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  1965.         /* 23 */ { "x" : 550, "y" : -80, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [700,-80 ] },
  1966.         /* 24 */ { "x" : 550, "y" : -240, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  1967.         /* 25 */ { "x" : 550, "y" : -240, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  1968.         /* 26 */ { "x" : -550, "y" : -240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "color" : "1e252a" },
  1969.         /* 27 */ { "x" : 550, "y" : -240, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "color" : "1e252a" },
  1970.  
  1971.         /* 28 */ { "x" : 0, "y" : -240, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1972.         /* 29 */ { "x" : 0, "y" : -82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1973.         /* 30 */ { "x" : 0, "y" : 82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1974.         /* 31 */ { "x" : 0, "y" : 240, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  1975.         /* 32 */ { "x" : 0, "y" : -82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  1976.         /* 33 */ { "x" : 0, "y" : 82, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  1977.         /* 34 */ { "x" : 0, "y" : 82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  1978.         /* 35 */ { "x" : 0, "y" : -82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  1979.         /* 36 */ { "x" : 0, "y" : 82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : 0 },
  1980.         /* 37 */ { "x" : 0, "y" : -82, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : 0 },
  1981.  
  1982.         /* 38 */ { "x" : -557.5, "y" : 80, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false, "pos" : [-700,80 ] },
  1983.         /* 39 */ { "x" : -557.5, "y" : 240, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  1984.         /* 40 */ { "x" : -557.5, "y" : -240, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1985.         /* 41 */ { "x" : -557.5, "y" : -80, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0, "pos" : [-700,-80 ] },
  1986.         /* 42 */ { "x" : 557.5, "y" : -240, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  1987.         /* 43 */ { "x" : 557.5, "y" : -80, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0, "pos" : [700,-80 ] },
  1988.         /* 44 */ { "x" : 557.5, "y" : 80, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false, "pos" : [700,80 ] },
  1989.         /* 45 */ { "x" : 557.5, "y" : 240, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  1990.  
  1991.         /* 46 */ { "x" : 0, "y" : 82, "bCoef" : 0.1, "trait" : "line", "color" : "afa370" },
  1992.         /* 47 */ { "x" : -550, "y" : -80, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  1993.         /* 48 */ { "x" : -550, "y" : 80, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  1994.         /* 49 */ { "x" : 550, "y" : -80, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  1995.         /* 50 */ { "x" : 550, "y" : 80, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  1996.         /* 51 */ { "x" : -548, "y" : 160, "bCoef" : 0.1, "trait" : "line", "color" : "737573", "curve" : -180 },
  1997.         /* 52 */ { "x" : -548, "y" : -160, "bCoef" : 0.1, "trait" : "line", "color" : "737573", "curve" : -180 },
  1998.         /* 53 */ { "x" : 548, "y" : 160, "bCoef" : 0.1, "trait" : "line", "color" : "737573", "curve" : 180 },
  1999.         /* 54 */ { "x" : 548, "y" : -160, "bCoef" : 0.1, "trait" : "line", "color" : "737573", "curve" : 180 },
  2000.         /* 55 */ { "x" : 0, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2001.         /* 56 */ { "x" : 0, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2002.         /* 57 */ { "x" : 0, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2003.         /* 58 */ { "x" : 0, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2004.         /* 59 */ { "x" : 480, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2005.         /* 60 */ { "x" : 480, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2006.         /* 61 */ { "x" : 480, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2007.         /* 62 */ { "x" : 480, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2008.         /* 63 */ { "x" : -480, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2009.         /* 64 */ { "x" : -480, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2010.         /* 65 */ { "x" : -480, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2011.         /* 66 */ { "x" : -480, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" }
  2012.  
  2013.     ],
  2014.  
  2015.     "segments" : [
  2016.         { "v0" : 6, "v1" : 7, "curve" : 0, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [-700,-80 ], "y" : -80 },
  2017.         { "v0" : 7, "v1" : 8, "curve" : -23, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "x" : -590, "bCoef" : 0.8 },
  2018.         { "v0" : 8, "v1" : 9, "curve" : 0, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [-700,80 ], "y" : 80 },
  2019.         { "v0" : 10, "v1" : 11, "curve" : 0, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [700,-80 ], "y" : -80 },
  2020.         { "v0" : 11, "v1" : 12, "curve" : 23, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "x" : 590, "bCoef" : 0.8 },
  2021.         { "v0" : 12, "v1" : 13, "curve" : 0, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [700,80 ], "y" : 80 },
  2022.  
  2023.         { "v0" : 2, "v1" : 3, "trait" : "kickOffBarrier" },
  2024.         { "v0" : 3, "v1" : 4, "curve" : 180, "vis" : true, "color" : "DA4D4B", "cGroup" : ["blueKO" ], "trait" : "kickOffBarrier" },
  2025.         { "v0" : 3, "v1" : 4, "curve" : -180, "vis" : true, "color" : "3377ae", "cGroup" : ["redKO" ], "trait" : "kickOffBarrier" },
  2026.         { "v0" : 4, "v1" : 5, "trait" : "kickOffBarrier" },
  2027.  
  2028.         { "v0" : 14, "v1" : 15, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -550, "_selected" : true },
  2029.         { "v0" : 16, "v1" : 17, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -550 },
  2030.         { "v0" : 18, "v1" : 19, "curve" : 0, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "y" : 240 },
  2031.         { "v0" : 20, "v1" : 21, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 550 },
  2032.         { "v0" : 22, "v1" : 23, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 550 },
  2033.         { "v0" : 24, "v1" : 25, "vis" : true, "color" : "F8F8F8", "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 550, "y" : -240 },
  2034.         { "v0" : 26, "v1" : 27, "curve" : 0, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "y" : -240 },
  2035.  
  2036.         { "v0" : 28, "v1" : 29, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  2037.         { "v0" : 30, "v1" : 31, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  2038.  
  2039.         { "v0" : 38, "v1" : 39, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -557.5 },
  2040.         { "v0" : 40, "v1" : 41, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -557.5 },
  2041.         { "v0" : 42, "v1" : 43, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 557.5 },
  2042.         { "v0" : 44, "v1" : 45, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 557.5 },
  2043.  
  2044.         { "v0" : 47, "v1" : 48, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -550 },
  2045.         { "v0" : 49, "v1" : 50, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 550 },
  2046.         { "v0" : 51, "v1" : 52, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2047.         { "v0" : 53, "v1" : 54, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 548 },
  2048.         { "v0" : 55, "v1" : 56, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2049.         { "v0" : 57, "v1" : 58, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2050.         { "v0" : 59, "v1" : 60, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 480 },
  2051.         { "v0" : 61, "v1" : 62, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 480 },
  2052.         { "v0" : 63, "v1" : 64, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -480 },
  2053.         { "v0" : 65, "v1" : 66, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -480 }
  2054.  
  2055.     ],
  2056.  
  2057.     "goals" : [
  2058.         { "p0" : [-556.3,-80 ], "p1" : [-556.3,80 ], "team" : "red" },
  2059.         { "p0" : [556.3,80 ], "p1" : [556.3,-80 ], "team" : "blue" }
  2060.  
  2061.     ],
  2062.  
  2063.     "discs" : [
  2064.         { "radius" : 5, "pos" : [-550,80 ], "color" : "ce9e9e", "trait" : "goalPost", "y" : 80 },
  2065.         { "radius" : 5, "pos" : [-550,-80 ], "color" : "ce9e9e", "trait" : "goalPost", "y" : -80, "x" : -560 },
  2066.         { "radius" : 5, "pos" : [550,80 ], "color" : "9eafce", "trait" : "goalPost", "y" : 80 },
  2067.         { "radius" : 5, "pos" : [550,-80 ], "color" : "9eafce", "trait" : "goalPost", "y" : -80 }
  2068.  
  2069.     ],
  2070.  
  2071.     "planes" : [
  2072.         { "normal" : [0,1 ], "dist" : -240, "bCoef" : 1, "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2073.         { "normal" : [0,-1 ], "dist" : -240, "bCoef" : 1, "trait" : "ballArea" },
  2074.  
  2075.         { "normal" : [0,1 ], "dist" : -270, "bCoef" : 0.1 },
  2076.         { "normal" : [0,-1 ], "dist" : -270, "bCoef" : 0.1 },
  2077.         { "normal" : [1,0 ], "dist" : -642, "bCoef" : 0.1 },
  2078.         { "normal" : [-1,0 ], "dist" : -644, "bCoef" : 0.1 },
  2079.  
  2080.         { "normal" : [1,0 ], "dist" : -642, "bCoef" : 0.1, "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2081.         { "normal" : [-1,0 ], "dist" : -643, "bCoef" : 0.1, "trait" : "ballArea", "vis" : false, "curve" : 0 }
  2082.  
  2083.     ],
  2084.  
  2085.     "traits" : {
  2086.         "ballArea" : { "vis" : false, "bCoef" : 1, "cMask" : ["ball" ] },
  2087.         "goalPost" : { "radius" : 8, "invMass" : 0, "bCoef" : 0.5 },
  2088.         "goalNet" : { "vis" : true, "bCoef" : 0.1, "cMask" : ["ball" ] },
  2089.         "line" : { "vis" : true, "bCoef" : 0.1, "cMask" : ["" ] },
  2090.         "kickOffBarrier" : { "vis" : false, "bCoef" : 0.1, "cGroup" : ["redKO","blueKO" ], "cMask" : ["red","blue" ] }
  2091.  
  2092.     },
  2093.  
  2094.     "playerPhysics" : {
  2095.         "bCoef" : 0,
  2096.         "acceleration" : 0.11,
  2097.         "kickingAcceleration" : 0.083,
  2098.         "kickStrength" : 4.2
  2099.  
  2100.     },
  2101.  
  2102.     "ballPhysics" : {
  2103.         "radius" : 5.8,
  2104.         "bCoef" : 0.412,
  2105.         "invMass" : 1.5,
  2106.         "damping" : 0.99,
  2107.         "color" : "ffd133"
  2108.  
  2109.     }
  2110. }`;
  2111.  
  2112.  
  2113. var smallmap = `{
  2114.  
  2115.     "name" : "[EFC] 1vs1 / 2vs2 by Oprah",
  2116.  
  2117.     "width" : 497,
  2118.  
  2119.     "height" : 220,
  2120.  
  2121.     "spawnDistance" : 350,
  2122.  
  2123.     "bg" : { "type" : "hockey" },
  2124.  
  2125.     "vertexes" : [
  2126.         /* 0 */ { "x" : 400, "y" : 190, "trait" : "ballArea" },
  2127.         /* 1 */ { "x" : 400, "y" : -190, "trait" : "ballArea" },
  2128.  
  2129.         /* 2 */ { "x" : 0, "y" : 220, "trait" : "kickOffBarrier" },
  2130.         /* 3 */ { "x" : 0, "y" : 60, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  2131.         /* 4 */ { "x" : 0, "y" : -60, "trait" : "kickOffBarrier", "color" : "3377ae", "vis" : true, "curve" : 180 },
  2132.         /* 5 */ { "x" : 0, "y" : -220, "trait" : "kickOffBarrier" },
  2133.  
  2134.         /* 6 */ { "x" : -400, "y" : -70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B", "pos" : [-700,-80 ] },
  2135.         /* 7 */ { "x" : -440, "y" : -70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "pos" : [-700,-80 ], "bCoef" : 0.8 },
  2136.         /* 8 */ { "x" : -440, "y" : 70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : -23, "color" : "DA4D4B", "pos" : [-700,80 ], "bCoef" : 0.8 },
  2137.         /* 9 */ { "x" : -400, "y" : 70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "DA4D4B", "pos" : [-700,80 ] },
  2138.         /* 10 */ { "x" : 400, "y" : -70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "3377ae", "pos" : [700,-80 ] },
  2139.         /* 11 */ { "x" : 440, "y" : -70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "pos" : [700,-80 ], "bCoef" : 0.8 },
  2140.         /* 12 */ { "x" : 440, "y" : 70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 23, "color" : "3377ae", "pos" : [700,80 ], "bCoef" : 0.8 },
  2141.         /* 13 */ { "x" : 400, "y" : 70, "cMask" : ["ball" ], "trait" : "goalNet", "curve" : 0, "color" : "3377ae", "pos" : [700,80 ] },
  2142.  
  2143.         /* 14 */ { "x" : -400, "y" : 70, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [-700,80 ] },
  2144.         /* 15 */ { "x" : -400, "y" : 190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2145.         /* 16 */ { "x" : -400, "y" : -70, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [-700,-80 ] },
  2146.         /* 17 */ { "x" : -400, "y" : -190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2147.         /* 18 */ { "x" : -400, "y" : 190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2148.         /* 19 */ { "x" : 400, "y" : 190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2149.         /* 20 */ { "x" : 400, "y" : 70, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "pos" : [700,80 ], "color" : "1e252a" },
  2150.         /* 21 */ { "x" : 400, "y" : 190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2151.         /* 22 */ { "x" : 400, "y" : -190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a" },
  2152.         /* 23 */ { "x" : 400, "y" : -70, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "color" : "1e252a", "pos" : [700,-80 ] },
  2153.         /* 24 */ { "x" : 400, "y" : -190, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  2154.         /* 25 */ { "x" : 400, "y" : -190, "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea" },
  2155.         /* 26 */ { "x" : -400, "y" : -190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "color" : "1e252a" },
  2156.         /* 27 */ { "x" : 400, "y" : -190, "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "color" : "1e252a" },
  2157.  
  2158.         /* 28 */ { "x" : 0, "y" : -190, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  2159.         /* 29 */ { "x" : 0, "y" : -62, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  2160.         /* 30 */ { "x" : 0, "y" : 62, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  2161.         /* 31 */ { "x" : 0, "y" : 190, "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier", "color" : "1e252a" },
  2162.         /* 32 */ { "x" : 0, "y" : -62, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  2163.         /* 33 */ { "x" : 0, "y" : 62, "bCoef" : 0.1, "cMask" : ["red","blue" ], "trait" : "kickOffBarrier", "vis" : true, "color" : "F8F8F8" },
  2164.         /* 34 */ { "x" : 0, "y" : 62, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  2165.         /* 35 */ { "x" : 0, "y" : -62, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : -180 },
  2166.         /* 36 */ { "x" : 0, "y" : 62, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : 0 },
  2167.         /* 37 */ { "x" : 0, "y" : -62, "trait" : "kickOffBarrier", "color" : "F8F8F8", "vis" : true, "curve" : 0 },
  2168.  
  2169.         /* 38 */ { "x" : -407.5, "y" : 70, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false, "pos" : [-700,80 ] },
  2170.         /* 39 */ { "x" : -407.5, "y" : 190, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  2171.         /* 40 */ { "x" : -407.5, "y" : -190, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2172.         /* 41 */ { "x" : -407.5, "y" : -70, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0, "pos" : [-700,-80 ] },
  2173.         /* 42 */ { "x" : 407.5, "y" : -190, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2174.         /* 43 */ { "x" : 407.5, "y" : -70, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0, "pos" : [700,-80 ] },
  2175.         /* 44 */ { "x" : 407.5, "y" : 70, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false, "pos" : [700,80 ] },
  2176.         /* 45 */ { "x" : 407.5, "y" : 190, "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "curve" : 0, "vis" : false },
  2177.  
  2178.         /* 46 */ { "x" : 0, "y" : 62, "bCoef" : 0.1, "trait" : "line", "color" : "afa370" },
  2179.         /* 47 */ { "x" : -400, "y" : -70, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2180.         /* 48 */ { "x" : -400, "y" : 70, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2181.         /* 49 */ { "x" : 400, "y" : -70, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2182.         /* 50 */ { "x" : 400, "y" : 70, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2183.         /* 51 */ { "x" : 0, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2184.         /* 52 */ { "x" : 0, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2185.         /* 53 */ { "x" : 0, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2186.         /* 54 */ { "x" : 0, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2187.         /* 55 */ { "x" : -398, "y" : -130, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2188.         /* 56 */ { "x" : -398, "y" : 130, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2189.         /* 57 */ { "x" : 398, "y" : -130, "bCoef" : 0.1, "trait" : "line", "curve" : -180, "color" : "737573" },
  2190.         /* 58 */ { "x" : 398, "y" : 130, "bCoef" : 0.1, "trait" : "line", "curve" : -180, "color" : "737573" },
  2191.         /* 59 */ { "x" : 350, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2192.         /* 60 */ { "x" : 350, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2193.         /* 61 */ { "x" : 350, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2194.         /* 62 */ { "x" : 350, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2195.         /* 63 */ { "x" : -350, "y" : -2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2196.         /* 64 */ { "x" : -350, "y" : 2, "bCoef" : 0.1, "trait" : "line", "color" : "737573" },
  2197.         /* 65 */ { "x" : -350, "y" : -2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" },
  2198.         /* 66 */ { "x" : -350, "y" : 2, "bCoef" : 0.1, "trait" : "line", "curve" : 180, "color" : "737573" }
  2199.  
  2200.     ],
  2201.  
  2202.     "segments" : [
  2203.         { "v0" : 6, "v1" : 7, "curve" : 0, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [-700,-80 ], "y" : -70 },
  2204.         { "v0" : 7, "v1" : 8, "curve" : -23, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "x" : -440, "bCoef" : 0.8 },
  2205.         { "v0" : 8, "v1" : 9, "curve" : 0, "color" : "DA4D4B", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [-700,80 ], "y" : 70 },
  2206.         { "v0" : 10, "v1" : 11, "curve" : 0, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [700,-80 ], "y" : -70 },
  2207.         { "v0" : 11, "v1" : 12, "curve" : 23, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "x" : 440, "bCoef" : 0.8 },
  2208.         { "v0" : 12, "v1" : 13, "curve" : 0, "color" : "3377ae", "cMask" : ["ball" ], "trait" : "goalNet", "pos" : [700,80 ], "y" : 70 },
  2209.  
  2210.         { "v0" : 2, "v1" : 3, "trait" : "kickOffBarrier" },
  2211.         { "v0" : 3, "v1" : 4, "curve" : 180, "vis" : true, "color" : "DA4D4B", "cGroup" : ["blueKO" ], "trait" : "kickOffBarrier" },
  2212.         { "v0" : 3, "v1" : 4, "curve" : -180, "vis" : true, "color" : "3377ae", "cGroup" : ["redKO" ], "trait" : "kickOffBarrier" },
  2213.         { "v0" : 4, "v1" : 5, "trait" : "kickOffBarrier" },
  2214.  
  2215.         { "v0" : 14, "v1" : 15, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -400 },
  2216.         { "v0" : 16, "v1" : 17, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -400 },
  2217.         { "v0" : 18, "v1" : 19, "curve" : 0, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "y" : 190 },
  2218.         { "v0" : 20, "v1" : 21, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 400 },
  2219.         { "v0" : 22, "v1" : 23, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 400 },
  2220.         { "v0" : 24, "v1" : 25, "vis" : true, "color" : "F8F8F8", "bCoef" : 0, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 400, "y" : -190 },
  2221.         { "v0" : 26, "v1" : 27, "curve" : 0, "vis" : true, "color" : "1e252a", "bCoef" : 1, "cMask" : ["ball" ], "trait" : "ballArea", "y" : -190 },
  2222.  
  2223.         { "v0" : 28, "v1" : 29, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  2224.         { "v0" : 30, "v1" : 31, "vis" : true, "color" : "1e252a", "bCoef" : 0.1, "cMask" : ["red","blue" ], "cGroup" : ["redKO","blueKO" ], "trait" : "kickOffBarrier" },
  2225.  
  2226.         { "v0" : 38, "v1" : 39, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -407.5 },
  2227.         { "v0" : 40, "v1" : 41, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : -407.5 },
  2228.         { "v0" : 42, "v1" : 43, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 407.5 },
  2229.         { "v0" : 44, "v1" : 45, "curve" : 0, "vis" : false, "color" : "F8F8F8", "bCoef" : 2, "cMask" : ["ball" ], "trait" : "ballArea", "x" : 407.5 },
  2230.  
  2231.         { "v0" : 47, "v1" : 48, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -400 },
  2232.         { "v0" : 49, "v1" : 50, "curve" : 0, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 400 },
  2233.         { "v0" : 51, "v1" : 52, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2234.         { "v0" : 53, "v1" : 54, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2235.         { "v0" : 55, "v1" : 56, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line" },
  2236.         { "v0" : 57, "v1" : 58, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 400 },
  2237.         { "v0" : 59, "v1" : 60, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 350 },
  2238.         { "v0" : 61, "v1" : 62, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : 350 },
  2239.         { "v0" : 63, "v1" : 64, "curve" : -180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -350 },
  2240.         { "v0" : 65, "v1" : 66, "curve" : 180, "vis" : true, "color" : "737573", "bCoef" : 0.1, "trait" : "line", "x" : -350 }
  2241.  
  2242.     ],
  2243.  
  2244.     "goals" : [
  2245.         { "p0" : [-406.3,-70 ], "p1" : [-406.3,70 ], "team" : "red" },
  2246.         { "p0" : [406.3,70 ], "p1" : [406.3,-70 ], "team" : "blue" }
  2247.  
  2248.     ],
  2249.  
  2250.     "discs" : [
  2251.         { "radius" : 5, "pos" : [-400,70 ], "color" : "ce9e9e", "trait" : "goalPost", "y" : 80 },
  2252.         { "radius" : 5, "pos" : [-400,-70 ], "color" : "ce9e9e", "trait" : "goalPost", "y" : -80, "x" : -560 },
  2253.         { "radius" : 5, "pos" : [400,70 ], "color" : "9eafce", "trait" : "goalPost", "y" : 80 },
  2254.         { "radius" : 5, "pos" : [400,-70 ], "color" : "9eafce", "trait" : "goalPost", "y" : -80 }
  2255.  
  2256.     ],
  2257.  
  2258.     "planes" : [
  2259.         { "normal" : [0,1 ], "dist" : -190, "bCoef" : 1, "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2260.         { "normal" : [0,-1 ], "dist" : -190, "bCoef" : 1, "trait" : "ballArea" },
  2261.  
  2262.         { "normal" : [0,1 ], "dist" : -220, "bCoef" : 0.1 },
  2263.         { "normal" : [0,-1 ], "dist" : -220, "bCoef" : 0.1 },
  2264.         { "normal" : [1,0 ], "dist" : -492, "bCoef" : 0.1 },
  2265.         { "normal" : [-1,0 ], "dist" : -492, "bCoef" : 0.1 },
  2266.  
  2267.         { "normal" : [1,0 ], "dist" : -490, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 },
  2268.         { "normal" : [-1,0 ], "dist" : -490, "bCoef" : 0.1, "cMask" : ["ball" ], "trait" : "ballArea", "vis" : false, "curve" : 0 }
  2269.  
  2270.     ],
  2271.  
  2272.     "traits" : {
  2273.         "ballArea" : { "vis" : false, "bCoef" : 1, "cMask" : ["ball" ] },
  2274.         "goalPost" : { "radius" : 8, "invMass" : 0, "bCoef" : 0.5 },
  2275.         "goalNet" : { "vis" : true, "bCoef" : 0.1, "cMask" : ["ball" ] },
  2276.         "line" : { "vis" : true, "bCoef" : 0.1, "cMask" : ["" ] },
  2277.         "kickOffBarrier" : { "vis" : false, "bCoef" : 0.1, "cGroup" : ["redKO","blueKO" ], "cMask" : ["red","blue" ] }
  2278.  
  2279.     },
  2280.  
  2281.     "playerPhysics" : {
  2282.         "bCoef" : 0,
  2283.         "acceleration" : 0.11,
  2284.         "kickingAcceleration" : 0.083,
  2285.         "kickStrength" : 4.2
  2286.  
  2287.     },
  2288.  
  2289.     "ballPhysics" : {
  2290.         "radius" : 5.8,
  2291.         "bCoef" : 0.412,
  2292.         "invMass" : 1.5,
  2293.         "damping" : 0.99,
  2294.         "color" : "ffd133"
  2295.  
  2296.     }
  2297. }`;
  2298.  
  2299.  
  2300. var maps = {
  2301.     "big": bigmap,
  2302.     "medium": mediummap,
  2303.     "small": smallmap
  2304. };
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top