Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active April 16, 2024 16:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nabbynz/001897878e5cf22d8fa1 to your computer and use it in GitHub Desktop.
Save nabbynz/001897878e5cf22d8fa1 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name TagPro KFC
// @description Show Kisses, Flaccids & Caps
// @version 2.0.1
// - Made compatible with new TagPro site design
// - Added Menu (so options don't get overwritten on script updates)
// - Added Timeline
// - Disabled Multi-Kills by default (affected game performance on some systems too much?)
// - Removed Bomb Snipes (not very accurate)
// - Added CapSavers
// - Added Multi-Kills
// - Added Boost Snipes
// @include http://tagpro-*.koalabeast.com*
// @include http://tangent.jukejuice.com*
// @include http://*.newcompte.fr*
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
// @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js
// @resource jqUI_CSS http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/themes/smoothness/jquery-ui.css
// @updateURL https://gist.github.com/nabbynz/001897878e5cf22d8fa1/raw/TagPro_KFC.user.js
// @downloadURL https://gist.github.com/nabbynz/001897878e5cf22d8fa1/raw/TagPro_KFC.user.js
// @grant GM_getResourceText
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @author nabby
// ==/UserScript==
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
var $uHome = $('#userscript-home');
var $uTop = $('#userscript-top');
var $uBottom = $('#userscript-bottom');
//GM_deleteValue('savedOptions') //you can uncomment this line to reset all the saved options to defaults (then re-comment it after reloading page)
tagpro.ready(function() {
var defaultOptions = {
//Best not to edit these options here (you can change them through the menu button on the server home page)...
headerPopups: { value: 'header', display:'Popups' },
showKissPopup: { value: true, display:'Kisses', title:'A Kiss is when the 2 FC\'s pop each other' },
showFlaccidsPopup: { value: true, display:'Flaccids', title:'A Flaccid is defined (here) as when you grab and drop the flag within 1 second' },
showCapsPopup: { value: true, display:'Caps', title:'Shows Caps in the Event Log. Also shows Boost Caps and CapTricks (also shows Hold)' },
showTPKillsPopup: { value: true, display:'TP Kills', title:'Shows when we pop someone using a TagPro' },
showMultiKillPopup: { value: false, display:'Multi-Kills', title:'Double/Triple/Quad Kills (in a row, by one player)\n\nWARNING: This MIGHT affect game smoothness' },
showBoostSnipesPopup: { value: true, display:'Boost Snipes', title:'By us when we boost and pop another player (either with a TP, or into the EFC)' },
showBoostDropsPopup: { value: true, display:'Boost Drops', title:'By us when we boost and pop ourself while carrying the flag' },
showCapSavers: { value: true, display:'Cap Savers', title:'When a player Grabs & Kisses within 3 secs it\'s a Cap-Saver (will override normal Kisses)' },
headerTimeline: { value: 'header', display:'Timeline' },
showTimeline: { value: true, display:'Use Timeline?', title:'If unchecked the Timeline will not be used' },
showOnScoreboard: { value: true, display:'Show On Scoreboard', title:'If checked the Timeline will append to the scoreboard.\nIf unchecked it will be placed at the bottom on the screen (under the timer on a 1080+ screen)' },
modifyScoreboardStyle: { value: true, display:'Modify Scoreboard Style', title:'Removes the social media links from the scoreboard, and makes some other minor adjustments' },
showTimeScale: { value: false, display:'Show Time Markers', title:'Shows "12 .. 0" minute markers below the timeline' },
showKissesOnTimeline: { value: true, display:'Kisses', title:'Show Kisses on Timeline (also shows Hold)' },
showFlaccidsOnTimeline: { value: true, display:'Flaccids', title:'Show Flaccids on Timeline' },
showCapsOnTimeline: { value: true, display:'Caps', title:'Show Captures on Timeline (also shows Hold)' },
showNFGrabsOnTimeline: { value: false, display:'NF Grabs', title:'Show all Red/Blue NF Grabs on Timeline' },
showMyHoldOnTimeline: { value: true, display:'My Hold', title:'Show My Hold time on Timeline' },
showMyReturnsOnTimeline: { value: true, display:'My Returns', title:'Show My Returns on Timeline (Red Dots)' },
showMyPUPsOnTimeline: { value: true, display:'My PUPs', title:'Show My Powerups on Timeline (Orange Dots)' },
showTPKillsOnTimeline: { value: true, display:'My TP Kills', title:'Show My TagPro Kills on Timeline (Green Dots)' },
showBoostSnipesOnTimeline: { value: true, display:'My Boost Snipes', title:'Show My Boost Snipes on Timeline' },
showLeaversOnTimeline: { value: true, display:'Leavers', title:'Show when a player leaves the game' },
showJoinersOnTimeline: { value: true, display:'Joiners', title:'Show when a player joins the game' },
showSwitchersOnTimeline: { value: true, display:'Switchers', title:'Show when a player switches teams' },
headerEventsWindow: { value: 'header', display:'Event Log Window' },
showEventsWindow: { value: true, display:'Show Event Log Window?', title:'Shows a log of Kisses, Flaccids, Caps, etc during the game (you can drag/resize this window!)' },
showEventsWindowEOG: { value: false, display:'Only Show at EOG', title:'Only show the log when the game is finished ("Show Event Log Window" must also be checked)' },
showLastGameonJoiner: { value: true, display:'Show Last Game on Joiner', title:'Show the last game\'s event log on the Joining page' },
showLastGameonHome: { value: true, display:'Show Last Game on Home', title:'Show the last game\'s event log on the Server Home page' },
showKisses: { value: true, display:'Kisses', title:'Show Kisses in the Event Log Window' },
showFlaccids: { value: true, display:'Flaccids', title:'Show Flaccids in the Event Log Window' },
showCaps: { value: true, display:'Caps', title:'Show Caps in the Event Log Window (also shows Hold)' },
showAllGrabs: { value: false, display:'All Grabs', title:'There will be lots!' },
onlyShowMyGrabs: { value: false, display:'My Grabs Only', title:'Only show my grabs' },
showAllDrops: { value: false, display:'All Drops', title:'There will be lots! Also shows hold time' },
onlyShowMyDrops: { value: false, display:'My Drops Only', title:'Only show my drops' },
showPops: { value: false, display:'My Pops', title:'Only when we get popped (or spike ourself)' },
showTPKills: { value: true, display:'My TP Kills', title:'When we tag someone using a TagPro' },
showMyPowerups: { value: false, display:'My Powerups', title:'Only shows my Powerups' },
showMultiKills: { value: false, display:'Multi-Kills', title:'Double/Triple/Quad Kills (in a row, by one player)\n\nWARNING: This MIGHT affect game smoothness' },
showBoostSnipes: { value: true, display:'Boost Snipes', title:'By us when we boost and pop another player (either with a TP, or into EFC)' },
showPlayerLeft: { value: true, display:'Leavers', title:'Show when a player leaves the game' },
showPlayerJoined: { value: true, display:'Joiners', title:'Show when a player joins the game' },
showPlayerSwitched: { value: true, display:'Switchers', title:'Show when a player switches teams' },
showJoinedAsSpec: { value: true, display:'Speccing Player', title:'Show the name of the player we are currently spectating' },
showTime: { value: true, display:'Show Time', title:'Show the current timer in the Event Log Window' },
showBorder: { value: true, display:'Border Event Window', title:'Show a dashed border around the Event Log Window' },
headerOther: { value: 'header', display:'Other' },
popupDelay: { value: 1200, display:'Popup Delay', title:'How long the Popup shows on screen for.\nDefault = 1200 (1.2 sec)' },
popupTop: { value: 10, display:'Popup Top % Position', title:'Position for the Popup from the Top of the page.\nDefault = 10% (nearer the top)' },
popupLeft: { value: 50, display:'Popup Left % Position', title:'Position for the Popup from the Left of the page.\nDefault = 50% (horizontally centered)' },
showTimerPopupEveryN: { value: 60, display:'Timer Popup Every x', title:'Displays a small popup every x seconds showing the remaining game time at the right of the screen\nDefault = 60 (set to 0 to disable)' },
//you can change these values, but they will revert when the script updates...
redTextColor: { value: '#F8B0B8', display:'ignore' }, //default in chat = #F8B0B8
blueTextColor: { value: '#C9C9F8', display:'ignore' }, //default in chat = #C9C9F8
kissColor: { value: '#FF1493', display:'ignore' },
flaccidColor: { value: '#FFFF00', display:'ignore' },
capColor: { value: '#00FF00', display:'ignore' },
capSaverColor: { value: '#BB00BB', display:'ignore' },
grabColor: { value: '#00FFFF', display:'ignore' },
dropColor: { value: '#FF8C00', display:'ignore' },
tpKillsColor: { value: '#228B22', display:'ignore' },
timeColor: { value: '#FFA500', display:'ignore' },
multiKillColor: { value: '#6A5ACD', display:'ignore' },
boostSnipeColor: { value: '#00CED1', display:'ignore' },
};
var options = $.extend(true, {}, defaultOptions, GM_getValue('savedOptions', defaultOptions));
$.each(options, function(key, value) {
if ( options.hasOwnProperty(key) && defaultOptions.hasOwnProperty(key) ) { //always use the latest display & title from the script
options[key].display = defaultOptions[key].display;
options[key].title = defaultOptions[key].title;
} else if (options.hasOwnProperty(key)) { //something has been removed from the default options, so best we remove it from our saved options too...
delete options[key];
GM_setValue('savedOptions', options);
}
});
if (!GM_getValue('savedOptions')) { //first time
GM_setValue('savedOptions', options);
}
//--------------------------
//Helper functions...
function ordinal_suffix_of(i) {
var j = i % 10,
k = i % 100;
if (j == 1 && k != 11) return i + "st";
if (j == 2 && k != 12) return i + "nd";
if (j == 3 && k != 13) return i + "rd";
return i + "th";
}
function capitaliseFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
function WhichPageAreWeOn(){
if (window.location.port) { //In a real game
return('ingame');
} else if (document.URL.indexOf('/games/find') > 0) { //Joining page
return('joining');
} else if ($('a[href^="/games/find"]').length) { //Chosen server homepage
return('server');
} else if (document.URL.indexOf('/profile/') > 0) {
if ($('#saveSettings').length) {
return('profile'); //Profile page and logged in
} else {
return('profileNotOurs'); //Profile page, but not our one (or we're logged out)
}
}
}
var PageLoc = WhichPageAreWeOn();
function secondsToHMS(d) {
d = Number(d);
var h = Math.floor(d / 3600);
var m = Math.floor(d % 3600 / 60);
var s = Math.floor(d % 3600 % 60);
return ((h > 0 ? h + ":" : "") + (m > 0 ? (h > 0 && m < 10 ? "0" : "") + m + ":" : "0:") + (s < 10 ? "0" : "") + s);
}
function hexToRgbA(hex, alpha){
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
var c = hex.substring(1).split('');
if (c.length === 3) c = [c[0], c[0], c[1], c[1], c[2], c[2]];
c = '0x' + c.join('');
if (!alpha || !$.isNumeric(alpha) || (alpha < 0) || (alpha > 1)) alpha = 1;
return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
}
}
//--------------------------
var startTime; //start of game time
var joinTime; //time we joined the game
var fullTime; //expected end of game time after 12 mins
var gameLength = 720000; //game length (12 mins)
var joinPoint;
var threshold = 8.2;
var grabCheckFlagsDelay = 120; //we need a delay after a grab until the tagpro object gets updated to show the flag holder. this value is adjusted later.
var ljs = [];
var last = { red:[], blue:[] };
var redY=0, blueY=0, redPadding=0, bluePadding=0;
var colors = { K:options.kissColor.value, F:options.flaccidColor.value, C:options.capColor.value, '+':'#ccc', '-':'#888', S:'salmon', '⤞':options.boostSnipeColor.value, TPK:'orange' };
var mapName='', mapAuthor='', mapType='';
var myGrabPoint, myDropPoint, myGrabTime, myDropTime;
function updateScoreLabels() {
var myTeam=1, redScore='R:', blueScore='B:', resultClass='CTS_MyTeam';
setTimeout(function() {
if (PageLoc === 'ingame') {
myTeam = tagpro.players[tagpro.playerId].team;
redScore = tagpro.score.r;
blueScore = tagpro.score.b;
if ((myTeam === 1) && (redScore > blueScore)) resultClass = 'CTS_MyTeamWin';
else if ((myTeam === 1) && (blueScore > redScore)) resultClass = 'CTS_MyTeamLoss';
else if ((myTeam === 2) && (blueScore > redScore)) resultClass = 'CTS_MyTeamWin';
else if ((myTeam === 2) && (redScore > blueScore)) resultClass = 'CTS_MyTeamLoss';
} else if (GM_getValue('ljs') !== undefined) {
var game = GM_getValue('ljs'), title='';
var playedFor = (game.timePlayed / game.fullGameLength * 100).toFixed(2);
if (playedFor > 100) playedFor = 100;
myTeam = game.team;
redScore = game.redScore;
blueScore = game.blueScore;
if (game.result === "Win") resultClass = 'CTS_MyTeamWin';
else if (game.result === "Loss") resultClass = 'CTS_MyTeamLoss';
title = game.mapName + ' by ' + game.mapAuthor + ' (' + game.mapType + ')' + "\n" +
new Date(parseInt(Date.parse(game.played))).toLocaleTimeString() + ' (' + new Date(parseInt(Date.parse(game.played))).toDateString() + (game.serverName ? ') on ' + game.serverName : ')') + "\n" +
'You ' + (game.spectator ? 'spec\'d' : 'played') + ' for ' + secondsToHMS(game.timePlayed) + ' ('+ playedFor + '%)';
if (myTeam === 1) {
$('#CTS_RedLabel').attr('title', title);
} else {
$('#CTS_BlueLabel').attr('title', title);
}
}
if (myTeam === 1) {
$('#CTS_RedLabel').text(redScore).removeClass().addClass(resultClass);
$('#CTS_BlueLabel').text(blueScore).removeClass();
} else {
$('#CTS_BlueLabel').text(blueScore).removeClass().addClass(resultClass);
$('#CTS_RedLabel').text(redScore).removeClass();
}
}, 100);
}
var useMethod1 = false;
var addEventToTimeline = function(value) {
var pc = ((value.time - startTime) / gameLength * 100).toFixed(1);
var timer = secondsToHMS((gameLength-(value.time-startTime))/1000);
var title, color;
var i=0;
if (value.type === 'PUP') {
$('#CTS').append('<div class="CTS_PUP" style="left:'+pc+'%;" title="My PowerUp @ '+timer+'"></div>'); //secondsToHMS((value.time - startTime)/1000)
} else if (value.type === 'RETURN') {
$('#CTS').append('<div class="CTS_Return" style="left:'+pc+'%;" title="Returned: '+value.name+' @ '+timer+'"></div>');
} else if (value.type === 'TPK') {
$('#CTS').append('<div class="CTS_TPKill" style="left:'+pc+'%;" title="TagPro.KILL\'d: '+value.name+' @ '+timer+'"></div>');
} else if (value.type === 'GRAB') {
myGrabPoint = pc;
} else if (value.type === 'DROP') {
myDropPoint = pc;
} else if (value.type === 'NFGRAB') {
$('#CTS').append('<div class="'+(value.team === 1 ? 'CTS_NFGrab_Red' : 'CTS_NFGrab_Blue') + '" style="left:'+pc+'%;" title="NF Grab: '+value.name+' @ '+timer+'"></div>');
} else if (value.type === 'SOG') {
$('#CTS').append('<div class="CTS_JoinPoint" style="left:'+pc+'%;" title="Joined @ '+timer+'"></div>');
} else if (value.type === 'EOG') {
//we need this here for the 'else'
} else {
if (value.type === 'K') {
title = (value.cs ? 'Cap Saving Kiss: ' : 'Kiss: ') + value.name + ' @ ' + timer + ' (Hold: ' + value.hold + ')';
color = (value.cs ? options.capSaverColor.value : colors[value.type]);
} else if (value.type === 'F') {
title = 'Flaccid: ' + value.name + ' @ ' + timer;
color = colors[value.type];
} else if (value.type === 'C') {
title = 'Cap: ' + value.name + ' @ ' + timer + ' (Hold: ' + value.hold + ')';
color = colors[value.type];
} else if (value.type === '+') {
title = 'Joined: ' + value.name + ' @ ' + timer;
color = colors[value.type];
} else if (value.type === '-') {
title = 'Left: ' + value.name + ' @ ' + timer;
color = colors[value.type];
} else if (value.type === 'S') {
title = 'Switched to ' + (value.team === 1 ? 'Red' : 'Blue') + ': ' + value.name + ' @ ' + timer;
color = colors[value.type];
} else if (value.type === '⤞') {
title = 'Sniped: ' + value.name + ' @ ' + timer;
color = colors[value.type];
} else {
title = '@ ' + timer;
color = 'white';
}
if (value.team === 1) {
for (i=0; i<last.red.length; i++) {
if (pc - last.red[i] > threshold) {
last.red[i] = pc;
redY = i * 10 + 10;
break;
}
}
if (i === last.red.length) {
last.red[i] = pc;
redY = i * 10 + 10;
}
if (redY > redPadding) redPadding = redY;
$('#CTS').append('<div class="CTS_RedMarker" style="left:'+pc+'%; background:'+color+';"><div class="CTS_Name'+(value.self ? ' CTS_Self' : '')+'" style="margin:-'+redY+'px 0 0 -2px; color:'+color+';" title="'+title+'"><span class="CTS_Event" style="background:'+color+'">'+value.type+'</span>'+value.name+'</div></div>');
if (value.self) {
myDropPoint = pc;
}
} else {
for (i=0; i<last.blue.length; i++) {
if (pc - last.blue[i] > threshold) {
last.blue[i] = pc;
blueY = i * 10 + 10;
break;
}
}
if (i === last.blue.length) {
last.blue[i] = pc;
blueY = i * 10 + 10;
}
if (blueY > bluePadding) bluePadding = blueY;
$('#CTS').append('<div class="CTS_BlueMarker" style="left:'+pc+'%; background:'+color+'"><div class="CTS_Name'+(value.self ? ' CTS_Self' : '')+'" style="margin:'+blueY+'px 0 0 -2px; color:'+color+';" title="'+title+'"><span class="CTS_Event" style="background:'+color+'">'+value.type+'</span>'+value.name+'</div></div>');
if (value.self) {
myDropPoint = pc;
}
}
}
if (options.showMyHoldOnTimeline.value && (myDropPoint === pc) && value.hold) {
$('#CTS').append('<div style="position:absolute; display:inline-block; margin-top:'+(value.team === 1 ? '0' : '0')+'px; height:1px; z-index:1; background:tomato; left:'+myGrabPoint+'%; width:'+(myDropPoint-myGrabPoint)+'%;" title="My Hold: '+value.hold+'"></div>');
}
};
var updateTimeline = function(singleEvent, position) {
var thisTime = Date.now();
if (position === undefined) position = ljs.length-1;
if (PageLoc !== 'ingame') {
if (!ljs.length) {
$('#CTS_Outer').text('No Last-Game Datas for Timeline');
$('#CTS_Container').fadeOut(3000);
return;
}
thisTime = ljs[position].time;
}
var thisPoint = ((thisTime - startTime) / gameLength * 100).toFixed(1);
var thisWidth = thisPoint - joinPoint;
var endWidth = 100 - thisPoint;
if (singleEvent) {
var value = ljs[position];
$('#CTS_Game').css({ left:joinPoint+'%', width:thisWidth+'%' });
$('#CTS_Post').css({ left:thisPoint+'%', width:endWidth+'%' });
updateScoreLabels();
addEventToTimeline(value);
} else {
if (!$('#CTS').length) {
$('#CTS_Outer').append('<div id="CTS"></div>');
if (joinPoint > 0) {
$('#CTS_Outer').append('<div id="CTS_Pre" style="width:'+joinPoint+'%"></div>');
}
$('#CTS_Outer').append('<div id="CTS_RedLabel"></div>');
$('#CTS_Outer').append('<div id="CTS_BlueLabel"></div>');
updateScoreLabels();
if (options.showTimeScale.value) {
$('#CTS_Outer').append('<div id="CTS_Scale"></div>');
for (var i=12; i>=0; i--) {
$('#CTS_Scale').append('<div class="CTS_ScalePoint" style="left:'+((12-i)/12*100).toFixed(2)+'%;">'+i+'</div>');
}
}
$('#CTS_Outer').append('<div id="CTS_Game" style="left:'+joinPoint+'%; width:'+thisWidth+'%;"></div>');
$('#CTS_Outer').append('<div id="CTS_Post" style="left:'+thisPoint+'%; width:'+endWidth+'%;"></div>');
if (PageLoc !== 'ingame') {
$.each(ljs, function(key, value) {
addEventToTimeline(value);
});
}
}
}
if (redPadding <= 20) redPadding = 25;
if (bluePadding <= 20) bluePadding = 25;
if (ljs.length) {
$('#CTS_Outer').css('padding', (redPadding+10)+'px 0 '+(bluePadding+(options.showTimeScale.value ? 20 : 10)+'px'));
} else {
$('#CTS_Outer').css('padding', (redPadding)+'px 0 '+(bluePadding+10)+'px');
}
};
var $KFC_EventHistory;
var $KFC_PopUp;
var $KFC_PopUpBefore;
var $KFC_PopUpMiddle;
var $KFC_PopUpAfter;
function addToPage() {
$('body').append('<div id="KFC_EventHistory" style="position:absolute; padding:5px 0; height:'+GM_getValue('size', {height:300}).height+'px; width:'+GM_getValue('size', {width:310}).width+'px;'+(options.showBorder.value ? ' border:1px dashed aquamarine; border-bottom:3px solid dodgerblue; ' : '')+' left:'+GM_getValue('position', {left:5}).left+'px; top:'+GM_getValue('position', {top:110}).top+'px; font:11px Arial; text-shadow:1px 1px 1px black; background:rgb(50,50,50); overflow-x:hidden; overflow-y:auto;"></div>');
$KFC_EventHistory = $('#KFC_EventHistory');
if (PageLoc === 'ingame') {
//Popup...
$('body').append('<div id="KFC_Popup" style="position:absolute; display:flex; justify-content:center; align-items:center; flex-flow:column; margin-left:-100px; top:'+options.popupTop.value+'%; left:'+options.popupLeft.value+'%; font-size:20px; font-weight:bold; text-shadow:2px 2px 2px black; height:150px; width:200px; border:3px dashed white; border-radius:12px; background:rgba(0,0,0,0.3); overflow:hidden;"><span id="KFC_PopupBefore"></span><span id="KFC_PopupMiddle" style="font-size:32px; padding:16px 0 28px 0; transform:rotate(-15deg);"></span><span id="KFC_PopupAfter"></span></div>');
$KFC_PopUp = $('#KFC_Popup');
$KFC_PopUpBefore = $('#KFC_PopupBefore');
$KFC_PopUpMiddle = $('#KFC_PopupMiddle');
$KFC_PopUpAfter = $('#KFC_PopupAfter');
$KFC_PopUp.show(0);
$KFC_PopUp.hide(0);
} else {
$KFC_EventHistory.append(GM_getValue('lastGameLog', ''));
}
GM_addStyle('#KFC_EventHistory::-webkit-scrollbar { width:2px }');
GM_addStyle('#KFC_EventHistory::-webkit-scrollbar-thumb { background:#b0b; }');
GM_addStyle('#KFC_EventHistory::-webkit-scrollbar-track { background:#ddd; }');
if (options.showTimeline.value) {
GM_addStyle('#CTS_Outer { position:relative; margin:0 60px 0 40px; padding:30px 0; text-align:left; }');
GM_addStyle('#CTS { position:absolute; display:inline-block; width:100%; }');
GM_addStyle('#CTS_Pre { position:absolute; display:inline-block; left:0px; border-bottom:1px dotted #666; }');
GM_addStyle('#CTS_Game { position:absolute; display:inline-block; border-bottom:1px solid #ddd; }');
GM_addStyle('#CTS_Post { position:absolute; display:inline-block; border-bottom:1px dashed #f00; }');
GM_addStyle('#CTS_RedLabel { position:absolute; display:inline-block; width:22px; height:23px; text-align:center; color:red; font:20px Arial; margin:-27px -25px; cursor:default; }');
GM_addStyle('#CTS_BlueLabel { position:absolute; display:inline-block; width:22px; height:23px; text-align:center; color:dodgerblue; font:20px Arial; margin:5px -25px; cursor:default; }');
GM_addStyle('.CTS_MyTeam { border:1px dashed #aaa; border-radius:50%; }');
GM_addStyle('.CTS_MyTeamWin { border:1px dashed #0d0; border-radius:50%; }');
GM_addStyle('.CTS_MyTeamLoss { border:1px dashed #d00; border-radius:50%; }');
GM_addStyle('#CTS_Scale { position:absolute; display:inline-block; width:100%; border-bottom:1px dotted gold; color:gold; font-size:10px; bottom:0px; margin:0 0 10px; }');
GM_addStyle('.CTS_ScalePoint { position:absolute; width:1px; height:10px; margin:0; padding:0 0 0 1px; border-left:1px solid gold; }');
GM_addStyle('.CTS_JoinPoint { position:absolute; width:1px; height:51px; margin:-25px 0 0; border-left:1px solid white; }');
GM_addStyle('.CTS_RedMarker { position:absolute; width:1px; height:10px; margin:-8px 0 0 0; }');
GM_addStyle('.CTS_BlueMarker { position:absolute; width:1px; height:10px; margin:-1px 0 0 0; }');
GM_addStyle('.CTS_Name { position:absolute; white-space:nowrap; font-size:9px; }');
GM_addStyle('.CTS_Self { text-decoration:underline }');
GM_addStyle('.CTS_Event { display:inline-block; margin-left:-3px; padding:0 1px; text-align:center; width:9px; color:black; border-radius:4px; }');
GM_addStyle('.CTS_Grab { position:absolute; width:1px; height:3px; margin:-1px 0 0; z-index:1; background:hotpink; }');
GM_addStyle('.CTS_Drop { position:absolute; width:1px; height:3px; margin:-1px 0 0; z-index:1; background:deeppink; }');
GM_addStyle('.CTS_NFGrab_Red { position:absolute; width:2px; height:5px; margin:-2px 0 0; z-index:1; background:tomato; }');
GM_addStyle('.CTS_NFGrab_Blue { position:absolute; width:2px; height:5px; margin:-2px 0 0; z-index:1; background:dodgerblue; }');
GM_addStyle('.CTS_PUP { position:absolute; width:3px; height:5px; margin:-2px 0 0; z-index:2; background:darkorange; }');
GM_addStyle('.CTS_Return { position:absolute; width:3px; height:5px; margin:-2px 0 0; z-index:2; background:#c00; }');
GM_addStyle('.CTS_TPKill { position:absolute; width:3px; height:5px; margin:-2px 0 0; z-index:2; background:darkgreen; }');
setTimeout(updateTimeline, 1200);
}
}
if (PageLoc === 'server') {
if (options.showLastGameonHome.value) {
if (options.showTimeline.value) {
$uHome.find('.row').append('<div id="CTS_Container" style="position:relative; display:flex; justify-content:center; align-items:center; margin:0 auto; top:20px; width:850px; left:0px; background:rgba(0,0,0,0.3); border:1px solid #555; border-radius:5px;"></div>');
$uHome.removeClass('hidden');
$('#CTS_Container').append('<div id="CTS_Outer" style="position:relative; width:100%; margin:0 60px 0 40px; padding:30px 0; text-align:left;"></div>');
if (GM_getValue('ljs')) {
ljs = GM_getValue('ljs').data.slice(0);
startTime = GM_getValue('ljs').startTime;
joinTime = GM_getValue('ljs').joinTime;
joinPoint = (joinTime - startTime) / gameLength * 100;
}
}
addToPage();
$KFC_EventHistory.prepend('<div style="text-align:center; margin-bottom:5px; text-decoration:underline">Last Game Event Log...</div>');
$KFC_EventHistory.animate({scrollTop: $KFC_EventHistory.get(0).scrollHeight}, 500);
$KFC_EventHistory.append('<div id="KFC_OptionsButton" style="position:absolute; display:inline-block; top:5px; right:0px; font-size:11px; color:chartreuse; text-align:center; height:13px; width:14px; border:1px solid chartreuse; border-radius:50%; cursor:pointer" title="KFC Options Menu">&#8286;</div>');
$KFC_EventHistory.append('<div id="KFC_OptionsMenu" style="position:absolute; display:none; background:indigo; top:22px; right:2px; font-size:9px; text-align:left; height:360px; width:165px; overflow-x:hidden; overflow-y:scroll; border:1px solid white; border-radius:5px"></div>');
} else {
$('.nav').find('ul').append('<li><a href="javascript:void(0);" id="KFC_OptionsButton" style="" title="KFC Options Menu"><span style="border-bottom:1px dotted;" title="Show Texture Pack Manager Menu">KFC</span></a></li>');
$('#KFC_OptionsButton').after('<div id="KFC_OptionsMenu" style="position:absolute; display:none; padding:0 10px; background:indigo; top:30px; font-size:9px; text-align:left; height:360px; width:200px; overflow-x:hidden; overflow-y:scroll; border:1px solid white; border-radius:5px; z-index:1"></div>');
GM_addStyle('#KFC_OptionsMenu li { display:block }');
GM_addStyle('#KFC_OptionsMenu li:hover { background:none }');
}
$.each(options, function(key, value) {
if (value.display === 'ignore') {
//
} else if (value.value === 'header') {
$('#KFC_OptionsMenu').append('<div style="margin:5px 0 1px 17px; color:gold; font-weight:bold; text-decoration:underline">'+value.display+'</div>');
} else if (key === 'popupDelay') {
$('#KFC_OptionsMenu').append('<li style="list-style:none; margin:0 5px 0;"><input type="number" min="200" max="3000" step="100" value="'+options[key].value+'" class="KFC_OptionNumber" data-name="'+key+'"><label title="'+value.title+'">' + value.display + '</label></li>');
} else if ((key === 'popupLeft') || (key === 'popupTop')) {
$('#KFC_OptionsMenu').append('<li style="list-style:none; margin:0 5px 0;"><input type="number" min="0" max="100" step="2" value="'+options[key].value+'" class="KFC_OptionNumber" data-name="'+key+'"><label title="'+value.title+'">' + value.display + '</label></li>');
} else if (key === 'showTimerPopupEveryN') {
$('#KFC_OptionsMenu').append('<li style="list-style:none; margin:0 5px 0;"><input type="number" min="0" max="120" step="10" value="'+options[key].value+'" class="KFC_OptionNumber" data-name="'+key+'"><label title="'+value.title+'">' + value.display + '</label></li>');
} else {
$('#KFC_OptionsMenu').append('<li style="list-style:none; margin:0; font-weight:normal;"><label title="'+value.title+'" style="margin:0; font-weight:normal;"><input type="checkbox" class="KFC_Option" data-name="'+key+'" ' + (options[key].value === true ? 'checked' : '') + '>' + value.display + '</label></li>');
}
});
GM_addStyle('.KFC_Option { margin:0 2px; height:10px; }');
GM_addStyle('.KFC_OptionNumber { margin:0 2px; width:44px; height:14px; color:black; font:11px Arial; text-align:right; }');
GM_addStyle('#KFC_OptionsMenu::-webkit-scrollbar { width:2px }');
GM_addStyle('#KFC_OptionsMenu::-webkit-scrollbar-thumb { background:forestgreen; }');
GM_addStyle('#KFC_OptionsMenu::-webkit-scrollbar-track { background:#ddd; }');
$('#KFC_OptionsButton').on('click', function() {
$('#KFC_OptionsMenu').slideToggle(400);
});
$('#KFC_OptionsMenu').find('.KFC_Option').on('click', function() {
options[$(this).data('name')].value = $(this).is(':checked');
GM_setValue('savedOptions', options);
});
$('#KFC_OptionsMenu').find('.KFC_OptionNumber').on('change', function() {
options[$(this).data('name')].value = $(this).val();
GM_setValue('savedOptions', options);
});
} else if (options.showLastGameonJoiner.value && PageLoc === 'joining') {
if (options.showTimeline.value) {
$uBottom.find('.row').append('<div id="CTS_Container" style="position:relative; margin:20px auto; width:900px; left:0px; background:rgba(0,0,0,0.3); border:1px solid #555; border-radius:5px;"></div>');
$uBottom.removeClass('hidden');
$('#CTS_Container').append('<div id="CTS_Outer" style="position:relative; margin:0 60px 0 40px; padding:30px 0; text-align:left;"></div>');
if (GM_getValue('ljs')) {
ljs = GM_getValue('ljs').data.slice(0);
startTime = GM_getValue('ljs').startTime;
joinTime = GM_getValue('ljs').joinTime;
joinPoint = (joinTime - startTime) / gameLength * 100;
}
}
addToPage();
$KFC_EventHistory.prepend('<div style="text-align:center; margin-bottom:5px; text-decoration:underline">Last Game Event Log...</div>');
$KFC_EventHistory.animate({scrollTop: $KFC_EventHistory.get(0).scrollHeight}, 500);
} else if (PageLoc === 'ingame') {
var jqUI_CssSrc = GM_getResourceText("jqUI_CSS");
GM_addStyle (jqUI_CssSrc);
var updateEventHistory = function(message, color) {
color = color || '#ffffff';
window.requestAnimationFrame(function() {
$KFC_EventHistory.append('<div style="color:'+color+'">' + ((options.showTime.value && (tagpro.state != 2)) ? '<span style="color:'+options.timeColor.value+'">'+tagpro.ui.sprites.timer.text+' </span>' : '') + message + '</div>');
$KFC_EventHistory.animate({scrollTop: $KFC_EventHistory.get(0).scrollHeight}, 500);
GM_setValue('lastGameLog', $KFC_EventHistory.html());
});
};
var showPopup = function(beforeText, beforeColor, middleText, middleColor, afterText, afterColor) {
if ($KFC_PopUp.is(':visible')) $KFC_PopUp.hide(0);
$KFC_PopUpBefore.html(beforeText).css('color', beforeColor);
$KFC_PopUpMiddle.html(middleText);
$KFC_PopUpAfter.html(afterText).css('color', afterColor);
$KFC_PopUp.css({color:middleColor, background:hexToRgbA(middleColor, 0.3), 'border-color':middleColor});
window.requestAnimationFrame(function() {
$KFC_PopUp.show(0).delay(options.popupDelay.value).hide(0);
});
};
var redHolder = 0;
var blueHolder = 0;
var whoHasFlags = function() {
redHolder=0;
blueHolder=0;
for (var playerId in tagpro.players) {
if (tagpro.players[playerId].flag === 1) {
blueHolder = Number(playerId);
} else if (tagpro.players[playerId].flag === 2) {
redHolder = Number(playerId);
} else if (tagpro.players[playerId].flag === 3) {
if (tagpro.players[playerId].team === 1) {
redHolder = Number(playerId);
} else if (tagpro.players[playerId].team === 2) {
blueHolder = Number(playerId);
}
}
}
};
var findClosestEnemy = function() {
var distance = 0;
var lowest = 10000;
var closestId = 0;
var me = tagpro.players[tagpro.playerId];
for (var playerId in tagpro.players) {
if ((tagpro.players[playerId].team != me.team) && (playerId != me.id) && (Math.abs(tagpro.players[playerId].x - me.x) < 100)) {
distance = Math.sqrt(Math.pow(tagpro.players[playerId].x - me.x, 2) + Math.pow(tagpro.players[playerId].y - me.y, 2));
if (distance < lowest) {
lowest = distance;
closestId = playerId;
}
}
}
return Number(closestId);
};
var spectator = false;
var prevSpec;
tagpro.socket.on('spectator', function(data) {
if ((data === 'watching') || (data === 'waiting')) {
spectator = true;
} else {
spectator = false;
}
});
var friendlyTeam;
var enemyTeam;
var friendlyGrabTime = 0;
var enemyGrabTime = 0;
var friendlyDropTime = 0;
var enemyDropTime = 0;
if (options.showPlayerLeft.value || options.showPlayerJoined.value || options.showJoinedAsSpec.value || options.showLeaversOnTimeline.value || options.showJoinersOnTimeline.value || options.showSwitchersOnTimeline.value) {
tagpro.socket.on('chat', function(data) {
if (data.from === null) { //system message
var hasLeft = data.message.indexOf('has left the');
var hasJoined = data.message.indexOf('has joined the');
var hasSwitched = data.message.indexOf('has switched to');
var specJoined = data.message.indexOf('joined a game as a spectator');
var name = '';
var teamColor = 'Red';
if ((options.showPlayerLeft.value || options.showLeaversOnTimeline.value) && (hasLeft >= 0) && (tagpro.state == 1)) {
setTimeout(function() {
name = data.message.substr(1, hasLeft - 3);
if (data.message.indexOf('Blue') >= 0) teamColor = 'Blue';
if (options.showPlayerLeft.value) updateEventHistory('<span style="font-style:italic">- Left '+teamColor+': <span style="color:'+(teamColor === 'Red' ? options.redTextColor.value : options.blueTextColor.value)+'">' + name + '</span></span>');
if (options.showTimeline.value && options.showLeaversOnTimeline.value) {
ljs.push( { name:name, time:Date.now(), team:(teamColor === 'Red' ? 1 : 2), type:'-' } );
setTimeout(updateTimeline(true, ljs.length-1), 200);
}
}, 200);
}
if ((options.showPlayerJoined.value || options.showJoinersOnTimeline.value) && (hasJoined >= 0) && (tagpro.state == 1)) {
setTimeout(function() {
name = data.message.substr(1, hasJoined - 3);
if (data.message.indexOf('Blue') >= 0) teamColor = 'Blue';
if (options.showPlayerJoined.value) updateEventHistory('<span style="font-style:italic">+ Joined '+teamColor+': <span style="color:'+(teamColor === 'Red' ? options.redTextColor.value : options.blueTextColor.value)+'">' + name + '</span></span>');
if (options.showTimeline.value && options.showJoinersOnTimeline.value) {
ljs.push( { name:name, time:Date.now(), team:(teamColor === 'Red' ? 1 : 2), type:'+' } );
setTimeout(updateTimeline(true, ljs.length-1), 200);
}
}, 200);
}
if ((options.showPlayerSwitched.value || options.showSwitchersOnTimeline.value) && (hasSwitched >= 0) && (tagpro.state == 1)) {
var myTeam = tagpro.players[tagpro.playerId].team;
setTimeout(function() {
if (myTeam != tagpro.players[tagpro.playerId].team) { //it was me who switched teams
friendlyTeam = (tagpro.players[tagpro.playerId].team === 1 ? 1 : 2);
enemyTeam = (tagpro.players[tagpro.playerId].team === 1 ? 2 : 1);
var temp = friendlyGrabTime;
friendlyGrabTime = enemyGrabTime;
enemyGrabTime = temp;
temp = friendlyDropTime;
friendlyDropTime = enemyDropTime;
enemyDropTime = temp;
whoHasFlags();
if (options.showTimeline.value) updateScoreLabels();
}
name = data.message.substr(1, hasSwitched - 3);
if (data.message.indexOf('Blue') >= 0) teamColor = 'Blue';
if (options.showPlayerSwitched.value) updateEventHistory('<span style="font-style:italic">&middot; Switched to '+teamColor+': <span style="color:'+(teamColor === 'Red' ? options.redTextColor.value : options.blueTextColor.value)+'">' + name + '</span></span>');
if (options.showTimeline.value && options.showSwitchersOnTimeline.value) {
ljs.push( { name:name, time:Date.now(), team:(teamColor === 'Red' ? 1 : 2), type:'S' } );
setTimeout(updateTimeline(true, ljs.length-1), 200);
}
}, 100);
}
if (options.showJoinedAsSpec.value && (specJoined >= 0)) {
setTimeout(function() {
updateEventHistory('<span style="font-style:italic">Speccing '+(tagpro.players[tagpro.playerId].team === 1 ? 'Red' : 'Blue')+': <span style="color:'+(tagpro.players[tagpro.playerId].team === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[tagpro.playerId].name + '</span></span>');
prevSpec = tagpro.playerId;
}, 1000);
}
}
});
}
$(document).on('keydown', function(key) {
if (spectator) { // && (prevSpec != tagpro.players[tagpro.playerId].id)
if ( (key.keyCode === 81) || (key.keyCode === 87) || (key.keyCode === 65) || (key.keyCode === 83) ) { //q = cycle forwards
setTimeout(function() {
updateEventHistory('<span style="font-style:italic">Speccing '+(tagpro.players[tagpro.playerId].team === 1 ? 'Red' : 'Blue')+': <span style="color:'+(tagpro.players[tagpro.playerId].team === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[tagpro.playerId].name + '</span></span>');
prevSpec = tagpro.playerId;
}, 100);
}
}
});
var kissThreshold = 20; //time between the 2 drops (usually between 1-10, but can be 30-40 too)
var flaccidThreshold = 1200; //1000 = 1 sec (grab -> drop)
var capSaverThreshold = 3000; //3000 = 3 secs (a grab & kiss within 3 secs = cap saving kiss)
var counts = { kisses: { red:0, blue:0 }, flaccids: { red:0, blue:0 }, tagProKillCount:0, boostSnipes:0 };
var speedpadBoost = false;
var bombBoost = false;
var lastSnipe = 0;
var lastTPKill = 0;
var timeoutHandle;
var preventSnipePopup = false;
tagpro.socket.on('map', function(data) {
mapName = data.info.name;
mapAuthor = data.info.author;
width: for (var i=0; i<tagpro.map.length; i++) { //find the flags which will tell us if it's a CTF or NF map...
height: for (var j=0; j<tagpro.map[i].length; j++) {
if (tagpro.map[i][j] == 16 || (tagpro.map[i][j] == 16.1)) { //yellow flag found
mapType = 'NF';
break width;
} else if ((tagpro.map[i][j] == 3) || (tagpro.map[i][j] == 3.1) || (tagpro.map[i][j] == 4) || (tagpro.map[i][j] == 4.1)) { //red or blue flag found
mapType = 'CTF';
break width;
}
}
}
if (options.showTimeline.value) {
if (options.showOnScoreboard.value) {
$('#options').append('<div id="CTS_Container" style="position:relative; background:rgba(0,0,0,0.3); border:1px solid #555; border-radius:5px;"></div>');
if (options.modifyScoreboardStyle.value) {
setTimeout(function () {
$('#options').css('background-color', 'rgba(0,0,0,0.35)'); //slightly more transparent
$('#options').css('padding', '5px'); //more space
$('#options').css('height', 'auto'); //less blank space
$('#options').css('font-size', '13px'); //13px is default
$('#options').css('border-radius', '8px'); //prettier
$('#optionsLinks').hide(0); //hide the social media links
$('#optionsAd').hide(0); //hide the advertisement
}, 1000);
}
} else {
$('body').append('<div id="CTS_Container" style="position:absolute; bottom:0; width:'+$('#viewport').width()+'px; left:'+$('#viewport').position().left+'px; background:rgba(0,0,0,0.3); border:1px solid #555; border-radius:5px;"></div>');
}
$('#CTS_Container').append('<div id="CTS_Outer" style="position:relative; margin:0 60px 0 40px; padding:30px 0; text-align:left;"></div>');
}
addToPage();
if (!options.showEventsWindow.value) $KFC_EventHistory.hide(0);
$($KFC_EventHistory).css('background', 'rgba(50,50,50,0.05)');
$($KFC_EventHistory).scrollTop(0);
$($KFC_EventHistory).resizable({
delay: 200,
distance: 3,
containment: 'document',
resize: function(event, ui) {
$($KFC_EventHistory).css('border', '1px dashed white');
},
stop: function(event, ui) {
GM_setValue('size', {'width':ui.size.width, 'height':ui.size.height});
GM_setValue('position', {'top':ui.position.top, 'left':ui.position.left});
$($KFC_EventHistory).css('border', '1px dashed gray');
}
});
$($KFC_EventHistory).draggable({
delay: 200,
containment: 'window',
scroll: false,
drag: function(event, ui) {
$($KFC_EventHistory).css('border', '1px dashed white');
},
stop: function(event, ui) {
GM_setValue('position', {'top':ui.position.top, 'left':ui.position.left});
$($KFC_EventHistory).css('border', '1px dashed gray');
}
});
whoHasFlags();
setTimeout(function() {
friendlyTeam = (tagpro.players[tagpro.playerId].team === 1 ? 1 : 2);
enemyTeam = (tagpro.players[tagpro.playerId].team === 1 ? 2 : 1);
}, 100);
}); //socket.on.map
tagpro.socket.on('time', function(message) {
if (tagpro.state == 3) { //before the actual start
joinTime = Date.now();
} else if (tagpro.state == 1) { //game has started
fullTime = Date.parse(tagpro.gameEndsAt);
startTime = fullTime - 12 * 60 * 1000;
if (joinTime) {
joinTime = startTime; //time game started (end - 12 mins)
} else {
joinTime = Date.now(); //time we joined (mid-game)
}
joinPoint = ((joinTime - startTime) / gameLength * 100).toFixed(1);
setTimeout(function() {
ljs.push( { name:'', time:joinTime, team:tagpro.players[tagpro.playerId].team, type:'SOG' } );
updateTimeline(true, ljs.length-1);
}, 5000);
if (options.showTimerPopupEveryN.value) {
if (!$.isNumeric(options.showTimerPopupEveryN.value)) options.showTimerPopupEveryN.value = 60;
setTimeout(function() {
if ((tagpro.ui.sprites.hasOwnProperty('timer')) && (tagpro.ui.sprites.timer.hasOwnProperty('text'))) {
$('body').append('<div id="KFC_TimerPopup" style="position:absolute; display:flex; justify-content:center; align-items:center; flex-flow:column; margin:auto; top:0; bottom:0; right:0; color:black; font-size:20px; font-weight:bold; height:50px; width:100px; border:3px double white; border-radius:50%; background:rgba(200,200,200,0.7); overflow:hidden;"></div>');
$('#KFC_TimerPopup').show(0).hide(0);
var timerText = tagpro.ui.sprites.timer.text;
var secondsRem = timerText.slice(-2) * 1000;
setTimeout(function() {
timerText = tagpro.ui.sprites.timer.text;
$('#KFC_TimerPopup').text(timerText).show(0).delay(options.popupDelay.value).hide(0);
setInterval(function() {
timerText = tagpro.ui.sprites.timer.text;
if (tagpro.state == 1) $('#KFC_TimerPopup').text(timerText).show(0).delay(options.popupDelay.value).hide(0);
}, options.showTimerPopupEveryN.value*1000);
}, secondsRem);
}
}, 5000);
}
} else if (tagpro.state == 2) { //game has ended
//if (options.showTimeline.value) setTimeout(updateTimeline, 500);
}
});
var setPreventSnipePopup = function() {
preventSnipePopup = true;
setTimeout(function() {
preventSnipePopup = false;
}, 1000);
};
tagpro.socket.on('sound', function(data) {
var dropperId, capperId, capperColor, capMessage;
var prevFlag, prevTags;
var capTime, holdTime, friendlyHoldTime, enemyHoldTime;
var kisser, kissee, kisserColor, kisseeColor, capSaver;
var me = tagpro.players[tagpro.playerId];
grabCheckFlagsDelay = tagpro.ping.avg + 30;
if (isNaN(grabCheckFlagsDelay) || grabCheckFlagsDelay <= 50) grabCheckFlagsDelay = 50;
//-----------------------------
//GRABS
//-----------------------------
//Friendly Grab...
if ((data.s === 'friendlyalert') && (data.v !== void 0)) {
friendlyGrabTime = Date.now();
//prevFlag = me.flag;
myGrabTime = friendlyGrabTime;
setTimeout(function() {
whoHasFlags();
if (options.showAllGrabs.value) {
updateEventHistory('<span style="color:'+options.grabColor.value+'">GRAB: </span>' + (friendlyTeam === 1 ? tagpro.players[redHolder].name : tagpro.players[blueHolder].name), (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
} else if (options.onlyShowMyGrabs.value && (me.flag && !prevFlag) && (mapType === 'CTF') && !tagpro.spectator) {
updateEventHistory('<span style="color:'+options.grabColor.value+'">MY GRAB: </span>' + (friendlyTeam === 1 ? tagpro.players[redHolder].name : tagpro.players[blueHolder].name), (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
}
if (options.showTimeline.value) { // && !prevFlag
if (options.showMyHoldOnTimeline.value && me.flag && !tagpro.spectator) {
ljs.push( { name:'', time:myGrabTime, team:friendlyTeam, type:'GRAB', self:true } );
updateTimeline(true, ljs.length-1);
}
if (options.showNFGrabsOnTimeline.value && (mapType === 'NF')) {
ljs.push( { name:(friendlyTeam === 1 ? tagpro.players[redHolder].name : tagpro.players[blueHolder].name), time:friendlyGrabTime, team:friendlyTeam, type:'NFGRAB' } );
updateTimeline(true, ljs.length-1);
}
}
}, grabCheckFlagsDelay);
//Enemy Grab...
} else if ((data.s === 'alert') && (data.v !== void 0)) {
enemyGrabTime = Date.now();
setTimeout(function() {
whoHasFlags();
if (options.showAllGrabs.value) {
updateEventHistory('<span style="color:'+options.grabColor.value+'">GRAB: </span>' + (friendlyTeam === 1 ? tagpro.players[blueHolder].name : tagpro.players[redHolder].name), (friendlyTeam === 1 ? options.blueTextColor.value : options.redTextColor.value));
}
if (options.showTimeline.value && options.showNFGrabsOnTimeline.value && (mapType === 'NF')) {
ljs.push( { name:(friendlyTeam === 1 ? tagpro.players[blueHolder].name : tagpro.players[redHolder].name), time:enemyGrabTime, team:enemyTeam, type:'NFGRAB' } );
updateTimeline(true, ljs.length-1);
}
}, grabCheckFlagsDelay);
//-----------------------------
//DROPS/KISSES/FLACCIDS...
//-----------------------------
//Friendly Drop...
} else if ((data.s === 'friendlydrop') && (data.v !== void 0)) { //&& data.hasOwnProperty('v')
friendlyDropTime = Date.now();
dropperId = (friendlyTeam === 1 ? redHolder : blueHolder);
if (options.showAllDrops.value) {
updateEventHistory('<span style="color:'+options.dropColor.value+'">DROP: </span>' + (friendlyTeam === 1 ? tagpro.players[redHolder].name : tagpro.players[blueHolder].name) + ' ('+secondsToHMS((friendlyDropTime-friendlyGrabTime)/1000)+' hold)', (friendlyTeam === 1 ? options.redTextColor.value : blueTextColor));
}
if (((options.onlyShowMyDrops.value && !options.showAllDrops.value) || options.showMyHoldOnTimeline.value) && me.flag && !tagpro.spectator) {
myDropTime = friendlyDropTime;
holdTime = (friendlyGrabTime ? secondsToHMS((friendlyDropTime-friendlyGrabTime)/1000) : '');
if (options.onlyShowMyDrops.value && (mapType === 'CTF')) {
updateEventHistory('<span style="color:'+options.grabColor.value+'">MY DROP: </span>' + (friendlyTeam === 1 ? tagpro.players[redHolder].name : tagpro.players[blueHolder].name) + ' (' + secondsToHMS((Date.now()-friendlyGrabTime)/1000) + ' hold)', (friendlyTeam === 1 ? options.redTextColor.value : blueTextColor));
}
if (options.showTimeline.value && options.showMyHoldOnTimeline.value) {
ljs.push( { name:'', time:friendlyDropTime, type:'DROP', hold:holdTime, self:true } );
updateTimeline(true, ljs.length-1);
}
}
//Kiss...
if ( (Math.abs(friendlyDropTime - enemyDropTime) < kissThreshold) && redHolder && blueHolder && dropperId) {
friendlyHoldTime = (friendlyGrabTime ? secondsToHMS((friendlyDropTime-friendlyGrabTime)/1000) : '');
enemyHoldTime = (enemyGrabTime ? secondsToHMS((enemyDropTime-enemyGrabTime)/1000) : '');
setPreventSnipePopup();
if (tagpro.players[redHolder].hasOwnProperty('kisses')) tagpro.players[redHolder].kisses++;
else tagpro.players[redHolder].kisses = 1;
if (tagpro.players[blueHolder].hasOwnProperty('kisses')) tagpro.players[blueHolder].kisses++;
else tagpro.players[blueHolder].kisses = 1;
if ( ((friendlyTeam === 1) && (friendlyGrabTime > enemyGrabTime)) || ((friendlyTeam === 2) && (enemyGrabTime > friendlyGrabTime)) ) {
kisser = redHolder;
kisserColor = options.redTextColor.value;
kissee = blueHolder;
kisseeColor = options.blueTextColor.value;
} else {
kisser = blueHolder;
kisserColor = options.blueTextColor.value;
kissee = redHolder;
kisseeColor = options.redTextColor.value;
}
//Cap Saving Kiss...
if (options.showCapSavers.value && ((friendlyDropTime - friendlyGrabTime < capSaverThreshold) || (enemyDropTime - enemyGrabTime < capSaverThreshold)) ) {
if (options.showKissPopup.value) {
showPopup(tagpro.players[kisser].name, kisserColor, 'CAP SAVER!', options.kissColor.value, tagpro.players[kissee].name, kisseeColor);
}
if (options.showKisses.value) {
updateEventHistory('CAP SAVER: <span style="color:'+kisserColor+'">' + tagpro.players[kisser].name + '</span><span style="color:'+kisseeColor+'"> (on ' + tagpro.players[kissee].name + ')</span>', options.capSaverColor.value);
}
//Normal Kiss...
} else {
if (options.showKissPopup.value) {
showPopup(tagpro.players[kisser].name, kisserColor, 'Kiss 💋', options.kissColor.value, tagpro.players[kissee].name, kisseeColor);
}
if (options.showKisses.value) {
updateEventHistory('KISS: <span style="color:'+kisserColor+'">' + tagpro.players[kisser].name + '</span><span style="color:white"> + </span><span style="color:'+kisseeColor+'">' + tagpro.players[kissee].name + '</span>', options.kissColor.value);
}
}
if (options.showTimeline.value && options.showKissesOnTimeline.value) {
if (friendlyDropTime - friendlyGrabTime < capSaverThreshold) {
if (friendlyTeam === 1) capSaver = redHolder;
else capSaver = blueHolder;
} else if (enemyDropTime - enemyGrabTime < capSaverThreshold) {
if (friendlyTeam === 1) capSaver = blueHolder;
else capSaver = redHolder;
} else {
capSaver = false;
}
ljs.push( { name:tagpro.players[redHolder].name, time:friendlyDropTime, team:1, type:'K', hold:(friendlyTeam === 1 ? friendlyHoldTime : enemyHoldTime), cs:(redHolder === capSaver ? true : false), self:(redHolder === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
ljs.push( { name:tagpro.players[blueHolder].name, time:friendlyDropTime, team:2, type:'K', hold:(friendlyTeam === 1 ? enemyHoldTime : friendlyHoldTime), cs:(blueHolder === capSaver ? true : false), self:(blueHolder === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
}
//Friendly Flaccid...
} else if ((friendlyDropTime - friendlyGrabTime < flaccidThreshold) && (mapType === 'CTF') && dropperId) {
setPreventSnipePopup();
if (tagpro.players[dropperId].hasOwnProperty('flaccids')) tagpro.players[dropperId].flaccids++;
else tagpro.players[dropperId].flaccids = 1;
if (options.showFlaccidsPopup.value) {
if (friendlyTeam === 1) {
showPopup('', '', 'Flaccid', options.flaccidColor.value, tagpro.players[redHolder].name, options.redTextColor.value);
} else {
showPopup('', '', 'Flaccid', options.flaccidColor.value, tagpro.players[blueHolder].name, options.blueTextColor.value);
}
}
if (options.showFlaccids.value) {
updateEventHistory('<span style="color:'+options.flaccidColor.value+'">FLACCID: </span>' + tagpro.players[dropperId].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
}
if (options.showTimeline.value && options.showFlaccidsOnTimeline.value) {
ljs.push( { name:tagpro.players[dropperId].name, time:friendlyDropTime, team:friendlyTeam, type:'F', self:(dropperId === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
}
//Boost & Drop...
} else if (options.showBoostDropsPopup.value && (speedpadBoost || bombBoost) && (dropperId === tagpro.playerId)) {
setPreventSnipePopup();
showPopup('', '', 'feck', '#DD6600', '', '');
}
setTimeout(whoHasFlags, 50);
//Enemy Drop...
} else if ((data.s === 'drop') && data.v !== void 0) {
enemyDropTime = Date.now();
dropperId = (friendlyTeam === 1 ? blueHolder : redHolder);
holdTime = (enemyGrabTime ? secondsToHMS((enemyDropTime-enemyGrabTime)/1000) : '');
if (options.showAllDrops.value) {
updateEventHistory('<span style="color:'+options.dropColor.value+'">DROP: </span>' + (friendlyTeam === 1 ? tagpro.players[blueHolder].name : tagpro.players[redHolder].name) + ' ('+secondsToHMS((enemyDropTime-enemyGrabTime)/1000)+' hold)', (friendlyTeam === 1 ? options.blueTextColor.value : options.redTextColor.value));
}
//Kiss...
if ( (Math.abs(friendlyDropTime - enemyDropTime) < kissThreshold) && redHolder && blueHolder && dropperId) {
friendlyHoldTime = (friendlyGrabTime ? secondsToHMS((friendlyDropTime-friendlyGrabTime)/1000) : '');
enemyHoldTime = (enemyGrabTime ? secondsToHMS((enemyDropTime-enemyGrabTime)/1000) : '');
setPreventSnipePopup();
if (tagpro.players[redHolder].hasOwnProperty('kisses')) tagpro.players[redHolder].kisses++;
else tagpro.players[redHolder].kisses = 1;
if (tagpro.players[blueHolder].hasOwnProperty('kisses')) tagpro.players[blueHolder].kisses++;
else tagpro.players[blueHolder].kisses = 1;
if ( ((friendlyTeam === 1) && (friendlyGrabTime > enemyGrabTime)) || ((friendlyTeam === 2) && (enemyGrabTime > friendlyGrabTime)) ) {
kisser = redHolder;
kisserColor = options.redTextColor.value;
kissee = blueHolder;
kisseeColor = options.blueTextColor.value;
} else {
kisser = blueHolder;
kisserColor = options.blueTextColor.value;
kissee = redHolder;
kisseeColor = options.redTextColor.value;
}
//Cap Saving Kiss...
if (options.showCapSavers.value && ((friendlyDropTime - friendlyGrabTime < capSaverThreshold) || (enemyDropTime - enemyGrabTime < capSaverThreshold)) ) {
if (options.showKissPopup.value) {
showPopup(tagpro.players[kisser].name, kisserColor, 'CAP SAVER!', options.kissColor.value, tagpro.players[kissee].name, kisseeColor);
}
if (options.showKisses.value) {
updateEventHistory('CAP SAVER: <span style="color:'+kisserColor+'">' + tagpro.players[kisser].name + '</span><span style="color:'+kisseeColor+'"> (on ' + tagpro.players[kissee].name + ')</span>', options.capSaverColor.value);
}
//Normal Kiss...
} else {
if (options.showKissPopup.value) {
showPopup(tagpro.players[kisser].name, kisserColor, 'Kiss 💋', options.kissColor.value, tagpro.players[kissee].name, kisseeColor);
}
if (options.showKisses.value) {
updateEventHistory('KISS: <span style="color:'+kisserColor+'">' + tagpro.players[kisser].name + '</span><span style="color:white"> + </span><span style="color:'+kisseeColor+'">' + tagpro.players[kissee].name + '</span>', options.kissColor.value);
}
}
if (options.showTimeline.value && options.showKissesOnTimeline.value) {
if (friendlyDropTime - friendlyGrabTime < capSaverThreshold) {
if (friendlyTeam === 1) capSaver = redHolder;
else capSaver = blueHolder;
} else if (enemyDropTime - enemyGrabTime < capSaverThreshold) {
if (friendlyTeam === 1) capSaver = blueHolder;
else capSaver = redHolder;
} else {
capSaver = false;
}
ljs.push( { name:tagpro.players[redHolder].name, time:enemyDropTime, team:1, type:'K', hold:(friendlyTeam === 1 ? friendlyHoldTime : enemyHoldTime), cs:(redHolder === capSaver ? true : false), self:(redHolder === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
ljs.push( { name:tagpro.players[blueHolder].name, time:enemyDropTime, team:2, type:'K', hold:(friendlyTeam === 1 ? enemyHoldTime : friendlyHoldTime), cs:(blueHolder === capSaver ? true : false), self:(blueHolder === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
}
//Enemy Flaccid...
} else if ((enemyDropTime - enemyGrabTime < flaccidThreshold) && (mapType === 'CTF') && dropperId) {
setPreventSnipePopup();
if (tagpro.players[dropperId].hasOwnProperty('flaccids')) tagpro.players[dropperId].flaccids++;
else tagpro.players[dropperId].flaccids = 1;
if (options.showFlaccidsPopup.value) {
if (friendlyTeam === 1) {
showPopup('', '', 'Flaccid', options.flaccidColor.value, tagpro.players[blueHolder].name, options.blueTextColor.value);
} else {
showPopup('', '', 'Flaccid', options.flaccidColor.value, tagpro.players[redHolder].name, options.redTextColor.value);
}
}
if (options.showFlaccids.value) {
updateEventHistory('<span style="color:'+options.flaccidColor.value+'">FLACCID: </span>' + tagpro.players[dropperId].name, (friendlyTeam === 1 ? options.blueTextColor.value : options.redTextColor.value));
}
if (options.showTimeline.value && options.showFlaccidsOnTimeline.value) {
ljs.push( { name:tagpro.players[dropperId].name, time:enemyDropTime, team:enemyTeam, type:'F', self:false } );
updateTimeline(true, ljs.length-1);
}
}
if (options.showTimeline.value && options.showMyReturnsOnTimeline.value && (mapType === 'CTF') && !tagpro.spectator) {
var prevReturns = me["s-returns"];
setTimeout(function(id) {
if (prevReturns+1 === me["s-returns"]) {
ljs.push( { name:tagpro.players[id].name, time:enemyDropTime, team:enemyTeam, type:'RETURN', hold:holdTime } );
updateTimeline(true, ljs.length-1);
}
}, grabCheckFlagsDelay, dropperId);
}
setTimeout(whoHasFlags, 50);
//-----------------------------
//CAPS...
//-----------------------------
//Friendly Cap...
} else if (data.s === 'cheering') {
capTime = Date.now();
holdTime = (friendlyGrabTime ? secondsToHMS((capTime-friendlyGrabTime)/1000) : '');
if (friendlyTeam === 1) {
capperId = redHolder;
capperColor = options.redTextColor.value;
} else {
capperId = blueHolder;
capperColor = options.blueTextColor.value;
}
if (capperId) {
if (tagpro.players[capperId].hasOwnProperty('caps')) tagpro.players[capperId].caps++;
else tagpro.players[capperId].caps = tagpro.players[capperId]['s-captures']+1;
if (options.showCapsPopup.value) {
if (tagpro.players[capperId]['s-captures'] === 3) {
showPopup('', '', 'CAPTRICK!', options.capColor.value, tagpro.players[capperId].name, capperColor);
} else if (speedpadBoost) {
showPopup('➸', options.capColor.value, 'BOOST CAP', options.capColor.value, tagpro.players[capperId].name, capperColor);
} else {
showPopup('', '', 'Cap! 😊', options.capColor.value, tagpro.players[capperId].name, capperColor);
}
}
if (options.showCaps.value) {
updateEventHistory('<span style="color:'+options.capColor.value+'">CAP! </span>' + tagpro.players[capperId].name + ' (' + (holdTime ? holdTime+' hold - ' : '') + ordinal_suffix_of(tagpro.players[capperId].caps) + ')', capperColor);
}
if (options.showTimeline.value && options.showCapsOnTimeline.value) {
ljs.push( { name:tagpro.players[capperId].name, time:capTime, team:tagpro.players[capperId].team, type:'C', hold:holdTime, self:(capperId === tagpro.playerId ? true : false) } );
updateTimeline(true, ljs.length-1);
}
}
setTimeout(whoHasFlags, 50);
//Enemy Cap...
} else if (data.s === 'sigh') {
capTime = Date.now();
holdTime = (enemyGrabTime ? secondsToHMS((capTime-enemyGrabTime)/1000) : '');
if (friendlyTeam === 1) {
capperId = blueHolder;
capperColor = options.blueTextColor.value;
} else {
capperId = redHolder;
capperColor = options.redTextColor.value;
}
if (capperId) {
if (tagpro.players[capperId].hasOwnProperty('caps')) tagpro.players[capperId].caps++;
else tagpro.players[capperId].caps = tagpro.players[capperId]['s-captures']+1;
if (options.showCapsPopup.value) {
if (tagpro.players[capperId]['s-captures'] === 3) {
showPopup('', '', 'CAPTRICK!', options.capColor.value, tagpro.players[capperId].name, capperColor);
} else if (speedpadBoost) {
showPopup('➸', options.capColor.value, 'BOOST CAP', options.capColor.value, tagpro.players[capperId].name, capperColor);
} else {
showPopup('', '', 'Cap! 😊', options.capColor.value, tagpro.players[capperId].name, capperColor);
}
}
if (options.showCaps.value) {
updateEventHistory('<span style="color:'+options.capColor.value+'">CAP! </span>' + (tagpro.players[capperId].name) + ' (' + (holdTime ? holdTime+' hold - ' : '') + ordinal_suffix_of(tagpro.players[capperId].caps) + ')', capperColor);
}
if (options.showTimeline.value && options.showCapsOnTimeline.value) {
ljs.push( { name:tagpro.players[capperId].name, time:capTime, team:tagpro.players[capperId].team, type:'C', hold:holdTime, self:false } );
updateTimeline(true, ljs.length-1);
}
}
setTimeout(whoHasFlags, 50);
//Boost...
} else if (data.s === 'burst') {
speedpadBoost = true;
bombBoost = false;
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function() {
speedpadBoost = false;
}, 1200);
//Bomb...
} else if ((data.s === 'explosion') || (data.s === 'dynamite')) {
if (!speedpadBoost) {
bombBoost = true;
clearTimeout(timeoutHandle);
timeoutHandle = setTimeout(function() {
bombBoost = false;
}, 1600);
}
//-----------------------------
//POPS...
//-----------------------------
//TagPro Kill & Snipes...
} else if (data.s === 'pop') {
if (options.showPops.value) updateEventHistory('<i>Pop :(</i>', 'darkgray');
prevTags = me["s-tags"];
var closestEnemy = findClosestEnemy(); //the closest enemy should be the one we just killed
var wasFC = false;
if (closestEnemy) {
wasFC = tagpro.players[closestEnemy].flag;
}
var haveTagPro = me.tagpro;
setTimeout(function(closestEnemy, wasFC, hadTagPro) {
if ((prevTags+1 === me["s-tags"])) {
if (speedpadBoost && (mapType === 'CTF') && (lastSnipe !== closestEnemy)) {
lastSnipe = closestEnemy;
setTimeout(function() { lastSnipe = 0; }, 1000);
counts.boostSnipes++;
if (options.showBoostSnipesPopup.value && !preventSnipePopup) {
showPopup('', '', '⤞ SNIPED', options.boostSnipeColor.value, tagpro.players[closestEnemy].name, (tagpro.players[closestEnemy].team === 1 ? options.redTextColor.value : options.blueTextColor.value)); //➸ ➟ ➔ ⤞
}
if (options.showBoostSnipes.value) {
updateEventHistory('Boost Snipe >> ' + tagpro.players[closestEnemy].name, options.boostSnipeColor.value);
}
if (options.showTimeline.value && options.showBoostSnipesOnTimeline.value && !tagpro.spectator) {
ljs.push( { name:tagpro.players[closestEnemy].name, time:Date.now(), team:me.team, FC:wasFC, type:'⤞' } );
updateTimeline(true, ljs.length-1);
}
} else if (hadTagPro && (lastTPKill != closestEnemy)) {
lastTPKill = closestEnemy;
setTimeout(function() { lastTPKill = 0; }, 1000);
counts.tagProKillCount++;
if (options.showTPKillsPopup.value && !preventSnipePopup) showPopup('🕱', options.tpKillsColor.value, 'TagPro.KILL', options.tpKillsColor.value, tagpro.players[closestEnemy].name + ' ('+ordinal_suffix_of(counts.tagProKillCount)+')', (tagpro.players[closestEnemy].team === 1 ? options.redTextColor.value : options.blueTextColor.value)); //🕱
if (options.showTPKills.value) updateEventHistory('TagPro.KILL\'d: ' + tagpro.players[closestEnemy].name + ' ('+ordinal_suffix_of(counts.tagProKillCount)+')', options.tpKillsColor.value);
if (options.showTimeline.value && options.showTPKillsOnTimeline.value && !tagpro.spectator) {
ljs.push( { name:tagpro.players[closestEnemy].name, time:Date.now(), team:me.team, FC:wasFC, type:'TPK' } );
updateTimeline(true, ljs.length-1);
}
}
}
}, grabCheckFlagsDelay, closestEnemy, wasFC, haveTagPro);
//-----------------------------
//POWERUPS...
//-----------------------------
} else if (data.s === 'powerup') {
if (options.showMyPowerups.value) {
var prevJJ = me.grip;
var prevRB = me.bomb;
var prevTP = me.tagpro;
var pupType = '';
setTimeout(function() {
if (me.grip && !prevJJ) {
pupType = 'Juke Juice';
} else if (me.bomb && !prevRB) {
pupType = 'Rolling Bomb';
} else if (me.tagpro && !prevRB) {
pupType = 'TagPro';
} else {
pupType = 'Unknown';
}
updateEventHistory('<i>Powerup Taken: '+pupType+'</i>', 'darkgray');
}, grabCheckFlagsDelay);
}
if (options.showTimeline.value && options.showMyPUPsOnTimeline.value && !tagpro.spectator) {
ljs.push( { name:'', time:Date.now(), team:0, type:'PUP', self:true } );
updateTimeline(true, ljs.length-1);
}
}
}); //socket.on.sound
if (options.showMultiKills.value || options.showMultiKillPopup.value) { //WARNING: this may slow the game down noticeably!
var lastTagger = {id:0, count:0, lastTagTime:0};
setTimeout(function() {
tagpro.socket.on('p', function(data) {
data = data.u || data;
var now = Date.now();
for (var i=0; i<data.length; i++) {
if (data[i].name === void 0) { //if the frame has a 'name' property we don't care about it
if (data[i]['s-tags'] !== void 0) {
if ((lastTagger.id === data[i].id) && (now - lastTagger.lastTagTime < 10000)) {
lastTagger.count++;
if (lastTagger.count === 1) {
//
} else if (lastTagger.count === 2) {
if (options.showMultiKills.value) updateEventHistory('Double-Kill: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[data[i].id].name + '</span>', options.multiKillColor.value);
if (options.showMultiKillPopup.value && !preventSnipePopup) showPopup('', '', 'Double Kill', options.tpKillsColor.value, tagpro.players[data[i].id].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
} else if (lastTagger.count === 3) {
if (options.showMultiKills.value) updateEventHistory('Triple Kill: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[data[i].id].name + '</span>', options.multiKillColor.value);
if (options.showMultiKillPopup.value && !preventSnipePopup) showPopup('', '', 'Triple Kill', options.tpKillsColor.value, tagpro.players[data[i].id].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
} else if (lastTagger.count === 4) {
if (options.showMultiKills.value) updateEventHistory('Quad Kill: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[data[i].id].name + '</span>', options.multiKillColor.value);
if (options.showMultiKillPopup.value && !preventSnipePopup) showPopup('', '', 'Quad Kill', options.tpKillsColor.value, tagpro.players[data[i].id].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
} else if (lastTagger.count === 5) {
if (options.showMultiKills.value) updateEventHistory('Ultra Kill: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[data[i].id].name + '</span>', options.multiKillColor.value);
if (options.showMultiKillPopup.value && !preventSnipePopup) showPopup('', '', 'Ultra Kill', options.tpKillsColor.value, tagpro.players[data[i].id].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
} else if (lastTagger.count > 5) {
if (options.showMultiKills.value) updateEventHistory('Killing Spree!: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[data[i].id].name + '</span>', options.multiKillColor.value);
if (options.showMultiKillPopup.value && !preventSnipePopup) showPopup('', '', 'Killing<br>Spree!', options.tpKillsColor.value, tagpro.players[data[i].id].name, (friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value));
}
} else {
lastTagger.id = data[i].id;
lastTagger.count = 1;
}
lastTagger.lastTagTime = now;
}
}
}
});
}, 2000);
}
tagpro.socket.on('end', function(data) {
var endTime = Date.now(); //actual end of game time
var fullGameLength = (endTime-startTime)/1000; //how long the whole game lasted (with or without us)
var playedGameLength = (endTime-joinTime)/1000; //how long we played for
var serverName = '';
var maxKisses = 0;
var maxKissers = [];
var maxFlaccids = 0;
var maxFlacciders = [];
var capTrickMessage = '';
GM_deleteValue('lastGameLog');
GM_deleteValue('ljs');
if (!options.showEventsWindow.value && options.showEventsWindowEOG.value) {
$('#KFC_EventHistory').fadeIn(200);
}
for (var playerId in tagpro.players) {
//Kisses - Totals & Maxs...
if (tagpro.players[playerId].hasOwnProperty('kisses')) {
if (tagpro.players[playerId].team === 1) {
counts.kisses.red += tagpro.players[playerId].kisses;
} else {
counts.kisses.blue += tagpro.players[playerId].kisses;
}
if (tagpro.players[playerId].kisses > maxKisses) {
maxKisses = tagpro.players[playerId].kisses;
maxKissers.length = 0;
maxKissers.push(playerId);
} else if (tagpro.players[playerId].kisses === maxKisses) {
maxKissers.push(playerId);
}
} else {
tagpro.players[playerId].kisses = 0;
}
//Flaccids - Totals & Maxs...
if (tagpro.players[playerId].hasOwnProperty('flaccids')) {
if (tagpro.players[playerId].team === 1) {
counts.flaccids.red += tagpro.players[playerId].flaccids;
} else {
counts.flaccids.blue += tagpro.players[playerId].flaccids;
}
if (tagpro.players[playerId].flaccids > maxFlaccids) {
maxFlaccids = tagpro.players[playerId].flaccids;
maxFlacciders.length = 0;
maxFlacciders.push(playerId);
} else if (tagpro.players[playerId].flaccids === maxFlaccids) {
maxFlacciders.push(playerId);
}
} else {
tagpro.players[playerId].flaccids = 0;
}
//Look for Cap-Tricks...
if (tagpro.players[playerId]['s-captures'] >= 3) capTrickMessage = 'CapTrick ('+tagpro.players[playerId]['s-captures']+' caps!) by ' + tagpro.players[playerId].name;
}
var worstFlacciders = '';
$.each(maxFlacciders, function(index, playerId) {
worstFlacciders += '<div style="color:'+(tagpro.players[playerId].team === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">' + tagpro.players[playerId].name + ' ('+tagpro.players[playerId].flaccids+')</div>';
});
if (options.showTimeline.value) updateScoreLabels();
setTimeout(function() {
var eogScore = tagpro.score.r + ':' + tagpro.score.b;
var result = '', resultText = '';
if (data.winner === 'tie') {
result = 'Tie';
resultText = 'Tie!' + (tagpro.players[tagpro.playerId].team === 1 ? ' We were on Red' : ' We were on Blue');
} else if ((data.winner === 'red') && (tagpro.players[tagpro.playerId].team === 1)) {
result = 'Win';
resultText = 'We (Red) Won!';
} else if ((data.winner === 'red') && (tagpro.players[tagpro.playerId].team === 2)) {
result = 'Loss';
resultText = 'We (Blue) Lost';
} else if ((data.winner === 'blue') && (tagpro.players[tagpro.playerId].team === 1)) {
result = 'Loss';
resultText = 'We (Red) Lost';
} else if ((data.winner === 'blue') && (tagpro.players[tagpro.playerId].team === 2)) {
result = 'Win';
resultText = 'We (Blue) Won!';
}
updateEventHistory('<div style="border-top:1px solid white; margin-top:5px"></div>');
updateEventHistory('<div style="text-align:center">End of Game. Score ' + eogScore + ' - ' + resultText + '</div>');
if (tagpro.spectator) {
updateEventHistory('<div style="text-align:center">We were watching: <span style="color:'+(friendlyTeam === 1 ? options.redTextColor.value : options.blueTextColor.value)+'">'+tagpro.players[tagpro.playerId].name+'</span></div>');
}
if (mapType === 'CTF') {
updateEventHistory('<div style="text-align:center"><span style="color:'+options.kissColor.value+'">My Kisses: ' + tagpro.players[tagpro.playerId].kisses + '</span> | <span style="color:'+options.flaccidColor.value+'">My Flaccids:' + tagpro.players[tagpro.playerId].flaccids + '</span></div>');
}
updateEventHistory('<div style="text-align:center"><span style="color:'+options.boostSnipeColor.value+'">My Boost Snipes: ' + counts.boostSnipes + '</span> | <span style="color:'+options.tpKillsColor.value+'">My TagPro Kills: ' + counts.tagProKillCount + '</span></div>');
if (capTrickMessage) updateEventHistory('<div style="text-align:center; background:#0c0; color:white">' + capTrickMessage + '</div>');
if (mapType === 'CTF') {
if (maxFlacciders.length) {
updateEventHistory('<div style="text-align:center; text-decoration:underline; margin-top:3px">Most Flaccids...</div>');
updateEventHistory('<div style="text-align:center">' + worstFlacciders + '</div>');
}
}
updateEventHistory('<div style="border-bottom:1px solid white"></div>');
if (tagpro.serverHost.indexOf('tagpro-') === 0) {
serverName = capitaliseFirstLetter(tagpro.serverHost.replace('tagpro-', '').replace('.koalabeast.com', ''));
}
ljs.push( { name:resultText+' ('+eogScore+')', time:Date.now(), team:(data.winner === 'tie' ? 0 : (data.winner === 'red' ? 1 : 2)), type:'EOG' } );
GM_setValue('ljs', {data: ljs,
startTime: startTime,
joinTime: joinTime,
fullTime: fullTime,
played: new Date(joinTime).toISOString(),
timePlayed: playedGameLength,
fullGameLength: fullGameLength,
serverName: serverName,
result: result,
redScore: tagpro.score.r,
blueScore: tagpro.score.b,
team: tagpro.players[tagpro.playerId].team,
mapName: mapName,
mapAuthor: mapAuthor,
mapType: mapType,
spectator:(tagpro.spectator ? true : false)
}
);
if (options.showTimeline.value) setTimeout(updateTimeline(true), 500);
}, 300);
}); //socket.on.end
} //if ingame
}); //tagpro.ready
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment