haxball_server/script_hecho.js
2024-05-16 17:17:26 +02:00

3745 lines
154 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// CHANGES BY BORRAGEIROS
//
// -Momento en el que se cambia al mapa grande, changeToBigMapOn variable
// -Momento en el que se cambia al mapa pequeño, changeToClassicMapOn variable
//
// -Traducciones
// USO:
// translate('example', { exampleVariable: "texto de ejemplo" }),
// translate('exampleWithOutVariable'),
function translate(key, args) {
try {
var str = key.split('.').reduce((obj, i) => obj[i], translations);
if (!args) return str;
return str.replace(/\${(.*?)}/g, (match, key) => args[key.trim()]);
} catch (error) {
console.error("Translation error:", error);
return "";
}
}
var translations = {
example: `Esto es un ejemplo de uso. Ejemplo de variable: \${exampleVariable}`,
exampleWithOutVariable: `Esto es un ejemplo de uso sin variable.`,
///////////////
wellcome: `👋 ¡Bienvenido \${name}! \n¡Escribe "t" antes de tu mensaje para usar el chat de equipo y "@@" seguido del nombre de un jugador para enviarle un mensaje privado!`,
commands: {
help: `Este comando muestra todos los comandos disponibles. También puede mostrar la descripción de un comando en particular.
Ejemplo: '!help bb' mostrará la descripción del comando '!bb'.`,
claim: "reclamar",
afk: `Este comando te pone en modo AFK.
Tiene restricciones: un mínimo de 1 minuto de tiempo AFK, un máximo de 5 minutos y un tiempo de enfriamiento de 10 minutos.`,
afks: "Este comando muestra todos los jugadores que están AFK.",
bb: "Este comando te hace salir instantáneamente (uso recomendado).",
me: "Este comando muestra tus estadísticas globales en la sala.",
rename: "Este comando te permite cambiar tu nombre para el marcador.",
games: "Este comando muestra a los 5 mejores jugadores con más partidas en la sala.",
wins: "Este comando muestra a los 5 mejores jugadores con más victorias en la sala.",
goals: "Este comando muestra a los 5 mejores jugadores con más goles en la sala.",
assists: "Este comando muestra a los 5 mejores jugadores con más asistencias en la sala.",
cs: "Este comando muestra a los 5 mejores jugadores con más CS en la sala.",
playtime: "Este comando muestra a los 5 mejores jugadores con más tiempo jugado en la sala.",
training: "Este comando carga el estadio de entrenamiento clásico.",
classic: "Este comando carga el estadio clásico.",
big: "Este comando carga el estadio grande.",
rr: "Este comando reinicia el juego.",
rrs: "Este comando intercambia los equipos y reinicia el juego.",
swap: "Este comando intercambia los equipos cuando el juego está detenido.",
kickred: "Este comando expulsa a todos los jugadores del equipo rojo, incluido el jugador que introdujo el comando. Puedes proporcionar como argumento la razón de la expulsión.",
kickblue: "Este comando expulsa a todos los jugadores del equipo azul, incluido el jugador que introdujo el comando. Puedes proporcionar como argumento la razón de la expulsión.",
kickspec: "Este comando expulsa a todos los jugadores del equipo de espectadores, incluido el jugador que introdujo el comando. Puedes proporcionar como argumento la razón de la expulsión.",
mute: `Este comando permite silenciar a un jugador. No podrá hablar durante una cierta duración y puede ser desmutado en cualquier momento por los administradores.
Toma 2 argumentos:
Argumento 1: #<id> donde <id> es el id del jugador objetivo. Esto no funcionará si el jugador es un administrador.
Argumento 2 (opcional): <duración> donde <duración> es la duración del mute en minutos. Si no se proporciona ningún valor, el mute dura la duración predeterminada, 5 minutos.
Ejemplo: '!mute #3 20' silenciará al jugador con id 3 durante 20 minutos.`,
unmute: `Este comando permite desmutear a alguien.
Toma 1 argumento:
Argumento 1: #<id> donde <id> es el id del jugador silenciado.
O
Argumento 1: <número> donde <número> es el número asociado con el mute dado por el comando 'muteList'.
Ejemplo: '!unmute #300' desmuteará al jugador con id 300,
'!unmute 8' desmuteará al jugador n°8 según el comando 'muteList'.`,
mutes: "Este comando muestra la lista de jugadores silenciados.",
clearbans: `Este comando desbanea a todos. También puede desbanear a un jugador en particular, añadiendo su ID como argumento.`,
bans: "Este comando muestra a todos los jugadores que fueron baneados y sus IDs.",
admins: "Este comando muestra a todos los jugadores que son administradores permanentes.",
setadmin: `Este comando permite convertir a alguien en administrador. Podrá conectarse como administrador y puede ser eliminado en cualquier momento por los maestros.
Toma 1 argumento:
Argumento 1: #<id> donde <id> es el id del jugador objetivo.
Ejemplo: '!setadmin #3' dará administrador al jugador con id 3.`,
removeadmin: `Este comando permite quitar a alguien como administrador.
Toma 1 argumento:
Argumento 1: #<id> donde <id> es el id del jugador objetivo.
O
Argumento 1: <número> donde <número> es el número asociado con el administrador dado por el comando 'admins'.
Ejemplo: '!removeadmin #300' quitará el administrador al jugador con id 300,
'!removeadmin 2' quitará el administrador n°2 según el comando 'admins'.`,
password: `Este comando permite agregar una contraseña a la sala.
Toma 1 argumento:
Argumento 1: <contraseña> donde <contraseña> es la contraseña que deseas para la sala.
Para eliminar la contraseña de la sala, simplemente introduce '!password'.`,
},
unmute: `Estás desmuteado.`,
invalidPlayer: `Jugador inválido, asegurate de que el nombre es correcto.`,
pmYourself: `No puedes enviarte un mensaje privado a ti mismo`,
with: `con`,
commandsInfo: `\nPara informarte sobre un comando, escribe '!help <command name>'`,
command: `comando`,
invalidCommand: `El comando que deseas comprobar no existe, Para ver los comandos existentes, escribe \'!help\'`,
changeUsername: `Te has cambiado el nombre \${name}`,
haventPlayed: `Todavía no has jugado en esta sala!`,
minAfk: `Hay un mínimo de \${min} minutos de AFK. No abuses del comando!`,
noAfk: `🌅 \${player} ya no está AFK!`,
everyAfk: `Solo puedes ir AFK cada \${min} minutos. No abuses del comando!`,
nowAfk: `😴 \${player} está AFK!`,
cantAfk: `No puedes ir AFK si estás en un equipo!`,
nobodyInList: `📢 No hay nadie en la lista \${list}`,
listAfk: `😴 Lista AFK: `,
listBan: `📢 Lista baneados: `,
listAdmin: `📢 Lista admins: `,
nowMaster: `\${player} es ahora un room master!`,
alreadyMaster: `Ya eres un room master!`,
teamsSwapped: `✔️ Equipos swapeados`,
stopBefore: `Por favor, para el juego antes.`,
teamKick: `Equipo kickeado por \${player}`,
stadiumNotFound: `No se encontró el estadio`,
haveBeenMuted: `\${player} ha sido silenciado por \${mins} minutos`,
haveBeenUnmuted: `\${player} ha sido desmutado!`,
isntMuted: `Este jugador no está muteado!`,
youCantMuteAdmin: `No puedes silenciar a un administrador`,
muteNotFound: `No se encontró el jugador con el ID proporcionado. Escribe '!help mute para más información'`,
invalidFormat: `Formato inválido. Escribe '!help mute para más información'`,
wrongArgsNumber: `Número de argumentos incorrecto. Escribe '!help mute' para más información`,
emptyMuteList: `🔇 No hay nadie en la lista de muteados.`,
muteList: `🔇 Lista de muteados: `,
bansCleared: `✔️ Baneos limpiados`,
unbannedFromRoom: `✔️ \${player} ha sido desbaneado de la sala!`,
clearBanIdNotFound: `El ID que escribiste no parece tener un ban asociado. Escribe '!help clearbans' para más información`,
// AQUI FUE LA ÚLTIMA TRADUCCIÓN, HAY QUE RETOMARLAS
masterConected: `El master \${player} se ha conectado a la sala!`,
adminConected: `El administrador \${player} se ha conectado a la sala!`,
firstGoalWins: `⚽ EL QUE META GANA! `,
blueTeamWins: `✨ Equipo azul gana \${blue} - \${red} ! Racha actual: \${streak}`,
redTeamWins: `✨ Equipo rojo gana \${red} - \${blue} ! Racha actual: \${streak}`,
possession: `📊 Posesión: 🔴 \${possession}\n`,
actionZone: `📊 Zona de acción: 🔴 \${action}\n`,
slowModeChanged: `🐢 Modo lento cambiado a modo elección, duración de: \${secs}s`,
players: `Jugadores : `,
toChooseAPlayer: `Para escoger a un jugador, escribe el número de su posición en la lista central o usa 'top', 'random' o 'bottom'.`,
chooseHurryUp: `Apura \${player}! Sólo quedan \${secs} segundos para escoger!`,
didntChoose: `No escogiste jugadores a tiempo!`,
invalidNumber: `El número es inválido!`,
youWillBeKicked: `\${player}, si no te mueves o mandas un mensaje en los próximos \${secs} segundos, serás kickeado!`,
goalByAssistBy: `\${time} Gol de \${goalBy}! Asistencia de \${assistBy}! Velocidad de \${speed}km/h!`,
goalBy: `\${time} Gol de \${goalBy}! Velocidad de \${speed}km/h!`,
ownGoalBy: `😂 \${time} Gol de \${goalBy}! Velocidad de \${speed}km/h!`,
goalFor: `\${time} Gol para \${team}! Velocidad de \${speed}km/h!`,
}
// FIN CHANGES BY BORRAGEIROS
/* VARIABLES */
/* ROOM */
const roomName = '🇪🇸..3⃣🆚3⃣..5⃣🆚5⃣..⚽FUTBOL SALA⚽';
const maxPlayers = 15;
const roomPublic = true;
const token = ""; // Insert token here
var roomWebhook = 'https://discord.com/api/webhooks/1240281077176864802/S3g6mEmedG8ae-8G8RGAqh48N36tmzO0FWa2IPTguVxvQjnzTj4tQ19_gLiz9_oJctDC'; // this webhook is used to send the details of the room (chat, join, leave) ; it should be in a private discord channel
var masterPasswordWebHook = 'https://discord.com/api/webhooks/1240682381132828722/t6dTMae0OB3dPQXllL9dNcxT_ruiJ2YuTVpDXmNdTkRHeLMG1XBVbFnJdXSzegVZusJg'; // webhook para mantar SOLO la contraseña de master
var webhookName = "HAXBALL SERVER";
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","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 = trainingMap;
const bigMap = `{"name":"Futsal 5x5","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;
var changeToClassicMapOn = 6;
// 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(
translate('unmute'),
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", "El santo"] // xoel
// ['INSERT_AUTH_HERE_1', 'NICK_OF_ADMIN_1'],
// ['INSERT_AUTH_HERE_2', 'NICK_OF_ADMIN_2'],
];
var masterList = [
// 'amuZ3Vk-M6Vk8_DuphOjismmfRRo4SQ44RyUuLb9nLc', // borrageiros
// '_LSQgSnedi0Y2E86tf5-ql6fLYORVHUDsEvilNFXKA4' // xoel
];
/* COMMANDS */
var commands = {
help: {
aliases: ['comandos'],
roles: Role.PLAYER,
desc: translate('commands.help'),
function: helpCommand,
},
claim: {
aliases: [],
roles: Role.PLAYER,
desc: false,
function: masterCommand,
},
afk: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.afk'),
function: afkCommand,
},
afks: {
aliases: ['afklist'],
roles: Role.PLAYER,
desc: translate('commands.afks'),
function: afkListCommand,
},
bb: {
aliases: ['bye', 'gn', 'cya'],
roles: Role.PLAYER,
desc: translate('commands.bb'),
function: leaveCommand,
},
me: {
aliases: ['stat', 'stats'],
roles: Role.PLAYER,
desc: translate('commands.me'),
function: globalStatsCommand,
},
rename: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.rename'),
function: renameCommand,
},
games: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.games'),
function: statsLeaderboardCommand,
},
wins: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.wins'),
function: statsLeaderboardCommand,
},
goals: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.goals'),
function: statsLeaderboardCommand,
},
assists: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.assists'),
function: statsLeaderboardCommand,
},
cs: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.cs'),
function: statsLeaderboardCommand,
},
playtime: {
aliases: [],
roles: Role.PLAYER,
desc: translate('commands.playtime'),
function: statsLeaderboardCommand,
},
training: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.training'),
function: stadiumCommand,
},
classic: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.classic'),
function: stadiumCommand,
},
big: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.big'),
function: stadiumCommand,
},
rr: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.rr'),
function: restartCommand,
},
rrs: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.rrs'),
function: restartSwapCommand,
},
swap: {
aliases: ['s'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.swap'),
function: swapCommand,
},
kickred: {
aliases: ['kickr'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.kickred'),
function: kickTeamCommand,
},
kickblue: {
aliases: ['kickb'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.kickblue'),
function: kickTeamCommand,
},
kickspec: {
aliases: ['kicks'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.kickspec'),
function: kickTeamCommand,
},
mute: {
aliases: ['m'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.mute'),
function: muteCommand,
},
unmute: {
aliases: ['um'],
roles: Role.ADMIN_TEMP,
desc: translate('commands.unmute'),
function: unmuteCommand,
},
mutes: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: translate('commands.mutes'),
function: muteListCommand,
},
clearbans: {
aliases: [],
roles: Role.MASTER,
desc: translate('commands.clearbans'),
function: clearbansCommand,
},
bans: {
aliases: ['listaban'],
roles: Role.MASTER,
desc: translate('commands.bans'),
function: banListCommand,
},
admins: {
aliases: ['listadmin'],
roles: Role.MASTER,
desc: translate('commands.admins'),
function: adminListCommand,
},
setadmin: {
aliases: ['admin'],
roles: Role.MASTER,
desc: translate('commands.setadmin'),
function: setAdminCommand,
},
removeadmin: {
aliases: ['unadmin'],
roles: Role.MASTER,
desc: translate('commands.removeadmin'),
function: removeAdminCommand,
},
password: {
aliases: ['pw'],
roles: Role.MASTER,
desc: translate('commands.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(
translate("invalidPlayer"),
player.id,
errorColor,
'bold',
null
);
return false;
}
var playerTarget = playersAll[playerTargetIndex];
if (player.id == playerTarget.id) {
room.sendAnnouncement(
translate("pmYourself"),
player.id,
errorColor,
'bold',
null
);
return false;
}
var messageFrom = `📝 [PM ${translate("with")} ${playerTarget.name}] ${player.name}: ${msgArray.slice(1).join(' ')}`
var messageTo = `📝 [PM ${translate("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 += translate("commandsInfo");
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}\' ${translate("command")} :\n${commands[commandName].desc}`,
player.id,
infoColor,
'bold',
HaxNotification.CHAT
);
else
room.sendAnnouncement(
translate("invalidCommand"),
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(
translate('changeUsername', { name: stats.playerName }),
player.id,
successColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
translate("haventPlayed"),
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(
translate('minAfk', { min: minAFKDuration }),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
} else {
AFKSet.delete(player.id);
room.sendAnnouncement(
translate('noAfk', { player: player.name }),
null,
announcementColor,
'bold',
null
);
updateTeams();
handlePlayersJoin();
}
} else {
if (AFKCooldownSet.has(player.id)) {
room.sendAnnouncement(
translate('everyAfk', { min: AFKCooldown }),
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(
translate('nowAfk', { player: player.name }),
null,
announcementColor,
'bold',
null
);
updateTeams();
handlePlayersLeave();
}
}
} else {
room.sendAnnouncement(
translate("cantAfk"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function afkListCommand(player, message) {
if (AFKSet.size == 0) {
room.sendAnnouncement(
translate("nobodyInList", { list: 'AFK' }),
player.id,
announcementColor,
'bold',
null
);
return;
}
var cstm = translate("listAfk");
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(
translate("nowMaster", { player: player.name}),
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
translate("alreadyMaster"),
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(
translate("teamsSwapped"),
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
translate("stopBefore"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function kickTeamCommand(player, message) {
var msgArray = message.split(/ +/);
var reasonString = translate("teamKick", { player: 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(
translate("stadiumNotFound"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("stopBefore"),
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(
translate("haveBeenMuted", { player: playerMute.name, mins: minutesMute }),
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
translate("youCantMuteAdmin"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("muteNotFound"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("invalidFormat"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("wrongArgsNumber", { command: '!help mute' }),
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(
translate("haveBeenUnmuted", { player: playerUnmute.name }),
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
translate("isntMuted"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("muteNotFound"),
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(
translate("haveBeenUnmuted", { player: playerUnmute.name }),
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
translate("invalidFormat"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("wrongArgsNumber", { command: '!help mute' }),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function muteListCommand(player, message) {
if (muteArray.list.length == 0) {
room.sendAnnouncement(
translate("emptyMuteList"),
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = translate("muteList");
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(
translate("bansCleared"),
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(
translate("unbannedFromRoom", { player: banList.filter((p) => p[1] == ID)[0][0] }),
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
translate("clearBanIdNotFound"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
banList = banList.filter((p) => p[1] != ID);
} else {
room.sendAnnouncement(
translate("clearBanIdNotFound"),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
translate("wrongArgsNumber", { command: '!help clearbans' }),
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function banListCommand(player, message) {
if (banList.length == 0) {
room.sendAnnouncement(
translate("nobodyInList", { list: 'de baneados' }),
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = translate("listBan");
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(
translate("nobodyInList", { list: 'de admins' }),
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = translate("listAdmin");
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(
translate("firstGoalWins"),
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(
translate("redTeamWins", { blue: scores.blue, red: scores.red, streak: streak }),
null,
redColor,
'bold',
HaxNotification.CHAT
);
} else if (winner == Team.BLUE) {
streak = 1;
room.sendAnnouncement(
translate("blueTeamWins", { blue: scores.blue, red: scores.red, 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(
translate("possession", { possession: possessionString }) +
translate("actionZone", { action: actionString }) +
`${CSString}`,
null,
announcementColor,
'bold',
HaxNotification.NONE
);
updateStats();
}
/* CHOOSING FUNCTIONS */
function activateChooseMode() {
chooseMode = true;
slowMode = chooseModeSlowMode;
room.sendAnnouncement(
translate("slowModeChanged", { secs: chooseModeSlowMode }),
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
function deactivateChooseMode() {
chooseMode = false;
clearTimeout(timeOutCap);
if (slowMode != defaultSlowMode) {
slowMode = defaultSlowMode;
room.sendAnnouncement(
translate("slowModeChanged", { secs: defaultSlowMode }),
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
redCaptainChoice = '';
blueCaptainChoice = '';
}
function getSpecList(player) {
if (player == null) return null;
var cstm = translate("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(
translate("toChooseAPlayer"),
captain.id,
infoColor,
'bold',
HaxNotification.MENTION
);
timeOutCap = setTimeout(
(player) => {
room.sendAnnouncement(
translate("chooseHurryUp", { player: player.name, secs: Number.parseInt(String(chooseTime / 2)) }),
player.id,
warningColor,
'bold',
HaxNotification.MENTION
);
timeOutCap = setTimeout(
(player) => {
room.kickPlayer(
player.id,
translate("didntChoose"),
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(
translate("invalidNumber"),
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(
translate("invalidNumber"),
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(
translate("youWillBeKicked", { player: player.name, secs: Math.floor(afkLimit / 3) }),
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 == changeToClassicMapOn) { // antes: (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 > 3 && players.length == changeToBigMapOn) { // ANTES: (teamSize > 2 && players.length == 6)
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 = translate("goalByAssistBy", {time: getTimeGame(scores.time), goalBy: goalAttribution[0].name, assistBy: goalAttribution[1].name, speed: ballSpeed.toFixed(2) });
game.goals.push(
new Goal(
scores.time,
team,
goalAttribution[0],
goalAttribution[1]
)
);
} else {
goalString = translate("goalBy", {time: getTimeGame(scores.time), goalBy: goalAttribution[0].name, speed: ballSpeed.toFixed(2) });
game.goals.push(
new Goal(scores.time, team, goalAttribution[0], null)
);
}
} else {
goalString = translate("ownGoalBy", {time: getTimeGame(scores.time), goalBy: goalAttribution[0].name, speed: ballSpeed.toFixed(2) });
game.goals.push(
new Goal(scores.time, team, goalAttribution[0], null)
);
}
} else {
goalString = translate("ownGoalBy", {time: getTimeGame(scores.time), team: team == Team.RED ? 'red' : 'blue', speed: ballSpeed.toFixed(2) });
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: webhookName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
room.sendAnnouncement(
translate('wellcome', { name: player.name }),
player.id,
welcomeColor,
'bold',
HaxNotification.CHAT
);
updateTeams();
updateAdmins();
if (masterList.findIndex((auth) => auth == player.auth) != -1) {
room.sendAnnouncement(
translate("masterConected", { player: player.name }),
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(
translate("adminConected", { player: player.name }),
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} está 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: webhookName,
}),
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: webhookName,
}),
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: webhookName,
}),
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: webhookName,
}),
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 (masterPasswordWebHook != '') {
fetch(masterPasswordWebHook, {
method: 'POST',
body: JSON.stringify({
content: `[${getDate()}] 🔗 LINK ${url}\nmasterPassword : ${masterPassword}`,
username: webhookName,
}),
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();
};