haxball_server/script_hecho.js

3661 lines
148 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
// -
// 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 = ''; // this webhook is used to send the details of the room (chat, join, leave) ; it should be in a private discord channel
var gameWebhook = ''; // this webhook is used to send the summary of the games ; it should be in a public discord channel
var fetchRecordingVariable = true;
var timeLimit = 7;
var scoreLimit = 3;
var gameConfig = {
roomName: roomName,
maxPlayers: maxPlayers,
public: roomPublic,
noPlayer: true,
}
if (typeof token == 'string' && token.length == 39) {
gameConfig.token = token;
}
var room = HBInit(gameConfig);
const trainingMap = `{"name":"Futsal 3x3","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;
// by borrageiros
var drawTimeLimit = Infinity;
var teamSize = 5;
var maxAdmins = 0;
var disableBans = false;
var debugMode = false;
var afkLimit = debugMode ? Infinity : 12;
var defaultSlowMode = 0.5;
var chooseModeSlowMode = 1;
var slowMode = defaultSlowMode;
var SMSet = new Set();
var hideClaimMessage = true;
var mentionPlayersUnpause = true;
/* OBJECTS */
class Goal {
constructor(time, team, striker, assist) {
this.time = time;
this.team = team;
this.striker = striker;
this.assist = assist;
}
}
class Game {
constructor() {
this.date = Date.now();
this.scores = room.getScores();
this.playerComp = getStartingLineups();
this.goals = [];
this.rec = room.startRecording();
this.touchArray = [];
}
}
class PlayerComposition {
constructor(player, auth, timeEntry, timeExit) {
this.player = player;
this.auth = auth;
this.timeEntry = timeEntry;
this.timeExit = timeExit;
this.inactivityTicks = 0;
this.GKTicks = 0;
}
}
class MutePlayer {
constructor(name, id, auth) {
this.id = MutePlayer.incrementId();
this.name = name;
this.playerId = id;
this.auth = auth;
this.unmuteTimeout = null;
}
static incrementId() {
if (!this.latestId) this.latestId = 1
else this.latestId++
return this.latestId
}
setDuration(minutes) {
this.unmuteTimeout = setTimeout(() => {
room.sendAnnouncement(
`You have been unmuted.`,
this.playerId,
announcementColor,
"bold",
HaxNotification.CHAT
);
this.remove();
}, minutes * 60 * 1000);
muteArray.add(this);
}
remove() {
this.unmuteTimeout = null;
muteArray.removeById(this.id);
}
}
class MuteList {
constructor() {
this.list = [];
}
add(mutePlayer) {
this.list.push(mutePlayer);
return mutePlayer;
}
getById(id) {
var index = this.list.findIndex(mutePlayer => mutePlayer.id === id);
if (index !== -1) {
return this.list[index];
}
return null;
}
getByPlayerId(id) {
var index = this.list.findIndex(mutePlayer => mutePlayer.playerId === id);
if (index !== -1) {
return this.list[index];
}
return null;
}
getByAuth(auth) {
var index = this.list.findIndex(mutePlayer => mutePlayer.auth === auth);
if (index !== -1) {
return this.list[index];
}
return null;
}
removeById(id) {
var index = this.list.findIndex(mutePlayer => mutePlayer.id === id);
if (index !== -1) {
this.list.splice(index, 1);
}
}
removeByAuth(auth) {
var index = this.list.findIndex(mutePlayer => mutePlayer.auth === auth);
if (index !== -1) {
this.list.splice(index, 1);
}
}
}
class BallTouch {
constructor(player, time, goal, position) {
this.player = player;
this.time = time;
this.goal = goal;
this.position = position;
}
}
class HaxStatistics {
constructor(playerName = '') {
this.playerName = playerName;
this.games = 0;
this.wins = 0;
this.winrate = '0.00%';
this.playtime = 0;
this.goals = 0;
this.assists = 0;
this.CS = 0;
this.ownGoals = 0;
}
}
/* PLAYERS */
const Team = { SPECTATORS: 0, RED: 1, BLUE: 2 };
const State = { PLAY: 0, PAUSE: 1, STOP: 2 };
const Role = { PLAYER: 0, ADMIN_TEMP: 1, ADMIN_PERM: 2, MASTER: 3 };
const HaxNotification = { NONE: 0, CHAT: 1, MENTION: 2 };
const Situation = { STOP: 0, KICKOFF: 1, PLAY: 2, GOAL: 3 };
var gameState = State.STOP;
var playSituation = Situation.STOP;
var goldenGoal = false;
var playersAll = [];
var players = [];
var teamRed = [];
var teamBlue = [];
var teamSpec = [];
var teamRedStats = [];
var teamBlueStats = [];
var banList = [];
/* STATS */
var possession = [0, 0];
var actionZoneHalf = [0, 0];
var lastWinner = Team.SPECTATORS;
var streak = 0;
/* AUTH */
var authArray = [];
var adminList = [
["amuZ3Vk-M6Vk8_DuphOjismmfRRo4SQ44RyUuLb9nLc", "borrageiros"], // borrageiros
["_LSQgSnedi0Y2E86tf5-ql6fLYORVHUDsEvilNFXKA4", "xoel"] // xoel
// ['INSERT_AUTH_HERE_1', 'NICK_OF_ADMIN_1'],
// ['INSERT_AUTH_HERE_2', 'NICK_OF_ADMIN_2'],
];
var masterList = [
'amuZ3Vk-M6Vk8_DuphOjismmfRRo4SQ44RyUuLb9nLc',
'_LSQgSnedi0Y2E86tf5-ql6fLYORVHUDsEvilNFXKA4'
];
/* COMMANDS */
var commands = {
help: {
aliases: ['commands'],
roles: Role.PLAYER,
desc: `
This command shows all the available commands. It also can show the description of a command in particular.
Example: \'!help bb\' will show the description of the \'bb\' command.`,
function: helpCommand,
},
claim: {
aliases: [],
roles: Role.PLAYER,
desc: false,
function: masterCommand,
},
afk: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command makes you go AFK.
It has constraints: 1 minute minimum of AFK time, 5 minutes maximum and 10 minutes cooldown.`,
function: afkCommand,
},
afks: {
aliases: ['afklist'],
roles: Role.PLAYER,
desc: `
This command shows all the players that are AFK.`,
function: afkListCommand,
},
bb: {
aliases: ['bye', 'gn', 'cya'],
roles: Role.PLAYER,
desc: `
This command makes you leave instantly (use recommended).`,
function: leaveCommand,
},
me: {
aliases: ['stat', 'stats'],
roles: Role.PLAYER,
desc: `
This command shows your global stats in the room.`,
function: globalStatsCommand,
},
rename: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command allows you to rename yourself for the leaderboard.`,
function: renameCommand,
},
games: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most games in the room.`,
function: statsLeaderboardCommand,
},
wins: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most wins in the room.`,
function: statsLeaderboardCommand,
},
goals: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most goals in the room.`,
function: statsLeaderboardCommand,
},
assists: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most assists in the room.`,
function: statsLeaderboardCommand,
},
cs: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most CS in the room.`,
function: statsLeaderboardCommand,
},
playtime: {
aliases: [],
roles: Role.PLAYER,
desc: `
This command shows the top 5 players with the most time played in the room.`,
function: statsLeaderboardCommand,
},
training: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command loads the classic training stadium.`,
function: stadiumCommand,
},
classic: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command loads the classic stadium.`,
function: stadiumCommand,
},
big: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command loads the big stadium.`,
function: stadiumCommand,
},
rr: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command restarts the game.`,
function: restartCommand,
},
rrs: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command swaps the teams and restarts the game.`,
function: restartSwapCommand,
},
swap: {
aliases: ['s'],
roles: Role.ADMIN_TEMP,
desc: `
This command swaps the teams when the game is stopped.`,
function: swapCommand,
},
kickred: {
aliases: ['kickr'],
roles: Role.ADMIN_TEMP,
desc: `
This command kicks all the players from the red team, including the player that entered the command. You can give as an argument the reason of the kick.`,
function: kickTeamCommand,
},
kickblue: {
aliases: ['kickb'],
roles: Role.ADMIN_TEMP,
desc: `
This command kicks all the players from the blue team, including the player that entered the command. You can give as an argument the reason of the kick.`,
function: kickTeamCommand,
},
kickspec: {
aliases: ['kicks'],
roles: Role.ADMIN_TEMP,
desc: `
This command kicks all the players from the spectators team, including the player that entered the command. You can give as an argument the reason of the kick.`,
function: kickTeamCommand,
},
mute: {
aliases: ['m'],
roles: Role.ADMIN_TEMP,
desc: `
This command allows to mute a player. He won't be able to talk for a certain duration, and can be unmuted at any time by admins.
It takes 2 arguments:
Argument 1: #<id> where <id> is the id of the player targeted. This won't work if the player is an admin.
Argument 2 (optional): <duration> where <duration> is the duration of the mute in minutes. If no value is provided, the mute lasts for the default duration, ${muteDuration} minutes.
Example: !mute #3 20 will mute the player with id 3 for 20 minutes.`,
function: muteCommand,
},
unmute: {
aliases: ['um'],
roles: Role.ADMIN_TEMP,
desc: `
This command allows to unmute someone.
It takes 1 argument:
Argument 1: #<id> where <id> is the id of the muted player.
OR
Argument 1: <number> where <number> is the number associated with the mute given by the 'muteList' command.
Example: !unmute #300 will unmute the player with id 300,
!unmute 8 will unmute the n°8 player according to the 'muteList' command.`,
function: unmuteCommand,
},
mutes: {
aliases: [],
roles: Role.ADMIN_TEMP,
desc: `
This command shows the list of muted players.`,
function: muteListCommand,
},
clearbans: {
aliases: [],
roles: Role.MASTER,
desc: `
This command unbans everyone. It also can unban one player in particular, by adding his ID as an argument.`,
function: clearbansCommand,
},
bans: {
aliases: ['banlist'],
roles: Role.MASTER,
desc: `
This command shows all the players that were banned and their IDs.`,
function: banListCommand,
},
admins: {
aliases: ['adminlist'],
roles: Role.MASTER,
desc: `
This command shows all the players that are permanent admins.`,
function: adminListCommand,
},
setadmin: {
aliases: ['admin'],
roles: Role.MASTER,
desc: `
This command allows to set someone as admin. He will be able to connect as admin, and can be removed at any time by masters.
It takes 1 argument:
Argument 1: #<id> where <id> is the id of the player targeted.
Example: !setadmin #3 will give admin to the player with id 3.`,
function: setAdminCommand,
},
removeadmin: {
aliases: ['unadmin'],
roles: Role.MASTER,
desc: `
This command allows to remove someone as admin.
It takes 1 argument:
Argument 1: #<id> where <id> is the id of the player targeted.
OR
Argument 1: <number> where <number> is the number associated with the admin given by the 'admins' command.
Example: !removeadmin #300 will remove admin to the player with id 300,
!removeadmin 2 will remove the admin n°2 according to the 'admins' command.`,
function: removeAdminCommand,
},
password: {
aliases: ['pw'],
roles: Role.MASTER,
desc: `
This command allows to add a password to the room.
It takes 1 argument:
Argument 1: <password> where <password> is the password you want for the room.
To remove the room password, simply enter '!password'.`,
function: passwordCommand,
},
};
/* GAME */
var lastTouches = Array(2).fill(null);
var lastTeamTouched;
var speedCoefficient = 100 / (5 * (0.99 ** 60 + 1));
var ballSpeed = 0;
var playerRadius = 15;
var ballRadius = 10;
var triggerDistance = playerRadius + ballRadius + 0.01;
/* COLORS */
var welcomeColor = 0xc4ff65;
var announcementColor = 0xffefd6;
var infoColor = 0xbebebe;
var privateMessageColor = 0xffc933;
var redColor = 0xff4c4c;
var blueColor = 0x62cbff;
var warningColor = 0xffa135;
var errorColor = 0xa40000;
var successColor = 0x75ff75;
var defaultColor = null;
/* AUXILIARY */
var checkTimeVariable = false;
var checkStadiumVariable = true;
var endGameVariable = false;
var cancelGameVariable = false;
var kickFetchVariable = false;
var chooseMode = false;
var timeOutCap;
var capLeft = false;
var redCaptainChoice = '';
var blueCaptainChoice = '';
var chooseTime = 20;
var AFKSet = new Set();
var AFKMinSet = new Set();
var AFKCooldownSet = new Set();
var minAFKDuration = 0;
var maxAFKDuration = 30;
var AFKCooldown = 0;
var muteArray = new MuteList();
var muteDuration = 5;
var removingPlayers = false;
var insertingPlayers = false;
var stopTimeout;
var startTimeout;
var unpauseTimeout;
var removingTimeout;
var insertingTimeout;
var emptyPlayer = {
id: 0,
};
stadiumCommand(emptyPlayer, "!training");
var game = new Game();
/* FUNCTIONS */
/* AUXILIARY FUNCTIONS */
if (typeof String.prototype.replaceAll != 'function') {
String.prototype.replaceAll = function (search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
}
function getDate() {
let d = new Date();
return d.toLocaleDateString() + ' ' + d.toLocaleTimeString();
}
/* MATH FUNCTIONS */
function getRandomInt(max) {
// returns a random number between 0 and max-1
return Math.floor(Math.random() * Math.floor(max));
}
function pointDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));
}
/* TIME FUNCTIONS */
function getHoursStats(time) {
return Math.floor(time / 3600);
}
function getMinutesGame(time) {
var t = Math.floor(time / 60);
return `${Math.floor(t / 10)}${Math.floor(t % 10)}`;
}
function getMinutesReport(time) {
return Math.floor(Math.round(time) / 60);
}
function getMinutesEmbed(time) {
var t = Math.floor(Math.round(time) / 60);
return `${Math.floor(t / 10)}${Math.floor(t % 10)}`;
}
function getMinutesStats(time) {
return Math.floor(time / 60) - getHoursStats(time) * 60;
}
function getSecondsGame(time) {
var t = Math.floor(time - Math.floor(time / 60) * 60);
return `${Math.floor(t / 10)}${Math.floor(t % 10)}`;
}
function getSecondsReport(time) {
var t = Math.round(time);
return Math.floor(t - getMinutesReport(t) * 60);
}
function getSecondsEmbed(time) {
var t = Math.round(time);
var t2 = Math.floor(t - Math.floor(t / 60) * 60);
return `${Math.floor(t2 / 10)}${Math.floor(t2 % 10)}`;
}
function getTimeGame(time) {
return `[${getMinutesGame(time)}:${getSecondsGame(time)}]`;
}
function getTimeEmbed(time) {
return `[${getMinutesEmbed(time)}:${getSecondsEmbed(time)}]`;
}
function getTimeStats(time) {
if (getHoursStats(time) > 0) {
return `${getHoursStats(time)}h${getMinutesStats(time)}m`;
} else {
return `${getMinutesStats(time)}m`;
}
}
function getGoalGame() {
return game.scores.red + game.scores.blue;
}
/* REPORT FUNCTIONS */
function findFirstNumberCharString(str) {
let str_number = str[str.search(/[0-9]/g)];
return str_number === undefined ? "0" : str_number;
}
function getIdReport() {
var d = new Date();
return `${d.getFullYear() % 100}${d.getMonth() < 9 ? '0' : ''}${d.getMonth() + 1}${d.getDate() < 10 ? '0' : ''}${d.getDate()}${d.getHours() < 10 ? '0' : ''}${d.getHours()}${d.getMinutes() < 10 ? '0' : ''}${d.getMinutes()}${d.getSeconds() < 10 ? '0' : ''}${d.getSeconds()}${findFirstNumberCharString(roomName)}`;
}
function getRecordingName(game) {
let d = new Date();
let redCap = game.playerComp[0][0] != undefined ? game.playerComp[0][0].player.name : 'Red';
let blueCap = game.playerComp[1][0] != undefined ? game.playerComp[1][0].player.name : 'Blue';
let day = d.getDate() < 10 ? '0' + d.getDate() : d.getDate();
let month = d.getMonth() < 10 ? '0' + (d.getMonth() + 1) : (d.getMonth() + 1);
let year = d.getFullYear() % 100 < 10 ? '0' + (d.getFullYear() % 100) : (d.getFullYear() % 100);
let hour = d.getHours() < 10 ? '0' + d.getHours() : d.getHours();
let minute = d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes();
return `${day}-${month}-${year}-${hour}h${minute}-${redCap}vs${blueCap}.hbr2`;
}
function fetchRecording(game) {
if (gameWebhook != "") {
let form = new FormData();
form.append(null, new File([game.rec], getRecordingName(game), { "type": "text/plain" }));
form.append("payload_json", JSON.stringify({
"username": roomName
}));
fetch(gameWebhook, {
method: 'POST',
body: form,
}).then((res) => res);
}
}
/* FEATURE FUNCTIONS */
function getCommand(commandStr) {
if (commands.hasOwnProperty(commandStr)) return commandStr;
for (const [key, value] of Object.entries(commands)) {
for (let alias of value.aliases) {
if (alias == commandStr) return key;
}
}
return false;
}
function getPlayerComp(player) {
if (player == null || player.id == 0) return null;
var comp = game.playerComp;
var index = comp[0].findIndex((c) => c.auth == authArray[player.id][0]);
if (index != -1) return comp[0][index];
index = comp[1].findIndex((c) => c.auth == authArray[player.id][0]);
if (index != -1) return comp[1][index];
return null;
}
function getTeamArray(team, includeAFK = true) {
if (team == Team.RED) return teamRed;
if (team == Team.BLUE) return teamBlue;
if (includeAFK) {
return playersAll.filter((p) => p.team === Team.SPECTATORS);
}
return teamSpec;
}
function sendAnnouncementTeam(message, team, color, style, mention) {
for (let player of team) {
room.sendAnnouncement(message, player.id, color, style, mention);
}
}
function teamChat(player, message) {
var msgArray = message.split(/ +/).slice(1);
var emoji = player.team == Team.RED ? '🔴' : player.team == Team.BLUE ? '🔵' : '⚪';
var message = `${emoji} [TEAM] ${player.name}: ${msgArray.join(' ')}`;
var team = getTeamArray(player.team, true);
var color = player.team == Team.RED ? redColor : player.team == Team.BLUE ? blueColor : null;
var style = 'bold';
var mention = HaxNotification.CHAT;
sendAnnouncementTeam(message, team, color, style, mention);
}
function playerChat(player, message) {
var msgArray = message.split(/ +/);
var playerTargetIndex = playersAll.findIndex(
(p) => p.name.replaceAll(' ', '_') == msgArray[0].substring(2)
);
if (playerTargetIndex == -1) {
room.sendAnnouncement(
`Invalid player, make sure the name you entered is correct.`,
player.id,
errorColor,
'bold',
null
);
return false;
}
var playerTarget = playersAll[playerTargetIndex];
if (player.id == playerTarget.id) {
room.sendAnnouncement(
`You can't send a PM to yourself!`,
player.id,
errorColor,
'bold',
null
);
return false;
}
var messageFrom = `📝 [PM with ${playerTarget.name}] ${player.name}: ${msgArray.slice(1).join(' ')}`
var messageTo = `📝 [PM with ${player.name}] ${player.name}: ${msgArray.slice(1).join(' ')}`
room.sendAnnouncement(
messageFrom,
player.id,
privateMessageColor,
'bold',
HaxNotification.CHAT
);
room.sendAnnouncement(
messageTo,
playerTarget.id,
privateMessageColor,
'bold',
HaxNotification.CHAT
);
}
/* PHYSICS FUNCTIONS */
function calculateStadiumVariables() {
if (checkStadiumVariable && teamRed.length + teamBlue.length > 0) {
checkStadiumVariable = false;
setTimeout(() => {
let ballDisc = room.getDiscProperties(0);
let playerDisc = room.getPlayerDiscProperties(teamRed.concat(teamBlue)[0].id);
ballRadius = ballDisc.radius;
playerRadius = playerDisc.radius;
triggerDistance = ballRadius + playerRadius + 0.01;
speedCoefficient = 100 / (5 * ballDisc.invMass * (ballDisc.damping ** 60 + 1));
}, 1);
}
}
function checkGoalKickTouch(array, index, goal) {
if (array != null && array.length >= index + 1) {
var obj = array[index];
if (obj != null && obj.goal != null && obj.goal == goal) return obj;
}
return null;
}
/* BUTTONS */
function topButton() {
if (teamSpec.length > 0) {
if (teamRed.length == teamBlue.length && teamSpec.length > 1) {
room.setPlayerTeam(teamSpec[0].id, Team.RED);
room.setPlayerTeam(teamSpec[1].id, Team.BLUE);
} else if (teamRed.length < teamBlue.length)
room.setPlayerTeam(teamSpec[0].id, Team.RED);
else room.setPlayerTeam(teamSpec[0].id, Team.BLUE);
}
}
function randomButton() {
if (teamSpec.length > 0) {
if (teamRed.length == teamBlue.length && teamSpec.length > 1) {
var r = getRandomInt(teamSpec.length);
room.setPlayerTeam(teamSpec[r].id, Team.RED);
teamSpec = teamSpec.filter((spec) => spec.id != teamSpec[r].id);
room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.BLUE);
} else if (teamRed.length < teamBlue.length)
room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.RED);
else
room.setPlayerTeam(teamSpec[getRandomInt(teamSpec.length)].id, Team.BLUE);
}
}
function blueToSpecButton() {
clearTimeout(removingTimeout);
removingPlayers = true;
removingTimeout = setTimeout(() => {
removingPlayers = false;
}, 100);
for (var i = 0; i < teamBlue.length; i++) {
room.setPlayerTeam(teamBlue[teamBlue.length - 1 - i].id, Team.SPECTATORS);
}
}
function redToSpecButton() {
clearTimeout(removingTimeout);
removingPlayers = true;
removingTimeout = setTimeout(() => {
removingPlayers = false;
}, 100);
for (var i = 0; i < teamRed.length; i++) {
room.setPlayerTeam(teamRed[teamRed.length - 1 - i].id, Team.SPECTATORS);
}
}
function resetButton() {
clearTimeout(removingTimeout);
removingPlayers = true;
removingTimeout = setTimeout(() => {
removingPlayers = false;
}, 100);
for (let i = 0; i < Math.max(teamRed.length, teamBlue.length); i++) {
if (Math.max(teamRed.length, teamBlue.length) - teamRed.length - i > 0)
room.setPlayerTeam(teamBlue[teamBlue.length - 1 - i].id, Team.SPECTATORS);
else if (Math.max(teamRed.length, teamBlue.length) - teamBlue.length - i > 0)
room.setPlayerTeam(teamRed[teamRed.length - 1 - i].id, Team.SPECTATORS);
else break;
}
for (let i = 0; i < Math.min(teamRed.length, teamBlue.length); i++) {
room.setPlayerTeam(
teamBlue[Math.min(teamRed.length, teamBlue.length) - 1 - i].id,
Team.SPECTATORS
);
room.setPlayerTeam(
teamRed[Math.min(teamRed.length, teamBlue.length) - 1 - i].id,
Team.SPECTATORS
);
}
}
function swapButton() {
clearTimeout(removingTimeout);
removingPlayers = true;
removingTimeout = setTimeout(() => {
removingPlayers = false;
}, 100);
for (let player of teamBlue) {
room.setPlayerTeam(player.id, Team.RED);
}
for (let player of teamRed) {
room.setPlayerTeam(player.id, Team.BLUE);
}
}
/* COMMAND FUNCTIONS */
/* PLAYER COMMANDS */
function leaveCommand(player, message) {
room.kickPlayer(player.id, 'Bye !', false);
}
function helpCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length == 0) {
var commandString = 'Player commands :';
for (const [key, value] of Object.entries(commands)) {
if (value.desc && value.roles == Role.PLAYER) commandString += ` !${key},`;
}
commandString = commandString.substring(0, commandString.length - 1) + '.\n';
if (getRole(player) >= Role.ADMIN_TEMP) {
commandString += `Admin commands :`;
for (const [key, value] of Object.entries(commands)) {
if (value.desc && value.roles == Role.ADMIN_TEMP) commandString += ` !${key},`;
}
if (commandString.slice(commandString.length - 1) == ':')
commandString += ` None,`;
commandString = commandString.substring(0, commandString.length - 1) + '.\n';
}
if (getRole(player) >= Role.MASTER) {
commandString += `Master commands :`;
for (const [key, value] of Object.entries(commands)) {
if (value.desc && value.roles == Role.MASTER) commandString += ` !${key},`;
}
if (commandString.slice(commandString.length - 1) == ':') commandString += ` None,`;
commandString = commandString.substring(0, commandString.length - 1) + '.\n';
}
commandString += "\nTo get information on a specific command, type ''!help <command name>'.";
room.sendAnnouncement(
commandString,
player.id,
infoColor,
'bold',
HaxNotification.CHAT
);
} else if (msgArray.length >= 1) {
var commandName = getCommand(msgArray[0].toLowerCase());
if (commandName != false && commands[commandName].desc != false)
room.sendAnnouncement(
`\'${commandName}\' command :\n${commands[commandName].desc}`,
player.id,
infoColor,
'bold',
HaxNotification.CHAT
);
else
room.sendAnnouncement(
`The command you tried to get information on does not exist. To check all available commands, type \'!help\'`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function globalStatsCommand(player, message) {
var stats = new HaxStatistics(player.name);
if (localStorage.getItem(authArray[player.id][0])) {
stats = JSON.parse(localStorage.getItem(authArray[player.id][0]));
}
var statsString = printPlayerStats(stats);
room.sendAnnouncement(
statsString,
player.id,
infoColor,
'bold',
HaxNotification.CHAT
);
}
function renameCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (localStorage.getItem(authArray[player.id][0])) {
var stats = JSON.parse(localStorage.getItem(authArray[player.id][0]));
if (msgArray.length == 0) {
stats.playerName = player.name;
} else {
stats.playerName = msgArray.join(' ');
}
localStorage.setItem(authArray[player.id][0], JSON.stringify(stats));
room.sendAnnouncement(
`You successfully renamed yourself ${stats.playerName} !`,
player.id,
successColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`You haven't played a game in this room yet !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function statsLeaderboardCommand(player, message) {
var key = message.split(/ +/)[0].substring(1).toLowerCase();
printRankings(key, player.id);
}
function afkCommand(player, message) {
if (player.team == Team.SPECTATORS || players.length == 1) {
if (AFKSet.has(player.id)) {
if (AFKMinSet.has(player.id)) {
room.sendAnnouncement(
`There is a minimum of ${minAFKDuration} minute of AFK time. Don't abuse the command !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
} else {
AFKSet.delete(player.id);
room.sendAnnouncement(
`🌅 ${player.name} is not AFK anymore !`,
null,
announcementColor,
'bold',
null
);
updateTeams();
handlePlayersJoin();
}
} else {
if (AFKCooldownSet.has(player.id)) {
room.sendAnnouncement(
`You can only go AFK every ${AFKCooldown} minutes. Don't abuse the command !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
} else {
AFKSet.add(player.id);
if (!player.admin) {
AFKMinSet.add(player.id);
AFKCooldownSet.add(player.id);
setTimeout(
(id) => {
AFKMinSet.delete(id);
},
minAFKDuration * 60 * 1000,
player.id
);
setTimeout(
(id) => {
AFKSet.delete(id);
},
maxAFKDuration * 60 * 1000,
player.id
);
setTimeout(
(id) => {
AFKCooldownSet.delete(id);
},
AFKCooldown * 60 * 1000,
player.id
);
}
room.setPlayerTeam(player.id, Team.SPECTATORS);
room.sendAnnouncement(
`😴 ${player.name} is now AFK !`,
null,
announcementColor,
'bold',
null
);
updateTeams();
handlePlayersLeave();
}
}
} else {
room.sendAnnouncement(
`You can't go AFK while in a team !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function afkListCommand(player, message) {
if (AFKSet.size == 0) {
room.sendAnnouncement(
"😴 There's nobody in the AFK list.",
player.id,
announcementColor,
'bold',
null
);
return;
}
var cstm = '😴 AFK list : ';
AFKSet.forEach((_, value) => {
var p = room.getPlayer(value);
if (p != null) cstm += p.name + `, `;
});
cstm = cstm.substring(0, cstm.length - 2) + '.';
room.sendAnnouncement(cstm, player.id, announcementColor, 'bold', null);
}
function masterCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (parseInt(msgArray[0]) == masterPassword) {
if (!masterList.includes(authArray[player.id][0])) {
room.setPlayerAdmin(player.id, true);
adminList = adminList.filter((a) => a[0] != authArray[player.id][0]);
masterList.push(authArray[player.id][0]);
room.sendAnnouncement(
`${player.name} is now a room master !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`You are a master already !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
}
/* ADMIN COMMANDS */
function restartCommand(player, message) {
instantRestart();
}
function restartSwapCommand(player, message) {
room.stopGame();
swapButton();
startTimeout = setTimeout(() => {
room.startGame();
}, 10);
}
function swapCommand(player, message) {
if (playSituation == Situation.STOP) {
swapButton();
room.sendAnnouncement(
'✔️ Teams swapped !',
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
`Please stop the game before swapping.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function kickTeamCommand(player, message) {
var msgArray = message.split(/ +/);
var reasonString = `Team kick by ${player.name}`;
if (msgArray.length > 1) {
reasonString = msgArray.slice(1).join(' ');
}
if (['!kickred', '!kickr'].includes(msgArray[0].toLowerCase())) {
for (let i = 0; i < teamRed.length; i++) {
setTimeout(() => {
room.kickPlayer(teamRed[0].id, reasonString, false);
}, i * 20)
}
} else if (['!kickblue', '!kickb'].includes(msgArray[0].toLowerCase())) {
for (let i = 0; i < teamBlue.length; i++) {
setTimeout(() => {
room.kickPlayer(teamBlue[0].id, reasonString, false);
}, i * 20)
}
} else if (['!kickspec', '!kicks'].includes(msgArray[0].toLowerCase())) {
for (let i = 0; i < teamSpec.length; i++) {
setTimeout(() => {
room.kickPlayer(teamSpec[0].id, reasonString, false);
}, i * 20)
}
}
}
function stadiumCommand(player, message) {
var msgArray = message.split(/ +/);
if (gameState == State.STOP) {
if (['!classic'].includes(msgArray[0].toLowerCase())) {
if (JSON.parse(classicMap).name == 'Classic') {
room.setDefaultStadium('Classic');
} else {
room.setCustomStadium(classicMap);
}
currentStadium = 'classic';
} else if (['!big'].includes(msgArray[0].toLowerCase())) {
if (JSON.parse(bigMap).name == 'Big') {
room.setDefaultStadium('Big');
} else {
room.setCustomStadium(bigMap);
}
currentStadium = 'big';
} else if (['!training'].includes(msgArray[0].toLowerCase())) {
room.setCustomStadium(trainingMap);
currentStadium = 'training';
} else {
room.sendAnnouncement(
`Stadium not recognized.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Please stop the game before using this command.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function muteCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length > 0) {
if (msgArray[0].length > 0 && msgArray[0][0] == '#') {
msgArray[0] = msgArray[0].substring(1, msgArray[0].length);
if (room.getPlayer(parseInt(msgArray[0])) != null) {
var playerMute = room.getPlayer(parseInt(msgArray[0]));
var minutesMute = muteDuration;
if (msgArray.length > 1 && parseInt(msgArray[1]) > 0) {
minutesMute = parseInt(msgArray[1]);
}
if (!playerMute.admin) {
var muteObj = new MutePlayer(playerMute.name, playerMute.id, authArray[playerMute.id][0]);
muteObj.setDuration(minutesMute);
room.sendAnnouncement(
`${playerMute.name} has been muted for ${minutesMute} minutes.`,
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
`You can't mute an admin.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`There is no player with such ID in the room. Enter "!help mute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Incorrect format for your argument. Enter "!help mute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Wrong number of arguments. Enter "!help mute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function unmuteCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length > 0) {
if (msgArray[0].length > 0 && msgArray[0][0] == '#') {
msgArray[0] = msgArray[0].substring(1, msgArray[0].length);
if (room.getPlayer(parseInt(msgArray[0])) != null) {
var playerUnmute = room.getPlayer(parseInt(msgArray[0]));
if (muteArray.getByPlayerId(playerUnmute.id) != null) {
var muteObj = muteArray.getByPlayerId(playerUnmute.id);
muteObj.remove()
room.sendAnnouncement(
`${playerUnmute.name} has been unmuted !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`This player isn't muted !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`There is no player with such ID in the room. Enter "!help unmute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else if (msgArray[0].length > 0 && parseInt(msgArray[0]) > 0 && muteArray.getById(parseInt(msgArray[0])) != null) {
var playerUnmute = muteArray.getById(parseInt(msgArray[0]));
playerUnmute.remove();
room.sendAnnouncement(
`${playerUnmute.name} has been unmuted !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`Incorrect format for your argument. Enter "!help unmute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Wrong number of arguments. Enter "!help unmute" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function muteListCommand(player, message) {
if (muteArray.list.length == 0) {
room.sendAnnouncement(
"🔇 There's nobody in the mute list.",
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = '🔇 Mute list : ';
for (let mute of muteArray.list) {
cstm += mute.name + `[${mute.id}], `;
}
cstm = cstm.substring(0, cstm.length - 2) + '.';
room.sendAnnouncement(
cstm,
player.id,
announcementColor,
'bold',
null
);
}
/* MASTER COMMANDS */
function clearbansCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length == 0) {
room.clearBans();
room.sendAnnouncement(
'✔️ Bans cleared !',
null,
announcementColor,
'bold',
null
);
banList = [];
} else if (msgArray.length == 1) {
if (parseInt(msgArray[0]) > 0) {
var ID = parseInt(msgArray[0]);
room.clearBan(ID);
if (banList.length != banList.filter((p) => p[1] != ID).length) {
room.sendAnnouncement(
`✔️ ${banList.filter((p) => p[1] == ID)[0][0]} has been unbanned from the room !`,
null,
announcementColor,
'bold',
null
);
} else {
room.sendAnnouncement(
`The ID you entered doesn't have a ban associated to. Enter "!help clearbans" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
banList = banList.filter((p) => p[1] != ID);
} else {
room.sendAnnouncement(
`Invalid ID entered. Enter "!help clearbans" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Wrong number of arguments. Enter "!help clearbans" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function banListCommand(player, message) {
if (banList.length == 0) {
room.sendAnnouncement(
"📢 There's nobody in the ban list.",
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = '📢 Ban list : ';
for (let ban of banList) {
cstm += ban[0] + `[${ban[1]}], `;
}
cstm = cstm.substring(0, cstm.length - 2) + '.';
room.sendAnnouncement(
cstm,
player.id,
announcementColor,
'bold',
null
);
}
function adminListCommand(player, message) {
if (adminList.length == 0) {
room.sendAnnouncement(
"📢 There's nobody in the admin list.",
player.id,
announcementColor,
'bold',
null
);
return false;
}
var cstm = '📢 Admin list : ';
for (let i = 0; i < adminList.length; i++) {
cstm += adminList[i][1] + `[${i}], `;
}
cstm = cstm.substring(0, cstm.length - 2) + '.';
room.sendAnnouncement(
cstm,
player.id,
announcementColor,
'bold',
null
);
}
function setAdminCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length > 0) {
if (msgArray[0].length > 0 && msgArray[0][0] == '#') {
msgArray[0] = msgArray[0].substring(1, msgArray[0].length);
if (room.getPlayer(parseInt(msgArray[0])) != null) {
var playerAdmin = room.getPlayer(parseInt(msgArray[0]));
if (!adminList.map((a) => a[0]).includes(authArray[playerAdmin.id][0])) {
if (!masterList.includes(authArray[playerAdmin.id][0])) {
room.setPlayerAdmin(playerAdmin.id, true);
adminList.push([authArray[playerAdmin.id][0], playerAdmin.name]);
room.sendAnnouncement(
`${playerAdmin.name} is now a room admin !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`This player is a master already !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`This player is a permanent admin already !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`There is no player with such ID in the room. Enter "!help setadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Incorrect format for your argument. Enter "!help setadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Wrong number of arguments. Enter "!help setadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function removeAdminCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length > 0) {
if (msgArray[0].length > 0 && msgArray[0][0] == '#') {
msgArray[0] = msgArray[0].substring(1, msgArray[0].length);
if (room.getPlayer(parseInt(msgArray[0])) != null) {
var playerAdmin = room.getPlayer(parseInt(msgArray[0]));
if (adminList.map((a) => a[0]).includes(authArray[playerAdmin.id][0])) {
room.setPlayerAdmin(playerAdmin.id, false);
adminList = adminList.filter((a) => a[0] != authArray[playerAdmin.id][0]);
room.sendAnnouncement(
`${playerAdmin.name} is not a room admin anymore !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`This player isn't a permanent admin !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`There is no player with such ID in the room. Enter "!help removeadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else if (msgArray[0].length > 0 && parseInt(msgArray[0]) < adminList.length) {
var index = parseInt(msgArray[0]);
var playerAdmin = adminList[index];
if (playersAll.findIndex((p) => authArray[p.id][0] == playerAdmin[0]) != -1) {
// check if there is the removed admin in the room
var indexRem = playersAll.findIndex((p) => authArray[p.id][0] == playerAdmin[0]);
room.setPlayerAdmin(playersAll[indexRem].id, false);
}
adminList.splice(index);
room.sendAnnouncement(
`${playerAdmin[1]} is not a room admin anymore !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`Incorrect format for your argument. Enter "!help removeadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
} else {
room.sendAnnouncement(
`Wrong number of arguments. Enter "!help removeadmin" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
function passwordCommand(player, message) {
var msgArray = message.split(/ +/).slice(1);
if (msgArray.length > 0) {
if (msgArray.length == 1 && msgArray[0] == '') {
roomPassword = '';
room.setPassword(null);
room.sendAnnouncement(
`The room password has been removed.`,
player.id,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
roomPassword = msgArray.join(' ');
room.setPassword(roomPassword);
room.sendAnnouncement(
`The room password has been set to ${roomPassword}`,
player.id,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
if (roomPassword != '') {
roomPassword = '';
room.setPassword(null);
room.sendAnnouncement(
`The room password has been removed.`,
player.id,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else {
room.sendAnnouncement(
`The room currently does not have a password. Enter "!help password" for more information.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
}
}
/* GAME FUNCTIONS */
function checkTime() {
const scores = room.getScores();
if (game != undefined) game.scores = scores;
if (Math.abs(scores.time - scores.timeLimit) <= 0.01 && scores.timeLimit != 0 && playSituation == Situation.PLAY) {
if (scores.red != scores.blue) {
if (!checkTimeVariable) {
checkTimeVariable = true;
setTimeout(() => {
checkTimeVariable = false;
}, 3000);
scores.red > scores.blue ? endGame(Team.RED) : endGame(Team.BLUE);
stopTimeout = setTimeout(() => {
room.stopGame();
}, 2000);
}
return;
}
if (drawTimeLimit != 0) {
goldenGoal = true;
room.sendAnnouncement(
'⚽ First goal wins !',
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
}
if (Math.abs(scores.time - drawTimeLimit * 60 - scores.timeLimit) <= 0.01 && scores.timeLimit != 0) {
if (!checkTimeVariable) {
checkTimeVariable = true;
setTimeout(() => {
checkTimeVariable = false;
}, 10);
endGame(Team.SPECTATORS);
room.stopGame();
goldenGoal = false;
}
}
}
function instantRestart() {
room.stopGame();
startTimeout = setTimeout(() => {
room.startGame();
}, 10);
}
function resumeGame() {
startTimeout = setTimeout(() => {
room.startGame();
}, 1000);
setTimeout(() => {
room.pauseGame(false);
}, 500);
}
function endGame(winner) {
if (players.length >= 2 * teamSize - 1) activateChooseMode();
const scores = room.getScores();
game.scores = scores;
lastWinner = winner;
endGameVariable = true;
if (winner == Team.RED) {
streak++;
room.sendAnnouncement(
`✨ Red Team won ${scores.red} - ${scores.blue} ! Current streak: ${streak}`,
null,
redColor,
'bold',
HaxNotification.CHAT
);
} else if (winner == Team.BLUE) {
streak = 1;
room.sendAnnouncement(
`✨ Blue Team won ${scores.blue} - ${scores.red} ! Current streak: ${streak}`,
null,
blueColor,
'bold',
HaxNotification.CHAT
);
} else {
streak = 0;
room.sendAnnouncement(
'💤 Draw limit reached !',
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
let possessionRedPct = (possession[0] / (possession[0] + possession[1])) * 100;
let possessionBluePct = 100 - possessionRedPct;
let possessionString = `🔴 ${possessionRedPct.toFixed(0)}% - ${possessionBluePct.toFixed(0)}% 🔵`;
let actionRedPct = (actionZoneHalf[0] / (actionZoneHalf[0] + actionZoneHalf[1])) * 100;
let actionBluePct = 100 - actionRedPct;
let actionString = `🔴 ${actionRedPct.toFixed(0)}% - ${actionBluePct.toFixed(0)}% 🔵`;
let CSString = getCSString(scores);
room.sendAnnouncement(
`📊 Possession: 🔴 ${possessionString}\n` +
`📊 Action Zone: 🔴 ${actionString}\n` +
`${CSString}`,
null,
announcementColor,
'bold',
HaxNotification.NONE
);
updateStats();
}
/* CHOOSING FUNCTIONS */
function activateChooseMode() {
chooseMode = true;
slowMode = chooseModeSlowMode;
room.sendAnnouncement(
`🐢 Slow mode changed to choose mode duration of: ${chooseModeSlowMode}s.`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
function deactivateChooseMode() {
chooseMode = false;
clearTimeout(timeOutCap);
if (slowMode != defaultSlowMode) {
slowMode = defaultSlowMode;
room.sendAnnouncement(
`🐢 Slow mode changed to choose mode duration of: ${defaultSlowMode}s.`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
redCaptainChoice = '';
blueCaptainChoice = '';
}
function getSpecList(player) {
if (player == null) return null;
var cstm = 'Players : ';
for (let i = 0; i < teamSpec.length; i++) {
cstm += teamSpec[i].name + `[${i + 1}], `;
}
cstm = cstm.substring(0, cstm.length - 2) + '.';
room.sendAnnouncement(
cstm,
player.id,
infoColor,
'bold',
HaxNotification.CHAT
);
}
function choosePlayer() {
clearTimeout(timeOutCap);
let captain;
if (teamRed.length <= teamBlue.length && teamRed.length != 0) {
captain = teamRed[0];
} else if (teamBlue.length < teamRed.length && teamBlue.length != 0) {
captain = teamBlue[0];
}
if (captain != null) {
room.sendAnnouncement(
"To choose a player, enter his number in the list given or use 'top', 'random' or 'bottom'.",
captain.id,
infoColor,
'bold',
HaxNotification.MENTION
);
timeOutCap = setTimeout(
(player) => {
room.sendAnnouncement(
`Hurry up ${player.name}, only ${Number.parseInt(String(chooseTime / 2))} seconds left to choose !`,
player.id,
warningColor,
'bold',
HaxNotification.MENTION
);
timeOutCap = setTimeout(
(player) => {
room.kickPlayer(
player.id,
"You didn't choose in time !",
false
);
},
chooseTime * 500,
captain
);
},
chooseTime * 1000,
captain
);
}
if (teamRed.length != 0 && teamBlue.length != 0) {
getSpecList(teamRed.length <= teamBlue.length ? teamRed[0] : teamBlue[0]);
}
}
function chooseModeFunction(player, message) {
var msgArray = message.split(/ +/);
if (player.id == teamRed[0].id || player.id == teamBlue[0].id) {
if (teamRed.length <= teamBlue.length && player.id == teamRed[0].id) {
if (['top', 'auto'].includes(msgArray[0].toLowerCase())) {
room.setPlayerTeam(teamSpec[0].id, Team.RED);
redCaptainChoice = 'top';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Top !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (['random', 'rand'].includes(msgArray[0].toLowerCase())) {
var r = getRandomInt(teamSpec.length);
room.setPlayerTeam(teamSpec[r].id, Team.RED);
redCaptainChoice = 'random';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Random !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (['bottom', 'bot'].includes(msgArray[0].toLowerCase())) {
room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.RED);
redCaptainChoice = 'bottom';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Bottom !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (!Number.isNaN(Number.parseInt(msgArray[0]))) {
if (Number.parseInt(msgArray[0]) > teamSpec.length || Number.parseInt(msgArray[0]) < 1) {
room.sendAnnouncement(
`Your number is invalid !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
} else {
room.setPlayerTeam(
teamSpec[Number.parseInt(msgArray[0]) - 1].id,
Team.RED
);
room.sendAnnouncement(
`${player.name} chose ${teamSpec[Number.parseInt(msgArray[0]) - 1].name} !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
} else return false;
return true;
}
if (teamRed.length > teamBlue.length && player.id == teamBlue[0].id) {
if (['top', 'auto'].includes(msgArray[0].toLowerCase())) {
room.setPlayerTeam(teamSpec[0].id, Team.BLUE);
blueCaptainChoice = 'top';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Top !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (['random', 'rand'].includes(msgArray[0].toLowerCase())) {
room.setPlayerTeam(
teamSpec[getRandomInt(teamSpec.length)].id,
Team.BLUE
);
blueCaptainChoice = 'random';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Random !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (['bottom', 'bot'].includes(msgArray[0].toLowerCase())) {
room.setPlayerTeam(teamSpec[teamSpec.length - 1].id, Team.BLUE);
blueCaptainChoice = 'bottom';
clearTimeout(timeOutCap);
room.sendAnnouncement(
`${player.name} chose Bottom !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
} else if (!Number.isNaN(Number.parseInt(msgArray[0]))) {
if (Number.parseInt(msgArray[0]) > teamSpec.length || Number.parseInt(msgArray[0]) < 1) {
room.sendAnnouncement(
`Your number is invalid !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
} else {
room.setPlayerTeam(
teamSpec[Number.parseInt(msgArray[0]) - 1].id,
Team.BLUE
);
room.sendAnnouncement(
`${player.name} chose ${teamSpec[Number.parseInt(msgArray[0]) - 1].name} !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
}
} else return false;
return true;
}
}
}
function checkCaptainLeave(player) {
if (
(teamRed.findIndex((red) => red.id == player.id) == 0 && chooseMode && teamRed.length <= teamBlue.length) ||
(teamBlue.findIndex((blue) => blue.id == player.id) == 0 && chooseMode && teamBlue.length < teamRed.length)
) {
choosePlayer();
capLeft = true;
setTimeout(() => {
capLeft = false;
}, 10);
}
}
function slowModeFunction(player, message) {
if (!player.admin) {
if (!SMSet.has(player.id)) {
SMSet.add(player.id);
setTimeout(
(number) => {
SMSet.delete(number);
},
slowMode * 1000,
player.id
);
} else {
return true;
}
}
return false;
}
/* PLAYER FUNCTIONS */
function updateTeams() {
playersAll = room.getPlayerList();
players = playersAll.filter((p) => !AFKSet.has(p.id));
teamRed = players.filter((p) => p.team == Team.RED);
teamBlue = players.filter((p) => p.team == Team.BLUE);
teamSpec = players.filter((p) => p.team == Team.SPECTATORS);
}
function updateAdmins(excludedPlayerID = 0) {
if (players.length != 0 && players.filter((p) => p.admin).length < maxAdmins) {
let playerArray = players.filter((p) => p.id != excludedPlayerID && !p.admin);
let arrayID = playerArray.map((player) => player.id);
room.setPlayerAdmin(Math.min(...arrayID), true);
}
}
function getRole(player) {
return (
!!masterList.find((a) => a == authArray[player.id][0]) * 2 +
!!adminList.find((a) => a[0] == authArray[player.id][0]) * 1 +
player.admin * 1
);
}
function ghostKickHandle(oldP, newP) {
var teamArrayId = getTeamArray(oldP.team, true).map((p) => p.id);
teamArrayId.splice(teamArrayId.findIndex((id) => id == oldP.id), 1, newP.id);
room.kickPlayer(oldP.id, 'Ghost kick', false);
room.setPlayerTeam(newP.id, oldP.team);
room.setPlayerAdmin(newP.id, oldP.admin);
room.reorderPlayers(teamArrayId, true);
if (oldP.team != Team.SPECTATORS && playSituation != Situation.STOP) {
var discProp = room.getPlayerDiscProperties(oldP.id);
room.setPlayerDiscProperties(newP.id, discProp);
}
}
/* ACTIVITY FUNCTIONS */
function handleActivityPlayer(player) {
let pComp = getPlayerComp(player);
if (pComp != null) {
pComp.inactivityTicks++;
if (pComp.inactivityTicks == 60 * ((2 / 3) * afkLimit)) {
room.sendAnnouncement(
`${player.name}, if you don't move or send a message in the next ${Math.floor(afkLimit / 3)} seconds, you will be kicked !`,
player.id,
warningColor,
'bold',
HaxNotification.MENTION
);
return;
}
if (pComp.inactivityTicks >= 60 * afkLimit) {
pComp.inactivityTicks = 0;
if (game.scores.time <= afkLimit - 0.5) {
setTimeout(() => {
!chooseMode ? instantRestart() : room.stopGame();
}, 10);
}
room.kickPlayer(player.id, 'AFK', false);
}
}
}
function handleActivityPlayerTeamChange(changedPlayer) {
if (changedPlayer.team == Team.SPECTATORS) {
let pComp = getPlayerComp(changedPlayer);
if (pComp != null) pComp.inactivityTicks = 0;
}
}
function handleActivityStop() {
for (let player of players) {
let pComp = getPlayerComp(player);
if (pComp != null) pComp.inactivityTicks = 0;
}
}
function handleActivity() {
if (gameState === State.PLAY && players.length > 1) {
for (let player of teamRed) {
handleActivityPlayer(player);
}
for (let player of teamBlue) {
handleActivityPlayer(player);
}
}
}
/* LINEUP FUNCTIONS */
function getStartingLineups() {
var compositions = [[], []];
for (let player of teamRed) {
compositions[0].push(
new PlayerComposition(player, authArray[player.id][0], [0], [])
);
}
for (let player of teamBlue) {
compositions[1].push(
new PlayerComposition(player, authArray[player.id][0], [0], [])
);
}
return compositions;
}
function handleLineupChangeTeamChange(changedPlayer) {
if (gameState != State.STOP) {
var playerLineup;
if (changedPlayer.team == Team.RED) {
// player gets in red team
var redLineupAuth = game.playerComp[0].map((p) => p.auth);
var ind = redLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]);
if (ind != -1) {
// Player goes back in
playerLineup = game.playerComp[0][ind];
if (playerLineup.timeExit.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
playerLineup.timeExit = playerLineup.timeExit.filter((t) => t != game.scores.time);
} else {
playerLineup.timeEntry.push(game.scores.time);
}
} else {
playerLineup = new PlayerComposition(
changedPlayer,
authArray[changedPlayer.id][0],
[game.scores.time],
[]
);
game.playerComp[0].push(playerLineup);
}
} else if (changedPlayer.team == Team.BLUE) {
// player gets in blue team
var blueLineupAuth = game.playerComp[1].map((p) => p.auth);
var ind = blueLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]);
if (ind != -1) {
// Player goes back in
playerLineup = game.playerComp[1][ind];
if (playerLineup.timeExit.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
playerLineup.timeExit = playerLineup.timeExit.filter((t) => t != game.scores.time);
} else {
playerLineup.timeEntry.push(game.scores.time);
}
} else {
playerLineup = new PlayerComposition(
changedPlayer,
authArray[changedPlayer.id][0],
[game.scores.time],
[]
);
game.playerComp[1].push(playerLineup);
}
}
if (teamRed.some((r) => r.id == changedPlayer.id)) {
// player leaves red team
var redLineupAuth = game.playerComp[0].map((p) => p.auth);
var ind = redLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]);
playerLineup = game.playerComp[0][ind];
if (playerLineup.timeEntry.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
if (game.scores.time == 0) {
game.playerComp[0].splice(ind, 1);
} else {
playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time);
}
} else {
playerLineup.timeExit.push(game.scores.time);
}
} else if (teamBlue.some((r) => r.id == changedPlayer.id)) {
// player leaves blue team
var blueLineupAuth = game.playerComp[1].map((p) => p.auth);
var ind = blueLineupAuth.findIndex((auth) => auth == authArray[changedPlayer.id][0]);
playerLineup = game.playerComp[1][ind];
if (playerLineup.timeEntry.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
if (game.scores.time == 0) {
game.playerComp[1].splice(ind, 1);
} else {
playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time);
}
} else {
playerLineup.timeExit.push(game.scores.time);
}
}
}
}
function handleLineupChangeLeave(player) {
if (playSituation != Situation.STOP) {
if (player.team == Team.RED) {
// player gets in red team
var redLineupAuth = game.playerComp[0].map((p) => p.auth);
var ind = redLineupAuth.findIndex((auth) => auth == authArray[player.id][0]);
var playerLineup = game.playerComp[0][ind];
if (playerLineup.timeEntry.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
if (game.scores.time == 0) {
game.playerComp[0].splice(ind, 1);
} else {
playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time);
}
} else {
playerLineup.timeExit.push(game.scores.time);
}
} else if (player.team == Team.BLUE) {
// player gets in blue team
var blueLineupAuth = game.playerComp[1].map((p) => p.auth);
var ind = blueLineupAuth.findIndex((auth) => auth == authArray[player.id][0]);
var playerLineup = game.playerComp[1][ind];
if (playerLineup.timeEntry.includes(game.scores.time)) {
// gets subbed off then in at the exact same time -> no sub
if (game.scores.time == 0) {
game.playerComp[1].splice(ind, 1);
} else {
playerLineup.timeEntry = playerLineup.timeEntry.filter((t) => t != game.scores.time);
}
} else {
playerLineup.timeExit.push(game.scores.time);
}
}
}
}
/* TEAM BALANCE FUNCTIONS */
function balanceTeams() {
if (!chooseMode) {
if (players.length == 0) {
room.stopGame();
room.setScoreLimit(scoreLimit);
room.setTimeLimit(timeLimit);
} else if (players.length == 1 && teamRed.length == 0) {
instantRestart();
setTimeout(() => {
stadiumCommand(emptyPlayer, `!training`);
}, 5);
room.setPlayerTeam(players[0].id, Team.RED);
} else if (Math.abs(teamRed.length - teamBlue.length) == teamSpec.length && teamSpec.length > 0) {
const n = Math.abs(teamRed.length - teamBlue.length);
if (players.length == 2) {
instantRestart();
setTimeout(() => {
stadiumCommand(emptyPlayer, `!classic`);
}, 5);
}
if (teamRed.length > teamBlue.length) {
for (var i = 0; i < n; i++) {
room.setPlayerTeam(teamSpec[i].id, Team.BLUE);
}
} else {
for (var i = 0; i < n; i++) {
room.setPlayerTeam(teamSpec[i].id, Team.RED);
}
}
} else if (Math.abs(teamRed.length - teamBlue.length) > teamSpec.length) {
const n = Math.abs(teamRed.length - teamBlue.length);
if (players.length == 1) {
instantRestart();
setTimeout(() => {
stadiumCommand(emptyPlayer, `!training`);
}, 5);
room.setPlayerTeam(players[0].id, Team.RED);
return;
} else if (teamSize > 2 && players.length == 5) {
instantRestart();
setTimeout(() => {
stadiumCommand(emptyPlayer, `!classic`);
}, 5);
}
if (players.length == teamSize * 2 - 1) {
teamRedStats = [];
teamBlueStats = [];
}
if (teamRed.length > teamBlue.length) {
for (var i = 0; i < n; i++) {
room.setPlayerTeam(
teamRed[teamRed.length - 1 - i].id,
Team.SPECTATORS
);
}
} else {
for (var i = 0; i < n; i++) {
room.setPlayerTeam(
teamBlue[teamBlue.length - 1 - i].id,
Team.SPECTATORS
);
}
}
} else if (Math.abs(teamRed.length - teamBlue.length) < teamSpec.length && teamRed.length != teamBlue.length) {
room.pauseGame(true);
activateChooseMode();
choosePlayer();
} else if (teamSpec.length >= 2 && teamRed.length == teamBlue.length && teamRed.length < teamSize) {
if (teamRed.length == 2) {
instantRestart();
setTimeout(() => {
stadiumCommand(emptyPlayer, `!big`);
}, 5);
}
topButton();
}
}
}
function handlePlayersJoin() {
if (chooseMode) {
if (teamSize > 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 = `${getTimeGame(scores.time)} Goal by ${goalAttribution[0].name} ! Assist by ${goalAttribution[1].name}. Goal speed : ${ballSpeed.toFixed(2)}km/h.`;
game.goals.push(
new Goal(
scores.time,
team,
goalAttribution[0],
goalAttribution[1]
)
);
} else {
goalString = `${getTimeGame(scores.time)} Goal by ${goalAttribution[0].name} ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`;
game.goals.push(
new Goal(scores.time, team, goalAttribution[0], null)
);
}
} else {
goalString = `😂 ${getTimeGame(scores.time)} Own goal by ${goalAttribution[0].name} ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`;
game.goals.push(
new Goal(scores.time, team, goalAttribution[0], null)
);
}
} else {
goalString = `${getTimeGame(scores.time)} Goal for ${team == Team.RED ? 'red' : 'blue'} team ! Goal speed : ${ballSpeed.toFixed(2)}km/h.`;
game.goals.push(
new Goal(scores.time, team, null, null)
);
}
return goalString;
}
/* ROOM STATS FUNCTIONS */
function updatePlayerStats(player, teamStats) {
var stats = new HaxStatistics(player.name);
var pComp = getPlayerComp(player);
if (localStorage.getItem(authArray[player.id][0])) {
stats = JSON.parse(localStorage.getItem(authArray[player.id][0]));
}
stats.games++;
if (lastWinner == teamStats) stats.wins++;
stats.winrate = ((100 * stats.wins) / (stats.games || 1)).toFixed(1) + `%`;
stats.goals += getGoalsPlayer(pComp);
stats.assists += getAssistsPlayer(pComp);
stats.ownGoals += getOwnGoalsPlayer(pComp);
stats.CS += getCSPlayer(pComp);
stats.playtime += getGametimePlayer(pComp);
localStorage.setItem(authArray[player.id][0], JSON.stringify(stats));
}
function updateStats() {
if (
players.length >= 2 * teamSize &&
(
game.scores.time >= (5 / 6) * game.scores.timeLimit ||
game.scores.red == game.scores.scoreLimit ||
game.scores.blue == game.scores.scoreLimit
) &&
teamRedStats.length >= teamSize && teamBlueStats.length >= teamSize
) {
for (let player of teamRedStats) {
updatePlayerStats(player, Team.RED);
}
for (let player of teamBlueStats) {
updatePlayerStats(player, Team.BLUE);
}
}
}
function printRankings(statKey, id = 0) {
var leaderboard = [];
statKey = statKey == "cs" ? "CS" : statKey;
for (var i = 0; i < localStorage.length; i++) {
var key = localStorage.key(i);
if (key.length == 43)
leaderboard.push([
JSON.parse(localStorage.getItem(key)).playerName,
JSON.parse(localStorage.getItem(key))[statKey],
]);
}
if (leaderboard.length < 5) {
if (id != 0) {
room.sendAnnouncement(
'Not enough games played yet !',
id,
errorColor,
'bold',
HaxNotification.CHAT
);
}
return;
}
leaderboard.sort(function (a, b) { return b[1] - a[1]; });
var rankingString = `${statKey.charAt(0).toUpperCase() + statKey.slice(1)}> `;
for (let i = 0; i < 5; i++) {
let playerName = leaderboard[i][0];
let playerStat = leaderboard[i][1];
if (statKey == 'playtime') playerStat = getTimeStats(playerStat);
rankingString += `#${i + 1} ${playerName} : ${playerStat}, `;
}
rankingString = rankingString.substring(0, rankingString.length - 2);
room.sendAnnouncement(
rankingString,
id,
infoColor,
'bold',
HaxNotification.CHAT
);
}
/* GET STATS FUNCTIONS */
function getGamePlayerStats(player) {
var stats = new HaxStatistics(player.name);
var pComp = getPlayerComp(player);
stats.goals += getGoalsPlayer(pComp);
stats.assists += getAssistsPlayer(pComp);
stats.ownGoals += getOwnGoalsPlayer(pComp);
stats.playtime += getGametimePlayer(pComp);
stats.CS += getCSPlayer(pComp);
return stats;
}
function getGametimePlayer(pComp) {
if (pComp == null) return 0;
var timePlayer = 0;
for (let j = 0; j < pComp.timeEntry.length; j++) {
if (pComp.timeExit.length < j + 1) {
timePlayer += game.scores.time - pComp.timeEntry[j];
} else {
timePlayer += pComp.timeExit[j] - pComp.timeEntry[j];
}
}
return Math.floor(timePlayer);
}
function getGoalsPlayer(pComp) {
if (pComp == null) return 0;
var goalPlayer = 0;
for (let goal of game.goals) {
if (goal.striker != null && goal.team === pComp.player.team) {
if (authArray[goal.striker.id][0] == pComp.auth) {
goalPlayer++;
}
}
}
return goalPlayer;
}
function getOwnGoalsPlayer(pComp) {
if (pComp == null) return 0;
var goalPlayer = 0;
for (let goal of game.goals) {
if (goal.striker != null && goal.team !== pComp.player.team) {
if (authArray[goal.striker.id][0] == pComp.auth) {
goalPlayer++;
}
}
}
return goalPlayer;
}
function getAssistsPlayer(pComp) {
if (pComp == null) return 0;
var assistPlayer = 0;
for (let goal of game.goals) {
if (goal.assist != null) {
if (authArray[goal.assist.id][0] == pComp.auth) {
assistPlayer++;
}
}
}
return assistPlayer;
}
function getGKPlayer(pComp) {
if (pComp == null) return 0;
let GKRed = getGK(Team.RED);
if (pComp.auth == GKRed?.auth) {
return Team.RED;
}
let GKBlue = getGK(Team.BLUE);
if (pComp.auth == GKBlue?.auth) {
return Team.BLUE;
}
return Team.SPECTATORS;
}
function getCSPlayer(pComp) {
if (pComp == null || game.scores == null) return 0;
if (getGKPlayer(pComp) == Team.RED && game.scores.blue == 0) {
return 1;
} else if (getGKPlayer(pComp) == Team.BLUE && game.scores.red == 0) {
return 1;
}
return 0;
}
function actionReportCountTeam(goals, team) {
let playerActionSummaryTeam = [];
let indexTeam = team == Team.RED ? 0 : 1;
let indexOtherTeam = team == Team.RED ? 1 : 0;
for (let goal of goals[indexTeam]) {
if (goal[0] != null) {
if (playerActionSummaryTeam.find(a => a[0].id == goal[0].id)) {
let index = playerActionSummaryTeam.findIndex(a => a[0].id == goal[0].id);
playerActionSummaryTeam[index][1]++;
} else {
playerActionSummaryTeam.push([goal[0], 1, 0, 0]);
}
if (goal[1] != null) {
if (playerActionSummaryTeam.find(a => a[0].id == goal[1].id)) {
let index = playerActionSummaryTeam.findIndex(a => a[0].id == goal[1].id);
playerActionSummaryTeam[index][2]++;
} else {
playerActionSummaryTeam.push([goal[1], 0, 1, 0]);
}
}
}
}
if (goals[indexOtherTeam].length == 0) {
let playerCS = getGK(team)?.player;
if (playerCS != null) {
if (playerActionSummaryTeam.find(a => a[0].id == playerCS.id)) {
let index = playerActionSummaryTeam.findIndex(a => a[0].id == playerCS.id);
playerActionSummaryTeam[index][3]++;
} else {
playerActionSummaryTeam.push([playerCS, 0, 0, 1]);
}
}
}
playerActionSummaryTeam.sort((a, b) => (a[1] + a[2] + a[3]) - (b[1] + b[2] + b[3]));
return playerActionSummaryTeam;
}
/* PRINT FUNCTIONS */
function printPlayerStats(stats) {
let statsString = '';
for (let [key, value] of Object.entries(stats)) {
if (key == 'playerName') statsString += `${value}: `;
else {
if (key == 'playtime') value = getTimeStats(value);
let reCamelCase = /([A-Z](?=[a-z]+)|[A-Z]+(?![a-z]))/g;
let statName = key.replaceAll(reCamelCase, ' $1').trim();
statsString += `${statName.charAt(0).toUpperCase() + statName.slice(1)}: ${value}, `;
}
}
statsString = statsString.substring(0, statsString.length - 2);
return statsString;
}
/* FETCH FUNCTIONS */
function fetchGametimeReport(game) {
var fieldGametimeRed = {
name: '🔴 **RED TEAM STATS**',
value: '⌛ __**Game Time:**__\n\n',
inline: true,
};
var fieldGametimeBlue = {
name: '🔵 **BLUE TEAM STATS**',
value: '⌛ __**Game Time:**__\n\n',
inline: true,
};
var redTeamTimes = game.playerComp[0].map((p) => [p.player, getGametimePlayer(p)]);
var blueTeamTimes = game.playerComp[1].map((p) => [p.player, getGametimePlayer(p)]);
for (let time of redTeamTimes) {
var minutes = getMinutesReport(time[1]);
var seconds = getSecondsReport(time[1]);
fieldGametimeRed.value += `> **${time[0].name}:** ${minutes > 0 ? `${minutes}m` : ''}` +
`${seconds > 0 || minutes == 0 ? `${seconds}s` : ''}\n`;
}
fieldGametimeRed.value += `\n${blueTeamTimes.length - redTeamTimes.length > 0 ? '\n'.repeat(blueTeamTimes.length - redTeamTimes.length) : ''
}`;
fieldGametimeRed.value += '=====================';
for (let time of blueTeamTimes) {
var minutes = getMinutesReport(time[1]);
var seconds = getSecondsReport(time[1]);
fieldGametimeBlue.value += `> **${time[0].name}:** ${minutes > 0 ? `${minutes}m` : ''}` +
`${seconds > 0 || minutes == 0 ? `${seconds}s` : ''}\n`;
}
fieldGametimeBlue.value += `\n${redTeamTimes.length - blueTeamTimes.length > 0 ? '\n'.repeat(redTeamTimes.length - blueTeamTimes.length) : ''
}`;
fieldGametimeBlue.value += '=====================';
return [fieldGametimeRed, fieldGametimeBlue];
}
function fetchActionsSummaryReport(game) {
var fieldReportRed = {
name: '🔴 **RED TEAM STATS**',
value: '📊 __**Player Stats:**__\n\n',
inline: true,
};
var fieldReportBlue = {
name: '🔵 **BLUE TEAM STATS**',
value: '📊 __**Player Stats:**__\n\n',
inline: true,
};
var goals = [[], []];
for (let i = 0; i < game.goals.length; i++) {
goals[game.goals[i].team - 1].push([game.goals[i].striker, game.goals[i].assist]);
}
var redActions = actionReportCountTeam(goals, Team.RED);
if (redActions.length > 0) {
for (let act of redActions) {
fieldReportRed.value += `> **${act[0].team != Team.RED ? '[OG] ' : ''}${act[0].name}:**` +
`${act[1] > 0 ? ` ${act[1]}G` : ''}` +
`${act[2] > 0 ? ` ${act[2]}A` : ''}` +
`${act[3] > 0 ? ` ${act[3]}CS` : ''}\n`;
}
}
var blueActions = actionReportCountTeam(goals, Team.BLUE);
if (blueActions.length > 0) {
for (let act of blueActions) {
fieldReportBlue.value += `> **${act[0].team != Team.BLUE ? '[OG] ' : ''}${act[0].name}:**` +
`${act[1] > 0 ? ` ${act[1]}G` : ''}` +
`${act[2] > 0 ? ` ${act[2]}A` : ''}` +
`${act[3] > 0 ? ` ${act[3]}CS` : ''}\n`;
}
}
fieldReportRed.value += `\n${blueActions.length - redActions.length > 0 ? '\n'.repeat(blueActions.length - redActions.length) : ''
}`;
fieldReportRed.value += '=====================';
fieldReportBlue.value += `\n${redActions.length - blueActions.length > 0 ? '\n'.repeat(redActions.length - blueActions.length) : ''
}`;
fieldReportBlue.value += '=====================';
return [fieldReportRed, fieldReportBlue];
}
function fetchSummaryEmbed(game) {
var fetchEndgame = [fetchGametimeReport, fetchActionsSummaryReport];
var logChannel = gameWebhook;
var fields = [
{
name: '🔴 **RED TEAM STATS**',
value: '=====================\n\n',
inline: true,
},
{
name: '🔵 **BLUE TEAM STATS**',
value: '=====================\n\n',
inline: true,
},
];
for (let i = 0; i < fetchEndgame.length; i++) {
var fieldsReport = fetchEndgame[i](game);
fields[0].value += fieldsReport[0].value + '\n\n';
fields[1].value += fieldsReport[1].value + '\n\n';
}
fields[0].value = fields[0].value.substring(0, fields[0].value.length - 2);
fields[1].value = fields[1].value.substring(0, fields[1].value.length - 2);
var possR = possession[0] / (possession[0] + possession[1]);
var possB = 1 - possR;
var possRString = (possR * 100).toFixed(0).toString();
var possBString = (possB * 100).toFixed(0).toString();
var zoneR = actionZoneHalf[0] / (actionZoneHalf[0] + actionZoneHalf[1]);
var zoneB = 1 - zoneR;
var zoneRString = (zoneR * 100).toFixed(0).toString();
var zoneBString = (zoneB * 100).toFixed(0).toString();
var win = (game.scores.red > game.scores.blue) * 1 + (game.scores.blue > game.scores.red) * 2;
var objectBodyWebhook = {
embeds: [
{
title: `📝 MATCH REPORT #${getIdReport()}`,
description:
`**${getTimeEmbed(game.scores.time)}** ` +
(win == 1 ? '**Red Team** ' : 'Red Team ') + game.scores.red +
' - ' +
game.scores.blue + (win == 2 ? ' **Blue Team**' : ' Blue Team') +
'\n```c\nPossession: ' + possRString + '% - ' + possBString + '%' +
'\nAction Zone: ' + zoneRString + '% - ' + zoneBString + '%\n```\n\n',
color: 9567999,
fields: fields,
footer: {
text: `Recording: ${getRecordingName(game)}`,
},
timestamp: new Date().toISOString(),
},
],
username: roomName
};
if (logChannel != '') {
fetch(logChannel, {
method: 'POST',
body: JSON.stringify(objectBodyWebhook),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
}
/* EVENTS */
/* PLAYER MOVEMENT */
room.onPlayerJoin = function (player) {
authArray[player.id] = [player.auth, player.conn];
if (roomWebhook != '') {
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: `[${getDate()}] ➡️ JOIN (${playersAll.length + 1}/${maxPlayers})\n**` +
`${player.name}** [${authArray[player.id][0]}] {${authArray[player.id][1]}}`,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
room.sendAnnouncement(
`👋 Welcome ${player.name} !\nEnter "t" before your message to use team chat and "@@" followed by a player name to PM him !`,
player.id,
welcomeColor,
'bold',
HaxNotification.CHAT
);
updateTeams();
updateAdmins();
if (masterList.findIndex((auth) => auth == player.auth) != -1) {
room.sendAnnouncement(
`Master ${player.name} has connected to the room !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
room.setPlayerAdmin(player.id, true);
} else if (adminList.map((a) => a[0]).findIndex((auth) => auth == player.auth) != -1) {
room.sendAnnouncement(
`Admin ${player.name} has connected to the room !`,
null,
announcementColor,
'bold',
HaxNotification.CHAT
);
room.setPlayerAdmin(player.id, true);
}
var sameAuthCheck = playersAll.filter((p) => p.id != player.id && authArray[p.id][0] == player.auth);
if (sameAuthCheck.length > 0 && !debugMode) {
var oldPlayerArray = playersAll.filter((p) => p.id != player.id && authArray[p.id][0] == player.auth);
for (let oldPlayer of oldPlayerArray) {
ghostKickHandle(oldPlayer, player);
}
}
handlePlayersJoin();
};
room.onPlayerTeamChange = function (changedPlayer, byPlayer) {
handleLineupChangeTeamChange(changedPlayer);
if (AFKSet.has(changedPlayer.id) && changedPlayer.team != Team.SPECTATORS) {
room.setPlayerTeam(changedPlayer.id, Team.SPECTATORS);
room.sendAnnouncement(
`${changedPlayer.name} is AFK !`,
null,
errorColor,
'bold',
HaxNotification.CHAT
);
return;
}
updateTeams();
if (gameState != State.STOP) {
if (changedPlayer.team != Team.SPECTATORS && game.scores.time <= (3 / 4) * game.scores.timeLimit && Math.abs(game.scores.blue - game.scores.red) < 2) {
changedPlayer.team == Team.RED ? teamRedStats.push(changedPlayer) : teamBlueStats.push(changedPlayer);
}
}
handleActivityPlayerTeamChange(changedPlayer);
handlePlayersTeamChange(byPlayer);
};
room.onPlayerLeave = function (player) {
setTimeout(() => {
if (!kickFetchVariable) {
if (roomWebhook != '') {
var stringContent = `[${getDate()}] ⬅️ LEAVE (${playersAll.length}/${maxPlayers})\n**${player.name}**` +
`[${authArray[player.id][0]}] {${authArray[player.id][1]}}`;
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: stringContent,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
} else kickFetchVariable = false;
}, 10);
handleLineupChangeLeave(player);
checkCaptainLeave(player);
updateTeams();
updateAdmins();
handlePlayersLeave();
};
room.onPlayerKicked = function (kickedPlayer, reason, ban, byPlayer) {
kickFetchVariable = true;
if (roomWebhook != '') {
var stringContent = `[${getDate()}] ⛔ ${ban ? 'BAN' : 'KICK'} (${playersAll.length}/${maxPlayers})\n` +
`**${kickedPlayer.name}** [${authArray[kickedPlayer.id][0]}] {${authArray[kickedPlayer.id][1]}} was ${ban ? 'banned' : 'kicked'}` +
`${byPlayer != null ? ' by **' + byPlayer.name + '** [' + authArray[byPlayer.id][0] + '] {' + authArray[byPlayer.id][1] + '}' : ''}`
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: stringContent,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
if ((ban && ((byPlayer != null &&
(byPlayer.id == kickedPlayer.id || getRole(byPlayer) < Role.MASTER)) || getRole(kickedPlayer) == Role.MASTER)) || disableBans
) {
room.clearBan(kickedPlayer.id);
return;
}
if (byPlayer != null && getRole(byPlayer) < Role.ADMIN_PERM) {
room.sendAnnouncement(
'You are not allowed to kick/ban players !',
byPlayer.id,
errorColor,
'bold',
HaxNotification.CHAT
);
room.setPlayerAdmin(byPlayer.id, false);
return;
}
if (ban) banList.push([kickedPlayer.name, kickedPlayer.id]);
};
/* PLAYER ACTIVITY */
room.onPlayerChat = function (player, message) {
if (gameState !== State.STOP && player.team != Team.SPECTATORS) {
let pComp = getPlayerComp(player);
if (pComp != null) pComp.inactivityTicks = 0;
}
let msgArray = message.split(/ +/);
if (!hideClaimMessage || msgArray[0] != '!claim') {
if (roomWebhook != '')
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: `[${getDate()}] 💬 CHAT\n**${player.name}** : ${message.replace('@', '@ ')}`,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
if (msgArray[0][0] == '!') {
let command = getCommand(msgArray[0].slice(1).toLowerCase());
if (command != false && commands[command].roles <= getRole(player)) commands[command].function(player, message);
else
room.sendAnnouncement(
`The command you tried to enter does not exist for you. Please enter '!help' to get the available commands to you.`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
return false;
}
if (msgArray[0].toLowerCase() == 't') {
teamChat(player, message);
return false;
}
if (msgArray[0].substring(0, 2) === '@@') {
playerChat(player, message);
return false;
}
if (chooseMode && teamRed.length * teamBlue.length != 0) {
var choosingMessageCheck = chooseModeFunction(player, message);
if (choosingMessageCheck) return false;
}
if (slowMode > 0) {
var filter = slowModeFunction(player, message);
if (filter) return false;
}
if (!player.admin && muteArray.getByAuth(authArray[player.id][0]) != null) {
room.sendAnnouncement(
`You are muted !`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
return false;
}
};
room.onPlayerActivity = function (player) {
if (gameState !== State.STOP) {
let pComp = getPlayerComp(player);
if (pComp != null) pComp.inactivityTicks = 0;
}
};
room.onPlayerBallKick = function (player) {
if (playSituation != Situation.GOAL) {
var ballPosition = room.getBallPosition();
if (game.touchArray.length == 0 || player.id != game.touchArray[game.touchArray.length - 1].player.id) {
if (playSituation == Situation.KICKOFF) playSituation = Situation.PLAY;
lastTeamTouched = player.team;
game.touchArray.push(
new BallTouch(
player,
game.scores.time,
getGoalGame(),
ballPosition
)
);
lastTouches[0] = checkGoalKickTouch(
game.touchArray,
game.touchArray.length - 1,
getGoalGame()
);
lastTouches[1] = checkGoalKickTouch(
game.touchArray,
game.touchArray.length - 2,
getGoalGame()
);
}
}
};
/* GAME MANAGEMENT */
room.onGameStart = function (byPlayer) {
clearTimeout(startTimeout);
if (byPlayer != null) clearTimeout(stopTimeout);
game = new Game();
possession = [0, 0];
actionZoneHalf = [0, 0];
gameState = State.PLAY;
endGameVariable = false;
goldenGoal = false;
playSituation = Situation.KICKOFF;
lastTouches = Array(2).fill(null);
lastTeamTouched = Team.SPECTATORS;
teamRedStats = [];
teamBlueStats = [];
if (teamRed.length == teamSize && teamBlue.length == teamSize) {
for (var i = 0; i < teamSize; i++) {
teamRedStats.push(teamRed[i]);
teamBlueStats.push(teamBlue[i]);
}
}
calculateStadiumVariables();
};
room.onGameStop = function (byPlayer) {
clearTimeout(stopTimeout);
clearTimeout(unpauseTimeout);
if (byPlayer != null) clearTimeout(startTimeout);
game.rec = room.stopRecording();
if (
!cancelGameVariable && game.playerComp[0].length + game.playerComp[1].length > 0 &&
(
(game.scores.timeLimit != 0 &&
((game.scores.time >= 0.5 * game.scores.timeLimit &&
game.scores.time < 0.75 * game.scores.timeLimit &&
game.scores.red != game.scores.blue) ||
game.scores.time >= 0.75 * game.scores.timeLimit)
) ||
endGameVariable
)
) {
fetchSummaryEmbed(game);
if (fetchRecordingVariable) {
setTimeout((gameEnd) => { fetchRecording(gameEnd); }, 500, game);
}
}
cancelGameVariable = false;
gameState = State.STOP;
playSituation = Situation.STOP;
updateTeams();
handlePlayersStop(byPlayer);
handleActivityStop();
};
room.onGamePause = function (byPlayer) {
if (mentionPlayersUnpause && gameState == State.PAUSE) {
if (byPlayer != null) {
room.sendAnnouncement(
`Game paused by ${byPlayer.name} !`,
null,
defaultColor,
'bold',
HaxNotification.NONE
);
} else {
room.sendAnnouncement(
`Game paused !`,
null,
defaultColor,
'bold',
HaxNotification.NONE
);
}
}
clearTimeout(unpauseTimeout);
gameState = State.PAUSE;
};
room.onGameUnpause = function (byPlayer) {
unpauseTimeout = setTimeout(() => {
gameState = State.PLAY;
}, 2000);
if (mentionPlayersUnpause) {
if (byPlayer != null) {
room.sendAnnouncement(
`Game unpaused by ${byPlayer.name} !`,
null,
defaultColor,
'bold',
HaxNotification.NONE
);
} else {
room.sendAnnouncement(
`Game unpaused !`,
null,
defaultColor,
'bold',
HaxNotification.NONE
);
}
}
if (
(teamRed.length == teamSize && teamBlue.length == teamSize && chooseMode) ||
(teamRed.length == teamBlue.length && teamSpec.length < 2 && chooseMode)
) {
deactivateChooseMode();
}
};
room.onTeamGoal = function (team) {
const scores = room.getScores();
game.scores = scores;
playSituation = Situation.GOAL;
ballSpeed = getBallSpeed();
var goalString = getGoalString(team);
for (let player of teamRed) {
var playerComp = getPlayerComp(player);
team == Team.RED ? playerComp.goalsScoredTeam++ : playerComp.goalsConcededTeam++;
}
for (let player of teamBlue) {
var playerComp = getPlayerComp(player);
team == Team.BLUE ? playerComp.goalsScoredTeam++ : playerComp.goalsConcededTeam++;
}
room.sendAnnouncement(
goalString,
null,
team == Team.RED ? redColor : blueColor,
null,
HaxNotification.CHAT
);
if (roomWebhook != '') {
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: `[${getDate()}] ${goalString}`,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
if ((scores.scoreLimit != 0 && (scores.red == scores.scoreLimit || scores.blue == scores.scoreLimit)) || goldenGoal) {
endGame(team);
goldenGoal = false;
stopTimeout = setTimeout(() => {
room.stopGame();
}, 1000);
}
};
room.onPositionsReset = function () {
lastTouches = Array(2).fill(null);
lastTeamTouched = Team.SPECTATORS;
playSituation = Situation.KICKOFF;
};
/* MISCELLANEOUS */
room.onRoomLink = function (url) {
console.log(`${url}\nmasterPassword : ${masterPassword}`);
if (roomWebhook != '') {
fetch(roomWebhook, {
method: 'POST',
body: JSON.stringify({
content: `[${getDate()}] 🔗 LINK ${url}\nmasterPassword : ${masterPassword}`,
username: roomName,
}),
headers: {
'Content-Type': 'application/json',
},
}).then((res) => res);
}
};
room.onPlayerAdminChange = function (changedPlayer, byPlayer) {
updateTeams();
if (!changedPlayer.admin && getRole(changedPlayer) >= Role.ADMIN_TEMP) {
room.setPlayerAdmin(changedPlayer.id, true);
return;
}
updateAdmins(byPlayer != null && !changedPlayer.admin && changedPlayer.id == byPlayer.id ? changedPlayer.id : 0);
};
room.onKickRateLimitSet = function (min, rate, burst, byPlayer) {
if (byPlayer != null) {
room.sendAnnouncement(
`It is not allowed to change the kickrate limit. It must stay at "6-0-0".`,
player.id,
errorColor,
'bold',
HaxNotification.CHAT
);
room.setKickRateLimit(6, 0, 0);
}
};
room.onStadiumChange = function (newStadiumName, byPlayer) {
if (byPlayer !== null) {
if (getRole(byPlayer) < Role.MASTER && currentStadium != 'other') {
room.sendAnnouncement(
`You can't change stadium manually ! Please use the stadium commands.`,
byPlayer.id,
errorColor,
'bold',
HaxNotification.CHAT
);
stadiumCommand(emptyPlayer, `!${currentStadium}`);
} else {
room.sendAnnouncement(
`Map changed. After you're done with this map, please use the stadium commands.`,
byPlayer.id,
infoColor,
'bold',
HaxNotification.CHAT
);
currentStadium = 'other';
}
}
checkStadiumVariable = true;
};
room.onGameTick = function () {
checkTime();
getLastTouchOfTheBall();
getGameStats();
handleActivity();
};