Last active
February 20, 2025 03:02
-
-
Save nabbynz/51b83e03714d710fa6e3b18e97332198 to your computer and use it in GitHub Desktop.
Show Powerup Time Remaining
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Show Powerup Time Remaining | |
// @description Shows the remaining active Powerup time. Plus a Tag count for the TagPro PUP. | |
// @version 0.5.0 | |
// @match *://*.koalabeast.com/game | |
// @match *://*.koalabeast.com/game?* | |
// @updateURL https://gist.github.com/nabbynz/51b83e03714d710fa6e3b18e97332198/raw/Show_Powerup_Time_Remaining.user.js | |
// @downloadURL https://gist.github.com/nabbynz/51b83e03714d710fa6e3b18e97332198/raw/Show_Powerup_Time_Remaining.user.js | |
// @grant none | |
// @author nabby | |
// ==/UserScript== | |
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')'); | |
'use strict'; | |
/* eslint-env jquery */ | |
/* globals tagpro, tagproConfig, PIXI */ | |
/* eslint-disable no-multi-spaces */ | |
let replayStarted = null; | |
tagpro.ready(() => { | |
let tr = tagpro.renderer; | |
if (tagproConfig.replay && tagpro.replayData && tagpro.replayData.packets[0][1] === 'recorder-metadata') { | |
replayStarted = tagpro.replayData.packets[0][2].started; | |
} | |
tr.updateJukeJuice = function(player) { | |
if (!player.sprites.jukeJuice) { | |
player.sprites.jukeJuice = tagpro.tiles.draw(player.sprites.ball, "jukeJuice", {x: 0, y: 23}, 17, 17); | |
} | |
if (!player.jukeJuice) { | |
player.sprites.jukeJuice.visible = false; | |
if (player.sprites.timerJJ) { | |
player.sprites.timerJJ.visible = false; | |
} | |
} else { | |
player.sprites.jukeJuice.visible = true; | |
addPUPTimer(player, 'jukeJuice', 'timerJJ', 'JJ:', '#00ffff'); | |
} | |
}; | |
tr.updateTagpro = function(player) { | |
if (!player.sprites.tagproTint) { | |
player.sprites.tagproTint = new PIXI.Graphics; | |
if (tagpro.events.fillTagproEffect) { | |
tagpro.events.fillTagproEffect[0].fillTagproEffect(player.sprites.tagproTint); | |
} else { | |
//player.sprites.tagproTint.beginFill(0x00FF00, 0.25).lineStyle(2, 0x00FF00).drawCircle(20, 20, 20); // default | |
player.sprites.tagproTint.lineStyle(2, 0x00FF20).beginFill(0x00FF20, 0.1).drawCircle(20, 20, 19); // color; lower fill opacity; 19px radius | |
} | |
player.sprites.tagproTint.alpha = 0.8; // lowers the opacity a bit | |
player.sprites.tagproTint.anchor = { x: 0.5, y: 0.5 }; | |
player.sprites.ball.addChild(player.sprites.tagproTint); | |
} | |
if (!player.tagpro) { | |
player.sprites.tagproTint.visible = false; | |
if (player.sprites.timerTP) { | |
player.sprites.timerTP.visible = false; | |
} | |
} else { | |
player.sprites.tagproTint.visible = true; | |
addPUPTimer(player, 'tagpro', 'timerTP', 'TP:', '#00ff60'); | |
} | |
if (!tr.options.disableParticles) { | |
if (player.tagpro && !player.sprites.tagproSparks) { | |
player.sprites.tagproSparks = tr.makeParticleEmitter(player.sprites.ball, [tr.particleFireTexture], tagpro.particleDefinitions.tagproSparks); | |
player.sprites.tagproSparks.player = player.id; | |
tr.emitters.push(player.sprites.tagproSparks); | |
} else if (!player.tagpro && player.sprites.tagproSparks) { | |
player.sprites.tagproSparks.emit = false; | |
tr.emitters.splice(tr.emitters.indexOf(player.sprites.tagproSparks), 1); | |
player.sprites.tagproSparks.destroy(); | |
player.sprites.tagproSparks.cleanup(); | |
player.sprites.tagproSparks = null; | |
} | |
} | |
}; | |
const rollingBombStarPath = drawStarPath(0, 0, 4, 14, 4, 0); | |
tr.updateRollingBomb = function(player) { | |
if (!player.sprites.bomb) { | |
player.sprites.bomb = new PIXI.Graphics; | |
if (tagpro.events.fillRollingBombEffect) { | |
tagpro.events.fillRollingBombEffect[0].fillRollingBombEffect(player.sprites.bomb); | |
} else { | |
//player.sprites.bomb.beginFill(0xFFFF00, 0.75).drawCircle(20, 20, 19); // default | |
player.sprites.bomb.lineStyle(2, 0xffff00, 1).drawCircle(0, 0, 14).lineStyle(1, 0xffff00, 0.8).drawCircle(0, 0, 17).beginFill(0xff8800, 1).lineStyle(1, 0x000000, 0.6).drawPolygon(rollingBombStarPath); // orange star | |
} | |
player.sprites.bomb.position.set(20, 20); | |
player.sprites.ball.addChild(player.sprites.bomb); | |
} | |
if (player.bomb) { | |
player.sprites.bomb.visible = true; | |
addPUPTimer(player, 'bomb', 'timerRB', 'TP:', '#eeaa00'); | |
} else { | |
player.sprites.bomb.visible = false; | |
if (player.sprites.timerRB) { | |
player.sprites.timerRB.visible = false; | |
} | |
} | |
if (!tr.options.disableParticles) { | |
if (player.bomb && !player.sprites.rollingBomb) { | |
player.sprites.rollingBomb = tr.makeParticleEmitter(player.sprites.ball, [tr.particleTexture], tagpro.particleDefinitions.rollingBomb); | |
tr.emitters.push(player.sprites.rollingBomb); | |
} else if (!player.bomb && player.sprites.rollingBomb) { | |
player.sprites.rollingBomb.emit = false; | |
tr.emitters.splice(tr.emitters.indexOf(player.sprites.rollingBomb), 1); | |
player.sprites.rollingBomb.destroy(); | |
player.sprites.rollingBomb = null; | |
} | |
} | |
}; | |
tr.updateRollingBombAlpha = function(player) { | |
if (player.bomb && player.sprites.bomb) { | |
player.sprites.bomb.alpha = Math.abs(1.0 * Math.sin(performance.now() / 80)); // brighter and faster flashing | |
} | |
}; | |
}); | |
let pupTimerText = function (text, color) { | |
return new PIXI.Text(text, { | |
fontFamily: 'Arial', | |
fontSize: '11px', | |
fontWeight: 'bold', | |
fill: color || '#FFFFFF', | |
stroke: '#000000', | |
strokeThickness: 2, | |
lineJoin: 'round', | |
dropShadow: true, | |
dropShadowColor: '#000000', | |
dropShadowAngle: 0, | |
dropShadowDistance: 0, | |
dropShadowBlur: 2, | |
dropShadowAlpha: 0.8, | |
}); | |
}; | |
let updatePUPTimers = function(player) { | |
if ((player.jukeJuice || player.tagpro || player.bomb) && tagpro.state !== 2) { // && now - player.sprites?.timersLastUpdate >= 100 * tagpro.replaySpeed | |
let now = replayStarted ? replayStarted + tagpro.replayPlayer.player.currentTime * tagpro.replaySpeed : Date.now(); | |
let posY = 6; | |
if (player.jukeJuice && player.sprites && player.sprites.timerJJ) { | |
if (tagpro.state === 5 && player.jukeJuice > 1 && player.flag && !player.prevFlag) { // player had a JJ, then grabbed flag in OT so reset timer now (server doesn't send update until current JJ expires?) | |
player.sprites.timerJJ.takenAt = now - 20; // allow an extra ~tick | |
} | |
const secondsLeft = 20 - (now - player.sprites.timerJJ.takenAt) / 1000; | |
player.sprites.timerJJ.text = secondsLeft >= 0 && secondsLeft <= 20 ? 'JJ:' + secondsLeft.toFixed(1) : ''; | |
player.sprites.timerJJ.x = player.sprites.name.x + 14; | |
player.sprites.timerJJ.y = posY; | |
posY += 11; | |
player.prevFlag = player.flag; | |
} | |
if (player.tagpro && player.sprites && player.sprites.timerTP) { | |
const secondsLeft = 20 - (now - player.sprites.timerTP.takenAt) / 1000; | |
player.sprites.timerTP.text = secondsLeft >= 0 && secondsLeft <= 20 ? 'TP:' + secondsLeft.toFixed(1) + ' [' + (player['s-tags'] - player.sprites.timerTP.tagCount) + ']' : ''; // this will include gate kills | |
player.sprites.timerTP.x = player.sprites.name.x + 14; | |
player.sprites.timerTP.y = posY; | |
posY += 11; | |
} | |
if (player.bomb && player.sprites && player.sprites.timerRB) { | |
const secondsLeft = 20 - (now - player.sprites.timerRB.takenAt) / 1000; | |
player.sprites.timerRB.text = secondsLeft >= 0 && secondsLeft <= 20 ? 'RB:' + secondsLeft.toFixed(1) : ''; | |
player.sprites.timerRB.x = player.sprites.name.x + 14; | |
player.sprites.timerRB.y = posY; | |
} | |
player.rafId = requestAnimationFrame(() => { | |
updatePUPTimers(player); | |
}); | |
} | |
}; | |
let addPUPTimer = function(player, pupType, timerType, prefix, color = '#dddddd') { | |
const takenAt = replayStarted ? player[pupType] > 1 ? player[pupType] + 20000 : replayStarted + tagpro.replayPlayer.player.currentTime * tagpro.replaySpeed : Date.now(); | |
if (!player.sprites[timerType]) { | |
player.sprites[timerType] = pupTimerText(prefix + '20.0', color); | |
player.sprites[timerType].x = player.sprites.name.x + 14; | |
player.sprites[timerType].y = 6; | |
player.sprites.info.addChild(player.sprites[timerType]); | |
player.sprites[timerType].visible = false; | |
} | |
if (tagpro.state === 5 && player.jukeJuice === true && player.sprites.timerJJ.visible && pupType === 'jukeJuice') { // don't reset timer if OT grab with JJ (handled in updatePUPTimers) | |
return; | |
} | |
player.sprites[timerType].takenAt = takenAt; | |
player.sprites[timerType].visible = true; | |
player.sprites[timerType].tagCount = player['s-tags']; // only for tagpro | |
if (player.rafId) { | |
cancelAnimationFrame(player.rafId); | |
} | |
updatePUPTimers(player); | |
}; | |
function drawStarPath(x, y, points, radius, innerRadius, rotation) { | |
if (rotation === void 0) { rotation = 0; } | |
innerRadius = innerRadius || radius / 2; | |
var startAngle = (-1 * Math.PI / 2) + rotation; | |
var len = points * 2; | |
var delta = (Math.PI * 2) / len; | |
var polygon = []; | |
for (var i = 0; i < len; i++) { | |
var r = i % 2 ? innerRadius : radius; | |
var angle = (i * delta) + startAngle; | |
polygon.push(x + (r * Math.cos(angle)), y + (r * Math.sin(angle))); | |
} | |
return polygon; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment