// CHANGES BY BORRAGEIROS // // -Momento en el que se cambia al mapa grande, changeToBigMapOn variable // - // CHANGES BY BORRAGEIROS /* VARIABLES */ /* ROOM */ const roomName = 'πŸ‡ͺπŸ‡Έ....3οΈβƒ£πŸ†š3️⃣....⚽FUTBOL SALA⚽'; const maxPlayers = 15; const roomPublic = true; const token = ""; // Insert token here var roomWebhook = ''; // this webhook is used to send the details of the room (chat, join, leave) ; it should be in a private discord channel var gameWebhook = ''; // this webhook is used to send the summary of the games ; it should be in a public discord channel var fetchRecordingVariable = true; var timeLimit = 7; var scoreLimit = 3; var gameConfig = { roomName: roomName, maxPlayers: maxPlayers, public: roomPublic, noPlayer: true, } if (typeof token == 'string' && token.length == 39) { gameConfig.token = token; } var room = HBInit(gameConfig); const trainingMap = `{ "name": "Futsal 3x3 4x4 from HaxMaps", "width": 755, "height": 339, "spawnDistance": 310, "bg": { "type": "hockey", "width": 665, "height": 290, "kickOffRadius": 80, "cornerRadius": 0 }, "vertexes": [ { "x": -665, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": 80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": -80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": -290, "trait": "ballArea", "bCoef": 1, "cMask": [ "ball" ] }, { "x": 665, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": 80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": -80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 0, "y": 306, "trait": "kickOffBarrier" }, { "x": 0, "y": 80, "trait": "kickOffBarrier" }, { "x": 0, "y": -80, "trait": "line" }, { "x": 0, "y": -306, "trait": "kickOffBarrier" }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": -693, "y": -80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": 693, "y": -80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": -693, "y": 80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": 693, "y": 80 }, { "trait": "line", "x": -665, "y": -215 }, { "trait": "line", "x": -500, "y": -50 }, { "trait": "line", "x": 665, "y": -215 }, { "trait": "line", "x": 500, "y": -50 }, { "trait": "line", "x": -665, "y": 215 }, { "trait": "line", "x": -500, "y": 50 }, { "trait": "line", "x": 665, "y": 215 }, { "trait": "line", "x": 500, "y": 50 }, { "bCoef": 1, "trait": "ballArea", "x": 665, "y": 290 }, { "bCoef": 1, "trait": "ballArea", "x": 665, "y": -290 }, { "bCoef": 0, "trait": "line", "x": 0, "y": 290 }, { "bCoef": 0, "trait": "line", "x": 0, "y": -290 }, { "x": 0, "y": 80, "trait": "kickOffBarrier" }, { "x": 0, "y": -80, "trait": "kickOffBarrier" }, { "x": 674, "y": -80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": -80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": 80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": 80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 } ], "segments": [ { "v0": 0, "v1": 1, "trait": "ballArea" }, { "v0": 2, "v1": 3, "trait": "ballArea" }, { "v0": 4, "v1": 5, "trait": "ballArea" }, { "v0": 6, "v1": 7, "trait": "ballArea" }, { "v0": 8, "v1": 9, "trait": "kickOffBarrier" }, { "v0": 9, "v1": 10, "trait": "kickOffBarrier", "curve": 180, "cGroup": [ "blueKO" ] }, { "v0": 9, "v1": 10, "trait": "kickOffBarrier", "curve": -180, "cGroup": [ "redKO" ] }, { "v0": 10, "v1": 11, "trait": "kickOffBarrier" }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 2, "v1": 12, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 6, "v1": 13, "color": "FFFFFF", "curve": 35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 1, "v1": 14, "color": "FFFFFF", "curve": 35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 5, "v1": 15, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 12, "v1": 14, "x": -585, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 13, "v1": 15, "x": 585, "color": "FFFFFF", "curve": 35 }, { "color": "FFFFFF", "trait": "line", "v0": 16, "v1": 17, "curve": 90 }, { "color": "FFFFFF", "trait": "line", "v0": 18, "v1": 19, "curve": -90 }, { "color": "FFFFFF", "trait": "line", "v0": 20, "v1": 21, "curve": -90 }, { "color": "FFFFFF", "trait": "line", "v0": 22, "v1": 23, "curve": 90 }, { "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 17, "v1": 21, "curve": 0 }, { "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 19, "v1": 23, "curve": 0 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 1, "v1": 0, "cMask": [ "ball" ], "x": -665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 5, "v1": 4, "cMask": [ "ball" ], "x": 665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 2, "v1": 3, "cMask": [ "ball" ], "x": -665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 6, "v1": 7, "cMask": [ "ball" ], "x": 665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 0, "v1": 24, "y": 290 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 3, "v1": 25, "y": -290 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 26, "v1": 27 }, { "curve": -180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 10, "v1": 9 }, { "curve": 180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 29, "v1": 28 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 2, "v1": 1 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 6, "v1": 5 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 30, "v1": 31, "cMask": [ "ball" ], "x": 614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 32, "v1": 33, "cMask": [ "ball" ], "x": -614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 34, "v1": 35, "cMask": [ "ball" ], "x": -614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 36, "v1": 37, "cMask": [ "ball" ], "x": 614 } ], "goals": [ { "p0": [ -674, -80 ], "p1": [ -674, 80 ], "team": "red" }, { "p0": [ 674, 80 ], "p1": [ 674, -80 ], "team": "blue" } ], "discs": [ { "pos": [ -665, 80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ -665, -80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ 665, 80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ 665, -80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 } ], "planes": [ { "normal": [ 0, 1 ], "dist": -290, "trait": "ballArea" }, { "normal": [ 0, -1 ], "dist": -290, "trait": "ballArea" }, { "normal": [ 0, 1 ], "dist": -339, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 0, -1 ], "dist": -339, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 1, 0 ], "dist": -755, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ -1, 0 ], "dist": -755, "bCoef": 0.2, "cMask": [ "all" ] } ], "traits": { "ballArea": { "vis": false, "bCoef": 1, "cMask": [ "ball" ] }, "goalPost": { "radius": 8, "invMass": 0, "bCoef": 1 }, "goalNet": { "vis": true, "bCoef": 0.1, "cMask": [ "all" ] }, "kickOffBarrier": { "vis": false, "bCoef": 0.1, "cGroup": [ "redKO", "blueKO" ], "cMask": [ "red", "blue" ] }, "line": { "vis": true, "bCoef": 0, "cMask": [ "" ] }, "arco": { "radius": 2, "cMask": [ "n\/d" ], "color": "cccccc" } }, "playerPhysics": { "acceleration": 0.11, "kickingAcceleration": 0.1, "kickStrength": 7 }, "ballPhysics": { "radius": 6.4, "color": "EAFF00" } }`; const classicMap = `{ "name": "Futsal 3x3 4x4 from HaxMaps", "width": 755, "height": 339, "spawnDistance": 310, "bg": { "type": "hockey", "width": 665, "height": 290, "kickOffRadius": 80, "cornerRadius": 0 }, "vertexes": [ { "x": -665, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": 80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": -80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -665, "y": -290, "trait": "ballArea", "bCoef": 1, "cMask": [ "ball" ] }, { "x": 665, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": 80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": -80, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 665, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 0, "y": 306, "trait": "kickOffBarrier" }, { "x": 0, "y": 80, "trait": "kickOffBarrier" }, { "x": 0, "y": -80, "trait": "line" }, { "x": 0, "y": -306, "trait": "kickOffBarrier" }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": -693, "y": -80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": 693, "y": -80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": -693, "y": 80 }, { "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": 693, "y": 80 }, { "trait": "line", "x": -665, "y": -215 }, { "trait": "line", "x": -500, "y": -50 }, { "trait": "line", "x": 665, "y": -215 }, { "trait": "line", "x": 500, "y": -50 }, { "trait": "line", "x": -665, "y": 215 }, { "trait": "line", "x": -500, "y": 50 }, { "trait": "line", "x": 665, "y": 215 }, { "trait": "line", "x": 500, "y": 50 }, { "bCoef": 1, "trait": "ballArea", "x": 665, "y": 290 }, { "bCoef": 1, "trait": "ballArea", "x": 665, "y": -290 }, { "bCoef": 0, "trait": "line", "x": 0, "y": 290 }, { "bCoef": 0, "trait": "line", "x": 0, "y": -290 }, { "x": 0, "y": 80, "trait": "kickOffBarrier" }, { "x": 0, "y": -80, "trait": "kickOffBarrier" }, { "x": 674, "y": -80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": -80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": -290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": 80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": -674, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": 80, "trait": "line", "cMask": [ "ball" ], "bCoef": 1 }, { "x": 674, "y": 290, "trait": "ballArea", "cMask": [ "ball" ], "bCoef": 1 } ], "segments": [ { "v0": 0, "v1": 1, "trait": "ballArea" }, { "v0": 2, "v1": 3, "trait": "ballArea" }, { "v0": 4, "v1": 5, "trait": "ballArea" }, { "v0": 6, "v1": 7, "trait": "ballArea" }, { "v0": 8, "v1": 9, "trait": "kickOffBarrier" }, { "v0": 9, "v1": 10, "trait": "kickOffBarrier", "curve": 180, "cGroup": [ "blueKO" ] }, { "v0": 9, "v1": 10, "trait": "kickOffBarrier", "curve": -180, "cGroup": [ "redKO" ] }, { "v0": 10, "v1": 11, "trait": "kickOffBarrier" }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 2, "v1": 12, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 6, "v1": 13, "color": "FFFFFF", "curve": 35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 1, "v1": 14, "color": "FFFFFF", "curve": 35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 5, "v1": 15, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 12, "v1": 14, "x": -585, "color": "FFFFFF", "curve": -35 }, { "vis": true, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "v0": 13, "v1": 15, "x": 585, "color": "FFFFFF", "curve": 35 }, { "color": "FFFFFF", "trait": "line", "v0": 16, "v1": 17, "curve": 90 }, { "color": "FFFFFF", "trait": "line", "v0": 18, "v1": 19, "curve": -90 }, { "color": "FFFFFF", "trait": "line", "v0": 20, "v1": 21, "curve": -90 }, { "color": "FFFFFF", "trait": "line", "v0": 22, "v1": 23, "curve": 90 }, { "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 17, "v1": 21, "curve": 0 }, { "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 19, "v1": 23, "curve": 0 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 1, "v1": 0, "cMask": [ "ball" ], "x": -665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 5, "v1": 4, "cMask": [ "ball" ], "x": 665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 2, "v1": 3, "cMask": [ "ball" ], "x": -665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 6, "v1": 7, "cMask": [ "ball" ], "x": 665 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 0, "v1": 24, "y": 290 }, { "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 3, "v1": 25, "y": -290 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 26, "v1": 27 }, { "curve": -180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 10, "v1": 9 }, { "curve": 180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 29, "v1": 28 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 2, "v1": 1 }, { "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "v0": 6, "v1": 5 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 30, "v1": 31, "cMask": [ "ball" ], "x": 614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 32, "v1": 33, "cMask": [ "ball" ], "x": -614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 34, "v1": 35, "cMask": [ "ball" ], "x": -614 }, { "vis": false, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "v0": 36, "v1": 37, "cMask": [ "ball" ], "x": 614 } ], "goals": [ { "p0": [ -674, -80 ], "p1": [ -674, 80 ], "team": "red" }, { "p0": [ 674, 80 ], "p1": [ 674, -80 ], "team": "blue" } ], "discs": [ { "pos": [ -665, 80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ -665, -80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ 665, 80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 }, { "pos": [ 665, -80 ], "trait": "goalPost", "color": "FFFFFF", "radius": 5 } ], "planes": [ { "normal": [ 0, 1 ], "dist": -290, "trait": "ballArea" }, { "normal": [ 0, -1 ], "dist": -290, "trait": "ballArea" }, { "normal": [ 0, 1 ], "dist": -339, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 0, -1 ], "dist": -339, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 1, 0 ], "dist": -755, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ -1, 0 ], "dist": -755, "bCoef": 0.2, "cMask": [ "all" ] } ], "traits": { "ballArea": { "vis": false, "bCoef": 1, "cMask": [ "ball" ] }, "goalPost": { "radius": 8, "invMass": 0, "bCoef": 1 }, "goalNet": { "vis": true, "bCoef": 0.1, "cMask": [ "all" ] }, "kickOffBarrier": { "vis": false, "bCoef": 0.1, "cGroup": [ "redKO", "blueKO" ], "cMask": [ "red", "blue" ] }, "line": { "vis": true, "bCoef": 0, "cMask": [ "" ] }, "arco": { "radius": 2, "cMask": [ "n\/d" ], "color": "cccccc" } }, "playerPhysics": { "acceleration": 0.11, "kickingAcceleration": 0.1, "kickStrength": 7 }, "ballPhysics": { "radius": 6.4, "color": "EAFF00" } }`; const bigMap = `{ "name": "Futsal x5 GLH ; By Bazinga! from HaxMaps", "width": 1080, "height": 532, "spawnDistance": 310, "bg": { "type": "hockey", "width": 950, "height": 460, "kickOffRadius": 6, "cornerRadius": 0 }, "vertexes": [ { "x": -950, "y": 460, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": -950, "y": 90, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0, "color": "ffffff" }, { "x": -950, "y": -90, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0, "color": "ffffff" }, { "x": -950, "y": -460, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": 950, "y": 456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": 950, "y": 90, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0, "color": "ffffff" }, { "x": 950, "y": -90, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0, "color": "ffffff" }, { "x": 950, "y": -456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": 0, "y": 508, "trait": "kickOffBarrier" }, { "x": 0, "y": 150, "trait": "kickOffBarrier" }, { "x": 0, "y": -150, "trait": "line" }, { "x": 0, "y": -508, "trait": "kickOffBarrier" }, { "x": -995, "y": -90, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "curve": 0 }, { "x": 995, "y": -90, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "curve": 0 }, { "x": -995, "y": 90, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "curve": 0 }, { "x": 995, "y": 90, "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "curve": 0 }, { "x": 951, "y": 460, "bCoef": 1, "trait": "ballArea" }, { "x": 951, "y": -460, "bCoef": 1, "trait": "ballArea" }, { "x": 0, "y": 460, "bCoef": 0, "trait": "line", "curve": 0 }, { "x": 0, "y": -460, "bCoef": 0, "trait": "line", "curve": 0 }, { "x": 0, "y": 150, "trait": "kickOffBarrier" }, { "x": 0, "y": -150, "trait": "kickOffBarrier" }, { "x": 958, "y": -90, "bCoef": 1, "cMask": [ "ball" ], "trait": "line", "curve": 0 }, { "x": 958, "y": -456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": -958, "y": -90, "bCoef": 1, "cMask": [ "ball" ], "trait": "line", "curve": 0 }, { "x": -958, "y": -456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": -958, "y": 90, "bCoef": 1, "cMask": [ "ball" ], "trait": "line", "curve": 0 }, { "x": -958, "y": 456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": 958, "y": 90, "bCoef": 1, "cMask": [ "ball" ], "trait": "line", "curve": 0 }, { "x": 958, "y": 456, "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "curve": 0 }, { "x": 0, "y": -9, "trait": "line", "curve": -180 }, { "x": 0, "y": 9, "trait": "line", "curve": -180 }, { "x": 0, "y": -9, "trait": "line", "curve": 180 }, { "x": 0, "y": 9, "trait": "line", "curve": 180 }, { "x": 634.21528583524, "y": -109.20953737271, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 0 }, { "x": 634.21528583524, "y": 114.16613046747, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 44.336382176589 }, { "x": 634.21528583524, "y": 114.16613046747, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 }, { "x": 950, "y": 324.62551819445, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 }, { "x": 634.21528583524, "y": -109.20953737271, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 90 }, { "x": -423.82978278939, "y": 449, "bCoef": 0.1, "trait": "line" }, { "x": -423.82978278939, "y": 471, "bCoef": 0.1, "trait": "line" }, { "x": -222.35509186163, "y": 449, "bCoef": 0.1, "trait": "line" }, { "x": -222.35509186163, "y": 471, "bCoef": 0.1, "trait": "line" }, { "x": 386.06898092163, "y": 449, "bCoef": 0.1, "trait": "line" }, { "x": 386.06898092163, "y": 471, "bCoef": 0.1, "trait": "line" }, { "x": 184.59428999387, "y": 449, "bCoef": 0.1, "trait": "line" }, { "x": 184.59428999387, "y": 471, "bCoef": 0.1, "trait": "line" }, { "x": -657.56254462949, "y": 460, "bCoef": 0.1, "trait": "line" }, { "x": -657.56254462949, "y": 473, "bCoef": 0.1, "trait": "line" }, { "x": 975, "y": 193.91895440419, "bCoef": 0.1, "trait": "line" }, { "x": 956, "y": 193.91895440419, "bCoef": 0.1, "trait": "line" }, { "x": 975, "y": -188.96236130943, "bCoef": 0.1, "trait": "line" }, { "x": 956, "y": -188.96236130943, "bCoef": 0.1, "trait": "line" }, { "x": -667.82213435646, "y": -460, "bCoef": 0.1, "trait": "line" }, { "x": -667.82213435646, "y": -473, "bCoef": 0.1, "trait": "line" }, { "x": 621.80174276174, "y": 460, "bCoef": 0.1, "trait": "line" }, { "x": 621.80174276174, "y": 473, "bCoef": 0.1, "trait": "line" }, { "x": 644.74331148229, "y": -460, "bCoef": 0.1, "trait": "line" }, { "x": 644.74331148229, "y": -473, "bCoef": 0.1, "trait": "line" }, { "x": 634.35340467604, "y": 4.2212921610516, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": 1.7712285482462, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": 6.6713557738571, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": -0.67883506455928, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": 0.54619674184346, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": 5.4463239674544, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": -1.2913509677606, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 634.35340467604, "y": 7.2838716770584, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 4.2212921610516, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 1.7712285482462, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 6.6713557738571, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": -0.67883506455928, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 0.54619674184346, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 5.4463239674544, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": -1.2913509677606, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 484.86942705432, "y": 7.2838716770584, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -975, "y": -191.85660774843, "bCoef": 0.1, "trait": "line" }, { "x": -956, "y": -191.96236130943, "bCoef": 0.1, "trait": "line" }, { "x": -975, "y": 190.91895440419, "bCoef": 0.1, "trait": "line" }, { "x": -956, "y": 190.91895440419, "bCoef": 0.1, "trait": "line" }, { "x": -950, "y": 432.90041943973, "bCoef": 0.1, "trait": "line", "curve": -90 }, { "x": -926.21802170761, "y": 460, "bCoef": 0.1, "trait": "line", "curve": -90 }, { "x": -950, "y": -433.32499678239, "bCoef": 0.1, "trait": "line", "curve": 90 }, { "x": -925.43621788149, "y": -460, "bCoef": 0.1, "trait": "line", "curve": 90 }, { "x": 950, "y": -433.36622514797, "bCoef": 0.1, "trait": "line", "curve": -90 }, { "x": 927.73220749769, "y": -460, "bCoef": 0.1, "trait": "line", "curve": -90 }, { "x": 950, "y": 434.55334331787, "bCoef": 0.1, "trait": "line", "curve": 90 }, { "x": 925.51401132381, "y": 460, "bCoef": 0.1, "trait": "line", "curve": 90 }, { "x": 950, "y": -319.66892509968, "bCoef": 0, "trait": "line", "curve": 90 }, { "x": -635.67083595539, "y": 111.16613046747, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 0 }, { "x": -635.67083595539, "y": -112.20953737271, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 44.336382176589 }, { "x": -950, "y": -322.66892509968, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 }, { "x": -635.82253673536, "y": -2.314063297901, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.83851134042, "y": 0.13595112921681, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.80656213031, "y": -4.764077725019, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.85448594547, "y": 2.5859655563347, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.84649864294, "y": 1.3609583427757, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.81454943284, "y": -3.53907051146, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.85847959673, "y": 3.1984691631142, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -635.80256847905, "y": -5.3765813317984, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.3415600448, "y": -1.3935524756233, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.35753464985, "y": 1.0564619514946, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.32558543975, "y": -3.8435669027412, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.3735092549, "y": 3.5064763786125, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.36552195238, "y": 2.2814691650535, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.33357274227, "y": -2.6185596891822, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.37750290617, "y": 4.1189799853919, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -486.32159178848, "y": -4.4560705095206, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -950, "y": 321.62551819445, "bCoef": 0, "trait": "line", "curve": 90 }, { "x": 486.4717644406, "y": -216.68073468914, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": 486.26181026907, "y": -213.90354363921, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": 484.90815678836, "y": 227.79125744183, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": 484.69820261683, "y": 230.56844849177, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": -487.89251107699, "y": -222.71985942166, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": -488.10246524852, "y": -219.94266837173, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": -487.11070725087, "y": 223.27169507557, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": -487.3206614224, "y": 226.04888612551, "bCoef": 0.1, "trait": "line", "curve": 200 }, { "x": -0.077614373673782, "y": -2.4626457981722, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.10499941090626, "y": 2.3835365851378, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.050229336441873, "y": -7.3088281814824, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.13238444813857, "y": 7.2297189684479, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.11869192952281, "y": 4.8066277767929, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.063921855057799, "y": -4.8857369898273, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.13923070744664, "y": 8.4412645642754, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -0.043383077133171, "y": -8.5203737773099, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 0.77952848346911, "y": 1.5373542018278, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 2.7521434462366, "y": 3.3835365851378, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 0.80691352070102, "y": -3.3088281814824, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 1.7247584090043, "y": 2.2297189684479, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 2.73845092762, "y": 5.8066277767929, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 0.79322100208503, "y": -0.88573698982727, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 1.7179121496962, "y": 3.4412645642754, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": 0.81375978000966, "y": -4.5203737773099, "bCoef": 0.1, "trait": "line", "curve": 180 }, { "x": -950, "y": -322.66892509968, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 }, { "x": -950, "y": 321.62551819445, "bCoef": 0, "trait": "line", "curve": 90 }, { "x": -635.67083595539, "y": 111.16613046747, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": 90 }, { "x": -950, "y": 321.62551819445, "bCoef": 0, "trait": "line", "curve": 90 }, { "x": -635.67083595539, "y": -112.20953737271, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 }, { "x": -950, "y": -322.66892509968, "bCoef": 0, "cMask": [ "" ], "trait": "line", "curve": -90 } ], "segments": [ { "v0": 0, "v1": 1, "curve": 0, "trait": "ballArea" }, { "v0": 2, "v1": 3, "trait": "ballArea" }, { "v0": 4, "v1": 5, "trait": "ballArea", "x": 951 }, { "v0": 6, "v1": 7, "trait": "ballArea", "x": 951 }, { "v0": 8, "v1": 9, "trait": "kickOffBarrier", "x": 0 }, { "v0": 9, "v1": 10, "curve": 180, "cGroup": [ "blueKO" ], "trait": "kickOffBarrier" }, { "v0": 9, "v1": 10, "curve": -180, "cGroup": [ "redKO" ], "trait": "kickOffBarrier" }, { "v0": 10, "v1": 11, "trait": "kickOffBarrier", "x": 0 }, { "v0": 2, "v1": 12, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "y": -95 }, { "v0": 6, "v1": 13, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "y": -95 }, { "v0": 1, "v1": 14, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "y": 95 }, { "v0": 5, "v1": 15, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "y": 95 }, { "v0": 12, "v1": 14, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": -821 }, { "v0": 13, "v1": 15, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0.1, "cMask": [ "ball" ], "trait": "goalNet", "x": 585 }, { "v0": 1, "v1": 0, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": -950 }, { "v0": 5, "v1": 4, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": 950 }, { "v0": 2, "v1": 3, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": -950 }, { "v0": 6, "v1": 7, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": 950 }, { "v0": 0, "v1": 16, "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "y": 460 }, { "v0": 3, "v1": 17, "vis": true, "color": "FFFFFF", "bCoef": 1, "trait": "ballArea", "y": -460 }, { "v0": 18, "v1": 19, "curve": 0, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line" }, { "v0": 10, "v1": 9, "curve": -180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line" }, { "v0": 21, "v1": 20, "curve": 180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line" }, { "v0": 2, "v1": 1, "curve": 0, "vis": true, "color": "ffffff", "bCoef": 0, "trait": "line", "x": -950 }, { "v0": 6, "v1": 5, "curve": 0, "vis": true, "color": "ffffff", "bCoef": 0, "trait": "line" }, { "v0": 22, "v1": 23, "curve": 0, "vis": false, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": 958 }, { "v0": 24, "v1": 25, "curve": 0, "vis": false, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": -958 }, { "v0": 26, "v1": 27, "curve": 0, "vis": false, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": -958 }, { "v0": 28, "v1": 29, "curve": 0, "vis": false, "color": "FFFFFF", "bCoef": 1, "cMask": [ "ball" ], "trait": "ballArea", "x": 958 }, { "v0": 30, "v1": 31, "curve": -180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "x": 572 }, { "v0": 32, "v1": 33, "curve": 180, "vis": true, "color": "FFFFFF", "bCoef": 0, "trait": "line", "x": 0 }, { "v0": 34, "v1": 35, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0, "cMask": [ "" ], "trait": "line" }, { "v0": 36, "v1": 37, "curve": -90, "vis": true, "color": "F8F8F8", "bCoef": 0, "cMask": [ "" ], "trait": "line" }, { "v0": 39, "v1": 40, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -240 }, { "v0": 41, "v1": 42, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -120 }, { "v0": 43, "v1": 44, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 240 }, { "v0": 45, "v1": 46, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 120 }, { "v0": 47, "v1": 48, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -381 }, { "v0": 49, "v1": 50, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -240, "y": 251.96814834 }, { "v0": 51, "v1": 52, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -240, "y": -251.96814834 }, { "v0": 53, "v1": 54, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -381 }, { "v0": 55, "v1": 56, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 381 }, { "v0": 57, "v1": 58, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 381 }, { "v0": 60, "v1": 59, "curve": 180.00000000015, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 59, "v1": 60, "curve": 180.00000000011, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 62, "v1": 61, "curve": 179.99999999999, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 61, "v1": 62, "curve": 180.00000000001, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 64, "v1": 63, "curve": 180.00000000006, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 63, "v1": 64, "curve": 180.00000000001, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 66, "v1": 65, "curve": 179.99999999999, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 65, "v1": 66, "curve": 179.99999999999, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 68, "v1": 67, "curve": 179.99999999994, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 67, "v1": 68, "curve": 180.00000000006, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 70, "v1": 69, "curve": 180, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 69, "v1": 70, "curve": 180, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 72, "v1": 71, "curve": 179.99999999998, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 71, "v1": 72, "curve": 179.99999999998, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 74, "v1": 73, "curve": 180, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 73, "v1": 74, "curve": 180, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 75, "v1": 76, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -240, "y": 123 }, { "v0": 77, "v1": 78, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": -240, "y": 251.96814834 }, { "v0": 80, "v1": 79, "curve": -91.636910923379, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 82, "v1": 81, "curve": 91.636910923384, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 84, "v1": 83, "curve": -91.636910923386, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 86, "v1": 85, "curve": 91.636910923367, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 38, "v1": 87, "curve": 90, "vis": true, "color": "F8F8F8", "bCoef": 0, "trait": "line" }, { "v0": 88, "v1": 89, "curve": 0, "vis": true, "color": "F8F8F8", "bCoef": 0, "cMask": [ "" ], "trait": "line" }, { "v0": 92, "v1": 91, "curve": 180.04149903472, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 91, "v1": 92, "curve": 180.04149903448, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 94, "v1": 93, "curve": 180.04149903461, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 93, "v1": 94, "curve": 180.04149903457, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 96, "v1": 95, "curve": 180.0414990346, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 95, "v1": 96, "curve": 180.04149903458, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 98, "v1": 97, "curve": 180.04149903458, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 97, "v1": 98, "curve": 180.0414990346, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 375 }, { "v0": 100, "v1": 99, "curve": 180.04149903447, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 99, "v1": 100, "curve": 180.04149903471, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 102, "v1": 101, "curve": 180.0414990346, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 101, "v1": 102, "curve": 180.04149903457, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 104, "v1": 103, "curve": 180.04149903454, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 103, "v1": 104, "curve": 180.04149903457, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 106, "v1": 105, "curve": 180.04149903458, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 105, "v1": 106, "curve": 180.04149903459, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 108, "v1": 109, "curve": -196.43548932859, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 109, "v1": 108, "curve": -211.97212519444, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 110, "v1": 111, "curve": -196.43548932841, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 111, "v1": 110, "curve": -211.97212519486, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 112, "v1": 113, "curve": -196.43548932818, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 113, "v1": 112, "curve": -211.97212519503, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 114, "v1": 115, "curve": -196.4354893283, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 115, "v1": 114, "curve": -211.97212519445, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line" }, { "v0": 117, "v1": 116, "curve": 179.83332296199, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 116, "v1": 117, "curve": 179.8333229623, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 119, "v1": 118, "curve": 179.83332296215, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 118, "v1": 119, "curve": 179.8333229621, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 121, "v1": 120, "curve": 179.83332296204, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 120, "v1": 121, "curve": 179.83332296211, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 123, "v1": 122, "curve": 179.8333229621, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 122, "v1": 123, "curve": 179.83332296208, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 125, "v1": 124, "curve": 179.83332296199, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 124, "v1": 125, "curve": 179.8333229623, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 127, "v1": 126, "curve": 179.83332296215, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 126, "v1": 127, "curve": 179.8333229621, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 129, "v1": 128, "curve": 179.83332296204, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 128, "v1": 129, "curve": 179.83332296211, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 131, "v1": 130, "curve": 179.8333229621, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 130, "v1": 131, "curve": 179.83332296208, "vis": true, "color": "F8F8F8", "bCoef": 0.1, "trait": "line", "x": 277.5 }, { "v0": 134, "v1": 135, "curve": 90, "vis": true, "color": "F8F8F8", "bCoef": 0, "trait": "line" }, { "v0": 136, "v1": 137, "curve": -90, "vis": true, "color": "F8F8F8", "bCoef": 0, "cMask": [ "" ], "trait": "line" } ], "goals": [ { "p0": [ -957.4, -90 ], "p1": [ -957.4, 90 ], "team": "red" }, { "p0": [ 957.4, 90 ], "p1": [ 957.4, -90 ], "team": "blue" } ], "discs": [ { "radius": 5, "pos": [ -950, 90 ], "color": "6666CC", "trait": "goalPost" }, { "radius": 5, "pos": [ -950, -90 ], "color": "6666CC", "trait": "goalPost" }, { "radius": 5, "pos": [ 950, 90 ], "color": "6666CC", "trait": "goalPost" }, { "radius": 5, "pos": [ 950, -90 ], "color": "6666CC", "trait": "goalPost" }, { "radius": 3, "invMass": 0, "pos": [ -950, 460 ], "color": "FFCC00", "bCoef": 0.1, "trait": "line" }, { "radius": 3, "invMass": 0, "pos": [ -950, -460 ], "color": "FFCC00", "bCoef": 0.1, "trait": "line" }, { "radius": 3, "invMass": 0, "pos": [ 950, -460 ], "color": "FFCC00", "bCoef": 0.1, "trait": "line" }, { "radius": 3, "invMass": 0, "pos": [ 950, 460 ], "color": "FFCC00", "bCoef": 0.1, "trait": "line" } ], "planes": [ { "normal": [ 0, 1 ], "dist": -456, "trait": "ballArea" }, { "normal": [ 0, -1 ], "dist": -456, "trait": "ballArea" }, { "normal": [ 0, 1 ], "dist": -508, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 0, -1 ], "dist": -508, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ 1, 0 ], "dist": -1002, "bCoef": 0.2, "cMask": [ "all" ] }, { "normal": [ -1, 0 ], "dist": -1002, "bCoef": 0.2, "cMask": [ "all" ] } ], "traits": { "ballArea": { "vis": false, "bCoef": 1, "cMask": [ "ball" ] }, "goalPost": { "radius": 8, "invMass": 0, "bCoef": 1 }, "goalNet": { "vis": true, "bCoef": 0.1, "cMask": [ "all" ] }, "kickOffBarrier": { "vis": false, "bCoef": 0.1, "cGroup": [ "redKO", "blueKO" ], "cMask": [ "red", "blue" ] }, "line": { "vis": true, "bCoef": 0, "cMask": [ "" ] }, "arco": { "radius": 2, "cMask": [ "n\/d" ], "color": "cccccc" } }, "playerPhysics": { "bCoef": 0, "acceleration": 0.11, "kickingAcceleration": 0.083, "kickStrength": 5 }, "ballPhysics": { "radius": 6.4, "bCoef": 0.4, "invMass": 1.5, "damping": 0.99, "color": "FFCC00" } }`; var currentStadium = 'training'; var bigMapObj = JSON.parse(trainingMap); room.setScoreLimit(scoreLimit); room.setTimeLimit(timeLimit); room.setTeamsLock(true); room.setKickRateLimit(6, 0, 0); var masterPassword = 10000 + getRandomInt(90000); var roomPassword = ''; /* OPTIONS */ // by borrageiros var changeToBigMapOn = 8; // by borrageiros var drawTimeLimit = Infinity; var teamSize = 5; var maxAdmins = 0; var disableBans = false; var debugMode = false; var afkLimit = debugMode ? Infinity : 12; var defaultSlowMode = 0.5; var chooseModeSlowMode = 1; var slowMode = defaultSlowMode; var SMSet = new Set(); var hideClaimMessage = true; var mentionPlayersUnpause = true; /* OBJECTS */ class Goal { constructor(time, team, striker, assist) { this.time = time; this.team = team; this.striker = striker; this.assist = assist; } } class Game { constructor() { this.date = Date.now(); this.scores = room.getScores(); this.playerComp = getStartingLineups(); this.goals = []; this.rec = room.startRecording(); this.touchArray = []; } } class PlayerComposition { constructor(player, auth, timeEntry, timeExit) { this.player = player; this.auth = auth; this.timeEntry = timeEntry; this.timeExit = timeExit; this.inactivityTicks = 0; this.GKTicks = 0; } } class MutePlayer { constructor(name, id, auth) { this.id = MutePlayer.incrementId(); this.name = name; this.playerId = id; this.auth = auth; this.unmuteTimeout = null; } static incrementId() { if (!this.latestId) this.latestId = 1 else this.latestId++ return this.latestId } setDuration(minutes) { this.unmuteTimeout = setTimeout(() => { room.sendAnnouncement( `You have been unmuted.`, this.playerId, announcementColor, "bold", HaxNotification.CHAT ); this.remove(); }, minutes * 60 * 1000); muteArray.add(this); } remove() { this.unmuteTimeout = null; muteArray.removeById(this.id); } } class MuteList { constructor() { this.list = []; } add(mutePlayer) { this.list.push(mutePlayer); return mutePlayer; } getById(id) { var index = this.list.findIndex(mutePlayer => mutePlayer.id === id); if (index !== -1) { return this.list[index]; } return null; } getByPlayerId(id) { var index = this.list.findIndex(mutePlayer => mutePlayer.playerId === id); if (index !== -1) { return this.list[index]; } return null; } getByAuth(auth) { var index = this.list.findIndex(mutePlayer => mutePlayer.auth === auth); if (index !== -1) { return this.list[index]; } return null; } removeById(id) { var index = this.list.findIndex(mutePlayer => mutePlayer.id === id); if (index !== -1) { this.list.splice(index, 1); } } removeByAuth(auth) { var index = this.list.findIndex(mutePlayer => mutePlayer.auth === auth); if (index !== -1) { this.list.splice(index, 1); } } } class BallTouch { constructor(player, time, goal, position) { this.player = player; this.time = time; this.goal = goal; this.position = position; } } class HaxStatistics { constructor(playerName = '') { this.playerName = playerName; this.games = 0; this.wins = 0; this.winrate = '0.00%'; this.playtime = 0; this.goals = 0; this.assists = 0; this.CS = 0; this.ownGoals = 0; } } /* PLAYERS */ const Team = { SPECTATORS: 0, RED: 1, BLUE: 2 }; const State = { PLAY: 0, PAUSE: 1, STOP: 2 }; const Role = { PLAYER: 0, ADMIN_TEMP: 1, ADMIN_PERM: 2, MASTER: 3 }; const HaxNotification = { NONE: 0, CHAT: 1, MENTION: 2 }; const Situation = { STOP: 0, KICKOFF: 1, PLAY: 2, GOAL: 3 }; var gameState = State.STOP; var playSituation = Situation.STOP; var goldenGoal = false; var playersAll = []; var players = []; var teamRed = []; var teamBlue = []; var teamSpec = []; var teamRedStats = []; var teamBlueStats = []; var banList = []; /* STATS */ var possession = [0, 0]; var actionZoneHalf = [0, 0]; var lastWinner = Team.SPECTATORS; var streak = 0; /* AUTH */ var authArray = []; var adminList = [ ["amuZ3Vk-M6Vk8_DuphOjismmfRRo4SQ44RyUuLb9nLc", "borrageiros"], // borrageiros ["_LSQgSnedi0Y2E86tf5-ql6fLYORVHUDsEvilNFXKA4", "xoel"] // xoel // ['INSERT_AUTH_HERE_1', 'NICK_OF_ADMIN_1'], // ['INSERT_AUTH_HERE_2', 'NICK_OF_ADMIN_2'], ]; var masterList = [ 'amuZ3Vk-M6Vk8_DuphOjismmfRRo4SQ44RyUuLb9nLc', '_LSQgSnedi0Y2E86tf5-ql6fLYORVHUDsEvilNFXKA4' ]; /* COMMANDS */ var commands = { help: { aliases: ['commands'], roles: Role.PLAYER, desc: ` This command shows all the available commands. It also can show the description of a command in particular. Example: \'!help bb\' will show the description of the \'bb\' command.`, function: helpCommand, }, claim: { aliases: [], roles: Role.PLAYER, desc: false, function: masterCommand, }, afk: { aliases: [], roles: Role.PLAYER, desc: ` This command makes you go AFK. It has constraints: 1 minute minimum of AFK time, 5 minutes maximum and 10 minutes cooldown.`, function: afkCommand, }, afks: { aliases: ['afklist'], roles: Role.PLAYER, desc: ` This command shows all the players that are AFK.`, function: afkListCommand, }, bb: { aliases: ['bye', 'gn', 'cya'], roles: Role.PLAYER, desc: ` This command makes you leave instantly (use recommended).`, function: leaveCommand, }, me: { aliases: ['stat', 'stats'], roles: Role.PLAYER, desc: ` This command shows your global stats in the room.`, function: globalStatsCommand, }, rename: { aliases: [], roles: Role.PLAYER, desc: ` This command allows you to rename yourself for the leaderboard.`, function: renameCommand, }, games: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most games in the room.`, function: statsLeaderboardCommand, }, wins: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most wins in the room.`, function: statsLeaderboardCommand, }, goals: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most goals in the room.`, function: statsLeaderboardCommand, }, assists: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most assists in the room.`, function: statsLeaderboardCommand, }, cs: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most CS in the room.`, function: statsLeaderboardCommand, }, playtime: { aliases: [], roles: Role.PLAYER, desc: ` This command shows the top 5 players with the most time played in the room.`, function: statsLeaderboardCommand, }, training: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command loads the classic training stadium.`, function: stadiumCommand, }, classic: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command loads the classic stadium.`, function: stadiumCommand, }, big: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command loads the big stadium.`, function: stadiumCommand, }, rr: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command restarts the game.`, function: restartCommand, }, rrs: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command swaps the teams and restarts the game.`, function: restartSwapCommand, }, swap: { aliases: ['s'], roles: Role.ADMIN_TEMP, desc: ` This command swaps the teams when the game is stopped.`, function: swapCommand, }, kickred: { aliases: ['kickr'], roles: Role.ADMIN_TEMP, desc: ` This command kicks all the players from the red team, including the player that entered the command. You can give as an argument the reason of the kick.`, function: kickTeamCommand, }, kickblue: { aliases: ['kickb'], roles: Role.ADMIN_TEMP, desc: ` This command kicks all the players from the blue team, including the player that entered the command. You can give as an argument the reason of the kick.`, function: kickTeamCommand, }, kickspec: { aliases: ['kicks'], roles: Role.ADMIN_TEMP, desc: ` This command kicks all the players from the spectators team, including the player that entered the command. You can give as an argument the reason of the kick.`, function: kickTeamCommand, }, mute: { aliases: ['m'], roles: Role.ADMIN_TEMP, desc: ` This command allows to mute a player. He won't be able to talk for a certain duration, and can be unmuted at any time by admins. It takes 2 arguments: Argument 1: # where is the id of the player targeted. This won't work if the player is an admin. Argument 2 (optional): where is the duration of the mute in minutes. If no value is provided, the mute lasts for the default duration, ${muteDuration} minutes. Example: !mute #3 20 will mute the player with id 3 for 20 minutes.`, function: muteCommand, }, unmute: { aliases: ['um'], roles: Role.ADMIN_TEMP, desc: ` This command allows to unmute someone. It takes 1 argument: Argument 1: # where is the id of the muted player. OR Argument 1: where is the number associated with the mute given by the 'muteList' command. Example: !unmute #300 will unmute the player with id 300, !unmute 8 will unmute the nΒ°8 player according to the 'muteList' command.`, function: unmuteCommand, }, mutes: { aliases: [], roles: Role.ADMIN_TEMP, desc: ` This command shows the list of muted players.`, function: muteListCommand, }, clearbans: { aliases: [], roles: Role.MASTER, desc: ` This command unbans everyone. It also can unban one player in particular, by adding his ID as an argument.`, function: clearbansCommand, }, bans: { aliases: ['banlist'], roles: Role.MASTER, desc: ` This command shows all the players that were banned and their IDs.`, function: banListCommand, }, admins: { aliases: ['adminlist'], roles: Role.MASTER, desc: ` This command shows all the players that are permanent admins.`, function: adminListCommand, }, setadmin: { aliases: ['admin'], roles: Role.MASTER, desc: ` This command allows to set someone as admin. He will be able to connect as admin, and can be removed at any time by masters. It takes 1 argument: Argument 1: # where is the id of the player targeted. Example: !setadmin #3 will give admin to the player with id 3.`, function: setAdminCommand, }, removeadmin: { aliases: ['unadmin'], roles: Role.MASTER, desc: ` This command allows to remove someone as admin. It takes 1 argument: Argument 1: # where is the id of the player targeted. OR Argument 1: where is the number associated with the admin given by the 'admins' command. Example: !removeadmin #300 will remove admin to the player with id 300, !removeadmin 2 will remove the admin nΒ°2 according to the 'admins' command.`, function: removeAdminCommand, }, password: { aliases: ['pw'], roles: Role.MASTER, desc: ` This command allows to add a password to the room. It takes 1 argument: Argument 1: where is the password you want for the room. To remove the room password, simply enter '!password'.`, function: passwordCommand, }, }; /* GAME */ var lastTouches = Array(2).fill(null); var lastTeamTouched; var speedCoefficient = 100 / (5 * (0.99 ** 60 + 1)); var ballSpeed = 0; var playerRadius = 15; var ballRadius = 10; var triggerDistance = playerRadius + ballRadius + 0.01; /* COLORS */ var welcomeColor = 0xc4ff65; var announcementColor = 0xffefd6; var infoColor = 0xbebebe; var privateMessageColor = 0xffc933; var redColor = 0xff4c4c; var blueColor = 0x62cbff; var warningColor = 0xffa135; var errorColor = 0xa40000; var successColor = 0x75ff75; var defaultColor = null; /* AUXILIARY */ var checkTimeVariable = false; var checkStadiumVariable = true; var endGameVariable = false; var cancelGameVariable = false; var kickFetchVariable = false; var chooseMode = false; var timeOutCap; var capLeft = false; var redCaptainChoice = ''; var blueCaptainChoice = ''; var chooseTime = 20; var AFKSet = new Set(); var AFKMinSet = new Set(); var AFKCooldownSet = new Set(); var minAFKDuration = 0; var maxAFKDuration = 30; var AFKCooldown = 0; var muteArray = new MuteList(); var muteDuration = 5; var removingPlayers = false; var insertingPlayers = false; var stopTimeout; var startTimeout; var unpauseTimeout; var removingTimeout; var insertingTimeout; var emptyPlayer = { id: 0, }; stadiumCommand(emptyPlayer, "!training"); var game = new Game(); /* FUNCTIONS */ /* AUXILIARY FUNCTIONS */ if (typeof String.prototype.replaceAll != 'function') { String.prototype.replaceAll = function (search, replacement) { var target = this; return target.split(search).join(replacement); }; } function getDate() { let d = new Date(); return d.toLocaleDateString() + ' ' + d.toLocaleTimeString(); } /* MATH FUNCTIONS */ function getRandomInt(max) { // returns a random number between 0 and max-1 return Math.floor(Math.random() * Math.floor(max)); } function pointDistance(p1, p2) { return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2)); } /* TIME FUNCTIONS */ function getHoursStats(time) { return Math.floor(time / 3600); } function getMinutesGame(time) { var t = Math.floor(time / 60); return `${Math.floor(t / 10)}${Math.floor(t % 10)}`; } function getMinutesReport(time) { return Math.floor(Math.round(time) / 60); } function getMinutesEmbed(time) { var t = Math.floor(Math.round(time) / 60); return `${Math.floor(t / 10)}${Math.floor(t % 10)}`; } function getMinutesStats(time) { return Math.floor(time / 60) - getHoursStats(time) * 60; } function getSecondsGame(time) { var t = Math.floor(time - Math.floor(time / 60) * 60); return `${Math.floor(t / 10)}${Math.floor(t % 10)}`; } function getSecondsReport(time) { var t = Math.round(time); return Math.floor(t - getMinutesReport(t) * 60); } function getSecondsEmbed(time) { var t = Math.round(time); var t2 = Math.floor(t - Math.floor(t / 60) * 60); return `${Math.floor(t2 / 10)}${Math.floor(t2 % 10)}`; } function getTimeGame(time) { return `[${getMinutesGame(time)}:${getSecondsGame(time)}]`; } function getTimeEmbed(time) { return `[${getMinutesEmbed(time)}:${getSecondsEmbed(time)}]`; } function getTimeStats(time) { if (getHoursStats(time) > 0) { return `${getHoursStats(time)}h${getMinutesStats(time)}m`; } else { return `${getMinutesStats(time)}m`; } } function getGoalGame() { return game.scores.red + game.scores.blue; } /* REPORT FUNCTIONS */ function findFirstNumberCharString(str) { let str_number = str[str.search(/[0-9]/g)]; return str_number === undefined ? "0" : str_number; } function getIdReport() { var d = new Date(); return `${d.getFullYear() % 100}${d.getMonth() < 9 ? '0' : ''}${d.getMonth() + 1}${d.getDate() < 10 ? '0' : ''}${d.getDate()}${d.getHours() < 10 ? '0' : ''}${d.getHours()}${d.getMinutes() < 10 ? '0' : ''}${d.getMinutes()}${d.getSeconds() < 10 ? '0' : ''}${d.getSeconds()}${findFirstNumberCharString(roomName)}`; } function getRecordingName(game) { let d = new Date(); let redCap = game.playerComp[0][0] != undefined ? game.playerComp[0][0].player.name : 'Red'; let blueCap = game.playerComp[1][0] != undefined ? game.playerComp[1][0].player.name : 'Blue'; let day = d.getDate() < 10 ? '0' + d.getDate() : d.getDate(); let month = d.getMonth() < 10 ? '0' + (d.getMonth() + 1) : (d.getMonth() + 1); let year = d.getFullYear() % 100 < 10 ? '0' + (d.getFullYear() % 100) : (d.getFullYear() % 100); let hour = d.getHours() < 10 ? '0' + d.getHours() : d.getHours(); let minute = d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes(); return `${day}-${month}-${year}-${hour}h${minute}-${redCap}vs${blueCap}.hbr2`; } function fetchRecording(game) { if (gameWebhook != "") { let form = new FormData(); form.append(null, new File([game.rec], getRecordingName(game), { "type": "text/plain" })); form.append("payload_json", JSON.stringify({ "username": roomName })); fetch(gameWebhook, { method: 'POST', body: form, }).then((res) => res); } } /* FEATURE FUNCTIONS */ function getCommand(commandStr) { if (commands.hasOwnProperty(commandStr)) return commandStr; for (const [key, value] of Object.entries(commands)) { for (let alias of value.aliases) { if (alias == commandStr) return key; } } return false; } function getPlayerComp(player) { if (player == null || player.id == 0) return null; var comp = game.playerComp; var index = comp[0].findIndex((c) => c.auth == authArray[player.id][0]); if (index != -1) return comp[0][index]; index = comp[1].findIndex((c) => c.auth == authArray[player.id][0]); if (index != -1) return comp[1][index]; return null; } function getTeamArray(team, includeAFK = true) { if (team == Team.RED) return teamRed; if (team == Team.BLUE) return teamBlue; if (includeAFK) { return playersAll.filter((p) => p.team === Team.SPECTATORS); } return teamSpec; } function sendAnnouncementTeam(message, team, color, style, mention) { for (let player of team) { room.sendAnnouncement(message, player.id, color, style, mention); } } function teamChat(player, message) { var msgArray = message.split(/ +/).slice(1); var emoji = player.team == Team.RED ? 'πŸ”΄' : player.team == Team.BLUE ? 'πŸ”΅' : 'βšͺ'; var message = `${emoji} [TEAM] ${player.name}: ${msgArray.join(' ')}`; var team = getTeamArray(player.team, true); var color = player.team == Team.RED ? redColor : player.team == Team.BLUE ? blueColor : null; var style = 'bold'; var mention = HaxNotification.CHAT; sendAnnouncementTeam(message, team, color, style, mention); } function playerChat(player, message) { var msgArray = message.split(/ +/); var playerTargetIndex = playersAll.findIndex( (p) => p.name.replaceAll(' ', '_') == msgArray[0].substring(2) ); if (playerTargetIndex == -1) { room.sendAnnouncement( `Invalid player, make sure the name you entered is correct.`, player.id, errorColor, 'bold', null ); return false; } var playerTarget = playersAll[playerTargetIndex]; if (player.id == playerTarget.id) { room.sendAnnouncement( `You can't send a PM to yourself!`, player.id, errorColor, 'bold', null ); return false; } var messageFrom = `πŸ“ [PM with ${playerTarget.name}] ${player.name}: ${msgArray.slice(1).join(' ')}` var messageTo = `πŸ“ [PM with ${player.name}] ${player.name}: ${msgArray.slice(1).join(' ')}` room.sendAnnouncement( messageFrom, player.id, privateMessageColor, 'bold', HaxNotification.CHAT ); room.sendAnnouncement( messageTo, playerTarget.id, privateMessageColor, 'bold', HaxNotification.CHAT ); } /* PHYSICS FUNCTIONS */ function calculateStadiumVariables() { if (checkStadiumVariable && teamRed.length + teamBlue.length > 0) { checkStadiumVariable = false; setTimeout(() => { let ballDisc = room.getDiscProperties(0); let playerDisc = room.getPlayerDiscProperties(teamRed.concat(teamBlue)[0].id); ballRadius = ballDisc.radius; playerRadius = playerDisc.radius; triggerDistance = ballRadius + playerRadius + 0.01; speedCoefficient = 100 / (5 * ballDisc.invMass * (ballDisc.damping ** 60 + 1)); }, 1); } } function checkGoalKickTouch(array, index, goal) { if (array != null && array.length >= index + 1) { var obj = array[index]; if (obj != null && obj.goal != null && obj.goal == goal) return obj; } return null; } /* BUTTONS */ function topButton() { if (teamSpec.length > 0) { if (teamRed.length == teamBlue.length && teamSpec.length > 1) { room.setPlayerTeam(teamSpec[0].id, Team.RED); room.setPlayerTeam(teamSpec[1].id, Team.BLUE); } else if (teamRed.length < teamBlue.length) room.setPlayerTeam(teamSpec[0].id, Team.RED); else room.setPlayerTeam(teamSpec[0].id, Team.BLUE); } } function randomButton() { if (teamSpec.length > 0) { if (teamRed.length == teamBlue.length && teamSpec.length > 1) { var r = getRandomInt(teamSpec.length); room.setPlayerTeam(teamSpec[r].id, Team.RED); teamSpec = teamSpec.filter((spec) => spec.id != teamSpec[r].id); room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.BLUE); } else if (teamRed.length < teamBlue.length) room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.RED); else room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.BLUE); } } function blueToSpecButton() { clearTimeout(removingTimeout); removingPlayers = true; removingTimeout = setTimeout(() => { removingPlayers = false; }, 100); for (var i = 0; i < teamBlue.length; i++) { room.setPlayerTeam(teamBlue[teamBlue.length - 1 - i].id, Team.SPECTATORS); } } function redToSpecButton() { clearTimeout(removingTimeout); removingPlayers = true; removingTimeout = setTimeout(() => { removingPlayers = false; }, 100); for (var i = 0; i < teamRed.length; i++) { room.setPlayerTeam(teamRed[teamRed.length - 1 - i].id, Team.SPECTATORS); } } function resetButton() { clearTimeout(removingTimeout); removingPlayers = true; removingTimeout = setTimeout(() => { removingPlayers = false; }, 100); for (let i = 0; i < Math.max(teamRed.length, teamBlue.length); i++) { if (Math.max(teamRed.length, teamBlue.length) - teamRed.length - i > 0) room.setPlayerTeam(teamBlue[teamBlue.length - 1 - i].id, Team.SPECTATORS); else if (Math.max(teamRed.length, teamBlue.length) - teamBlue.length - i > 0) room.setPlayerTeam(teamRed[teamRed.length - 1 - i].id, Team.SPECTATORS); else break; } for (let i = 0; i < Math.min(teamRed.length, teamBlue.length); i++) { room.setPlayerTeam( teamBlue[Math.min(teamRed.length, teamBlue.length) - 1 - i].id, Team.SPECTATORS ); room.setPlayerTeam( teamRed[Math.min(teamRed.length, teamBlue.length) - 1 - i].id, Team.SPECTATORS ); } } function swapButton() { clearTimeout(removingTimeout); removingPlayers = true; removingTimeout = setTimeout(() => { removingPlayers = false; }, 100); for (let player of teamBlue) { room.setPlayerTeam(player.id, Team.RED); } for (let player of teamRed) { room.setPlayerTeam(player.id, Team.BLUE); } } /* COMMAND FUNCTIONS */ /* PLAYER COMMANDS */ function leaveCommand(player, message) { room.kickPlayer(player.id, 'Bye !', false); } function helpCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length == 0) { var commandString = 'Player commands :'; for (const [key, value] of Object.entries(commands)) { if (value.desc && value.roles == Role.PLAYER) commandString += ` !${key},`; } commandString = commandString.substring(0, commandString.length - 1) + '.\n'; if (getRole(player) >= Role.ADMIN_TEMP) { commandString += `Admin commands :`; for (const [key, value] of Object.entries(commands)) { if (value.desc && value.roles == Role.ADMIN_TEMP) commandString += ` !${key},`; } if (commandString.slice(commandString.length - 1) == ':') commandString += ` None,`; commandString = commandString.substring(0, commandString.length - 1) + '.\n'; } if (getRole(player) >= Role.MASTER) { commandString += `Master commands :`; for (const [key, value] of Object.entries(commands)) { if (value.desc && value.roles == Role.MASTER) commandString += ` !${key},`; } if (commandString.slice(commandString.length - 1) == ':') commandString += ` None,`; commandString = commandString.substring(0, commandString.length - 1) + '.\n'; } commandString += "\nTo get information on a specific command, type ''!help '."; room.sendAnnouncement( commandString, player.id, infoColor, 'bold', HaxNotification.CHAT ); } else if (msgArray.length >= 1) { var commandName = getCommand(msgArray[0].toLowerCase()); if (commandName != false && commands[commandName].desc != false) room.sendAnnouncement( `\'${commandName}\' command :\n${commands[commandName].desc}`, player.id, infoColor, 'bold', HaxNotification.CHAT ); else room.sendAnnouncement( `The command you tried to get information on does not exist. To check all available commands, type \'!help\'`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function globalStatsCommand(player, message) { var stats = new HaxStatistics(player.name); if (localStorage.getItem(authArray[player.id][0])) { stats = JSON.parse(localStorage.getItem(authArray[player.id][0])); } var statsString = printPlayerStats(stats); room.sendAnnouncement( statsString, player.id, infoColor, 'bold', HaxNotification.CHAT ); } function renameCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (localStorage.getItem(authArray[player.id][0])) { var stats = JSON.parse(localStorage.getItem(authArray[player.id][0])); if (msgArray.length == 0) { stats.playerName = player.name; } else { stats.playerName = msgArray.join(' '); } localStorage.setItem(authArray[player.id][0], JSON.stringify(stats)); room.sendAnnouncement( `You successfully renamed yourself ${stats.playerName} !`, player.id, successColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `You haven't played a game in this room yet !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function statsLeaderboardCommand(player, message) { var key = message.split(/ +/)[0].substring(1).toLowerCase(); printRankings(key, player.id); } function afkCommand(player, message) { if (player.team == Team.SPECTATORS || players.length == 1) { if (AFKSet.has(player.id)) { if (AFKMinSet.has(player.id)) { room.sendAnnouncement( `There is a minimum of ${minAFKDuration} minute of AFK time. Don't abuse the command !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } else { AFKSet.delete(player.id); room.sendAnnouncement( `πŸŒ… ${player.name} is not AFK anymore !`, null, announcementColor, 'bold', null ); updateTeams(); handlePlayersJoin(); } } else { if (AFKCooldownSet.has(player.id)) { room.sendAnnouncement( `You can only go AFK every ${AFKCooldown} minutes. Don't abuse the command !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } else { AFKSet.add(player.id); if (!player.admin) { AFKMinSet.add(player.id); AFKCooldownSet.add(player.id); setTimeout( (id) => { AFKMinSet.delete(id); }, minAFKDuration * 60 * 1000, player.id ); setTimeout( (id) => { AFKSet.delete(id); }, maxAFKDuration * 60 * 1000, player.id ); setTimeout( (id) => { AFKCooldownSet.delete(id); }, AFKCooldown * 60 * 1000, player.id ); } room.setPlayerTeam(player.id, Team.SPECTATORS); room.sendAnnouncement( `😴 ${player.name} is now AFK !`, null, announcementColor, 'bold', null ); updateTeams(); handlePlayersLeave(); } } } else { room.sendAnnouncement( `You can't go AFK while in a team !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function afkListCommand(player, message) { if (AFKSet.size == 0) { room.sendAnnouncement( "😴 There's nobody in the AFK list.", player.id, announcementColor, 'bold', null ); return; } var cstm = '😴 AFK list : '; AFKSet.forEach((_, value) => { var p = room.getPlayer(value); if (p != null) cstm += p.name + `, `; }); cstm = cstm.substring(0, cstm.length - 2) + '.'; room.sendAnnouncement(cstm, player.id, announcementColor, 'bold', null); } function masterCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (parseInt(msgArray[0]) == masterPassword) { if (!masterList.includes(authArray[player.id][0])) { room.setPlayerAdmin(player.id, true); adminList = adminList.filter((a) => a[0] != authArray[player.id][0]); masterList.push(authArray[player.id][0]); room.sendAnnouncement( `${player.name} is now a room master !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `You are a master already !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } } /* ADMIN COMMANDS */ function restartCommand(player, message) { instantRestart(); } function restartSwapCommand(player, message) { room.stopGame(); swapButton(); startTimeout = setTimeout(() => { room.startGame(); }, 10); } function swapCommand(player, message) { if (playSituation == Situation.STOP) { swapButton(); room.sendAnnouncement( 'βœ”οΈ Teams swapped !', null, announcementColor, 'bold', null ); } else { room.sendAnnouncement( `Please stop the game before swapping.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function kickTeamCommand(player, message) { var msgArray = message.split(/ +/); var reasonString = `Team kick by ${player.name}`; if (msgArray.length > 1) { reasonString = msgArray.slice(1).join(' '); } if (['!kickred', '!kickr'].includes(msgArray[0].toLowerCase())) { for (let i = 0; i < teamRed.length; i++) { setTimeout(() => { room.kickPlayer(teamRed[0].id, reasonString, false); }, i * 20) } } else if (['!kickblue', '!kickb'].includes(msgArray[0].toLowerCase())) { for (let i = 0; i < teamBlue.length; i++) { setTimeout(() => { room.kickPlayer(teamBlue[0].id, reasonString, false); }, i * 20) } } else if (['!kickspec', '!kicks'].includes(msgArray[0].toLowerCase())) { for (let i = 0; i < teamSpec.length; i++) { setTimeout(() => { room.kickPlayer(teamSpec[0].id, reasonString, false); }, i * 20) } } } function stadiumCommand(player, message) { var msgArray = message.split(/ +/); if (gameState == State.STOP) { if (['!classic'].includes(msgArray[0].toLowerCase())) { if (JSON.parse(classicMap).name == 'Classic') { room.setDefaultStadium('Classic'); } else { room.setCustomStadium(classicMap); } currentStadium = 'classic'; } else if (['!big'].includes(msgArray[0].toLowerCase())) { if (JSON.parse(bigMap).name == 'Big') { room.setDefaultStadium('Big'); } else { room.setCustomStadium(bigMap); } currentStadium = 'big'; } else if (['!training'].includes(msgArray[0].toLowerCase())) { room.setCustomStadium(trainingMap); currentStadium = 'training'; } else { room.sendAnnouncement( `Stadium not recognized.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Please stop the game before using this command.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function muteCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length > 0) { if (msgArray[0].length > 0 && msgArray[0][0] == '#') { msgArray[0] = msgArray[0].substring(1, msgArray[0].length); if (room.getPlayer(parseInt(msgArray[0])) != null) { var playerMute = room.getPlayer(parseInt(msgArray[0])); var minutesMute = muteDuration; if (msgArray.length > 1 && parseInt(msgArray[1]) > 0) { minutesMute = parseInt(msgArray[1]); } if (!playerMute.admin) { var muteObj = new MutePlayer(playerMute.name, playerMute.id, authArray[playerMute.id][0]); muteObj.setDuration(minutesMute); room.sendAnnouncement( `${playerMute.name} has been muted for ${minutesMute} minutes.`, null, announcementColor, 'bold', null ); } else { room.sendAnnouncement( `You can't mute an admin.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `There is no player with such ID in the room. Enter "!help mute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Incorrect format for your argument. Enter "!help mute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Wrong number of arguments. Enter "!help mute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function unmuteCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length > 0) { if (msgArray[0].length > 0 && msgArray[0][0] == '#') { msgArray[0] = msgArray[0].substring(1, msgArray[0].length); if (room.getPlayer(parseInt(msgArray[0])) != null) { var playerUnmute = room.getPlayer(parseInt(msgArray[0])); if (muteArray.getByPlayerId(playerUnmute.id) != null) { var muteObj = muteArray.getByPlayerId(playerUnmute.id); muteObj.remove() room.sendAnnouncement( `${playerUnmute.name} has been unmuted !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `This player isn't muted !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `There is no player with such ID in the room. Enter "!help unmute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else if (msgArray[0].length > 0 && parseInt(msgArray[0]) > 0 && muteArray.getById(parseInt(msgArray[0])) != null) { var playerUnmute = muteArray.getById(parseInt(msgArray[0])); playerUnmute.remove(); room.sendAnnouncement( `${playerUnmute.name} has been unmuted !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `Incorrect format for your argument. Enter "!help unmute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Wrong number of arguments. Enter "!help unmute" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function muteListCommand(player, message) { if (muteArray.list.length == 0) { room.sendAnnouncement( "πŸ”‡ There's nobody in the mute list.", player.id, announcementColor, 'bold', null ); return false; } var cstm = 'πŸ”‡ Mute list : '; for (let mute of muteArray.list) { cstm += mute.name + `[${mute.id}], `; } cstm = cstm.substring(0, cstm.length - 2) + '.'; room.sendAnnouncement( cstm, player.id, announcementColor, 'bold', null ); } /* MASTER COMMANDS */ function clearbansCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length == 0) { room.clearBans(); room.sendAnnouncement( 'βœ”οΈ Bans cleared !', null, announcementColor, 'bold', null ); banList = []; } else if (msgArray.length == 1) { if (parseInt(msgArray[0]) > 0) { var ID = parseInt(msgArray[0]); room.clearBan(ID); if (banList.length != banList.filter((p) => p[1] != ID).length) { room.sendAnnouncement( `βœ”οΈ ${banList.filter((p) => p[1] == ID)[0][0]} has been unbanned from the room !`, null, announcementColor, 'bold', null ); } else { room.sendAnnouncement( `The ID you entered doesn't have a ban associated to. Enter "!help clearbans" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } banList = banList.filter((p) => p[1] != ID); } else { room.sendAnnouncement( `Invalid ID entered. Enter "!help clearbans" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Wrong number of arguments. Enter "!help clearbans" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function banListCommand(player, message) { if (banList.length == 0) { room.sendAnnouncement( "πŸ“’ There's nobody in the ban list.", player.id, announcementColor, 'bold', null ); return false; } var cstm = 'πŸ“’ Ban list : '; for (let ban of banList) { cstm += ban[0] + `[${ban[1]}], `; } cstm = cstm.substring(0, cstm.length - 2) + '.'; room.sendAnnouncement( cstm, player.id, announcementColor, 'bold', null ); } function adminListCommand(player, message) { if (adminList.length == 0) { room.sendAnnouncement( "πŸ“’ There's nobody in the admin list.", player.id, announcementColor, 'bold', null ); return false; } var cstm = 'πŸ“’ Admin list : '; for (let i = 0; i < adminList.length; i++) { cstm += adminList[i][1] + `[${i}], `; } cstm = cstm.substring(0, cstm.length - 2) + '.'; room.sendAnnouncement( cstm, player.id, announcementColor, 'bold', null ); } function setAdminCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length > 0) { if (msgArray[0].length > 0 && msgArray[0][0] == '#') { msgArray[0] = msgArray[0].substring(1, msgArray[0].length); if (room.getPlayer(parseInt(msgArray[0])) != null) { var playerAdmin = room.getPlayer(parseInt(msgArray[0])); if (!adminList.map((a) => a[0]).includes(authArray[playerAdmin.id][0])) { if (!masterList.includes(authArray[playerAdmin.id][0])) { room.setPlayerAdmin(playerAdmin.id, true); adminList.push([authArray[playerAdmin.id][0], playerAdmin.name]); room.sendAnnouncement( `${playerAdmin.name} is now a room admin !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `This player is a master already !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `This player is a permanent admin already !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `There is no player with such ID in the room. Enter "!help setadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Incorrect format for your argument. Enter "!help setadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Wrong number of arguments. Enter "!help setadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function removeAdminCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length > 0) { if (msgArray[0].length > 0 && msgArray[0][0] == '#') { msgArray[0] = msgArray[0].substring(1, msgArray[0].length); if (room.getPlayer(parseInt(msgArray[0])) != null) { var playerAdmin = room.getPlayer(parseInt(msgArray[0])); if (adminList.map((a) => a[0]).includes(authArray[playerAdmin.id][0])) { room.setPlayerAdmin(playerAdmin.id, false); adminList = adminList.filter((a) => a[0] != authArray[playerAdmin.id][0]); room.sendAnnouncement( `${playerAdmin.name} is not a room admin anymore !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `This player isn't a permanent admin !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `There is no player with such ID in the room. Enter "!help removeadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else if (msgArray[0].length > 0 && parseInt(msgArray[0]) < adminList.length) { var index = parseInt(msgArray[0]); var playerAdmin = adminList[index]; if (playersAll.findIndex((p) => authArray[p.id][0] == playerAdmin[0]) != -1) { // check if there is the removed admin in the room var indexRem = playersAll.findIndex((p) => authArray[p.id][0] == playerAdmin[0]); room.setPlayerAdmin(playersAll[indexRem].id, false); } adminList.splice(index); room.sendAnnouncement( `${playerAdmin[1]} is not a room admin anymore !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `Incorrect format for your argument. Enter "!help removeadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } else { room.sendAnnouncement( `Wrong number of arguments. Enter "!help removeadmin" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } function passwordCommand(player, message) { var msgArray = message.split(/ +/).slice(1); if (msgArray.length > 0) { if (msgArray.length == 1 && msgArray[0] == '') { roomPassword = ''; room.setPassword(null); room.sendAnnouncement( `The room password has been removed.`, player.id, announcementColor, 'bold', HaxNotification.CHAT ); } roomPassword = msgArray.join(' '); room.setPassword(roomPassword); room.sendAnnouncement( `The room password has been set to ${roomPassword}`, player.id, announcementColor, 'bold', HaxNotification.CHAT ); } else { if (roomPassword != '') { roomPassword = ''; room.setPassword(null); room.sendAnnouncement( `The room password has been removed.`, player.id, announcementColor, 'bold', HaxNotification.CHAT ); } else { room.sendAnnouncement( `The room currently does not have a password. Enter "!help password" for more information.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } } } /* GAME FUNCTIONS */ function checkTime() { const scores = room.getScores(); if (game != undefined) game.scores = scores; if (Math.abs(scores.time - scores.timeLimit) <= 0.01 && scores.timeLimit != 0 && playSituation == Situation.PLAY) { if (scores.red != scores.blue) { if (!checkTimeVariable) { checkTimeVariable = true; setTimeout(() => { checkTimeVariable = false; }, 3000); scores.red > scores.blue ? endGame(Team.RED) : endGame(Team.BLUE); stopTimeout = setTimeout(() => { room.stopGame(); }, 2000); } return; } if (drawTimeLimit != 0) { goldenGoal = true; room.sendAnnouncement( '⚽ First goal wins !', null, announcementColor, 'bold', HaxNotification.CHAT ); } } if (Math.abs(scores.time - drawTimeLimit * 60 - scores.timeLimit) <= 0.01 && scores.timeLimit != 0) { if (!checkTimeVariable) { checkTimeVariable = true; setTimeout(() => { checkTimeVariable = false; }, 10); endGame(Team.SPECTATORS); room.stopGame(); goldenGoal = false; } } } function instantRestart() { room.stopGame(); startTimeout = setTimeout(() => { room.startGame(); }, 10); } function resumeGame() { startTimeout = setTimeout(() => { room.startGame(); }, 1000); setTimeout(() => { room.pauseGame(false); }, 500); } function endGame(winner) { if (players.length >= 2 * teamSize - 1) activateChooseMode(); const scores = room.getScores(); game.scores = scores; lastWinner = winner; endGameVariable = true; if (winner == Team.RED) { streak++; room.sendAnnouncement( `✨ Red Team won ${scores.red} - ${scores.blue} ! Current streak: ${streak}`, null, redColor, 'bold', HaxNotification.CHAT ); } else if (winner == Team.BLUE) { streak = 1; room.sendAnnouncement( `✨ Blue Team won ${scores.blue} - ${scores.red} ! Current streak: ${streak}`, null, blueColor, 'bold', HaxNotification.CHAT ); } else { streak = 0; room.sendAnnouncement( 'πŸ’€ Draw limit reached !', null, announcementColor, 'bold', HaxNotification.CHAT ); } let possessionRedPct = (possession[0] / (possession[0] + possession[1])) * 100; let possessionBluePct = 100 - possessionRedPct; let possessionString = `πŸ”΄ ${possessionRedPct.toFixed(0)}% - ${possessionBluePct.toFixed(0)}% πŸ”΅`; let actionRedPct = (actionZoneHalf[0] / (actionZoneHalf[0] + actionZoneHalf[1])) * 100; let actionBluePct = 100 - actionRedPct; let actionString = `πŸ”΄ ${actionRedPct.toFixed(0)}% - ${actionBluePct.toFixed(0)}% πŸ”΅`; let CSString = getCSString(scores); room.sendAnnouncement( `πŸ“Š Possession: πŸ”΄ ${possessionString}\n` + `πŸ“Š Action Zone: πŸ”΄ ${actionString}\n` + `${CSString}`, null, announcementColor, 'bold', HaxNotification.NONE ); updateStats(); } /* CHOOSING FUNCTIONS */ function activateChooseMode() { chooseMode = true; slowMode = chooseModeSlowMode; room.sendAnnouncement( `🐒 Slow mode changed to choose mode duration of: ${chooseModeSlowMode}s.`, null, announcementColor, 'bold', HaxNotification.CHAT ); } function deactivateChooseMode() { chooseMode = false; clearTimeout(timeOutCap); if (slowMode != defaultSlowMode) { slowMode = defaultSlowMode; room.sendAnnouncement( `🐒 Slow mode changed to choose mode duration of: ${defaultSlowMode}s.`, null, announcementColor, 'bold', HaxNotification.CHAT ); } redCaptainChoice = ''; blueCaptainChoice = ''; } function getSpecList(player) { if (player == null) return null; var cstm = 'Players : '; for (let i = 0; i < teamSpec.length; i++) { cstm += teamSpec[i].name + `[${i + 1}], `; } cstm = cstm.substring(0, cstm.length - 2) + '.'; room.sendAnnouncement( cstm, player.id, infoColor, 'bold', HaxNotification.CHAT ); } function choosePlayer() { clearTimeout(timeOutCap); let captain; if (teamRed.length <= teamBlue.length && teamRed.length != 0) { captain = teamRed[0]; } else if (teamBlue.length < teamRed.length && teamBlue.length != 0) { captain = teamBlue[0]; } if (captain != null) { room.sendAnnouncement( "To choose a player, enter his number in the list given or use 'top', 'random' or 'bottom'.", captain.id, infoColor, 'bold', HaxNotification.MENTION ); timeOutCap = setTimeout( (player) => { room.sendAnnouncement( `Hurry up ${player.name}, only ${Number.parseInt(String(chooseTime / 2))} seconds left to choose !`, player.id, warningColor, 'bold', HaxNotification.MENTION ); timeOutCap = setTimeout( (player) => { room.kickPlayer( player.id, "You didn't choose in time !", false ); }, chooseTime * 500, captain ); }, chooseTime * 1000, captain ); } if (teamRed.length != 0 && teamBlue.length != 0) { getSpecList(teamRed.length <= teamBlue.length ? teamRed[0] : teamBlue[0]); } } function chooseModeFunction(player, message) { var msgArray = message.split(/ +/); if (player.id == teamRed[0].id || player.id == teamBlue[0].id) { if (teamRed.length <= teamBlue.length && player.id == teamRed[0].id) { if (['top', 'auto'].includes(msgArray[0].toLowerCase())) { room.setPlayerTeam(teamSpec[0].id, Team.RED); redCaptainChoice = 'top'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Top !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (['random', 'rand'].includes(msgArray[0].toLowerCase())) { var r = getRandomInt(teamSpec.length); room.setPlayerTeam(teamSpec[r].id, Team.RED); redCaptainChoice = 'random'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Random !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (['bottom', 'bot'].includes(msgArray[0].toLowerCase())) { room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.RED); redCaptainChoice = 'bottom'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Bottom !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (!Number.isNaN(Number.parseInt(msgArray[0]))) { if (Number.parseInt(msgArray[0]) > teamSpec.length || Number.parseInt(msgArray[0]) < 1) { room.sendAnnouncement( `Your number is invalid !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } else { room.setPlayerTeam( teamSpec[Number.parseInt(msgArray[0]) - 1].id, Team.RED ); room.sendAnnouncement( `${player.name} chose ${teamSpec[Number.parseInt(msgArray[0]) - 1].name} !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } } else return false; return true; } if (teamRed.length > teamBlue.length && player.id == teamBlue[0].id) { if (['top', 'auto'].includes(msgArray[0].toLowerCase())) { room.setPlayerTeam(teamSpec[0].id, Team.BLUE); blueCaptainChoice = 'top'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Top !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (['random', 'rand'].includes(msgArray[0].toLowerCase())) { room.setPlayerTeam( teamSpec[getRandomInt(teamSpec.length)].id, Team.BLUE ); blueCaptainChoice = 'random'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Random !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (['bottom', 'bot'].includes(msgArray[0].toLowerCase())) { room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.BLUE); blueCaptainChoice = 'bottom'; clearTimeout(timeOutCap); room.sendAnnouncement( `${player.name} chose Bottom !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } else if (!Number.isNaN(Number.parseInt(msgArray[0]))) { if (Number.parseInt(msgArray[0]) > teamSpec.length || Number.parseInt(msgArray[0]) < 1) { room.sendAnnouncement( `Your number is invalid !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); } else { room.setPlayerTeam( teamSpec[Number.parseInt(msgArray[0]) - 1].id, Team.BLUE ); room.sendAnnouncement( `${player.name} chose ${teamSpec[Number.parseInt(msgArray[0]) - 1].name} !`, null, announcementColor, 'bold', HaxNotification.CHAT ); } } else return false; return true; } } } function checkCaptainLeave(player) { if ( (teamRed.findIndex((red) => red.id == player.id) == 0 && chooseMode && teamRed.length <= teamBlue.length) || (teamBlue.findIndex((blue) => blue.id == player.id) == 0 && chooseMode && teamBlue.length < teamRed.length) ) { choosePlayer(); capLeft = true; setTimeout(() => { capLeft = false; }, 10); } } function slowModeFunction(player, message) { if (!player.admin) { if (!SMSet.has(player.id)) { SMSet.add(player.id); setTimeout( (number) => { SMSet.delete(number); }, slowMode * 1000, player.id ); } else { return true; } } return false; } /* PLAYER FUNCTIONS */ function updateTeams() { playersAll = room.getPlayerList(); players = playersAll.filter((p) => !AFKSet.has(p.id)); teamRed = players.filter((p) => p.team == Team.RED); teamBlue = players.filter((p) => p.team == Team.BLUE); teamSpec = players.filter((p) => p.team == Team.SPECTATORS); } function updateAdmins(excludedPlayerID = 0) { if (players.length != 0 && players.filter((p) => p.admin).length < maxAdmins) { let playerArray = players.filter((p) => p.id != excludedPlayerID && !p.admin); let arrayID = playerArray.map((player) => player.id); room.setPlayerAdmin(Math.min(...arrayID), true); } } function getRole(player) { return ( !!masterList.find((a) => a == authArray[player.id][0]) * 2 + !!adminList.find((a) => a[0] == authArray[player.id][0]) * 1 + player.admin * 1 ); } function ghostKickHandle(oldP, newP) { var teamArrayId = getTeamArray(oldP.team, true).map((p) => p.id); teamArrayId.splice(teamArrayId.findIndex((id) => id == oldP.id), 1, newP.id); room.kickPlayer(oldP.id, 'Ghost kick', false); room.setPlayerTeam(newP.id, oldP.team); room.setPlayerAdmin(newP.id, oldP.admin); room.reorderPlayers(teamArrayId, true); if (oldP.team != Team.SPECTATORS && playSituation != Situation.STOP) { var discProp = room.getPlayerDiscProperties(oldP.id); room.setPlayerDiscProperties(newP.id, discProp); } } /* ACTIVITY FUNCTIONS */ function handleActivityPlayer(player) { let pComp = getPlayerComp(player); if (pComp != null) { pComp.inactivityTicks++; if (pComp.inactivityTicks == 60 * ((2 / 3) * afkLimit)) { room.sendAnnouncement( `β›” ${player.name}, if you don't move or send a message in the next ${Math.floor(afkLimit / 3)} seconds, you will be kicked !`, player.id, warningColor, 'bold', HaxNotification.MENTION ); return; } if (pComp.inactivityTicks >= 60 * afkLimit) { pComp.inactivityTicks = 0; if (game.scores.time <= afkLimit - 0.5) { setTimeout(() => { !chooseMode ? instantRestart() : room.stopGame(); }, 10); } room.kickPlayer(player.id, 'AFK', false); } } } function handleActivityPlayerTeamChange(changedPlayer) { if (changedPlayer.team == Team.SPECTATORS) { let pComp = getPlayerComp(changedPlayer); if (pComp != null) pComp.inactivityTicks = 0; } } function handleActivityStop() { for (let player of players) { let pComp = getPlayerComp(player); if (pComp != null) pComp.inactivityTicks = 0; } } function handleActivity() { if (gameState === State.PLAY && players.length > 1) { for (let player of teamRed) { handleActivityPlayer(player); } for (let player of teamBlue) { handleActivityPlayer(player); } } } /* LINEUP FUNCTIONS */ function getStartingLineups() { var compositions = [[], []]; for (let player of teamRed) { compositions[0].push( new PlayerComposition(player, authArray[player.id][0], [0], []) ); } for (let player of teamBlue) { compositions[1].push( new PlayerComposition(player, authArray[player.id][0], [0], []) ); } return compositions; } function handleLineupChangeTeamChange(changedPlayer) { if (gameState != State.STOP) { var playerLineup; if (changedPlayer.team == Team.RED) { // player gets in red team var redLineupAuth = game.playerComp[0].map((p) => p.auth); var ind = redLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]); if (ind != -1) { // Player goes back in playerLineup = game.playerComp[0][ind]; if (playerLineup.timeExit.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub playerLineup.timeExit = playerLineup.timeExit.filter((t) => t != game.scores.time); } else { playerLineup.timeEntry.push(game.scores.time); } } else { playerLineup = new PlayerComposition( changedPlayer, authArray[changedPlayer.id][0], [game.scores.time], [] ); game.playerComp[0].push(playerLineup); } } else if (changedPlayer.team == Team.BLUE) { // player gets in blue team var blueLineupAuth = game.playerComp[1].map((p) => p.auth); var ind = blueLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]); if (ind != -1) { // Player goes back in playerLineup = game.playerComp[1][ind]; if (playerLineup.timeExit.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub playerLineup.timeExit = playerLineup.timeExit.filter((t) => t != game.scores.time); } else { playerLineup.timeEntry.push(game.scores.time); } } else { playerLineup = new PlayerComposition( changedPlayer, authArray[changedPlayer.id][0], [game.scores.time], [] ); game.playerComp[1].push(playerLineup); } } if (teamRed.some((r) => r.id == changedPlayer.id)) { // player leaves red team var redLineupAuth = game.playerComp[0].map((p) => p.auth); var ind = redLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]); playerLineup = game.playerComp[0][ind]; if (playerLineup.timeEntry.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub if (game.scores.time == 0) { game.playerComp[0].splice(ind, 1); } else { playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time); } } else { playerLineup.timeExit.push(game.scores.time); } } else if (teamBlue.some((r) => r.id == changedPlayer.id)) { // player leaves blue team var blueLineupAuth = game.playerComp[1].map((p) => p.auth); var ind = blueLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]); playerLineup = game.playerComp[1][ind]; if (playerLineup.timeEntry.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub if (game.scores.time == 0) { game.playerComp[1].splice(ind, 1); } else { playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time); } } else { playerLineup.timeExit.push(game.scores.time); } } } } function handleLineupChangeLeave(player) { if (playSituation != Situation.STOP) { if (player.team == Team.RED) { // player gets in red team var redLineupAuth = game.playerComp[0].map((p) => p.auth); var ind = redLineupAuth.findIndex((auth) => auth == authArray[player.id][0]); var playerLineup = game.playerComp[0][ind]; if (playerLineup.timeEntry.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub if (game.scores.time == 0) { game.playerComp[0].splice(ind, 1); } else { playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time); } } else { playerLineup.timeExit.push(game.scores.time); } } else if (player.team == Team.BLUE) { // player gets in blue team var blueLineupAuth = game.playerComp[1].map((p) => p.auth); var ind = blueLineupAuth.findIndex((auth) => auth == authArray[player.id][0]); var playerLineup = game.playerComp[1][ind]; if (playerLineup.timeEntry.includes(game.scores.time)) { // gets subbed off then in at the exact same time -> no sub if (game.scores.time == 0) { game.playerComp[1].splice(ind, 1); } else { playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time); } } else { playerLineup.timeExit.push(game.scores.time); } } } } /* TEAM BALANCE FUNCTIONS */ function balanceTeams() { if (!chooseMode) { if (players.length == 0) { room.stopGame(); room.setScoreLimit(scoreLimit); room.setTimeLimit(timeLimit); } else if (players.length == 1 && teamRed.length == 0) { instantRestart(); setTimeout(() => { stadiumCommand(emptyPlayer, `!training`); }, 5); room.setPlayerTeam(players[0].id, Team.RED); } else if (Math.abs(teamRed.length - teamBlue.length) == teamSpec.length && teamSpec.length > 0) { const n = Math.abs(teamRed.length - teamBlue.length); if (players.length == 2) { instantRestart(); setTimeout(() => { stadiumCommand(emptyPlayer, `!classic`); }, 5); } if (teamRed.length > teamBlue.length) { for (var i = 0; i < n; i++) { room.setPlayerTeam(teamSpec[i].id, Team.BLUE); } } else { for (var i = 0; i < n; i++) { room.setPlayerTeam(teamSpec[i].id, Team.RED); } } } else if (Math.abs(teamRed.length - teamBlue.length) > teamSpec.length) { const n = Math.abs(teamRed.length - teamBlue.length); if (players.length == 1) { instantRestart(); setTimeout(() => { stadiumCommand(emptyPlayer, `!training`); }, 5); room.setPlayerTeam(players[0].id, Team.RED); return; } else if (teamSize > 2 && players.length == 5) { instantRestart(); setTimeout(() => { stadiumCommand(emptyPlayer, `!classic`); }, 5); } if (players.length == teamSize * 2 - 1) { teamRedStats = []; teamBlueStats = []; } if (teamRed.length > teamBlue.length) { for (var i = 0; i < n; i++) { room.setPlayerTeam( teamRed[teamRed.length - 1 - i].id, Team.SPECTATORS ); } } else { for (var i = 0; i < n; i++) { room.setPlayerTeam( teamBlue[teamBlue.length - 1 - i].id, Team.SPECTATORS ); } } } else if (Math.abs(teamRed.length - teamBlue.length) < teamSpec.length && teamRed.length != teamBlue.length) { room.pauseGame(true); activateChooseMode(); choosePlayer(); } else if (teamSpec.length >= 2 && teamRed.length == teamBlue.length && teamRed.length < teamSize) { if (teamRed.length == 2) { instantRestart(); setTimeout(() => { stadiumCommand(emptyPlayer, `!big`); }, 5); } topButton(); } } } function handlePlayersJoin() { if (chooseMode) { if (teamSize > 2 && players.length == changeToBigMapOn) { setTimeout(() => { stadiumCommand(emptyPlayer, `!big`); }, 5); } getSpecList(teamRed.length <= teamBlue.length ? teamRed[0] : teamBlue[0]); } balanceTeams(); } function handlePlayersLeave() { if (gameState != State.STOP) { var scores = room.getScores(); if (players.length >= 2 * teamSize && scores.time >= (5 / 6) * game.scores.timeLimit && teamRed.length != teamBlue.length) { var rageQuitCheck = false; if (teamRed.length < teamBlue.length) { if (scores.blue - scores.red == 2) { endGame(Team.BLUE); rageQuitCheck = true; } } else { if (scores.red - scores.blue == 2) { endGame(Team.RED); rageQuitCheck = true; } } if (rageQuitCheck) { room.sendAnnouncement( "Ragequit detected, game ended.", null, infoColor, 'bold', HaxNotification.MENTION ) stopTimeout = setTimeout(() => { room.stopGame(); }, 100); return; } } } if (chooseMode) { if (teamSize > 2 && players.length == 5) { setTimeout(() => { stadiumCommand(emptyPlayer, `!classic`); }, 5); } if (teamRed.length == 0 || teamBlue.length == 0) { room.setPlayerTeam(teamSpec[0].id, teamRed.length == 0 ? Team.RED : Team.BLUE); return; } if (Math.abs(teamRed.length - teamBlue.length) == teamSpec.length) { deactivateChooseMode(); resumeGame(); var b = teamSpec.length; if (teamRed.length > teamBlue.length) { for (var i = 0; i < b; i++) { clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { room.setPlayerTeam(teamSpec[0].id, Team.BLUE); }, 5 * i); } insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 5 * b); } else { for (var i = 0; i < b; i++) { clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { room.setPlayerTeam(teamSpec[0].id, Team.RED); }, 5 * i); } insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 5 * b); } return; } if (streak == 0 && gameState == State.STOP) { if (Math.abs(teamRed.length - teamBlue.length) == 2) { var teamIn = teamRed.length > teamBlue.length ? teamRed : teamBlue; room.setPlayerTeam(teamIn[teamIn.length - 1].id, Team.SPECTATORS) } } if (teamRed.length == teamBlue.length && teamSpec.length < 2) { deactivateChooseMode(); resumeGame(); return; } if (capLeft) { choosePlayer(); } else { getSpecList(teamRed.length <= teamBlue.length ? teamRed[0] : teamBlue[0]); } } balanceTeams(); } function handlePlayersTeamChange(byPlayer) { if (chooseMode && !removingPlayers && byPlayer == null) { if (Math.abs(teamRed.length - teamBlue.length) == teamSpec.length) { deactivateChooseMode(); resumeGame(); var b = teamSpec.length; if (teamRed.length > teamBlue.length) { for (var i = 0; i < b; i++) { clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { room.setPlayerTeam(teamSpec[0].id, Team.BLUE); }, 5 * i); } insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 5 * b); } else { for (var i = 0; i < b; i++) { clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { room.setPlayerTeam(teamSpec[0].id, Team.RED); }, 5 * i); } insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 5 * b); } return; } else if ( (teamRed.length == teamSize && teamBlue.length == teamSize) || (teamRed.length == teamBlue.length && teamSpec.length < 2) ) { deactivateChooseMode(); resumeGame(); } else if (teamRed.length <= teamBlue.length && redCaptainChoice != '') { if (redCaptainChoice == 'top') { room.setPlayerTeam(teamSpec[0].id, Team.RED); } else if (redCaptainChoice == 'random') { var r = getRandomInt(teamSpec.length); room.setPlayerTeam(teamSpec[r].id, Team.RED); } else { room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.RED); } return; } else if (teamBlue.length < teamRed.length && blueCaptainChoice != '') { if (blueCaptainChoice == 'top') { room.setPlayerTeam(teamSpec[0].id, Team.BLUE); } else if (blueCaptainChoice == 'random') { var r = getRandomInt(teamSpec.length); room.setPlayerTeam(teamSpec[r].id, Team.BLUE); } else { room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.BLUE); } return; } else { choosePlayer(); } } } function handlePlayersStop(byPlayer) { if (byPlayer == null && endGameVariable) { if (chooseMode) { if (players.length == 2 * teamSize) { chooseMode = false; resetButton(); for (var i = 0; i < teamSize; i++) { clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { randomButton(); }, 200 * i); } insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 200 * teamSize); startTimeout = setTimeout(() => { room.startGame(); }, 2000); } else { if (lastWinner == Team.RED) { blueToSpecButton(); } else if (lastWinner == Team.BLUE) { redToSpecButton(); setTimeout(() => { swapButton(); }, 10); } else { resetButton(); } clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { topButton(); }, 300); insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 300); } } else { if (players.length == 2) { if (lastWinner == Team.BLUE) { swapButton(); } startTimeout = setTimeout(() => { room.startGame(); }, 2000); } else if (players.length == 3 || players.length >= 2 * teamSize + 1) { if (lastWinner == Team.RED) { blueToSpecButton(); } else { redToSpecButton(); setTimeout(() => { swapButton(); }, 5); } clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { topButton(); }, 200); insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 300); startTimeout = setTimeout(() => { room.startGame(); }, 2000); } else if (players.length == 4) { resetButton(); clearTimeout(insertingTimeout); insertingPlayers = true; setTimeout(() => { randomButton(); setTimeout(() => { randomButton(); }, 500); }, 500); insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 2000); startTimeout = setTimeout(() => { room.startGame(); }, 2000); } else if (players.length == 5 || players.length >= 2 * teamSize + 1) { if (lastWinner == Team.RED) { blueToSpecButton(); } else { redToSpecButton(); setTimeout(() => { swapButton(); }, 5); } clearTimeout(insertingTimeout); insertingPlayers = true; insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 200); setTimeout(() => { topButton(); }, 200); activateChooseMode(); } else if (players.length == 6) { resetButton(); clearTimeout(insertingTimeout); insertingPlayers = true; insertingTimeout = setTimeout(() => { insertingPlayers = false; }, 1500); setTimeout(() => { randomButton(); setTimeout(() => { randomButton(); setTimeout(() => { randomButton(); }, 500); }, 500); }, 500); startTimeout = setTimeout(() => { room.startGame(); }, 2000); } } } } /* STATS FUNCTIONS */ /* GK FUNCTIONS */ function handleGKTeam(team) { if (team == Team.SPECTATORS) { return null; } let teamArray = team == Team.RED ? teamRed : teamBlue; let playerGK = teamArray.reduce((prev, current) => { if (team == Team.RED) { return (prev?.position.x < current.position.x) ? prev : current } else { return (prev?.position.x > current.position.x) ? prev : current } }, null); let playerCompGK = getPlayerComp(playerGK); return playerCompGK; } function handleGK() { let redGK = handleGKTeam(Team.RED); if (redGK != null) { redGK.GKTicks++; } let blueGK = handleGKTeam(Team.BLUE); if (blueGK != null) { blueGK.GKTicks++; } } function getGK(team) { if (team == Team.SPECTATORS) { return null; } let teamArray = team == Team.RED ? game.playerComp[0] : game.playerComp[1]; let playerGK = teamArray.reduce((prev, current) => { return (prev?.GKTicks > current.GKTicks) ? prev : current }, null); return playerGK; } function getCS(scores) { let playersNameCS = []; let redGK = getGK(Team.RED); let blueGK = getGK(Team.BLUE); if (redGK != null && scores.blue == 0) { playersNameCS.push(redGK.player.name); } if (blueGK != null && scores.red == 0) { playersNameCS.push(blueGK.player.name); } return playersNameCS; } function getCSString(scores) { let playersCS = getCS(scores); if (playersCS.length == 0) { return "πŸ₯… No CS"; } else if (playersCS.length == 1) { return `πŸ₯… ${playersCS[0]} had a CS.`; } else { return `πŸ₯… ${playersCS[0]} and ${playersCS[1]} had a CS.`; } } /* GLOBAL STATS FUNCTIONS */ function getLastTouchOfTheBall() { const ballPosition = room.getBallPosition(); updateTeams(); let playerArray = []; for (let player of players) { if (player.position != null) { var distanceToBall = pointDistance(player.position, ballPosition); if (distanceToBall < triggerDistance) { if (playSituation == Situation.KICKOFF) playSituation = Situation.PLAY; playerArray.push([player, distanceToBall]); } } } if (playerArray.length != 0) { let playerTouch = playerArray.sort((a, b) => a[1] - b[1])[0][0]; if (lastTeamTouched == playerTouch.team || lastTeamTouched == Team.SPECTATORS) { if (lastTouches[0] == null || (lastTouches[0] != null && lastTouches[0].player.id != playerTouch.id)) { game.touchArray.push( new BallTouch( playerTouch, game.scores.time, getGoalGame(), ballPosition ) ); lastTouches[0] = checkGoalKickTouch( game.touchArray, game.touchArray.length - 1, getGoalGame() ); lastTouches[1] = checkGoalKickTouch( game.touchArray, game.touchArray.length - 2, getGoalGame() ); } } lastTeamTouched = playerTouch.team; } } function getBallSpeed() { var ballProp = room.getDiscProperties(0); return Math.sqrt(ballProp.xspeed ** 2 + ballProp.yspeed ** 2) * speedCoefficient; } function getGameStats() { if (playSituation == Situation.PLAY && gameState == State.PLAY) { lastTeamTouched == Team.RED ? possession[0]++ : possession[1]++; var ballPosition = room.getBallPosition(); ballPosition.x < 0 ? actionZoneHalf[0]++ : actionZoneHalf[1]++; handleGK(); } } /* GOAL ATTRIBUTION FUNCTIONS */ function getGoalAttribution(team) { var goalAttribution = Array(2).fill(null); if (lastTouches[0] != null) { if (lastTouches[0].player.team == team) { // Direct goal scored by player if (lastTouches[1] != null && lastTouches[1].player.team == team) { goalAttribution = [lastTouches[0].player, lastTouches[1].player]; } else { goalAttribution = [lastTouches[0].player, null]; } } else { // Own goal goalAttribution = [lastTouches[0].player, null]; } } return goalAttribution; } function getGoalString(team) { var goalString; var scores = game.scores; var goalAttribution = getGoalAttribution(team); if (goalAttribution[0] != null) { if (goalAttribution[0].team == team) { if (goalAttribution[1] != null && goalAttribution[1].team == team) { goalString = `⚽ ${getTimeGame(scores.time)} Goal by ${goalAttribution[0].name} ! Assist by ${goalAttribution[1].name}. Goal speed : ${ballSpeed.toFixed(2)}km/h.`; game.goals.push( new Goal( scores.time, team, goalAttribution[0], goalAttribution[1] ) ); } else { goalString = `⚽ ${getTimeGame(scores.time)} Goal by ${goalAttribution[0].name} ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`; game.goals.push( new Goal(scores.time, team, goalAttribution[0], null) ); } } else { goalString = `πŸ˜‚ ${getTimeGame(scores.time)} Own goal by ${goalAttribution[0].name} ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`; game.goals.push( new Goal(scores.time, team, goalAttribution[0], null) ); } } else { goalString = `⚽ ${getTimeGame(scores.time)} Goal for ${team == Team.RED ? 'red' : 'blue'} team ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`; game.goals.push( new Goal(scores.time, team, null, null) ); } return goalString; } /* ROOM STATS FUNCTIONS */ function updatePlayerStats(player, teamStats) { var stats = new HaxStatistics(player.name); var pComp = getPlayerComp(player); if (localStorage.getItem(authArray[player.id][0])) { stats = JSON.parse(localStorage.getItem(authArray[player.id][0])); } stats.games++; if (lastWinner == teamStats) stats.wins++; stats.winrate = ((100 * stats.wins) / (stats.games || 1)).toFixed(1) + `%`; stats.goals += getGoalsPlayer(pComp); stats.assists += getAssistsPlayer(pComp); stats.ownGoals += getOwnGoalsPlayer(pComp); stats.CS += getCSPlayer(pComp); stats.playtime += getGametimePlayer(pComp); localStorage.setItem(authArray[player.id][0], JSON.stringify(stats)); } function updateStats() { if ( players.length >= 2 * teamSize && ( game.scores.time >= (5 / 6) * game.scores.timeLimit || game.scores.red == game.scores.scoreLimit || game.scores.blue == game.scores.scoreLimit ) && teamRedStats.length >= teamSize && teamBlueStats.length >= teamSize ) { for (let player of teamRedStats) { updatePlayerStats(player, Team.RED); } for (let player of teamBlueStats) { updatePlayerStats(player, Team.BLUE); } } } function printRankings(statKey, id = 0) { var leaderboard = []; statKey = statKey == "cs" ? "CS" : statKey; for (var i = 0; i < localStorage.length; i++) { var key = localStorage.key(i); if (key.length == 43) leaderboard.push([ JSON.parse(localStorage.getItem(key)).playerName, JSON.parse(localStorage.getItem(key))[statKey], ]); } if (leaderboard.length < 5) { if (id != 0) { room.sendAnnouncement( 'Not enough games played yet !', id, errorColor, 'bold', HaxNotification.CHAT ); } return; } leaderboard.sort(function (a, b) { return b[1] - a[1]; }); var rankingString = `${statKey.charAt(0).toUpperCase() + statKey.slice(1)}> `; for (let i = 0; i < 5; i++) { let playerName = leaderboard[i][0]; let playerStat = leaderboard[i][1]; if (statKey == 'playtime') playerStat = getTimeStats(playerStat); rankingString += `#${i + 1} ${playerName} : ${playerStat}, `; } rankingString = rankingString.substring(0, rankingString.length - 2); room.sendAnnouncement( rankingString, id, infoColor, 'bold', HaxNotification.CHAT ); } /* GET STATS FUNCTIONS */ function getGamePlayerStats(player) { var stats = new HaxStatistics(player.name); var pComp = getPlayerComp(player); stats.goals += getGoalsPlayer(pComp); stats.assists += getAssistsPlayer(pComp); stats.ownGoals += getOwnGoalsPlayer(pComp); stats.playtime += getGametimePlayer(pComp); stats.CS += getCSPlayer(pComp); return stats; } function getGametimePlayer(pComp) { if (pComp == null) return 0; var timePlayer = 0; for (let j = 0; j < pComp.timeEntry.length; j++) { if (pComp.timeExit.length < j + 1) { timePlayer += game.scores.time - pComp.timeEntry[j]; } else { timePlayer += pComp.timeExit[j] - pComp.timeEntry[j]; } } return Math.floor(timePlayer); } function getGoalsPlayer(pComp) { if (pComp == null) return 0; var goalPlayer = 0; for (let goal of game.goals) { if (goal.striker != null && goal.team === pComp.player.team) { if (authArray[goal.striker.id][0] == pComp.auth) { goalPlayer++; } } } return goalPlayer; } function getOwnGoalsPlayer(pComp) { if (pComp == null) return 0; var goalPlayer = 0; for (let goal of game.goals) { if (goal.striker != null && goal.team !== pComp.player.team) { if (authArray[goal.striker.id][0] == pComp.auth) { goalPlayer++; } } } return goalPlayer; } function getAssistsPlayer(pComp) { if (pComp == null) return 0; var assistPlayer = 0; for (let goal of game.goals) { if (goal.assist != null) { if (authArray[goal.assist.id][0] == pComp.auth) { assistPlayer++; } } } return assistPlayer; } function getGKPlayer(pComp) { if (pComp == null) return 0; let GKRed = getGK(Team.RED); if (pComp.auth == GKRed?.auth) { return Team.RED; } let GKBlue = getGK(Team.BLUE); if (pComp.auth == GKBlue?.auth) { return Team.BLUE; } return Team.SPECTATORS; } function getCSPlayer(pComp) { if (pComp == null || game.scores == null) return 0; if (getGKPlayer(pComp) == Team.RED && game.scores.blue == 0) { return 1; } else if (getGKPlayer(pComp) == Team.BLUE && game.scores.red == 0) { return 1; } return 0; } function actionReportCountTeam(goals, team) { let playerActionSummaryTeam = []; let indexTeam = team == Team.RED ? 0 : 1; let indexOtherTeam = team == Team.RED ? 1 : 0; for (let goal of goals[indexTeam]) { if (goal[0] != null) { if (playerActionSummaryTeam.find(a => a[0].id == goal[0].id)) { let index = playerActionSummaryTeam.findIndex(a => a[0].id == goal[0].id); playerActionSummaryTeam[index][1]++; } else { playerActionSummaryTeam.push([goal[0], 1, 0, 0]); } if (goal[1] != null) { if (playerActionSummaryTeam.find(a => a[0].id == goal[1].id)) { let index = playerActionSummaryTeam.findIndex(a => a[0].id == goal[1].id); playerActionSummaryTeam[index][2]++; } else { playerActionSummaryTeam.push([goal[1], 0, 1, 0]); } } } } if (goals[indexOtherTeam].length == 0) { let playerCS = getGK(team)?.player; if (playerCS != null) { if (playerActionSummaryTeam.find(a => a[0].id == playerCS.id)) { let index = playerActionSummaryTeam.findIndex(a => a[0].id == playerCS.id); playerActionSummaryTeam[index][3]++; } else { playerActionSummaryTeam.push([playerCS, 0, 0, 1]); } } } playerActionSummaryTeam.sort((a, b) => (a[1] + a[2] + a[3]) - (b[1] + b[2] + b[3])); return playerActionSummaryTeam; } /* PRINT FUNCTIONS */ function printPlayerStats(stats) { let statsString = ''; for (let [key, value] of Object.entries(stats)) { if (key == 'playerName') statsString += `${value}: `; else { if (key == 'playtime') value = getTimeStats(value); let reCamelCase = /([A-Z](?=[a-z]+)|[A-Z]+(?![a-z]))/g; let statName = key.replaceAll(reCamelCase, ' $1').trim(); statsString += `${statName.charAt(0).toUpperCase() + statName.slice(1)}: ${value}, `; } } statsString = statsString.substring(0, statsString.length - 2); return statsString; } /* FETCH FUNCTIONS */ function fetchGametimeReport(game) { var fieldGametimeRed = { name: 'πŸ”΄ **RED TEAM STATS**', value: 'βŒ› __**Game Time:**__\n\n', inline: true, }; var fieldGametimeBlue = { name: 'πŸ”΅ **BLUE TEAM STATS**', value: 'βŒ› __**Game Time:**__\n\n', inline: true, }; var redTeamTimes = game.playerComp[0].map((p) => [p.player, getGametimePlayer(p)]); var blueTeamTimes = game.playerComp[1].map((p) => [p.player, getGametimePlayer(p)]); for (let time of redTeamTimes) { var minutes = getMinutesReport(time[1]); var seconds = getSecondsReport(time[1]); fieldGametimeRed.value += `> **${time[0].name}:** ${minutes > 0 ? `${minutes}m` : ''}` + `${seconds > 0 || minutes == 0 ? `${seconds}s` : ''}\n`; } fieldGametimeRed.value += `\n${blueTeamTimes.length - redTeamTimes.length > 0 ? '\n'.repeat(blueTeamTimes.length - redTeamTimes.length) : '' }`; fieldGametimeRed.value += '====================='; for (let time of blueTeamTimes) { var minutes = getMinutesReport(time[1]); var seconds = getSecondsReport(time[1]); fieldGametimeBlue.value += `> **${time[0].name}:** ${minutes > 0 ? `${minutes}m` : ''}` + `${seconds > 0 || minutes == 0 ? `${seconds}s` : ''}\n`; } fieldGametimeBlue.value += `\n${redTeamTimes.length - blueTeamTimes.length > 0 ? '\n'.repeat(redTeamTimes.length - blueTeamTimes.length) : '' }`; fieldGametimeBlue.value += '====================='; return [fieldGametimeRed, fieldGametimeBlue]; } function fetchActionsSummaryReport(game) { var fieldReportRed = { name: 'πŸ”΄ **RED TEAM STATS**', value: 'πŸ“Š __**Player Stats:**__\n\n', inline: true, }; var fieldReportBlue = { name: 'πŸ”΅ **BLUE TEAM STATS**', value: 'πŸ“Š __**Player Stats:**__\n\n', inline: true, }; var goals = [[], []]; for (let i = 0; i < game.goals.length; i++) { goals[game.goals[i].team - 1].push([game.goals[i].striker, game.goals[i].assist]); } var redActions = actionReportCountTeam(goals, Team.RED); if (redActions.length > 0) { for (let act of redActions) { fieldReportRed.value += `> **${act[0].team != Team.RED ? '[OG] ' : ''}${act[0].name}:**` + `${act[1] > 0 ? ` ${act[1]}G` : ''}` + `${act[2] > 0 ? ` ${act[2]}A` : ''}` + `${act[3] > 0 ? ` ${act[3]}CS` : ''}\n`; } } var blueActions = actionReportCountTeam(goals, Team.BLUE); if (blueActions.length > 0) { for (let act of blueActions) { fieldReportBlue.value += `> **${act[0].team != Team.BLUE ? '[OG] ' : ''}${act[0].name}:**` + `${act[1] > 0 ? ` ${act[1]}G` : ''}` + `${act[2] > 0 ? ` ${act[2]}A` : ''}` + `${act[3] > 0 ? ` ${act[3]}CS` : ''}\n`; } } fieldReportRed.value += `\n${blueActions.length - redActions.length > 0 ? '\n'.repeat(blueActions.length - redActions.length) : '' }`; fieldReportRed.value += '====================='; fieldReportBlue.value += `\n${redActions.length - blueActions.length > 0 ? '\n'.repeat(redActions.length - blueActions.length) : '' }`; fieldReportBlue.value += '====================='; return [fieldReportRed, fieldReportBlue]; } function fetchSummaryEmbed(game) { var fetchEndgame = [fetchGametimeReport, fetchActionsSummaryReport]; var logChannel = gameWebhook; var fields = [ { name: 'πŸ”΄ **RED TEAM STATS**', value: '=====================\n\n', inline: true, }, { name: 'πŸ”΅ **BLUE TEAM STATS**', value: '=====================\n\n', inline: true, }, ]; for (let i = 0; i < fetchEndgame.length; i++) { var fieldsReport = fetchEndgame[i](game); fields[0].value += fieldsReport[0].value + '\n\n'; fields[1].value += fieldsReport[1].value + '\n\n'; } fields[0].value = fields[0].value.substring(0, fields[0].value.length - 2); fields[1].value = fields[1].value.substring(0, fields[1].value.length - 2); var possR = possession[0] / (possession[0] + possession[1]); var possB = 1 - possR; var possRString = (possR * 100).toFixed(0).toString(); var possBString = (possB * 100).toFixed(0).toString(); var zoneR = actionZoneHalf[0] / (actionZoneHalf[0] + actionZoneHalf[1]); var zoneB = 1 - zoneR; var zoneRString = (zoneR * 100).toFixed(0).toString(); var zoneBString = (zoneB * 100).toFixed(0).toString(); var win = (game.scores.red > game.scores.blue) * 1 + (game.scores.blue > game.scores.red) * 2; var objectBodyWebhook = { embeds: [ { title: `πŸ“ MATCH REPORT #${getIdReport()}`, description: `**${getTimeEmbed(game.scores.time)}** ` + (win == 1 ? '**Red Team** ' : 'Red Team ') + game.scores.red + ' - ' + game.scores.blue + (win == 2 ? ' **Blue Team**' : ' Blue Team') + '\n```c\nPossession: ' + possRString + '% - ' + possBString + '%' + '\nAction Zone: ' + zoneRString + '% - ' + zoneBString + '%\n```\n\n', color: 9567999, fields: fields, footer: { text: `Recording: ${getRecordingName(game)}`, }, timestamp: new Date().toISOString(), }, ], username: roomName }; if (logChannel != '') { fetch(logChannel, { method: 'POST', body: JSON.stringify(objectBodyWebhook), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } } /* EVENTS */ /* PLAYER MOVEMENT */ room.onPlayerJoin = function (player) { authArray[player.id] = [player.auth, player.conn]; if (roomWebhook != '') { fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: `[${getDate()}] ➑️ JOIN (${playersAll.length + 1}/${maxPlayers})\n**` + `${player.name}** [${authArray[player.id][0]}] {${authArray[player.id][1]}}`, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } room.sendAnnouncement( `πŸ‘‹ Welcome ${player.name} !\nEnter "t" before your message to use team chat and "@@" followed by a player name to PM him !`, player.id, welcomeColor, 'bold', HaxNotification.CHAT ); updateTeams(); updateAdmins(); if (masterList.findIndex((auth) => auth == player.auth) != -1) { room.sendAnnouncement( `Master ${player.name} has connected to the room !`, null, announcementColor, 'bold', HaxNotification.CHAT ); room.setPlayerAdmin(player.id, true); } else if (adminList.map((a) => a[0]).findIndex((auth) => auth == player.auth) != -1) { room.sendAnnouncement( `Admin ${player.name} has connected to the room !`, null, announcementColor, 'bold', HaxNotification.CHAT ); room.setPlayerAdmin(player.id, true); } var sameAuthCheck = playersAll.filter((p) => p.id != player.id && authArray[p.id][0] == player.auth); if (sameAuthCheck.length > 0 && !debugMode) { var oldPlayerArray = playersAll.filter((p) => p.id != player.id && authArray[p.id][0] == player.auth); for (let oldPlayer of oldPlayerArray) { ghostKickHandle(oldPlayer, player); } } handlePlayersJoin(); }; room.onPlayerTeamChange = function (changedPlayer, byPlayer) { handleLineupChangeTeamChange(changedPlayer); if (AFKSet.has(changedPlayer.id) && changedPlayer.team != Team.SPECTATORS) { room.setPlayerTeam(changedPlayer.id, Team.SPECTATORS); room.sendAnnouncement( `${changedPlayer.name} is AFK !`, null, errorColor, 'bold', HaxNotification.CHAT ); return; } updateTeams(); if (gameState != State.STOP) { if (changedPlayer.team != Team.SPECTATORS && game.scores.time <= (3 / 4) * game.scores.timeLimit && Math.abs(game.scores.blue - game.scores.red) < 2) { changedPlayer.team == Team.RED ? teamRedStats.push(changedPlayer) : teamBlueStats.push(changedPlayer); } } handleActivityPlayerTeamChange(changedPlayer); handlePlayersTeamChange(byPlayer); }; room.onPlayerLeave = function (player) { setTimeout(() => { if (!kickFetchVariable) { if (roomWebhook != '') { var stringContent = `[${getDate()}] ⬅️ LEAVE (${playersAll.length}/${maxPlayers})\n**${player.name}**` + `[${authArray[player.id][0]}] {${authArray[player.id][1]}}`; fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: stringContent, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } } else kickFetchVariable = false; }, 10); handleLineupChangeLeave(player); checkCaptainLeave(player); updateTeams(); updateAdmins(); handlePlayersLeave(); }; room.onPlayerKicked = function (kickedPlayer, reason, ban, byPlayer) { kickFetchVariable = true; if (roomWebhook != '') { var stringContent = `[${getDate()}] β›” ${ban ? 'BAN' : 'KICK'} (${playersAll.length}/${maxPlayers})\n` + `**${kickedPlayer.name}** [${authArray[kickedPlayer.id][0]}] {${authArray[kickedPlayer.id][1]}} was ${ban ? 'banned' : 'kicked'}` + `${byPlayer != null ? ' by **' + byPlayer.name + '** [' + authArray[byPlayer.id][0] + '] {' + authArray[byPlayer.id][1] + '}' : ''}` fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: stringContent, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } if ((ban && ((byPlayer != null && (byPlayer.id == kickedPlayer.id || getRole(byPlayer) < Role.MASTER)) || getRole(kickedPlayer) == Role.MASTER)) || disableBans ) { room.clearBan(kickedPlayer.id); return; } if (byPlayer != null && getRole(byPlayer) < Role.ADMIN_PERM) { room.sendAnnouncement( 'You are not allowed to kick/ban players !', byPlayer.id, errorColor, 'bold', HaxNotification.CHAT ); room.setPlayerAdmin(byPlayer.id, false); return; } if (ban) banList.push([kickedPlayer.name, kickedPlayer.id]); }; /* PLAYER ACTIVITY */ room.onPlayerChat = function (player, message) { if (gameState !== State.STOP && player.team != Team.SPECTATORS) { let pComp = getPlayerComp(player); if (pComp != null) pComp.inactivityTicks = 0; } let msgArray = message.split(/ +/); if (!hideClaimMessage || msgArray[0] != '!claim') { if (roomWebhook != '') fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: `[${getDate()}] πŸ’¬ CHAT\n**${player.name}** : ${message.replace('@', '@ ')}`, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } if (msgArray[0][0] == '!') { let command = getCommand(msgArray[0].slice(1).toLowerCase()); if (command != false && commands[command].roles <= getRole(player)) commands[command].function(player, message); else room.sendAnnouncement( `The command you tried to enter does not exist for you. Please enter '!help' to get the available commands to you.`, player.id, errorColor, 'bold', HaxNotification.CHAT ); return false; } if (msgArray[0].toLowerCase() == 't') { teamChat(player, message); return false; } if (msgArray[0].substring(0, 2) === '@@') { playerChat(player, message); return false; } if (chooseMode && teamRed.length * teamBlue.length != 0) { var choosingMessageCheck = chooseModeFunction(player, message); if (choosingMessageCheck) return false; } if (slowMode > 0) { var filter = slowModeFunction(player, message); if (filter) return false; } if (!player.admin && muteArray.getByAuth(authArray[player.id][0]) != null) { room.sendAnnouncement( `You are muted !`, player.id, errorColor, 'bold', HaxNotification.CHAT ); return false; } }; room.onPlayerActivity = function (player) { if (gameState !== State.STOP) { let pComp = getPlayerComp(player); if (pComp != null) pComp.inactivityTicks = 0; } }; room.onPlayerBallKick = function (player) { if (playSituation != Situation.GOAL) { var ballPosition = room.getBallPosition(); if (game.touchArray.length == 0 || player.id != game.touchArray[game.touchArray.length - 1].player.id) { if (playSituation == Situation.KICKOFF) playSituation = Situation.PLAY; lastTeamTouched = player.team; game.touchArray.push( new BallTouch( player, game.scores.time, getGoalGame(), ballPosition ) ); lastTouches[0] = checkGoalKickTouch( game.touchArray, game.touchArray.length - 1, getGoalGame() ); lastTouches[1] = checkGoalKickTouch( game.touchArray, game.touchArray.length - 2, getGoalGame() ); } } }; /* GAME MANAGEMENT */ room.onGameStart = function (byPlayer) { clearTimeout(startTimeout); if (byPlayer != null) clearTimeout(stopTimeout); game = new Game(); possession = [0, 0]; actionZoneHalf = [0, 0]; gameState = State.PLAY; endGameVariable = false; goldenGoal = false; playSituation = Situation.KICKOFF; lastTouches = Array(2).fill(null); lastTeamTouched = Team.SPECTATORS; teamRedStats = []; teamBlueStats = []; if (teamRed.length == teamSize && teamBlue.length == teamSize) { for (var i = 0; i < teamSize; i++) { teamRedStats.push(teamRed[i]); teamBlueStats.push(teamBlue[i]); } } calculateStadiumVariables(); }; room.onGameStop = function (byPlayer) { clearTimeout(stopTimeout); clearTimeout(unpauseTimeout); if (byPlayer != null) clearTimeout(startTimeout); game.rec = room.stopRecording(); if ( !cancelGameVariable && game.playerComp[0].length + game.playerComp[1].length > 0 && ( (game.scores.timeLimit != 0 && ((game.scores.time >= 0.5 * game.scores.timeLimit && game.scores.time < 0.75 * game.scores.timeLimit && game.scores.red != game.scores.blue) || game.scores.time >= 0.75 * game.scores.timeLimit) ) || endGameVariable ) ) { fetchSummaryEmbed(game); if (fetchRecordingVariable) { setTimeout((gameEnd) => { fetchRecording(gameEnd); }, 500, game); } } cancelGameVariable = false; gameState = State.STOP; playSituation = Situation.STOP; updateTeams(); handlePlayersStop(byPlayer); handleActivityStop(); }; room.onGamePause = function (byPlayer) { if (mentionPlayersUnpause && gameState == State.PAUSE) { if (byPlayer != null) { room.sendAnnouncement( `Game paused by ${byPlayer.name} !`, null, defaultColor, 'bold', HaxNotification.NONE ); } else { room.sendAnnouncement( `Game paused !`, null, defaultColor, 'bold', HaxNotification.NONE ); } } clearTimeout(unpauseTimeout); gameState = State.PAUSE; }; room.onGameUnpause = function (byPlayer) { unpauseTimeout = setTimeout(() => { gameState = State.PLAY; }, 2000); if (mentionPlayersUnpause) { if (byPlayer != null) { room.sendAnnouncement( `Game unpaused by ${byPlayer.name} !`, null, defaultColor, 'bold', HaxNotification.NONE ); } else { room.sendAnnouncement( `Game unpaused !`, null, defaultColor, 'bold', HaxNotification.NONE ); } } if ( (teamRed.length == teamSize && teamBlue.length == teamSize && chooseMode) || (teamRed.length == teamBlue.length && teamSpec.length < 2 && chooseMode) ) { deactivateChooseMode(); } }; room.onTeamGoal = function (team) { const scores = room.getScores(); game.scores = scores; playSituation = Situation.GOAL; ballSpeed = getBallSpeed(); var goalString = getGoalString(team); for (let player of teamRed) { var playerComp = getPlayerComp(player); team == Team.RED ? playerComp.goalsScoredTeam++ : playerComp.goalsConcededTeam++; } for (let player of teamBlue) { var playerComp = getPlayerComp(player); team == Team.BLUE ? playerComp.goalsScoredTeam++ : playerComp.goalsConcededTeam++; } room.sendAnnouncement( goalString, null, team == Team.RED ? redColor : blueColor, null, HaxNotification.CHAT ); if (roomWebhook != '') { fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: `[${getDate()}] ${goalString}`, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } if ((scores.scoreLimit != 0 && (scores.red == scores.scoreLimit || scores.blue == scores.scoreLimit)) || goldenGoal) { endGame(team); goldenGoal = false; stopTimeout = setTimeout(() => { room.stopGame(); }, 1000); } }; room.onPositionsReset = function () { lastTouches = Array(2).fill(null); lastTeamTouched = Team.SPECTATORS; playSituation = Situation.KICKOFF; }; /* MISCELLANEOUS */ room.onRoomLink = function (url) { console.log(`${url}\nmasterPassword : ${masterPassword}`); if (roomWebhook != '') { fetch(roomWebhook, { method: 'POST', body: JSON.stringify({ content: `[${getDate()}] πŸ”— LINK ${url}\nmasterPassword : ${masterPassword}`, username: roomName, }), headers: { 'Content-Type': 'application/json', }, }).then((res) => res); } }; room.onPlayerAdminChange = function (changedPlayer, byPlayer) { updateTeams(); if (!changedPlayer.admin && getRole(changedPlayer) >= Role.ADMIN_TEMP) { room.setPlayerAdmin(changedPlayer.id, true); return; } updateAdmins(byPlayer != null && !changedPlayer.admin && changedPlayer.id == byPlayer.id ? changedPlayer.id : 0); }; room.onKickRateLimitSet = function (min, rate, burst, byPlayer) { if (byPlayer != null) { room.sendAnnouncement( `It is not allowed to change the kickrate limit. It must stay at "6-0-0".`, player.id, errorColor, 'bold', HaxNotification.CHAT ); room.setKickRateLimit(6, 0, 0); } }; room.onStadiumChange = function (newStadiumName, byPlayer) { if (byPlayer !== null) { if (getRole(byPlayer) < Role.MASTER && currentStadium != 'other') { room.sendAnnouncement( `You can't change stadium manually ! Please use the stadium commands.`, byPlayer.id, errorColor, 'bold', HaxNotification.CHAT ); stadiumCommand(emptyPlayer, `!${currentStadium}`); } else { room.sendAnnouncement( `Map changed. After you're done with this map, please use the stadium commands.`, byPlayer.id, infoColor, 'bold', HaxNotification.CHAT ); currentStadium = 'other'; } } checkStadiumVariable = true; }; room.onGameTick = function () { checkTime(); getLastTouchOfTheBall(); getGameStats(); handleActivity(); };