Last active
February 20, 2025 02:48
-
-
Save nabbynz/4a231295bef494d4c5de3637fb8c41f5 to your computer and use it in GitHub Desktop.
Alternative Pizza Respawn Warnings
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 Alternative Pizza Respawn Warnings | |
// @description An alternative to the default Pizza Tile Respawn Warnings | |
// @version 2.1.0 | |
// @match *://*.koalabeast.com/game | |
// @match *://*.koalabeast.com/game?* | |
// @updateURL https://gist.github.com/nabbynz/4a231295bef494d4c5de3637fb8c41f5/raw/Alternative_Pizza_Respawn_Warnings.user.js | |
// @downloadURL https://gist.github.com/nabbynz/4a231295bef494d4c5de3637fb8c41f5/raw/Alternative_Pizza_Respawn_Warnings.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 */ | |
// use false or '' to not apply that style. | |
// use 'auto' for text_color to match the texture pack color. | |
const tilesToRedraw = { | |
'5.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // neutral boosts | |
'14.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // red boosts | |
'15.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // blue boosts | |
'6.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // juke juice | |
'6.2': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // rolling bomb | |
'6.3': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // tagpro | |
'6.4': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // max speed | |
'10.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // bombs | |
'13.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // neutral portals | |
'24.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // red portals | |
'25.1': { circle_stroke_color: '#555555', circle_fill_color: '#111111', text_color: 'auto', text_background_color: '#000000', text_background_opacity: 0.8 }, // blue portals | |
}; | |
tagpro.ready(function() { | |
let redrawBaseDynamicTiles = function() { | |
const height = Object.keys(tilesToRedraw).length * 40; | |
const canvas = createCanvas(480, height); | |
const ctx = canvas.getContext('2d'); | |
const start = 1.5 * Math.PI; | |
const portion = 2 * Math.PI / 12; | |
let y = 0; | |
for (let tileId in tilesToRedraw) { | |
for (let i = 1; i <= 12; i++) { | |
const suffix = tileId.slice(-1) * 100 + i; | |
const fullTileId = Math.floor(tileId) + '.' + suffix; | |
const x = (i - 1) * 40; | |
ctx.save(); | |
if (tilesToRedraw[tileId].circle_fill_color) { | |
ctx.fillStyle = tilesToRedraw[tileId].circle_fill_color; | |
ctx.beginPath(); | |
ctx.arc(x + 20, y + 20, 15, 0, Math.PI * 2); | |
ctx.fill(); | |
} | |
if (tilesToRedraw[tileId].circle_stroke_color) { | |
ctx.strokeStyle = tilesToRedraw[tileId].circle_stroke_color; | |
ctx.lineWidth = 2; | |
ctx.setLineDash([4, 4]); | |
ctx.beginPath(); | |
ctx.arc(x + 20, y + 20, 15.5, 0, Math.PI * 2); | |
ctx.stroke(); | |
ctx.closePath(); | |
ctx.setLineDash([]); | |
} | |
if (tilesToRedraw[tileId].text_color) { // draw 5, 4, 3, 2, 1 text | |
const secondsLeft = Math.floor((14 - i) / 2); | |
ctx.drawImage(PIXI.utils.TextureCache[fullTileId].baseTexture.resource.source, PIXI.utils.TextureCache[fullTileId].orig.x, PIXI.utils.TextureCache[fullTileId].orig.y, PIXI.utils.TextureCache[fullTileId].orig.width, PIXI.utils.TextureCache[fullTileId].orig.height, x, y, 40, 40); | |
if (tilesToRedraw[tileId].text_background_color && tilesToRedraw[tileId].text_background_opacity > 0) { | |
ctx.fillStyle = tilesToRedraw[tileId].text_background_color; | |
ctx.globalAlpha = tilesToRedraw[tileId].text_background_opacity; | |
ctx.beginPath(); | |
ctx.arc(x + 20, y + 20, 10, 0, Math.PI * 2); | |
ctx.fill(); | |
} | |
if (i > 2) { // skips the first 500ms | |
ctx.fillStyle = tilesToRedraw[tileId].text_color === 'auto' ? (tilesToRedraw[tileId].average_color ? tilesToRedraw[tileId].average_color : '#cccccc') : tilesToRedraw[tileId].text_color; | |
ctx.globalAlpha = 1; | |
ctx.font = 'bold 21px monospace'; | |
ctx.textAlign = 'center'; | |
ctx.fillText(secondsLeft, x + 20, y + 27); | |
} | |
} else { // draw pizza segments... | |
ctx.beginPath(); | |
ctx.moveTo(x + 20, y + 20); | |
ctx.arc(x + 20, y + 20, 15, start, start + i * portion); | |
ctx.lineTo(x + 20, y + 20); | |
ctx.clip(); | |
ctx.drawImage(PIXI.utils.TextureCache[fullTileId].baseTexture.resource.source, PIXI.utils.TextureCache[fullTileId].orig.x, PIXI.utils.TextureCache[fullTileId].orig.y, PIXI.utils.TextureCache[fullTileId].orig.width, PIXI.utils.TextureCache[fullTileId].orig.height, x, y, 40, 40); | |
} | |
ctx.restore(); | |
delete tagpro.tiles[fullTileId].slices; // prevents the default pizzas | |
} | |
y += 40; | |
} | |
let baseTexture = PIXI.Texture.from(canvas); | |
y = 0; | |
for (let tileId in tilesToRedraw) { | |
for (let i = 1; i <= 12; i++) { | |
const suffix = tileId.slice(-1) * 100 + i; | |
const fullTileId = Math.floor(tileId) + '.' + suffix; | |
const x = (i - 1) * 40; | |
let texture = new PIXI.Texture(baseTexture, new PIXI.Rectangle(x, y, 40, 40)); | |
texture.isAPRW = true; | |
if (PIXI.utils.TextureCache[fullTileId]) { | |
PIXI.Texture.removeFromCache(fullTileId); | |
} | |
PIXI.Texture.addToCache(texture, fullTileId); | |
} | |
y += 40; | |
} | |
}; | |
let getTexturePackAverageColors = function() { | |
for (let tileId in tilesToRedraw) { | |
let textureCacheId = tileId; | |
if (tileId === '5.1' || tileId === '14.1' || tileId === '15.1' || tileId === '13.1' || tileId === '24.1' || tileId === '25.1') { | |
textureCacheId += '01'; | |
} else if (tileId === '10.1') { | |
textureCacheId = '10'; | |
} | |
if (textureCacheId) { | |
const tile = PIXI.utils.TextureCache[textureCacheId]; | |
if (tile) { | |
const canvas = tile.baseTexture.resource.source; | |
if (canvas && (canvas instanceof HTMLCanvasElement || canvas instanceof OffscreenCanvas)) { | |
let ctx = canvas.getContext('2d', { willReadFrequently: true }); | |
let pixelData = ctx.getImageData(tile.frame.x, tile.frame.y, tile.frame.width, tile.frame.height).data; | |
tilesToRedraw[tileId].average_color = getAverageColor(pixelData, true, true, 1); | |
} | |
} | |
} | |
} | |
}; | |
setTimeout(() => { // <--- need a trigger here when ??? is ready | |
let doGetTexturePackAverageColors = false; | |
for (let tileId in tilesToRedraw) { | |
if (tilesToRedraw[tileId].text_color === 'auto') { | |
doGetTexturePackAverageColors = true; | |
break; | |
} | |
} | |
let start = function() { | |
document.removeEventListener('visibilitychange', start); | |
if (tagpro.isPTM === 'loading') { // need to wait for "Preset Texture Mods" to finish (if installed) | |
setTimeout(start, 100); | |
return; | |
} | |
if (doGetTexturePackAverageColors) { | |
getTexturePackAverageColors(); | |
} | |
redrawBaseDynamicTiles(); | |
}; | |
if (document.visibilityState === 'hidden') { | |
document.addEventListener('visibilitychange', start); | |
} else { | |
start(); | |
} | |
}, 1000); | |
}); // tagpro.ready() | |
function createCanvas(width, height, forceDOM = false) { | |
if (!forceDOM && typeof OffscreenCanvas !== 'undefined') { | |
return new OffscreenCanvas(width, height); // An 'OffscreenCanvas' is smaller and faster than a normal canvas. | |
} else { | |
let canvas = document.createElement('canvas'); | |
canvas.width = width; | |
canvas.height = height; | |
return canvas; | |
} | |
} | |
function getAverageColor(data, asHex = false, ignoreGrey = false, pixelInterval = 1) { | |
let rgb = { r: null, g: null, b: null }; | |
let count = 0; | |
let i = -4; | |
while ((i += pixelInterval * 4) < data.length) { | |
// const luminance = data[i] * 0.299 + data[i + 1] * 0.587 + data[i + 2] * 0.114; // perceptive luminance (/ 255) | |
const isGrey = ignoreGrey && (Math.abs(data[i] - data[i + 1]) + Math.abs(data[i + 1] - data[i + 2]) < 30); | |
if (!isGrey && data[i + 3]) { | |
rgb.r += data[i]; | |
rgb.g += data[i + 1]; | |
rgb.b += data[i + 2]; | |
count++; | |
} | |
} | |
if (count === 0) { // transparent or all grey | |
return null; | |
} | |
rgb.r = Math.floor(rgb.r / count); | |
rgb.g = Math.floor(rgb.g / count); | |
rgb.b = Math.floor(rgb.b / count); | |
if (asHex) { | |
return '#' + tagpro.renderer.rgbToHex(rgb.r, rgb.g, rgb.b).slice(2); | |
} else { | |
return rgb; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment