Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active October 26, 2024 01:18
Show Gist options
  • Save nabbynz/bc5edeae66f0a6d6b0a21cc0d9ab78fc to your computer and use it in GitHub Desktop.
Save nabbynz/bc5edeae66f0a6d6b0a21cc0d9ab78fc to your computer and use it in GitHub Desktop.
Scoreboard Enhancer BASIC
// ==UserScript==
// @name Scoreboard Enhancer BASIC
// @version 0.5.8
// @description A cleaner Scoreboard. Shows: Maximums, Team Stats, Old Scoreboard Position, Custom Weighted Scoreboard Position, Flaccids, Handoffs, K/D, G/C, Comeback!, OT Respawn in Replays. Quitters.
// @match https://tagpro.koalabeast.com/game
// @match https://tagpro.koalabeast.com/game?*
// @updateURL https://gist.github.com/nabbynz/bc5edeae66f0a6d6b0a21cc0d9ab78fc/raw/Scoreboard_Enhancer_BASIC.user.js
// @downloadURL https://gist.github.com/nabbynz/bc5edeae66f0a6d6b0a21cc0d9ab78fc/raw/Scoreboard_Enhancer_BASIC.user.js
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @grant GM_addStyle
// @author nabby
// ==/UserScript==
'use strict';
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
/* eslint-env jquery */
/* globals tagpro, tagproConfig */
/* eslint-disable no-multi-spaces */
//---------- Options ----------
const SHOW_OLD_SCORE_POSITION = true; // show the *position* you would have been on the old pre-IPM scoreboard (S1)
const SHOW_OLD_SCORE_AS_VALUE = false; // instead of position, show the *points* you would have received on the old pre-IPM scoreboard
const SHOW_CUSTOM_SCORE_POSITION = false; // show the *position* you would have been on the custom weighted scoreboard (edit the `customWeight` values around line 181) (S2)
const SHOW_CUSTOM_SCORE_AS_VALUE = false; // instead of position, show the *points* you would have received on the custom weighted scoreboard
const SHOW_TOTAL_IPM = true; // show the T-IPM Score (NISH)
const SHOW_O_IPM = true; // show the O-IPM Score (NISH)
const SHOW_D_IPM = true; // show the D-IPM Score (NISH)
const STANDARDIZE_IPM_SCORES_TO_100 = true; // so the top player for "Score | O | D" always gets 100
const SHOW_FLACCIDS = true; // CTF Only. When you grab and drop the flag within 2 seconds.
const SHOW_HANDOFFS = false; // CTF Handoff: When a teammate grabs within 2 seconds of a flaccid. NF Handoff: When the flag is quickly transferred to an enemy, and then to a teammate for cap within 2 seconds
const SHOW_GOOD_HANDOFFS = false; // CTF Good-Handoff: When a teammate grabs within 2 seconds of a flaccid AND they escape the prevent radius. NF Good-Handoff: When the flag is quickly transferred to an enemy, and then to a teammate for cap within 2 seconds (same as Handoff in NF?)
const SHOW_KD = true; // show the K/D (Tags/Pops)
const SHOW_GC = true; // show the G/C (Grabs/Caps)
const SHOW_OT_RESPAWN_TIMES = true; // show the Overtime Respawn Times (Replays only)
const SHOW_TIME_PLAYED_AS_PERCENTAGE = true; // show Active Time Played as a % of Time Played (Replays only)
//---------------------------
//---------- Colors & Styles ----------
const MAX_HIGHLIGHT_RED_COLOR = '#a13636';
const MAX_HIGHLIGHT_BLUE_COLOR = '#194773';
const SCORE_BACKGROUND_COLOR = 'rgba(0, 0, 0, 0.2)'; // use `revert` for none (yellow: 'rgba(185, 185, 23, 0.25)')
const O_BACKGROUND_COLOR = 'revert'; // use `revert` for none (red: 'rgba(240, 35, 61, 0.25)')
const D_BACKGROUND_COLOR = 'revert'; // use `revert` for none (blue: 'rgba(64, 116, 219, 0.25)')
const CAPS_BACKGROUND_COLOR = 'rgba(0, 0, 0, 0.2)'; // use `false` or `revert` for none
$('#options').css({ 'border':'2px outset #8bc34a', 'border-radius':'8px', 'box-shadow':'-10px 5px 20px black, 10px 5px 20px black' });
$('#stats thead').find('th:contains("Popped")').text('Pops');
$('#stats thead').find('th:contains("Captures")').text('Caps');
$('#stats thead').find('th:contains("Power-ups")').text('PUPs');
//------------------------------------
/***** CHECK FOR EVENT - START *****/
let isEvent = false;
let isHalloween = false;
let isBirthday = false;
let isEaster = false;
let isEgg = false;
let isHockey = false;
let isChristmas = false;
let isRacing = false;
let isAprilFools = false;
let isEggEvent;
let checkForEvent = function() {
let scriptSrcs = [];
if (tagproConfig.replay) {
let packets = tagpro.replayData.packets;
if (!Array.isArray(packets)) {
packets = packets.split('\n');
}
for (let i = 0; i < packets.length; i++) {
const packet = Array.isArray(packets[i]) ? packets[i] : JSON.parse(packets[i]);
if (packet[1] === 'clientInfo' && packet[2].hasOwnProperty('eventScripts') && packet[2].eventScripts.length) {
scriptSrcs = packet[2].eventScripts;
break;
}
}
}
let scripts = $('script[src]').toArray();
scripts.forEach(script => {
scriptSrcs.push(script.src);
})
if (scriptSrcs) {
let scriptNames = ['halloween', 'birthday', 'easter', 'egg', 'hockey', 'pirates', 'christmas', 'racing']; // disable for certain events
for (let scriptName of scriptNames) {
if (scriptSrcs.some(e => e.includes(scriptName))) { //eg: https://static.koalabeast.com/events/easter-2017.js
isEvent = true;
if (scriptName === 'halloween') isHalloween = true;
if (scriptName === 'birthday' || scriptName === 'pirates') isBirthday = true;
if (scriptName === 'easter') isEaster = true;
if (scriptName === 'egg') isEgg = true;
if (scriptName === 'hockey') isHockey = true;
if (scriptName === 'christmas') isChristmas = true;
if (scriptName === 'racing') isRacing = true;
break;
}
}
}
isEggEvent = isEaster || isEgg || isHockey;
isAprilFools = !!document.querySelector('#redspecial'); // to detect the April Fools Event triangle & square ball shapes
console.log(GM_info.script.name + ':: checkForEvent() isEvent:'+isEvent, 'isHalloween:'+isHalloween, 'isBirthday:'+isBirthday, 'isEaster:'+isEaster, 'isEgg:'+isEgg, 'isHockey:'+isHockey, 'isChristmas:'+isChristmas, 'isRacing:'+isRacing, 'isAprilFools:'+isAprilFools, 'isEggEvent:'+isEggEvent);
};
/***** CHECK FOR EVENT - END *****/
tagpro.ready(function() {
checkForEvent();
if (isEvent) {
// return;
}
let cats = $('#stats').children().eq(0).find('th'); //grab column headers
let order = ['name', 'score', 'oscore', 'dscore', 's-tags', 's-pops', 's-grabs', 's-drops', 's-hold', 's-captures', 's-prevent', 's-returns', 's-support', 's-powerups']; // , 'points', 'playTime'
let sorted = [];
for (let i = 0; i < cats.length; i++) { //setup column names and ids
let col = cats.eq(i);
col.attr('id', i);
if (!col.attr('name')) col.attr('name', order[i]);
}
tagpro.events.register({
sortPlayers: function(players) {
sorted = $.extend([], players);
},
modifyScoreUI: function() {
let current;
let max = [];
//find the maximum values in each column...
for (let i = 0; i < sorted.length; i++) { // player
for (let j = 0; j < cats.length - 4; j++) { // for each element that can be highlighted (skip: Rank Pts, Active, Report)
if (!max[j]) {
max[j] = [i];
} else {
if (sorted[i][cats.eq(j + 1).attr('name')] > sorted[max[j][0]][cats.eq(j + 1).attr('name')]) {
max[j] = [i];
} else if (sorted[i][cats.eq(j + 1).attr('name')] === sorted[max[j][0]][cats.eq(j + 1).attr('name')]) {
max[j].push(i);
}
}
}
}
// highlight the matching cell/s in each column...
for (let i = 0; i < max.length; i++) {
if (max[i].length !== sorted.length) { // don't highlight if everyone has max value
current = $('.template').next();
for (let j = 0; j < sorted.length; j++) {
if (max[i].indexOf(j) > -1) {
current.children().eq(i + 1).css('background-color', sorted[j].team === 1 ? MAX_HIGHLIGHT_RED_COLOR : MAX_HIGHLIGHT_BLUE_COLOR);
} else {
current.children().eq(i + 1).css('background-color', 'revert-layer');
}
current = current.next();
}
}
}
// highlight the row we are positioned at...
current = $('.template').next();
for (let i = 0; i < sorted.length; i++) {
if (sorted[i].id === tagpro.playerId) {
current.children().eq(0).css('border-left', '1px solid white');
current.children().last().css('border-right', '1px solid white');
} else {
current.children().eq(0).css('border-left', 'none');
current.children().last().css('border-right', 'none');
}
current = current.next();
}
}
});
let getDataFromReplay = function(packets, players, quitters) {
if (!Array.isArray(packets)) {
packets = packets.split('\n');
}
for (let i = 0; i < packets.length; i++) {
const packet = Array.isArray(packets[i]) ? packets[i] : JSON.parse(packets[i]);
if (packet[1] === 'p') {
const arr = packet[2];
for (let j = 0; j < arr.length; j++) {
const obj = arr[j];
if (quitters[obj.id]) {
quitters[obj.id] = Object.assign(quitters[obj.id], obj);
}
}
} else if (packet[1] === 'chat') {
if (packet[2].from === null && packet[2].to == packet[2].for && packet[2].c !== '#63FE22') { // tips
let message = String(packet[2].message);
if (message.includes('During overtime, each death increases time to respawn. Currently:')) {
players[packet[2].for].otspawn = +message.slice(message.lastIndexOf(':') + 2);
}
}
}
}
};
let createScoreboardData = function(players) {
let data = [];
let totals = {
// `weight` is the old pre-NISH scoreboard weightings (S1)
// `customWeight` can be used to compare different weighting values (change the values to see how it would affect the S2 scoreboard positions)
tags: { value:0, weight: 50, customWeight: 40 }, // 40
pops: { value:0, weight:-50, customWeight:-25 }, // -25
grabs: { value:0, weight: 50, customWeight: 0 }, // 0
drops: { value:0, weight:-50, customWeight: 0 }, // 0
hold: { value:0, weight: 50, customWeight: 45 }, // 45
captures: { value:0, weight: 50, customWeight: 30 }, // 30
prevent: { value:0, weight: 50, customWeight: 25 }, // 25
returns: { value:0, weight: 50, customWeight: 40 }, // 40
support: { value:0, weight: 50, customWeight: 10 }, // 10
powerups: { value:0, weight: 50, customWeight: 0 }, // 0
};
let totalWeight = 0;
let totalCustomWeight = 0;
let doOnce = false;
let isNish = false; // for old scoreboards in replays
let hasFlaccids = false;
let quitters = {};
for (let playerId in players) {
for (let stat in totals) {
totals[stat].value += players[playerId]['s-' + stat];
if (!doOnce) {
totalWeight += totals[stat].weight;
totalCustomWeight += totals[stat].customWeight;
}
}
if (!doOnce) {
if (players[playerId].hasOwnProperty('oscore')) {
isNish = true;
}
if (players[playerId].hasOwnProperty('s-flaccids')) {
hasFlaccids = true;
}
doOnce = true;
}
}
if (tagproConfig.replay && tagpro.replayData && tagpro.replayData.packets[0][1] === 'recorder-metadata') {
let metadata = tagpro.replayData.packets[0][2];
let actualGameStarted = metadata.started;
let actualGameDuration = metadata.duration;
let gameFinish = metadata.started + metadata.duration;
for (let i in metadata.players) {
if (metadata.players[i].finished) {
players[metadata.players[i].id].timePlayed = gameFinish - Math.max(metadata.players[i].joined, actualGameStarted);
players[metadata.players[i].id].timePlayedPC = players[metadata.players[i].id].timePlayed / actualGameDuration;
} else {
if (!quitters.hasOwnProperty([metadata.players[i].id])) {
quitters[metadata.players[i].id] = { userId: metadata.players[i].userId }; // displayName: metadata.players[i].displayName, userId: metadata.players[i].userId, joinedGame: metadata.players[i].joined, leftGame: metadata.players[i].left, team: metadata.players[i].team
}
}
}
getDataFromReplay(tagpro.replayData.packets, players, quitters);
}
for (let playerId in players) {
let thisData = {
id: playerId,
name: players[playerId].name,
team: players[playerId].team,
auth: players[playerId].auth,
tags: players[playerId]['s-tags'],
pops: players[playerId]['s-pops'],
grabs: players[playerId]['s-grabs'],
drops: players[playerId]['s-drops'],
hold: players[playerId]['s-hold'],
captures: players[playerId]['s-captures'],
prevent: players[playerId]['s-prevent'],
returns: players[playerId]['s-returns'],
support: players[playerId]['s-support'],
powerups: players[playerId]['s-powerups'],
flaccids: players[playerId]['s-flaccids'],
handoffs: players[playerId]['s-handoffs'], // assists
goodHandoffs: players[playerId]['s-goodHandoffs'],
oldScore: 0,
oldPos: '',
customScore: 0,
customPos: '',
score: +players[playerId].score,
oscore: +players[playerId].oscore,
dscore: +players[playerId].dscore,
points: players[playerId].points,
otspawn: players[playerId].otspawn || 0,
timePlayed: players[playerId].timePlayed || 0,
timePlayedPC: players[playerId].timePlayedPC || 0,
};
for (let stat in totals) {
thisData.oldScore += players[playerId]['s-' + stat] / (totals[stat].value || 1) * totals[stat].weight * 300 / totalWeight;
thisData.customScore += players[playerId]['s-' + stat] / (totals[stat].value || 1) * totals[stat].customWeight * 300 / totalCustomWeight;
}
data.push(thisData);
}
data.sort(function(a, b) {
return (b.oldScore - a.oldScore ? b.oldScore - a.oldScore : a.id - b.id);
});
for (let i = 0; i < data.length; i++) {
data[i].oldPos = i + 1;
}
data.sort(function(a, b) {
return (b.customScore - a.customScore ? b.customScore - a.customScore : a.id - b.id);
});
for (let i = 0; i < data.length; i++) {
data[i].customPos = i + 1;
}
data.sort(function(a, b) {
return (b.score - a.score ? b.score - a.score : a.id - b.id);
});
return { data:data, isNish:isNish, hasFlaccids:hasFlaccids, quitters: quitters };
};
let addSortability = function() {
$('#stats thead tr th').on('click', function() {
const dataset = this.dataset.column;
if (!dataset || dataset === 'player') {
return;
}
const index = this.cellIndex;
let sortasc = false;
if (!this.dataset.sortasc || this.dataset.sortasc === 'false') {
this.dataset.sortasc = 'true';
sortasc = true;
} else {
this.dataset.sortasc = 'false';
sortasc = false;
}
$('#stats tbody tr.SBEB_Sortable').sort(function(a, b) {
if (sortasc) {
return a.children[index].innerText.localeCompare(b.children[index].innerText, 'en', { numeric: true} );
} else {
return b.children[index].innerText.localeCompare(a.children[index].innerText, 'en', { numeric: true} );
}
}).prependTo( $('#stats tbody') );
$('#stats thead tr th').css({ 'text-decoration': 'none' });
$(this).css({ 'text-decoration': 'underline' });
});
};
let getColumnIndex = function(columnHeading) {
const lastColumn = $('#stats thead tr th').last().index();
for (let i = 0; i <= lastColumn; i++) {
const thisColumnHeading = $('#stats thead tr th:nth-child(' + i + ')').text().trim();
if (thisColumnHeading === columnHeading) {
return i;
break;
}
}
return -1;
};
let addQuitters = function(quitters) {
$('#stats').after('<div id="SBEB_ShowQuitters" style="text-align:right; font-size:12px; color:#dd5e13; margin:-5px 10px 0 0; cursor:pointer;">Show Quitters [' + Object.keys(quitters).length + ']</div>');
$('#SBEB_ShowQuitters').on('click', function() {
$('#SBEB_ShowQuitters').remove();
let ths = '<th>Quitter</th>';
let trs = '';
let columnsToShow = { // we're just going to show these columns (if they are visible on the main scoreboard)...
tags: { title: 'Tags', stat: 's-tags' },
pops: { title: 'Pops', stat: 's-pops' },
grabs: { title: 'Grabs', stat: 's-grabs' },
drops: { title: 'Drops', stat: 's-drops' },
hold: { title: 'Hold', stat: 's-hold' },
captures: { title: 'Caps', stat: 's-captures' },
prevent: { title: 'Prevent', stat: 's-prevent' },
returns: { title: 'Returns', stat: 's-returns' },
support: { title: 'Support', stat: 's-support' },
powerups: { title: 'PUPs', stat: 's-powerups' },
active: { title: 'Active', stat: 'playTime' }
};
for (let column in columnsToShow) {
if ($('#stats thead th[data-column="' + column + '"]').is(':visible')) {
columnsToShow[column].visible = true;
ths += '<th>' + columnsToShow[column].title + '</th>';
}
}
for (let quitter in quitters) {
let tds = '<td class="scoreName' + (quitters[quitter].team === 1 ? ' team-red' : quitters[quitter].team === 2 ? ' team-blue' : '') + '">' + (quitters[quitter].auth ? '<span class="scoreAuth">✓&nbsp;</span>' : '') + (quitters[quitter].userId ? '<a href="/profile/' + quitters[quitter].userId + '" target="_blank" style="color:inherit;" title="View Profile (New Tab)">' + quitters[quitter].name + '</a>' : quitters[quitter].name) + '</td>';
for (let column in columnsToShow) {
if (columnsToShow[column].visible) {
tds += '<td>' + (quitters[quitter].playTime === '00:00' ? '-' : quitters[quitter][columnsToShow[column].stat]) + '</td>';
}
}
trs += '<tr>' + tds + '</tr>';
}
$('#stats').after('<div id="SBEB_Quitters_Container" style="margin:0 10px 10px auto; padding:5px; width:720px; background:rgba(0, 0, 0, 0.5); border:1px dashed #dd5e13; border-radius: 5px;"><table class="table table-stripped" style="margin:0;">' +
' <thead><tr>' + ths + '</tr></thead>' +
' <tbody>' + trs + '</tbody>' +
'</table></div>');
});
};
let redTeamName = 'Red';
let blueTeamName = 'Blue';
let mercyRule = 3; // assume 3 for a pub game. Will change if in a group.
let modifyScoreboard = function(data) {
let playersSorted = data.data;
let isNish = data.isNish;
let hasFlaccids = data.hasFlaccids;
let isOvertime = tagpro.overtimeStartedAt;
let trs = $('#stats tbody tr');
let stats = [ 'oldScore', 'customScore', 'score', 'oscore', 'dscore', 'tags', 'pops', 'grabs', 'drops', 'hold', 'captures', 'prevent', 'returns', 'support', 'powerups', 'points', 'flaccids', 'handoffs', 'goodHandoffs', 'timePlayed', 'otspawn' ];
let rStats = { oldScore:0, customScore:0, score:0, oscore:0, dscore:0, tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, points:0, flaccids:0, handoffs:0, goodHandoffs:0, timePlayed:0, otspawn:0 };
let bStats = { oldScore:0, customScore:0, score:0, oscore:0, dscore:0, tags:0, pops:0, grabs:0, drops:0, hold:0, captures:0, prevent:0, returns:0, support:0, powerups:0, points:0, flaccids:0, handoffs:0, goodHandoffs:0, timePlayed:0, otspawn:0 };
let scoreboard = '';
let maxScore = 0;
let maxOScore = 0;
let maxDScore = 0;
const thTitles = {
'S1': 'Pre-NISH Scoreboard Position / Score',
'S2': 'Custom Weighted Scoreboard Position / Score',
'FLA': 'CTF Flaccid: When you grab and drop the flag within 2 seconds\nNF Flaccid: Not applicable',
'HO': 'CTF Handoff: When a teammate grabs within 2 seconds of a flaccid\nNF Handoff: When the flag is quickly transferred to an enemy, and then to a teammate for cap within 2 seconds',
'GHO': 'CTF Good-Handoff: When a teammate grabs within 2 seconds of a flaccid AND they escape the prevent radius\nNF Good-Handoff: When the flag is quickly transferred to an enemy, and then to a teammate for cap within 2 seconds (same as Handoff in NF?)',
'K/D': 'Tags / Pops',
'G/C': 'Grabs / Caps',
};
// modify header...
$('#stats thead tr th[data-column="player"]').after('<th data-column="s1" title="' + thTitles.S1 + '">S1</th><th data-column="s2" title="' + thTitles.S2 + '">S2</th>');
if (tagproConfig.replay) {
if (SHOW_TIME_PLAYED_AS_PERCENTAGE) {
$('#stats thead tr th[data-column="active"]').text('Time');
}
if (isOvertime) {
$('#stats thead tr th').last().text('OT').attr('title', 'Overtime Re-Spawn Times').attr('data-column', 'ot');
} else {
$('#stats thead tr th').last().remove(); // report/mute
}
}
$('#stats thead tr th[data-column="active"]').after('<th data-column="flaccids" title="' + thTitles.FLA + '">FLA</th><th data-column="handoffs" title="' + thTitles.HO + '">HO</th><th data-column="goodhandoffs" title="' + thTitles.GHO + '">GHO</th><th data-column="kd" title="' + thTitles['K/D'] + '">K/D</th><th data-column="gc" title="' + thTitles['G/C'] + '">G/C</th>');
$('#stats thead tr th[data-column="score"]').css({ 'text-decoration': 'underline' }); // default sort
// modify rows...
trs.each(function() {
$(this).addClass('SBEB_Sortable'); // for <th> click to sort
$(this).find('td').eq(0).after('<td data-column="s1">-</td><td data-column="s2">-</td>'); // Old Score | Custom Weighted Score
if (tagproConfig.replay) {
if (isOvertime) {
$(this).find('td[data-column="report"]').text('x'); // re-use this column for overtime spawn times
} else {
$(this).find('td[data-column="report"]').remove(); // remove the redundant report/mute cell
}
}
$(this).find('td[data-column="active"]').after('<td data-column="flaccids">-</td><td data-column="handoffs">-</td><td data-column="goodhandoffs">-</td><td data-column="kd">-</td><td data-column="gc">-</td>'); // Assists | Flaccids | Good H/O | K/D | G/C
});
// insert new values...
for (let i in playersSorted) {
let player = playersSorted[i];
$('#stats tbody tr').eq(i).attr('data-team', player.team);
$('#stats tbody tr').eq(i).find('td[data-column="s1"]').text(player.oldPos.toFixed(0)).attr('title', player.oldScore.toFixed(0));
$('#stats tbody tr').eq(i).find('td[data-column="s2"]').text(player.customPos.toFixed(0)).attr('title', player.customScore.toFixed(0));
$('#stats tbody tr').eq(i).find('td[data-column="flaccids"]').text(player.grabs > 0 ? player.flaccids + '/' + player.grabs : '-').attr('title', (player.flaccids / player.grabs * 100).toFixed(0) + '% Flaccid Grabs');
$('#stats tbody tr').eq(i).find('td[data-column="handoffs"]').text(player.handoffs > 0 ? (player.handoffs) + '' : '-').attr('title', player.handoffs + ' Handoffs (Assists)');
$('#stats tbody tr').eq(i).find('td[data-column="goodhandoffs"]').text(player.goodHandoffs > 0 ? (player.goodHandoffs ) + '' : '-').attr('title', player.goodHandoffs + ' Good Handoffs');
$('#stats tbody tr').eq(i).find('td[data-column="kd"]').text(player.tags > 0 ? (player.tags / (player.pops || 1)).toFixed(2) : '-');
$('#stats tbody tr').eq(i).find('td[data-column="gc"]').text(player.captures > 0 ? (player.grabs / player.captures).toFixed(2) : '-');
if (tagproConfig.replay) {
if (SHOW_TIME_PLAYED_AS_PERCENTAGE) {
$('#stats tbody tr').eq(i).find('td[data-column="active"]').text((player.timePlayedPC * 100).toFixed(0) + '%').attr('title', 'Played for ' + tagpro.helpers.timeFromSeconds(Math.floor(player.timePlayed / 1000), true));
}
if (isOvertime) {
$('#stats tbody tr').eq(i).find('td[data-column="report"]').text(player.otspawn || '-');
}
}
for (let stat of stats) {
if (player.team === 1) {
rStats[stat] += player[stat];
} else if (player.team === 2) {
bStats[stat] += player[stat];
}
}
if (player.score > maxScore) {
maxScore = player.score;
}
if (player.oscore > maxOScore) {
maxOScore = player.oscore;
}
if (player.dscore > maxDScore) {
maxDScore = player.dscore;
}
}
GM_addStyle('.game div#options .table.table-stripped td[data-column="s1"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:revert; }'); // S1
GM_addStyle('.game div#options .table.table-stripped td[data-column="s2"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:revert; }'); // S2
GM_addStyle('.game div#options .table.table-stripped td[data-column="score"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (SCORE_BACKGROUND_COLOR || 'revert') + '; opacity:1; }'); // Score
GM_addStyle('.game div#options .table.table-stripped td[data-column="oscore"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (O_BACKGROUND_COLOR || 'revert') + '; opacity:1; }'); // O
GM_addStyle('.game div#options .table.table-stripped td[data-column="dscore"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (D_BACKGROUND_COLOR || 'revert') + '; opacity:1; }'); // D
GM_addStyle('.game div#options .table.table-stripped td.o-ipm, .game div#options .table.table-stripped td.d-ipm { color:#ddd; font-weight:inherit !important; font-size:inherit !important; }'); // another O & D
GM_addStyle('#stats td[data-column="player"], #stats th[data-column="player"] { border-right:1px solid #4b4b4b !important; }'); // right of "Player" column
GM_addStyle('#stats td[data-column="score"], #stats th[data-column="score"] { border-right:none !important; }'); // clear previous in-game style from "Score" column
GM_addStyle('#stats td[data-column="dscore"], #stats th[data-column="dscore"] { border-right:1px solid #4b4b4b !important; }'); // right of "D" column
GM_addStyle('#stats td[data-column="active"], #stats th[data-column="active"] { border-right:1px solid #4b4b4b !important; }'); // right of "Active" column
GM_addStyle('#stats tbody tr:hover { background:rgba(15, 65, 15, 0.8) !important; }'); // row hover color
// highlght maxs...
setTimeout(() => {
let lastColumn = $('#stats thead tr th').last().index() + 1;
for (let i = 4; i <= lastColumn; i++) { // skip: Player | S1 | S2
let column = $('#stats tbody tr td:nth-child(' + i + ')');
let columnData = $('#stats tbody tr td:nth-child(' + i + ')').data('column');
let prevMax = 0;
if (columnData === 'active' || columnData === 'flaccids') {
continue;
}
if (columnData === 'gc') {
prevMax = -9999;
}
$(column).each(function() {
let thisText = $(this).text().replace('%', '');
if (thisText.includes(':')) {
thisText = toSeconds(thisText);
} else {
thisText = +thisText;
}
if (columnData === 'gc') {
thisText *= -1;
}
if (thisText > prevMax) {
$(column).removeClass('SBEB_SB_Max_Red SBEB_SB_Max_Blue');
$(this).addClass( $(this).parent().data('team') === 1 ? 'SBEB_SB_Max_Red' : $(this).parent().data('team') === 2 ? 'SBEB_SB_Max_Blue' : '' );
$(column).css({ 'color':'#ddd', 'background-color':'revert-layer' });
$(this).css({ 'color':'#fff', 'background-color':$(this).parent().data('team') === 1 ? MAX_HIGHLIGHT_RED_COLOR : $(this).parent().data('team') === 2 ? MAX_HIGHLIGHT_BLUE_COLOR : 'rgba(0, 0, 0, 0)' });
prevMax = thisText;
} else if (thisText === prevMax && prevMax !== 0) {
$(this).addClass( $(this).parent().data('team') === 1 ? 'SBEB_SB_Max_Red' : $(this).parent().data('team') === 2 ? 'SBEB_SB_Max_Blue' : '' );
$(this).css({ 'color':'#fff', 'background-color':$(this).parent().data('team') === 1 ? MAX_HIGHLIGHT_RED_COLOR : $(this).parent().data('team') === 2 ? MAX_HIGHLIGHT_BLUE_COLOR : 'rgba(0, 0, 0, 0)' });
} else {
if (columnData === 'score' && SCORE_BACKGROUND_COLOR && SCORE_BACKGROUND_COLOR !== 'revert') {
$(this).css({ 'color':'#ddd', 'background-color': SCORE_BACKGROUND_COLOR });
}
if (columnData === 'oscore' && O_BACKGROUND_COLOR && O_BACKGROUND_COLOR !== 'revert') {
$(this).css({ 'color':'#ddd', 'background-color': O_BACKGROUND_COLOR });
}
if (columnData === 'dscore' && D_BACKGROUND_COLOR && D_BACKGROUND_COLOR !== 'revert') {
$(this).css({ 'color':'#ddd', 'background-color': D_BACKGROUND_COLOR });
}
if (columnData === 'captures' && CAPS_BACKGROUND_COLOR && CAPS_BACKGROUND_COLOR !== 'revert') {
$(this).css({ 'color':'#ddd', 'background-color': CAPS_BACKGROUND_COLOR });
$('#stats thead tr th[data-column="captures"]').css('background', 'rgba(0, 0, 0, 0.2)')
}
}
if (STANDARDIZE_IPM_SCORES_TO_100) {
if (columnData === 'score' && maxScore) {
$(this).attr('title', thisText).text( (+thisText / maxScore * 100).toFixed(0) );
} else if (columnData === 'oscore' && maxOScore) {
$(this).attr('title', thisText).text( (+thisText / maxOScore * 100).toFixed(0) );
} else if (columnData === 'dscore' && maxDScore) {
$(this).attr('title', thisText).text( (+thisText / maxDScore * 100).toFixed(0) );
}
}
});
}
// teams stats...
if (!isEvent) {
GM_addStyle('.SBEB_SB_Max_Red { color:#fff !important; background-color:' + MAX_HIGHLIGHT_RED_COLOR + ' !important; }');
GM_addStyle('.SBEB_SB_Max_Blue { color:#fff !important; background-color:' + MAX_HIGHLIGHT_BLUE_COLOR + ' !important; }');
let redFG = (rStats.flaccids / (rStats.grabs || 1) * 100).toFixed(0); // Flaccid Grab %
let blueFG = (bStats.flaccids / (bStats.grabs || 1) * 100).toFixed(0);
let redKD = (rStats.tags / (rStats.pops || 1)).toFixed(2);
let blueKD = (bStats.tags / (bStats.pops || 1)).toFixed(2);
let redGC = rStats.captures ? (rStats.grabs / (rStats.captures || 1)).toFixed(2) : 0;
let blueGC = bStats.captures ? (bStats.grabs / (bStats.captures || 1)).toFixed(2) : 0;
$('#stats tbody').append('<tr><td colspan="100" id="SBEB_TeamStatsDivider" style="background:#adadad; padding:1px !important;"></td></tr>');
$('#stats tbody').append('<tr>' +
' <td style="color:#ffb5bd; text-align:right; font-weight:bold; padding-right:3px !important;">' + redTeamName + ':</td>' +
' <td' + (rStats.customScore >= bStats.customScore ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="s1">' + rStats.customScore.toFixed(0) + '</td>' +
' <td' + (rStats.oldScore >= bStats.oldScore ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="s2">' + rStats.oldScore.toFixed(0) + '</td>' +
' <td' + (rStats.score >= bStats.score ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="score">' + rStats.score + '</td>' +
' <td' + (rStats.oscore >= bStats.oscore ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="oscore">' + rStats.oscore + '</td>' +
' <td' + (rStats.dscore >= bStats.dscore ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="dscore">' + rStats.dscore + '</td>' +
' <td' + (rStats.tags >= bStats.tags ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="tags">' + rStats.tags + '</td>' +
' <td' + (rStats.pops >= bStats.pops ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="pops">' + rStats.pops + '</td>' +
' <td' + (rStats.grabs >= bStats.grabs ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="grabs">' + rStats.grabs + '</td>' +
' <td' + (rStats.drops >= bStats.drops ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="drops">' + rStats.drops + '</td>' +
' <td' + (rStats.hold >= bStats.hold ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="hold">' + tagpro.helpers.timeFromSeconds(rStats.hold, true) + '</td>' +
' <td' + (rStats.captures >= bStats.captures ? ' class="SBEB_SB_Max_Red"' : ' style="background-color:rgba(0, 0, 0, 0.2);"') + ' data-column="captures">' + rStats.captures + '</td>' +
' <td' + (rStats.prevent >= bStats.prevent ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="prevent">' + tagpro.helpers.timeFromSeconds(rStats.prevent, true) + '</td>' +
' <td' + (rStats.returns >= bStats.returns ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="returns">' + rStats.returns + '</td>' +
' <td' + (rStats.support >= bStats.support ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="support">' + rStats.support + '</td>' +
' <td' + (rStats.powerups >= bStats.powerups ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="powerups">' + rStats.powerups + '</td>' +
' <td' + (rStats.points >= bStats.points ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="rankpoints">' + (rStats.points ? rStats.points : '-') + '</td>' +
' <td>-</td>' + // Time
' <td title="' + redFG + '% Flaccid Grabs"' + (rStats.flaccids && bStats.flaccids && rStats.flaccids >= bStats.flaccids ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="flaccids">' + (rStats.grabs ? rStats.flaccids + '/' + rStats.grabs : '-') + '</td>' +
' <td' + (rStats.handoffs && bStats.handoffs && rStats.handoffs >= bStats.handoffs ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="handoffs">' + (rStats.handoffs ? rStats.handoffs : '-') + '</td>' +
' <td' + (rStats.goodHandoffs && bStats.goodHandoffs && rStats.goodHandoffs >= bStats.goodHandoffs ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="goodhandoffs">' + (rStats.goodHandoffs ? rStats.goodHandoffs : '-') + '</td>' +
' <td' + (+redKD >= +blueKD ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="kd">' + (+redKD ? redKD : '-') + '</td>' +
' <td' + ((redGC > 0 && blueGC === 0) || (redGC > 0 && +redGC <= +blueGC) ? ' class="SBEB_SB_Max_Red"' : '') + ' data-column="gc">' + (+redGC ? redGC : '-') + '</td>' +
(isOvertime ? ' <td' + (rStats.otspawn >= bStats.otspawn ? ' class="SBEB_SB_Max_Red"':'') + ' data-column="rankpoints">' + (rStats.otspawn ? rStats.otspawn : '-') + '</td>' : '') +
'</tr>');
$('#stats tbody').append('<tr>' +
' <td style="color:#cfcfff; text-align:right; font-weight:bold; padding-right:3px !important;">' + blueTeamName + ':</td>' +
' <td' + (bStats.customScore >= rStats.customScore ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="s1">' + bStats.customScore.toFixed(0) + '</td>' +
' <td' + (bStats.oldScore >= rStats.oldScore ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="s2">' + bStats.oldScore.toFixed(0) + '</td>' +
' <td' + (bStats.score >= rStats.score ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="score">' + bStats.score + '</td>' +
' <td' + (bStats.oscore >= rStats.oscore ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="oscore">' + bStats.oscore + '</td>' +
' <td' + (bStats.dscore >= rStats.dscore ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="dscore">' + bStats.dscore + '</td>' +
' <td' + (bStats.tags >= rStats.tags ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="tags">' + bStats.tags + '</td>' +
' <td' + (bStats.pops >= rStats.pops ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="pops">' + bStats.pops + '</td>' +
' <td' + (bStats.grabs >= rStats.grabs ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="grabs">' + bStats.grabs + '</td>' +
' <td' + (bStats.drops >= rStats.drops ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="drops">' + bStats.drops + '</td>' +
' <td' + (bStats.hold >= rStats.hold ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="hold">' + tagpro.helpers.timeFromSeconds(bStats.hold, true) + '</td>' +
' <td' + (bStats.captures >= rStats.captures ? ' class="SBEB_SB_Max_Blue"' : ' style="background-color:rgba(0, 0, 0, 0.2);"') + ' data-column="captures">' + bStats.captures + '</td>' +
' <td' + (bStats.prevent >= rStats.prevent ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="prevent">' + tagpro.helpers.timeFromSeconds(bStats.prevent, true) + '</td>' +
' <td' + (bStats.returns >= rStats.returns ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="returns">' + bStats.returns + '</td>' +
' <td' + (bStats.support >= rStats.support ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="support">' + bStats.support + '</td>' +
' <td' + (bStats.powerups >= rStats.powerups ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="powerups">' + bStats.powerups + '</td>' +
' <td' + (bStats.points >= rStats.points ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="ot">' + (bStats.points ? bStats.points : '-') + '</td>' +
' <td>-</td>' + // Time
' <td title="' + blueFG + '% Flaccid Grabs"' + (rStats.flaccids && bStats.flaccids && bStats.flaccids >= rStats.flaccids ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="flaccids">' + (bStats.grabs ? bStats.flaccids + '/' + bStats.grabs : '-') + '</td>' +
' <td' + (rStats.handoffs && bStats.handoffs && bStats.handoffs >= rStats.handoffs ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="handoffs">' + (bStats.handoffs ? bStats.handoffs : '-') + '</td>' +
' <td' + (rStats.goodHandoffs && bStats.goodHandoffs && bStats.goodHandoffs >= rStats.goodHandoffs ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="goodhandoffs">' + (bStats.goodHandoffs ? bStats.goodHandoffs : '-') + '</td>' +
' <td' + (+blueKD >= +redKD ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="kd">' + (+blueKD ? blueKD : '-') + '</td>' +
' <td' + ((blueGC > 0 && redGC === 0) || (blueGC > 0 && +blueGC <= +redGC) ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="gc">' + (+blueGC ? blueGC : '-') + '</td>' +
(isOvertime ? '<td' + (bStats.otspawn >= rStats.otspawn ? ' class="SBEB_SB_Max_Blue"' : '') + ' data-column="ot">' + (bStats.otspawn ? bStats.otspawn : '-') + '</td>' : '') +
'</tr>');
}
// hide columns as per options...
trs = $('#stats tr');
if (isNish && !SHOW_OLD_SCORE_POSITION || isEvent) {
$('#stats thead tr th[data-column="s1"]').hide();
$('#stats tbody tr td[data-column="s1"]').hide();
}
if (!SHOW_CUSTOM_SCORE_POSITION || isEvent) {
$('#stats thead tr th[data-column="s2"]').hide();
$('#stats tbody tr td[data-column="s2"]').hide();
}
if (!isNish || isNish && !SHOW_TOTAL_IPM) {
$('#stats thead tr th[data-column="score"]').hide();
$('#stats tbody tr td[data-column="score"]').hide();
}
if (!isNish) {
$('#stats thead tr th[data-column="score"]').text('Score');
}
if (!isNish || !SHOW_O_IPM || isEvent) {
$('#stats thead tr th[data-column="oscore"]').hide();
$('#stats tbody tr td[data-column="oscore"]').hide();
}
if (!isNish || !SHOW_D_IPM || isEvent) {
$('#stats thead tr th[data-column="dscore"]').hide();
$('#stats tbody tr td[data-column="dscore"]').hide();
}
if (!hasFlaccids || !SHOW_FLACCIDS || isEvent) {
$('#stats thead tr th[data-column="flaccids"]').hide();
$('#stats tbody tr td[data-column="flaccids"]').hide();
}
if (!hasFlaccids || !SHOW_HANDOFFS || isEvent) {
$('#stats thead tr th[data-column="handoffs"]').hide();
$('#stats tbody tr td[data-column="handoffs"]').hide();
}
if (!hasFlaccids || !SHOW_GOOD_HANDOFFS || isEvent) {
$('#stats thead tr th[data-column="goodhandoffs"]').hide();
$('#stats tbody tr td[data-column="goodhandoffs"]').hide();
}
if (!SHOW_KD || isEvent) {
$('#stats thead tr th[data-column="kd"]').hide();
$('#stats tbody tr td[data-column="kd"]').hide();
}
if (!SHOW_GC || isEvent) {
$('#stats thead tr th[data-column="gc"]').hide();
$('#stats tbody tr td[data-column="gc"]').hide();
}
if (!SHOW_OT_RESPAWN_TIMES && tagproConfig.replay && isEvent) {
$('#stats thead tr th[data-column="gc"]').hide();
$('#stats tbody tr td[data-column="gc"]').hide();
}
trs.each(function() {
if ((!isNish || SHOW_OLD_SCORE_AS_VALUE) && SHOW_OLD_SCORE_POSITION) {
const prevText = $(this).find('td').eq(1).text();
const prevTitle = $(this).find('td').eq(1).attr('title');
$(this).find('td').eq(1).text(prevTitle).attr('title', 'Position: ' + prevText);
}
if ((!isNish || SHOW_CUSTOM_SCORE_AS_VALUE) && SHOW_CUSTOM_SCORE_POSITION) {
const prevText = $(this).find('td').eq(2).text();
const prevTitle = $(this).find('td').eq(2).attr('title');
$(this).find('td').eq(2).text(prevTitle).attr('title', 'Position: ' + prevText);
}
});
$('#SBEB_TeamStatsDivider').show();
if (!isEvent) {
updateComeback();
}
addSortability();
if (tagproConfig.replay && Object.keys(data.quitters).length) {
addQuitters(data.quitters);
}
$('#options').fadeIn(300);
// the rounded width is so we don't get pixel blur between columns
GM_addStyle('.game #options { width:auto !important; }');
//GM_addStyle('.game #options { width:' + Math.max(960, (Math.round($('#options').width() / 2) * 2 + 24)) + 'px !important; top:180px !important; left:50% !important; translate:-50%; }');
GM_addStyle('.game #options { width:' + Math.max(960, (Math.round($('#options').width() / 2) * 2 + 24)) + 'px !important; top:' + (Math.floor($('#viewport').position().top) + 50 + 65) + 'px !important; left:50% !important; translate:-50%; }');
// this moves the "Red Wins!" sprite up 50px so it's more visible...
tagpro.renderer.layers.ui.children.every(sprite => {
if (sprite.text && sprite.text.includes('Wins!')) {
sprite.y = 50;
return false;
}
return true;
});
}, 100);
};
/******* Comeback! *******/
let scores = [];
tagpro.socket.on('score', function(data) {
let scoreDiff = data.r - data.b;
if (scores.length === 0) {
scores.push({ score: { r:data.r, b:data.b }, diff:scoreDiff, time:0 });
} else if (scores[scores.length - 1].diff !== scoreDiff) {
scores.push({ score: { r:data.r, b:data.b }, diff:scoreDiff, time:Date.now() });
}
});
GM_addStyle('.SBEB_Message { position:absolute; left:50%; translate:-50%; font-size:26px; text-align:center; font-family:Verdana; font-weight:bold; z-index:1; }');
GM_addStyle('.SBEB_Message_Red { color:#fff; text-shadow:0px 0px 18px #f70, 0px 0px 10px #f00, 0px 0px 5px #f00, 1px 1px 2px black; }');
GM_addStyle('.SBEB_Message_Blue { color:#fff; text-shadow:0px 0px 18px #0089ff, 0px 0px 10px #00ffdc, 0px 0px 5px #00ffdc, 1px 1px 2px black; }');
function updateComeback() {
$('#options').prepend('<div id="SBEB_Options_Header" style="position:relative; font-size:12px; max-width:340px; min-height:60px;"></div>' +
'<div id="SBEB_Table_Container" style="position:relative; min-height:280px; max-height:370px; overflow-x:hidden; overflow-y:auto;"></div>');
$('#SBEB_Options_Header').append($('#gameSocket'));
$('#SBEB_Options_Header').append($('#mapInfo').css({ 'margin-top':'2px' }));
$('#SBEB_Options_Header').append($('#musicInfo').css({ 'margin-bottom':'2px', 'font-weight':'bold' }));
$('#SBEB_Options_Header').append($('#flairInfo').css({ 'margin-top':'2px', 'margin-bottom':'2px' }));
$('#SBEB_Table_Container').append($('table#stats'));
$('#replayInfo').css({ 'position':'absolute', 'z-index':'2', 'top':'5px', 'right':'10px' });
$('#optionsName').css({ 'margin':'-12px 0 0 0' });
$('#mapRatingContainer').css({ 'margin':'-12px 0 0 10px' });
$('#optionsLinks').css({ 'padding':'12px 0 0 0' });
$('#optionsAd').remove();
// make the players table scrollable (for when there are lots of players/dnf's)...
GM_addStyle('#SBEB_Table_Container::-webkit-scrollbar { width:2px; }');
GM_addStyle('#SBEB_Table_Container::-webkit-scrollbar-thumb { background:#292; border-radius:4px; }');
GM_addStyle('#SBEB_Table_Container::-webkit-scrollbar-track { background:#ddd; border-radius:4px; }');
for (let i = 0; i < scores.length; i++) {
if (tagpro.score.b > tagpro.score.r && scores[i].diff !== 0) {
scores[i].diff = scores[i].diff * -1;
}
}
let lowestScoreDifferenceIndex;
let i = scores.length - 1;
while (i > 0) {
if (scores[i - 1].diff < scores[i].diff) {
if (scores[i - 1].diff < 0) {
lowestScoreDifferenceIndex = i - 1;
}
} else {
break;
}
i--;
}
let winningTeamName = '';
let colorClass = '';
let winMargin = Math.abs(tagpro.score.r - tagpro.score.b);
if (tagpro.score.r > tagpro.score.b) {
winningTeamName = redTeamName;
colorClass = 'SBEB_Message_Red';
} else if (tagpro.score.r < tagpro.score.b) {
winningTeamName = blueTeamName;
colorClass = 'SBEB_Message_Blue';
}
if (tagpro.score.r !== tagpro.score.b && lowestScoreDifferenceIndex >= 0) {
if (tagpro.overtimeStartedAt) {
$('#options').prepend('<div class="SBEB_Message ' + colorClass + '" style="top:40px; font-size:18px; font-style:italic;">Overtime Win</div>');
}
$('#options').prepend('<div class="SBEB_Message ' + colorClass + '">' + scores[lowestScoreDifferenceIndex].score.r + '-' + scores[lowestScoreDifferenceIndex].score.b + ' Comeback!</div>');
} else {
if (tagpro && tagpro.group && tagpro.group.socket !== null && tagpro.group.socket.connected) {
$('#options').prepend('<div class="SBEB_Message ' + colorClass + '">+' + winMargin + ' ' + winningTeamName + ' Win!</div>');
} else if (mercyRule > 0 && (winMargin === mercyRule)) {
$('#options').prepend('<div class="SBEB_Message ' + colorClass + '">+' + mercyRule + ' Mercy Win!</div>');
} else if (tagpro.overtimeStartedAt) {
$('#options').prepend('<div class="SBEB_Message ' + colorClass + '">Overtime Win!</div>');
}
}
}
/*************************/
// these styles are for the scoreboard during the game (they will be changed at the EOG)...
GM_addStyle('.game div#options .table.table-stripped td[data-column="score"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (SCORE_BACKGROUND_COLOR || 'revert') + '; }'); // Score
GM_addStyle('.game div#options .table.table-stripped td[data-column="oscore"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (O_BACKGROUND_COLOR || 'revert') + '; }'); // O
GM_addStyle('.game div#options .table.table-stripped td[data-column="dscore"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (D_BACKGROUND_COLOR || 'revert') + '; }'); // D
GM_addStyle('.game div#options .table.table-stripped td[data-column="captures"] { color:#ddd; font-weight:inherit; font-size:inherit; background-color:' + (CAPS_BACKGROUND_COLOR || 'revert') + '; }'); // Caps
GM_addStyle('.game div#options .table.table-stripped td.o-ipm, .game div#options .table.table-stripped td.d-ipm { color:#ddd; font-weight:inherit !important; font-size:inherit !important; }'); // another O & D style
GM_addStyle('.game div#options table tbody td { text-shadow:1px 1px 2px #000; border-right:none; }');
GM_addStyle('.game #options { width:' + Math.max(960, (Math.round($('#options').width() / 2) * 2 + 24)) + 'px; left:50% !important; translate:-50%; }');
GM_addStyle('#stats tbody { color: #ddd; }');
GM_addStyle('.game div#options table td:nth-child(n+2), .game div#options table th:nth-child(n+2) { min-width:45px !important; width:45px; padding:3px 5px !important; white-space:nowrap; }');
GM_addStyle('#stats td:first-child, #stats th:first-child { min-width:120px !important; width:120px !important; }');
GM_addStyle('#stats td[data-column="dscore"], #stats th[data-column="dscore"] { border-right:1px solid #4b4b4b !important; }'); // right of "D" column
tagpro.socket.on('end', function() {
$('#options').hide();
setTimeout(() => { // need a delay here
$('#stats tbody').removeClass('stats'); // stop the scoreboard from updating
$('#stats tbody tr.template').remove(); // not needed anymore
let playersSorted = createScoreboardData(tagpro.players);
modifyScoreboard(playersSorted);
}, 100);
});
// detect some group settings...
let startCounter = 0;
let waitForGroupSocket = function() {
if (!tagpro || !tagpro.group || tagpro.group.socket !== null && !tagpro.group.socket.connected) {
startCounter++;
if (startCounter < 50) {
setTimeout(waitForGroupSocket, 20);
return false;
}
}
if (tagpro && tagpro.group && tagpro.group.socket !== null && tagpro.group.socket.connected) {
let settingCount = 0;
function handleSetting(data) {
// console.log('SBEB:: handleSetting():', data.name, data.value);
if (data.name === 'mercyRule') {
mercyRule = data.value;
settingCount++;
} else if (data.name === 'redTeamName') {
redTeamName = data.value;
settingCount++;
} else if (data.name === 'blueTeamName') {
blueTeamName = data.value;
settingCount++;
}
if (settingCount === 3) {
tagpro.group.socket.removeListener('setting', handleSetting);
}
}
tagpro.group.socket.on('setting', handleSetting);
}
};
waitForGroupSocket();
//Helpers...
function toSeconds(value) {
return value.split(':').reduce((acc, time) => (60 * acc) + +time);
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment