Skip to content

Instantly share code, notes, and snippets.

@nabbynz
Last active June 13, 2017 01:43
Show Gist options
  • Save nabbynz/01c918c3b0ea42cb28e6b388cb8b5e5d to your computer and use it in GitHub Desktop.
Save nabbynz/01c918c3b0ea42cb28e6b388cb8b5e5d to your computer and use it in GitHub Desktop.
TagPro Texture Page Enhancer MAX
// ==UserScript==
// @name TagPro Texture Page Enhancer MAX
// @description Adds options for: previews, saving custom packs, ball transparency, game backgrounds, ball glow, floor tiles, grids & more.
// @version 0.4.6
//
// NOTE: This script includes the following scripts (or parts of)...
// - "Texture Pack Previewer"
// - "Floor Tiles"
// - "TagPro Tile Pattern" by snaps
// - "Scoreboard Position Labels" by Rattpack (optional)
// You will need to disable any other version of these scripts if you're already using them!
//
// @include http://tagpro-*.koalabeast.com/textures/
// @include http://tagpro-*.koalabeast.com:*
// @include http://*.newcompte.fr:*
// @updateURL https://gist.github.com/nabbynz/01c918c3b0ea42cb28e6b388cb8b5e5d/raw/TagPro_Texture_Page_Enhancer_MAX.user.js
// @downloadURL https://gist.github.com/nabbynz/01c918c3b0ea42cb28e6b388cb8b5e5d/raw/TagPro_Texture_Page_Enhancer_MAX.user.js
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_deleteValue
// @grant GM_addStyle
// @author nabby (also uses code by snaps, Rattpack & ballparts)
// ==/UserScript==
console.log('START: ' + GM_info.script.name + ' (v' + GM_info.script.version + ' by ' + GM_info.script.author + ')');
var defaultOptions = {
gameoptions: {
ball_transparency: '0',
fading_splats: false,
transparent_background: false,
filters_brightness: false,
filters_brightness_value: 75,
},
ballglow: {
modify: false,
red_color: '#FF0000',
red_opacity: '60',
blue_color: '#2591FF',
blue_opacity: '70',
},
sbpl: {
modify: false,
x: '18',
y: '18',
color: '#ffd700',
opacity: '60',
},
gamewallpaper: {
type: 'none',
imagedata: '',
stretch: true,
gradient_type: 'circle',
gradient_preset: 'blue',
color: '#000040',
color1: '#222222',
color2: '#090909',
},
altSpawnShadow: {
modify: false,
red_color: '#ff4040',
blue_color: '#5555ff',
},
modify_TP: {
modify: false,
line_color: '#00FF00',
line_opacity: '100',
line_width: '2',
line_radius: '19',
fill_color: '#00FF00',
fill_opacity: '15',
},
modify_RB: {
modify: false,
line_color: '#FFFF00',
line_opacity: '0',
line_width: '0',
line_radius: '19',
fill_color: '#FFFF00',
fill_opacity: '75',
speed: '150'
},
modify_JJ: {
modify: false,
line_color: '#235957',
fill_color: '#40A8A5',
x: '8',
y: '32',
radius: '5',
},
textures: {
tiles: '',
speedpad: '',
speedpadRed: '',
speedpadBlue: '',
portal: '',
splats: '',
gravityWell: '',
},
floortiles: {
modify: false,
plain: false,
tint_color: '#000000',
tint_opacity: '50',
transparency: '0',
margin: '0',
specks: false,
specks_color: '#FFFFFF',
specks_length: '1',
specks_width: '1',
specks_angle: '45',
specks_count: '50',
specks_opacity: '25',
checkered: false,
checkered_random: false,
checkered_altTintColor: '#000000',
checkered_altTintOpacity: '5',
grids_square: false,
grids_square_size: '40',
grids_square_color: '#777777',
grids_square_linewidth: '1',
grids_square_opacity: '50',
grids_square_dashed: false,
grids_diagonal: false,
grids_diagonal_size: '40',
grids_diagonal_color: '#777777',
grids_diagonal_opacity: '50',
grids_diagonal_dashed: false,
},
shapes: {
centerline: false,
centerline_color: '#00FF00',
centerline_width: '2',
centerline_dashsize: '5',
centerline_opacity: '100',
circle: false,
circle_red_color: '#FF4040',
circle_blue_color: '#5555FF',
circle_yellow_color: '#FFFF80',
circle_width: '10',
circle_radius: '95',
circle_opacity: '80',
octagon: false,
octagon_red_color: '#FF4040',
octagon_blue_color: '#5555FF',
octagon_yellow_color: '#FFFF80',
octagon_width: '6',
octagon_radius: '80',
octagon_opacity: '80',
octagon_sides: '8',
octagon_fillopacity: '0',
cross: false,
cross_red_color: '#FF4040',
cross_blue_color: '#5555FF',
cross_yellow_color: '#FFFF80',
cross_width: '5',
cross_radius_inner: '35',
cross_radius_outer: '140',
cross_opacity: '80',
baseradius: false,
baseradius_red_color: '#FF4040',
baseradius_blue_color: '#5555FF',
baseradius_opacity: '80',
baseradius_width: '4',
baseradius_dashsize: '40',
basefill: false,
basefill_red_color: '#FF4040',
basefill_blue_color: '#5555FF',
basefill_opacity: '5',
},
walls: {
modify: false,
color: '#00FFFF',
opacity: '40',
},
spikes: {
modify: false,
color: '#FF8877',
opacity: '60',
floortint: false,
floortint_color: '#cccccc',
floortint_stroke: true,
floortint_opacity: '40',
floortint_rounded: '3',
floortint_margin: '2',
floortint_dash: '0',
floortint_fill: false,
floortint_fillopacity: '12',
},
bombs: {
modify: false,
color: '#BB00BB',
opacity: '60',
floortint: false,
floortint_color: '#BB00BB',
floortint_stroke: true,
floortint_opacity: '25',
floortint_margin: '1',
floortint_dash: '0',
floortint_fill: false,
floortint_fillopacity: '12',
},
redball: {
modify: false,
color: '#FF0000',
size:'19',
opacity:'100',
gradient: false,
gradient_color: '#000000',
gradient_start: '5',
gradient_stop: '25',
gradient_position: '20',
border_width: '0',
border_segments: '0',
shapes_arc: false,
shapes_arc_width: '2',
shapes_arc_position: '14',
shapes_arc_size: '4',
shapes_star: false,
shapes_star_width: '2',
shapes_star_spikes: '4',
shapes_star_inner: '5',
shapes_star_outer: '12',
shapes_overlay: false,
shapes_overlay_transparency: '20',
},
blueball: {
modify: false,
color: '#0080FF',
size:'19',
opacity:'100',
gradient: false,
gradient_color: '#000000',
gradient_start: '5',
gradient_stop: '25',
gradient_position: '20',
border_width: '0',
border_segments: '0',
shapes_arc: false,
shapes_arc_width: '2',
shapes_arc_position: '14',
shapes_arc_size: '4',
shapes_star: false,
shapes_star_width: '2',
shapes_star_spikes: '4',
shapes_star_inner: '5',
shapes_star_outer: '12',
shapes_overlay: false,
shapes_overlay_transparency: '20',
}
};
var options = $.extend(true, {}, defaultOptions, GM_getValue('options', defaultOptions));
var TINT_COLOR = options.floortiles.tint_color;
var OPACITY = options.floortiles.tint_opacity / 100;
var baseTintColor = '';
var doBaseFill = false;
var doBaseRadius = false;
var doBaseCircle = false;
var doSpikeTileFill = false;
var doBombTileFill = false;
var baseCircle = {};
var doTintWall = false;
var flagRadius = null;
var evenTile = false;
var evenX = false;
var evenY = false;
var redTint = '#FF4040';
var blueTint = '#5555FF';
var yellowTint = '#FFFF80';
var centerLineTint = '';
var flagLocs = { red:{x:null, y:null}, blue:{x:null, y:null}, yellow:{x:null, y:null}, ezred:{x:null, y:null}, ezblue:{x:null, y:null} };
var halfwayX, halfwayY;
var previewCanvas = document.createElement('canvas');
if (!GM_getValue('firsttime', false)) {
var message = 'Texture Pack Enhancer MAX includes the following scripts (or parts of)...\n\n' +
' - Texture Pack Previewer\n' +
' - Texture Pack Enhancer\n' +
' - TagPro Tile Pattern by snaps (in options)\n' +
' - Floor Tiles (in options)\n' +
' - Scoreboard Position Labels by Rattpack (in options)\n\n' +
'You will need to disable any other version of these scripts if you\'re already using them (other texture scripts may also need to be disabled).\n\n' +
'NOTE: There are a lot of options available and some combinations will make the game look bad - use the presets to get started!\n\n' +
'[This message will not appear again]\n\n';
alert(message);
GM_setValue('firsttime', true);
}
tagpro.ready(function() {
if (window.location.port) { //we're in a game...
var tr = tagpro.renderer;
//From: http://www.html5gamedevs.com/topic/518-hack-making-all-2d-drawing-functions-available-to-pixi/
PIXI.Texture.Draw = function(callback) {
var canvas = document.createElement('canvas');
if (typeof callback == 'function') callback(canvas);
return PIXI.Texture.fromCanvas(canvas);
};
//Base Shapes...
if (options.shapes.centerline || options.shapes.basefill || options.shapes.baseradius || options.shapes.circle || options.shapes.octagon || options.shapes.cross) {
var drawPolygon = function(ctx, x, y, radius, sides, rotateAngle) {
if (sides < 3) return;
else if (sides === 3) rotateAngle = 30;
else if (sides === 4) rotateAngle = 45;
else if (sides === 5) rotateAngle = 54;
else if (sides === 6) rotateAngle = 60;
else if (sides === 8) rotateAngle = 22.5;
rotateAngle = rotateAngle * Math.PI / 180;
var a = (Math.PI * 2) / sides;
ctx.save();
ctx.beginPath();
ctx.translate(x, y);
ctx.rotate(rotateAngle);
ctx.moveTo(radius,0);
for (var i = 1; i < sides; i++) {
ctx.lineTo(radius*Math.cos(a*i),radius*Math.sin(a*i));
}
ctx.closePath();
ctx.restore();
};
var drawBaseShape = function(color) {
var shapeSprite = new PIXI.Sprite(PIXI.Texture.Draw(function(canvas) {
let canvasSize = 400;
let canvasCenter = canvasSize/2;
canvas.width = canvasSize;
canvas.height = canvasSize;
let ctx = canvas.getContext('2d');
if (options.shapes.cross) {
let radius_inner = Number(options.shapes.cross_radius_inner);
let radius_outer = Number(options.shapes.cross_radius_outer) * 0.707;
let i = canvasCenter - radius_outer;
let j = canvasCenter + radius_outer;
ctx.strokeStyle = hexToRgbA(color, options.shapes.cross_opacity / 100);
ctx.lineWidth = options.shapes.cross_width;
ctx.beginPath();
ctx.moveTo(i, i);
ctx.lineTo(j, j);
ctx.moveTo(j, i);
ctx.lineTo(i, j);
ctx.closePath();
ctx.stroke();
ctx.save();
ctx.arc(canvasCenter, canvasCenter, radius_inner, 0, Math.PI*2);
ctx.clip();
ctx.clearRect(i, i, j, j);
ctx.restore();
}
if (options.shapes.octagon) {
let octagonRadius = options.shapes.octagon_radius;
let numberSides = options.shapes.octagon_sides;
let fillOpacity = options.shapes.octagon_fillopacity / 100;
ctx.restore();
ctx.strokeStyle = hexToRgbA(color, options.shapes.octagon_opacity / 100);
ctx.lineWidth = options.shapes.octagon_width;
drawPolygon(ctx, canvasCenter, canvasCenter, octagonRadius, numberSides);
if (fillOpacity > 0) {
ctx.fillStyle = hexToRgbA(color, fillOpacity);
ctx.fill();
}
ctx.stroke();
}
}));
return shapeSprite;
};
//we're drawing the base shapes directly on to the background texture...
tr.createBackgroundTexture = function(container) {
var backgroundTexture = new PIXI.RenderTexture(tagpro.map.length * 40, tagpro.map[0].length * 40, new PIXI.CanvasRenderer());
backgroundTexture.render(container);
var baseSprite;
if (flagLocs.yellow.x && flagLocs.yellow.y) {
baseSprite = drawBaseShape(options.shapes.circle_yellow_color);
let doc = new PIXI.DisplayObjectContainer(); //we need a DOC so we can position the sprite
baseSprite.position.x = flagLocs.yellow.x+20;
baseSprite.position.y = flagLocs.yellow.y+20;
baseSprite.anchor.x = 0.5;
baseSprite.anchor.y = 0.5;
doc.addChild(baseSprite);
backgroundTexture.render(doc);
} else {
if (flagLocs.red.x && flagLocs.red.y) {
baseSprite = drawBaseShape(options.shapes.circle_red_color);
let doc = new PIXI.DisplayObjectContainer();
baseSprite.position.x = flagLocs.red.x+20;
baseSprite.position.y = flagLocs.red.y+20;
baseSprite.anchor.x = 0.5;
baseSprite.anchor.y = 0.5;
doc.addChild(baseSprite);
backgroundTexture.render(doc);
}
if (flagLocs.blue.x && flagLocs.blue.y) {
baseSprite = drawBaseShape(options.shapes.circle_blue_color);
let doc = new PIXI.DisplayObjectContainer();
baseSprite.position.x = flagLocs.blue.x+20;
baseSprite.position.y = flagLocs.blue.y+20;
baseSprite.anchor.x = 0.5;
baseSprite.anchor.y = 0.5;
doc.addChild(baseSprite);
backgroundTexture.render(doc);
}
}
tr.chunkifyBackground(backgroundTexture);
};
//Set the wallpaper...
var setGameWallpaper = function() {
if (options.gamewallpaper.type === 'image') {
if (options.gamewallpaper.imagedata) {
$('html').css('background', '#000 url("'+options.gamewallpaper.imagedata+'") center / ' + (options.gamewallpaper.stretch ? 'cover' : 'contain') + ' no-repeat fixed');
}
} else if (options.gamewallpaper.type === 'color') {
$('body.game-page').css('background', options.gamewallpaper.color || '#000000');
} else if (options.gamewallpaper.type === 'gradient') {
if (options.gamewallpaper.gradient_type === 'circle') {
$('html').css('background', 'radial-gradient(circle, ' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ')');
} else if (options.gamewallpaper.gradient_type === 'ellipse') {
$('html').css('background', 'radial-gradient(' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ')');
} else if (options.gamewallpaper.gradient_type === 'horizontal') {
$('html').css('background', 'linear-gradient(to right, ' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ', ' + options.gamewallpaper.color1 + ')');
} else if (options.gamewallpaper.gradient_type === 'vertical') {
$('html').css('background', 'linear-gradient(' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ', ' + options.gamewallpaper.color1 + ')');
} else if (options.gamewallpaper.gradient_type === 'team') {
let angle = 90;
if (flagLocs.yellow.x && flagLocs.yellow.y) {
angle = Math.atan2(flagLocs.ezblue.y - flagLocs.ezred.y, flagLocs.ezblue.x - flagLocs.ezred.x) * 180 / Math.PI + 90;
} else {
angle = Math.atan2(flagLocs.blue.y - flagLocs.red.y, flagLocs.blue.x - flagLocs.red.x) * 180 / Math.PI + 90;
}
$('html').css('background', 'linear-gradient('+angle+'deg, '+options.gamewallpaper.color1+', '+options.gamewallpaper.color2+')');
}
}
};
tagpro.socket.on('map', function(data) {
for (var x=0; x<tagpro.map.length; x++) {
for (var y=0; y<tagpro.map[x].length; y++) {
var tileId = tagpro.map[x][y];
if ((tileId == 3) || (tileId == 3.1)) { //red flag
flagLocs.red.x = x*40;
flagLocs.red.y = y*40;
} else if ((tileId == 4) || (tileId == 4.1)) { //blue flag
flagLocs.blue.x = x*40;
flagLocs.blue.y = y*40;
} else if ((tileId == 16) || (tileId == 16.1)) { //yellow flag
flagLocs.yellow.x = x*40;
flagLocs.yellow.y = y*40;
} else if (tileId == 17 && !flagLocs.ezblue.x) { //red endzone
flagLocs.ezblue.x = x*40;
flagLocs.ezblue.y = y*40;
} else if (tileId == 18 && !flagLocs.ezred.x) { //blue endzone
flagLocs.ezred.x = x*40;
flagLocs.ezred.y = y*40;
}
}
}
if (flagLocs.yellow.x && flagLocs.yellow.y) {
if (tagpro.map.length > tagpro.map[0].length) {
halfwayX = Math.floor(tagpro.map.length/2)*40;
} else if (tagpro.map.length < tagpro.map[0].length) {
halfwayY = Math.floor(tagpro.map[0].length/2)*40;
} else {
//Do nothing???
}
} else if ( Math.abs(flagLocs.red.x - flagLocs.blue.x) > Math.abs(flagLocs.red.y - flagLocs.blue.y) ) { //width is greater
halfwayX = Math.floor(tagpro.map.length/2)*40;
} else if ( Math.abs(flagLocs.red.x - flagLocs.blue.x) < Math.abs(flagLocs.red.y - flagLocs.blue.y) ) { //height is greater
halfwayY = Math.floor(tagpro.map[0].length/2)*40;
} else {
if (tagpro.map.length > tagpro.map[0].length) {
halfwayX = Math.floor(tagpro.map.length/2)*40;
} else if (tagpro.map.length < tagpro.map[0].length) {
halfwayY = Math.floor(tagpro.map[0].length/2)*40;
} else {
//Do nothing???
}
}
if (flagLocs.red.x && flagLocs.blue.x) {
var tempY = flagLocs.red.y;
if (flagLocs.red.y > tagpro.map[0].length * 40 - flagLocs.red.y) tempY = tagpro.map[0].length * 40 - flagLocs.red.y;
if (flagLocs.red.x <= tempY) {
flagRadius = flagLocs.red.x;
} else {
flagRadius = tempY;
}
if (flagRadius < 240) flagRadius = 240; //minimum
if (flagRadius > 360) flagRadius = 360; //maximum
if ((Math.abs(flagLocs.red.x - flagLocs.blue.x) / 2 < flagRadius) && (Math.abs(flagLocs.red.y - flagLocs.blue.y) / 2 < flagRadius)) { //maps where the 2 flags are close together (eg Glory Hole)
flagRadius = Math.abs(flagLocs.red.x - flagLocs.blue.x) / 2;
}
}
setGameWallpaper();
});
}
//Game Background Transparency...
if (options.gameoptions.transparent_background) {
var oldCanvas = $(tr.canvas);
var newCanvas = $('<canvas id="viewport" width="1280" height="800"></canvas>');
oldCanvas.after(newCanvas);
oldCanvas.remove();
tr.canvas = newCanvas.get(0);
tr.options.transparent = true;
tr.renderer = tr.createRenderer();
tr.resizeAndCenterView();
newCanvas.show();
}
var dP = tr.drawPlayer;
var cBS = tr.createBallSprite;
var uPC = tr.updatePlayerColor;
var uPSP = tr.updatePlayerSpritePosition;
var uPF = tr.updatePlayerFlag;
//Ball Glow...
if (options.ballglow.modify) {
var glow = 'http://i.imgur.com/jkQrynA.png'; //TCY9qSm-80, jkQrynA-120, hI93CS5-160
var addGlow = function(player) {
var glowColor = player.team === 1 ? '0x' + options.ballglow.red_color.substr(1) : '0x' + options.ballglow.blue_color.substr(1);
var glowOpacity = player.team === 1 ? options.ballglow.red_opacity / 100 : options.ballglow.blue_opacity / 100;
player.sprites.bottomGlow = new PIXI.Sprite(PIXI.Texture.fromImage(glow));
player.sprites.bottomGlow.alpha = glowOpacity;
player.sprites.bottomGlow.tint = glowColor;
player.sprites.bottomGlow.anchor = new PIXI.Point(0.5, 0.5);
tr.layers.background.addChildAt(player.sprites.bottomGlow, 0);
};
tr.drawPlayer = function(player) {
if (player.draw && player.sprites && !player.sprites.bottomGlow) addGlow(player);
return dP.apply(this, arguments);
};
}
//Modify Spawn Shadow...
if (options.altSpawnShadow.modify) {
tr.drawSpawn = function(x, y, team, timeout) {
if (!tr.layers.foreground) {
setTimeout(tr.drawSpawn, 0, x, y, team, timeout);
return;
}
var tile = team === 1 ? "redspawnball" : "bluespawnball";
//create the new texture once and add it to the cache...
if (!tagpro.tiles[tile] || !PIXI.TextureCache[tile]) {
var canvas = document.createElement("canvas");
canvas.width = 40;
canvas.height = 40;
var ctx = canvas.getContext("2d");
ctx.fillStyle = team === 1 ? options.altSpawnShadow.red_color || "#880000" : options.altSpawnShadow.blue_color || "#000088";
ctx.beginPath();
ctx.arc(20,20,18,0,Math.PI*2);
ctx.fill();
ctx.strokeStyle = '#FFFFFF';
ctx.fillStyle = "#FFFFFF";
ctx.beginPath();
ctx.arc(20,20,19,0,Math.PI*2);
ctx.stroke();
//'x' eyes...
ctx.font="Bold 11px Arial";
ctx.fillText('X', 5, 20);
ctx.font="Bold 12px Arial";
ctx.fillText('X', 22, 18);
//mouth...
ctx.beginPath();
ctx.arc(28, 53, 28, 1.28*Math.PI, 1.55*Math.PI);
ctx.stroke();
ctx.drawImage(canvas, 0, 0);
if (!tagpro.tiles[tile]) tagpro.tiles[tile] = tile;
if (!PIXI.TextureCache[tile]) PIXI.TextureCache[tile] = PIXI.Texture.fromCanvas(canvas);
canvas = null;
}
var sprite = tagpro.tiles.draw(tr.layers.foreground, tile, {x: x, y: y}, null, null, 0.35, true);
setTimeout(function() {
if (sprite) sprite.parent.removeChild(sprite);
}, timeout); // - (tagpro.ping ? tagpro.ping : 50)
};
}
//Faded Splats...
if (options.gameoptions.fading_splats) {
tr.drawSplat = function (x, y, team, showDeath, fadeAway) {
var startColor, stopColor;
if (team === 1) {
startColor = "ff0000";
} else {
startColor = "0000ff";
}
stopColor = "ffffff";
if (showDeath) {
if (tr.options.disableParticles) {
tr.drawBallPop(x + 19, y + 19, team);
} else {
tr.startDeathEmitter(startColor, stopColor, x + 19, y + 19);
}
}
fadeAway = true;
tr.addSplat(team, x, y, fadeAway);
};
}
var modifyBall = function(player) {
var prefix = 'TPE_';
var tileId = (player.team === 1 ? 'redball' : 'blueball');
if (player.team === 1 && options.redball.modify) {
//??
} else if (player.team === 2 && options.blueball.modify) {
//??
} else {
if (!PIXI.TextureCache[tileId]) {
player.sprites.actualBall = tagpro.tiles.draw(player.sprites.ball, tileId, {x: 0, y: 0});
} else {
player.sprites.actualBall.setTexture( PIXI.TextureCache[tileId] );
}
player.sprites.actualBall.tileId = tileId;
return;
}
var canvas = document.createElement("canvas");
canvas.width = 40;
canvas.height = 40;
var ctx = canvas.getContext("2d");
if (options.gameoptions.filters_brightness) {
if (tagpro.playerId === player.id) {
prefix += 'ME_';
//filters += 'brightness(100%) ';
//filters += 'contrast('+80+'%) ';
//filters += 'saturate('+80+'%) ';
//filters += 'sepia('+30+'%) ';
} else {
let filters = '';
filters += 'brightness('+options.gameoptions.filters_brightness_value+'%) ';
ctx.filter = filters;
}
}
drawBall(ctx, tileId);
if (options[tileId].shapes_overlay) drawOverlay(ctx, tileId);
if (options[tileId].border_width > 0) drawBorder(ctx, tileId);
if (options[tileId].shapes_arc) drawArc(ctx, tileId);
if (options[tileId].shapes_star) drawStar(ctx, tileId);
ctx.drawImage(canvas, 0, 0);
var texture = PIXI.Texture.fromCanvas(canvas);
player.sprites.actualBall.setTexture(texture);
player.sprites.actualBall.tileId = tileId;
//tagpro.tiles[tileId] = texture; //need this???
//tagpro.tiles[prefix+tileId] = texture;
PIXI.TextureCache[tileId] = texture; //this is just for other scripts that might use this tile (like "Ball Indicators")
if (!PIXI.TextureCache[prefix+tileId]) PIXI.TextureCache[prefix+tileId] = texture;
canvas = null;
};
//Ball Transparency...
tr.createBallSprite = function(player) {
cBS.apply(this, arguments);
if ( (options.redball.modify && player.team === 1) || (options.blueball.modify && player.team === 2) ) {
var prefix = 'TPE_';
var tileId = (player.team === 1 ? 'redball' : 'blueball');
if (options.gameoptions.filters_brightness && tagpro.playerId === player.id) {
prefix += 'ME_';
}
if (!PIXI.TextureCache[prefix + tileId]) {
modifyBall(player);
} else {
player.sprites.actualBall.setTexture( PIXI.TextureCache[prefix + tileId] );
}
}
player.sprites.actualBall.alpha = ((100 - options.gameoptions.ball_transparency) / 100);
player.sprites.actualBall.anchor.x = 0.5;
player.sprites.actualBall.anchor.y = 0.5;
player.sprites.actualBall.x = 20;
player.sprites.actualBall.y = 20;
player.sprites.actualBall.interactive = true;
player.sprites.actualBall.buttonMode = true;
//player.sprites.name.interactive = true;
//player.sprites.name.buttonMode = true;
};
if (options.ballglow.modify || options.redball.modify || options.blueball.modify) {
tr.updatePlayerColor = function(player) {
var tileId = (player.team === 1 ? 'redball' : 'blueball');
if (player.sprites.actualBall.tileId !== tileId) {
if (options.ballglow.modify) {
tr.layers.background.removeChild(player.sprites.bottomGlow);
addGlow(player);
}
if ( (options.redball.modify && player.team === 1) || (options.blueball.modify && player.team === 2) ) {
var prefix = 'TPE_';
if (options.gameoptions.filters_brightness && tagpro.playerId === player.id) {
prefix += 'ME_';
}
if (!PIXI.TextureCache[prefix + tileId]) {
modifyBall(player);
} else {
player.sprites.actualBall.setTexture( PIXI.TextureCache[prefix + tileId] );
}
} else {
var baseTexture = tagpro.tiles.getTexture(tileId);
var texture = new PIXI.Texture(baseTexture);
player.sprites.actualBall.setTexture(texture);
}
player.sprites.actualBall.tileId = tileId;
}
};
}
//Ball Glow...
if (options.ballglow.modify) {
tr.updatePlayerSpritePosition = function(player) {
if (!player.sprites.bottomGlow) addGlow(player);
player.sprites.bottomGlow.position = {x:Math.round(player.x)+20, y:Math.round(player.y)+20};
return uPSP.apply(this, arguments);
};
}
//modify juke juice effect (makes the jj icon a small blue circle => no lag for live player position script!)...
if (options.modify_JJ.modify) {
let lineColor = '0x' + options.modify_JJ.line_color.substr(1);
let lineWidth = 2;
let fillColor = '0x' + options.modify_JJ.fill_color.substr(1) ;
let radius = options.modify_JJ.radius;
let x = options.modify_JJ.x;
let y = options.modify_JJ.y;
tr.updateGrip = function (player, context, drawPos) {
if (player.grip) {
if (!player.sprites.grip) {
player.sprites.grip = new PIXI.Graphics();
player.sprites.grip.beginFill(fillColor, 1).lineStyle(lineWidth, lineColor).drawCircle(+x, +y, +radius); //3, 37
player.sprites.ball.addChild(player.sprites.grip);
}
} else {
if (player.sprites.grip) {
player.sprites.ball.removeChild(player.sprites.grip);
player.sprites.grip = null;
}
}
};
}
//modify tagpro effect (color, width, radius)...
if (options.modify_TP.modify) {
let radius = options.modify_TP.line_radius;
let lineWidth = options.modify_TP.line_width;
let lineColor = '0x' + options.modify_TP.line_color.substr(1);
let lineOpacity = options.modify_TP.line_opacity / 100;
let fillColor = '0x' + options.modify_TP.fill_color.substr(1) ;
let fillOpacity = options.modify_TP.fill_opacity / 100;
let center = 20;
if (lineWidth % 2 !== 0) center = 19.5;
tr.updateTagpro = function(player) {
if (player.tagpro) {
if (!player.sprites.tagproTint) {
var tint = player.sprites.tagproTint = new PIXI.Graphics();
tint.beginFill(fillColor, fillOpacity).lineStyle(lineWidth, lineColor, lineOpacity).drawCircle(center, center, radius);
player.sprites.ball.addChild(tint);
if (!tr.options.disableParticles) {
player.sprites.tagproSparks = new cloudkid.Emitter(
player.sprites.ball,
[tr.particleFireTexture],
tagpro.particleDefinitions.tagproSparks);
player.sprites.tagproSparks.player = player.id;
tr.emitters.push(player.sprites.tagproSparks);
}
}
} else {
if (player.sprites.tagproTint) {
player.sprites.ball.removeChild(player.sprites.tagproTint);
player.sprites.tagproTint = null;
}
if (player.sprites.tagproSparks) {
player.sprites.tagproSparks.emit = false;
var sparksIndex = tr.emitters.indexOf(player.sprites.tagproSparks);
tr.emitters.splice(sparksIndex, 1);
player.sprites.tagproSparks.destroy();
player.sprites.tagproSparks = null;
}
}
};
}
//modify rolling bomb effect...
if (options.modify_RB.modify) {
let radius = options.modify_RB.line_radius;
let lineWidth = options.modify_RB.line_width;
let lineColor = '0x' + options.modify_RB.line_color.substr(1);
let lineOpacity = options.modify_RB.line_opacity / 100;
let fillColor = '0x' + options.modify_RB.fill_color.substr(1) ;
let fillOpacity = options.modify_RB.fill_opacity / 100;
let speed = options.modify_RB.speed;
let maxOpacity = (options.modify_RB.fill_opacity / 100) || (options.modify_RB.line_opacity / 100) || 0.75;
let center = 20;
if (lineWidth % 2 !== 0) center = 19.5;
tr.updateRollingBomb = function(player) {
if (player.bomb) {
if (!player.sprites.bomb) {
if (!tr.options.disableParticles) {
player.sprites.rollingBomb = new cloudkid.Emitter(
player.sprites.ball,
[tr.particleTexture],
tagpro.particleDefinitions.rollingBomb);
tr.emitters.push(player.sprites.rollingBomb);
}
player.sprites.bomb = new PIXI.Graphics();
player.sprites.bomb.beginFill(fillColor, fillOpacity).lineStyle(lineWidth, lineColor, lineOpacity).drawCircle(center, center, radius);
player.sprites.ball.addChild(player.sprites.bomb);
} else {
player.sprites.bomb.alpha = Math.abs(maxOpacity * Math.sin(performance.now() / speed));
}
} else {
if (player.sprites.bomb) {
player.sprites.ball.removeChild(player.sprites.bomb);
player.sprites.bomb = null;
}
if (player.sprites.rollingBomb) {
if (player.sprites.rollingBomb instanceof cloudkid.Emitter) {
player.sprites.rollingBomb.emit = false;
tr.emitters.splice(tr.emitters.indexOf(player.sprites.rollingBomb), 1);
player.sprites.rollingBomb.destroy();
} else {
player.sprites.rollingBomb.visible = false;
}
player.sprites.rollingBomb = null;
}
}
};
}
//shows the current scoreboard position for each player on their ball (by Rattpack - it's really cool, try it!)...
if (options.sbpl.modify) {
tr.drawScoreboardPosition = function(playerId, position) {
if (!playerId || !tagpro.players.hasOwnProperty(playerId)) return;
var player = tagpro.players[playerId];
if (player.hasOwnProperty('sprites') && player.sprites.hasOwnProperty('SBL')) player.sprites.info.removeChild(player.sprites.SBL);
player.sprites.SBL = tr.veryPrettyText(position, options.sbpl.color);
player.sprites.info.addChild(player.sprites.SBL);
player.sprites.SBL.alpha = options.sbpl.opacity / 100;
player.sprites.SBL.x = +options.sbpl.x+1;
player.sprites.SBL.y = +options.sbpl.y+8;
};
var getAllPlayers = function() {
var players = [];
for (var playerId in tagpro.players) {
if (tagpro.players.hasOwnProperty(playerId)) {
players.push( { id:playerId, score:tagpro.players[playerId].score } );
}
}
players.sort(function(a, b) {
return (b.score - a.score ? b.score - a.score : a.id - b.id);
});
$.each(players, function(key, value) {
try {
tr.drawScoreboardPosition(value.id, key+1);
} catch(e) {
//alert('err');
console.log('ERROR: ',GM_info.script.name, e);
}
});
};
setInterval(function() {
getAllPlayers();
}, 5000);
}
} else { //not in a game...
/*-------------------------------------------------------------------------------*/
// Functions...
/*-------------------------------------------------------------------------------*/
var updateBGPreview = function() {
var backgroundType = $('#TPE_WP').val();
if (backgroundType === 'none') {
$('#TPE_DropZone').css({ 'background': '#000 url("/images/background.jpg") center center / cover no-repeat' });
$('.TPE_WPG_Color').hide(0);
$('.TPE_WPG_Gradient').hide(0);
$('.TPE_WPG_Image').hide(0);
} else if (backgroundType === 'color') {
$('#TPE_DropZone').css({ 'background': $('#TPE_WPG_Color').val() });
$('#TPE_WP').val('color');
$('.TPE_WPG_Color').show(0);
$('.TPE_WPG_Gradient').hide(0);
$('.TPE_WPG_Image').hide(0);
} else if (backgroundType === 'gradient') {
var gradientType = $('#TPE_GradientTypes').val();
var c1 = $('#TPE_GameWallPaper_Color1').val();
var c2 = $('#TPE_GameWallPaper_Color2').val();
if (gradientType === 'vertical') {
$('#TPE_DropZone').css({ 'background': 'linear-gradient('+c1+', '+c2+', '+c1+')' });
} else if (gradientType === 'horizontal') {
$('#TPE_DropZone').css({ 'background': 'linear-gradient(to right, '+c1+', '+c2+', '+c1+')' });
} else if (gradientType === 'circle' || gradientType === 'ellipse') {
$('#TPE_DropZone').css({ 'background': 'radial-gradient('+gradientType+', '+c1+', '+c2+')' });
} else if (gradientType === 'team') {
$('#TPE_DropZone').css({ 'background': 'linear-gradient(135deg, '+c1+', '+c2+')' });
}
$('.TPE_WPG_Color').hide(0);
$('.TPE_WPG_Gradient').show(0);
$('.TPE_WPG_Image').hide(0);
} else if (backgroundType === 'image') {
if (options.gamewallpaper.imagedata) {
$('#TPE_DropZone').css({ 'background': '#000 url("'+options.gamewallpaper.imagedata+'") center / '+(options.gamewallpaper.stretch ? 'cover' : 'contain')+' no-repeat' });
} else {
$('#TPE_DropZone').css({ 'background': 'none' });
}
$('#TPE_WP').val('image');
$('#TPE_WPG_Image_Size').text((options.gamewallpaper.imagedata.length/1024/1024).toFixed(2)+'MB');
$('.TPE_WPG_Color').hide(0);
$('.TPE_WPG_Gradient').hide(0);
$('.TPE_WPG_Image').show(0);
}
};
var handleDrop = function(e, what) {
var data = e.originalEvent.dataTransfer;
if (data.files[0]) { // Handle as a file...
var reader = new FileReader();
var filename = data.files[0].name;
reader.onload = function(file) {
if (what === 'wallpaper') {
options.gamewallpaper.imagedata = file.target.result;
GM_setValue('options', options);
setTimeout(function() {
updateBGPreview();
}, 100);
}
};
reader.readAsDataURL(data.files[0]);
} else { // Handle as a URL...
data.items[0].getAsString(function(url) {
if (!url.startsWith('http')) url = 'http://' + url;
if (what === 'wallpaper') {
options.gamewallpaper.imagedata = url;
GM_setValue('options', options);
setTimeout(function() {
updateBGPreview();
}, 100);
}
});
}
};
/*-------------------------------------------------------------------------------*/
var saveValue = function(value, save=true) {
var saveto = $(value).data('saveto');
var val;
if (!saveto) return;
if (value.type === 'checkbox') {
val = value.checked;
} else if (value.type === 'radio') {
if (value.checked && value.dataset.type) {
val = value.dataset.type;
} else {
return true;
}
} else {
val = value.value;
}
if (saveto.includes('.')) {
var index = saveto.split('.');
options[index[0]][index[1]] = val;
} else {
options[saveto] = val;
}
if (save) GM_setValue('options', options);
};
var saveValues = function() {
$('#TPE_Container, #TPE_Container_Balls').find('input, select').each(function() {
saveValue(this, false);
});
GM_setValue('options', options);
};
var checkOptions = function() {
var parent = '';
const loopNestedObj = (obj) => {
Object.keys(obj).forEach(key => {
if (key !== 'textures') {
if (obj[key] && typeof obj[key] === 'object') {
parent = key;
loopNestedObj(obj[key]);
parent = '';
} else {
let hasDot = key.includes('.');
let hasLength = $('#TPE_Container, #TPE_Container_Balls').find('input[data-saveto="'+key+'"], select[data-saveto="'+key+'"]').length;
if (!hasDot) {
if (!parent) {
if (!hasLength) {
delete options[key];
}
} else {
hasLength = $('#TPE_Container, #TPE_Container_Balls').find('input[data-saveto="'+parent+'.'+key+'"], select[data-saveto="'+parent+'.'+key+'"]').length;
if (!hasLength) {
delete options[parent][key];
if (!Object.keys(options[parent]).length) {
delete options[parent];
}
}
}
} else {
delete options[key];
}
}
}
});
};
loopNestedObj(options);
};
/*-------------------------------------------------------------------------------*/
var getCurrentPack = function() {
var currentPack = {};
$.each($('#custom').find('input[type="text"]'), function() {
currentPack[this.id] = this.value;
});
return currentPack;
};
/*-------------------------------------------------------------------------------*/
var createNewPackIcon = function(name) {
var myPacks = GM_getValue('myPacks', {});
var tilesImg = new Image();
tilesImg.onload = function() {
let thumbnail = createPreview(tilesImg, true); //.toDataURL('image/png');
$('#TPE_MySavedPacks').append('<div class="TPE_MySavedPack" data-name="'+name+'" title="Load this saved custom textures pack"><div class="TPE_DeleteSavedPack" title="Delete this saved custom textures pack">x</div><div class="TPE_MySavedPackLabel">'+name+'</div></div>');
$('#TPE_MySavedPacks').find('div.TPE_MySavedPack[data-name="'+name+'"]').prepend(thumbnail);
};
tilesImg.crossOrigin = "Anonymous";
tilesImg.src = myPacks[name].tiles;
};
/*-------------------------------------------------------------------------------*/
var createNewOptionsIcon = function(name) {
var myOptions = GM_getValue('myOptions', {});
var title = 'Load this saved custom options set';
var displayName = name;
if (myOptions.hasOwnProperty(name)) {
if (myOptions[name].hasOwnProperty('textures')) {
title += ' (includes texture links)';
displayName = '<span style="color:mediumorchid">*</span>' + name;
}
}
$('#TPE_MySavedOptions').append('<div class="TPE_MySavedOptions" data-name="'+name+'" title="'+title+'">'+displayName+'<div class="TPE_DeleteSavedOptions" title="Delete this saved custom options set">x</div></div>');
};
/*-------------------------------------------------------------------------------*/
var loadOptionsValues = function(createIcons=false) {
$('#TPE_Container, #TPE_Container_Balls').find('input, select').each(function(key, value) {
var saveto = value.dataset.saveto;
var group = value.dataset.group;
var rgroup = value.dataset.rgroup;
var index;
var val;
index = saveto.split('.');
if (index[1]) {
if (options.hasOwnProperty(index[0])) {
if (options[index[0]].hasOwnProperty(index[1])) {
val = options[index[0]][index[1]];
} else {
if (this.type === 'checkbox') options[index[0]][index[1]] = false;
else if (this.type === 'color') options[index[0]][index[1]] = '#000000';
val = options[index[0]];
}
} else {
options[index[0]] = {};
if (this.type === 'checkbox') options[index[0]][index[1]] = false;
else if (this.type === 'color') options[index[0]][index[1]] = '#000000';
val = options[index[0]][index[1]];
}
} else if (index[0]) {
if (options.hasOwnProperty(index[0])) {
val = options[index[0]];
} else {
if (this.type === 'checkbox') options[index[0]] = false;
else if (this.type === 'color') options[index[0]] = '#000000';
val = options[index[0]];
}
} else {
return true;
}
if (this.type === 'checkbox') {
$(this).prop('checked', val);
} else if (this.type === 'radio') {
if (val === this.dataset.type) {
$(this).prop('checked', true);
if (val === 'custom') {
$('input[data-saveto="'+index[0]+'.shapes_overlay_base64"]').show();
} else {
$('input[data-saveto="'+index[0]+'.shapes_overlay_base64"]').hide();
}
}
} else {
$(this).val(val);
}
if (group) {
if ( $(this).is(':checked') || ($(this).val() > 0) ) $('#TPE_Container, #TPE_Container_Balls').find('.'+group).fadeIn();
else $('#TPE_Container, #TPE_Container_Balls').find('.'+group).fadeOut();
}
if (rgroup) {
if ( $(this).is(':checked') || ($(this).val() > 0) ) $('#TPE_Container, #TPE_Container_Balls').find('.'+rgroup).fadeOut();
else $('#TPE_Container, #TPE_Container_Balls').find('.'+rgroup).fadeIn();
}
});
$('#TPE_TransparentBallValue').text(options.gameoptions.ball_transparency);
if (options.hasOwnProperty('textures')) {
$.each(options.textures, function(key, value) {
if (value) $('#'+key).val(value);
});
$('#custom-textures-btn').trigger('click');
}
if (!options.ballglow.modify) $('.TPE_Group_BallGlow').hide();
else $('.TPE_Group_BallGlow').show();
if (createIcons) {
var myOptions = GM_getValue('myOptions', {});
$.each(myOptions, function(key, value) {
createNewOptionsIcon(key);
});
}
};
/*-------------------------------------------------------------------------------*/
var loadCustomValues = function() {
var texturePacks = JSON.parse($('#texture-pack-data').text());
var extraPacks = {};
var myPacks = GM_getValue('myPacks', {});
//default packs...
texturePacks.sort(function(a, b) {
if (a.name.toLowerCase() < b.name.toLowerCase()) return -1;
if (a.name.toLowerCase() > b.name.toLowerCase()) return 1;
return 0;
});
for (let i=0; i<texturePacks.length; i++) {
if (texturePacks[i].name === 'Classic') { //put this one at the start :)
texturePacks.splice(0, 0, texturePacks.splice(i, 1)[0]);
}
}
//some extra packs...
var message = '(Note: this texture is not part of the official TagPro texture packs collection)';
extraPacks['24K'] = { author:'MagicPigeon\n'+message, tiles:'https://i.imgur.com/mU3RG02.png', speedpad:'https://i.imgur.com/XGbQS0m.png', speedpadRed:'https://i.imgur.com/7ezs4BA.png', speedpadBlue:'https://i.imgur.com/rVFx0HE.png', portal:'https://i.imgur.com/f0HY7Tu.png', splats:'https://i.imgur.com/nRbpdju.png' };
extraPacks['88 Electric'] = { author:'Rob Flagetti\n'+message, tiles:'http://i.imgur.com/kG50m2X.png', speedpad:'http://i.imgur.com/5i2b07D.png', speedpadRed:'http://i.imgur.com/WwQ70DK.png', speedpadBlue:'http://i.imgur.com/fIeILub.png', portal:'http://i.imgur.com/RFQgPXz.png', splats:'http://i.imgur.com/2kLd2Rn.png' };
extraPacks['Aperture Laboratories'] = { author:'SuperSans\n'+message, tiles:'http://i.imgur.com/SveoaoC.png', speedpad:'https://i.imgur.com/CPoMTrR.png', speedpadRed:'https://i.imgur.com/Az9vhYO.png', speedpadBlue:'https://i.imgur.com/nMVO8KV.png', portal:'https://i.imgur.com/nPdqzJ2.png', splats:'https://i.imgur.com/HSufen1.png' };
extraPacks['Brioche Light'] = { author:'Brioche\n'+message, tiles:'http://i.imgur.com/WDLyCrr.png', speedpad:'http://i.imgur.com/wtpkZWw.png', speedpadRed:'http://i.imgur.com/l6OMel5.png', speedpadBlue:'http://i.imgur.com/IAAOkQz.png', portal:'http://i.imgur.com/CXgNNTs.png', splats:'http://i.imgur.com/kbkOC6x.png' };
extraPacks['Derezzed'] = { author:'-salt-\n'+message, tiles:'http://i.imgur.com/H9qQUAW.png', speedpad:'http://i.imgur.com/BXtUHQG.png', speedpadRed:'http://i.imgur.com/G92Af0J.png', speedpadBlue:'http://i.imgur.com/R9FAvpp.png', portal:'http://i.imgur.com/vJDZam9.png', splats:'http://i.imgur.com/WXHAA3I.png' };
extraPacks['Halloween'] = { author:'TagPro\n'+message, tiles:'/images/events/halloween/tiles.png', speedpad:'/images/events/halloween/speedpad.png', speedpadRed:'/images/events/halloween/speedpadred.png', speedpadBlue:'/images/events/halloween/speedpadblue.png', portal:'/images/events/halloween/portal.png', splats:'/images/events/halloween/splats.png' };
extraPacks['Kindergarten'] = { author:'Clydas\n'+message, tiles:'http://i.imgur.com/y3tbmOS.png', speedpad:'http://i.imgur.com/UEpX1wb.png', speedpadRed:'http://i.imgur.com/tUC9CMG.png', speedpadBlue:'http://i.imgur.com/5yA3IOx.png', portal:'http://i.imgur.com/6Lbd9Aw.png', splats:'http://i.imgur.com/ZGSTp2s.png' };
extraPacks['Next Classic'] = { author:'MagicPigeon\n'+message, tiles:'https://i.imgur.com/hmI65un.png', speedpad:'https://i.imgur.com/w7pW8SC.png', speedpadRed:'https://i.imgur.com/FHjSv04.png', speedpadBlue:'https://i.imgur.com/SSK4Hno.png', portal:'https://i.imgur.com/gdJfGV9.png', splats:'http://i.imgur.com/GObCQoT.png' };
extraPacks['Seaweed R/B'] = { author:'Borgen\n'+message, tiles:'http://i.imgur.com/OAYQaMw.png', speedpad:'http://i.imgur.com/ONxlcFL.png', speedpadRed:'http://i.imgur.com/DwUHM2I.png', speedpadBlue:'http://i.imgur.com/DpJS96w.png', portal:'http://i.imgur.com/44fPSBq.png', splats:'http://i.imgur.com/ZrimG2x.png' };
extraPacks['Starlight+'] = { author:'MagicPigeon\n'+message, tiles:'https://i.imgur.com/PGVnwDs.png', speedpad:'https://i.imgur.com/Kzdjpjx.png', speedpadRed:'https://i.imgur.com/sYcoBZq.png', speedpadBlue:'https://i.imgur.com/MvKkWyf.png', portal:'https://i.imgur.com/SgvHlC2.png', splats:'https://i.imgur.com/FQL3CYa.png' };
extraPacks['Star Wars'] = { author:'Moosen\n'+message, tiles:'https://i.imgur.com/lxV0cnH.png', speedpad:'http://i.imgur.com/WgeuDEz.png', speedpadRed:'http://i.imgur.com/cqY1LTe.png', speedpadBlue:'http://i.imgur.com/bCUoqXq.png', portal:'http://i.imgur.com/FtLHfuz.png', splats:'https://i.imgur.com/XIndyGS.png' };
extraPacks['TagPro Ultra'] = { author:'MuscleCaps\n'+message, tiles:'http://i.imgur.com/HFF6UeV.png', speedpad:'http://i.imgur.com/dLPehvN.png', speedpadRed:'http://i.imgur.com/U9eQnIa.png', speedpadBlue:'http://i.imgur.com/CtRmTaF.png', portal:'http://i.imgur.com/yiLdTR9.png', splats:'http://i.imgur.com/TTuhrS5.png' };
extraPacks['Ultra Smooth'] = { author:'ProfessorTag\n'+message, tiles:'http://i.imgur.com/zltfpGb.png', speedpad:'http://i.imgur.com/zxubWbQ.png', speedpadRed:'http://i.imgur.com/yJGhLPt.png', speedpadBlue:'http://i.imgur.com/K02G9jE.png', portal:'http://i.imgur.com/hffUZ2J.png', splats:'http://i.imgur.com/xMMkRce.png' };
extraPacks['Vanilla Pro'] = { author:'ProfessorTag\n'+message, tiles:'http://i.imgur.com/x8mUxdq.png', speedpad:'http://i.imgur.com/6h2Fna8.png', speedpadRed:'http://i.imgur.com/pF4l9SO.png', speedpadBlue:'http://i.imgur.com/NlepAuW.png', portal:'http://i.imgur.com/qpg0wCt.png', splats:'http://i.imgur.com/ABTYq4t.png' };
extraPacks['Vortex'] = { author:'MagicPigeon\n'+message, tiles:'http://i.imgur.com/jlbr0Gr.png', speedpad:'http://i.imgur.com/hL1YlFu.png', speedpadRed:'http://i.imgur.com/gxQeYTw.png', speedpadBlue:'http://i.imgur.com/pbXh4b1.png', portal:'http://i.imgur.com/H1cHH5w.png', splats:'http://i.imgur.com/36fUJG2.png' };
extraPacks['Yin-Yang'] = { author:'Browncoat\n'+message, tiles:'http://i.imgur.com/ptDXVC0.png', speedpad:'http://i.imgur.com/NVPIQ1y.png', speedpadRed:'http://i.imgur.com/e18kH49.png', speedpadBlue:'http://i.imgur.com/lv8pcWF.png', portal:'http://i.imgur.com/DZried3.png', splats:'http://i.imgur.com/0GTWyyW.png' };
extraPacks['Zed'] = { author:'Nabby\n'+message, tiles:'http://i.imgur.com/FujbRvv.png', speedpad:'http://i.imgur.com/hhj8bD6.png', speedpadRed:'http://i.imgur.com/Y0NpDmI.png', speedpadBlue:'http://i.imgur.com/BLm2Od2.png', portal:'http://i.imgur.com/rGEEQ2s.png', splats:'http://i.imgur.com/GObCQoT.png', gravityWell:'http://i.imgur.com/zPdBr5d.png' };
extraPacks['MAF'] = { author:'Nabby\n'+message, tiles:'http://i.imgur.com/GABiA5B.png', speedpad:'http://i.imgur.com/hhj8bD6.png', speedpadRed:'http://i.imgur.com/Y0NpDmI.png', speedpadBlue:'http://i.imgur.com/BLm2Od2.png', portal:'http://i.imgur.com/rGEEQ2s.png', splats:'http://i.imgur.com/GObCQoT.png', gravityWell:'http://i.imgur.com/zPdBr5d.png' };
$.each($('#custom').find('input[type="text"]'), function() {
var type = this.id;
var name = $(this).siblings('label').text();
$(this).siblings('label').after('<select id="TPE_Packs_'+type+'" class="TPE_Packs" style="margin:0 0 0 5px; width:20px; color:black; font-size:12px; border-radius:5px;" title="Loads a SINGLE link for &quot;'+name+'&quot;"></select>');
$('#TPE_Packs_'+type).append('<optgroup label="Default Packs..." style="color:#e00; font-size:14px">');
$.each(texturePacks, function(key, value) {
$('#TPE_Packs_'+type).append('<option value="'+value[type]+'"'+(value.author?' title="Created by '+value.author+'"':'')+'>'+value.name+'</option>');
});
$('#TPE_Packs_'+type).append('</optgroup>');
$('#TPE_Packs_'+type).append('<optgroup label="Extra Packs..." style="color:#e00; font-size:14px">');
$.each(extraPacks, function(key, value) {
$('#TPE_Packs_'+type).append('<option value="'+value[type]+'"'+(value.author?' title="Created by '+value.author+'"':'')+'>'+key+'</option>');
});
$('#TPE_Packs_'+type).append('</optgroup>');
$('#TPE_Packs_'+type).append('<optgroup id="TPE_MyPacks_OptGroup_'+type+'" label="My Saved Packs..." style="color:#e00; font-size:14px">');
$.each(myPacks, function(key, value) {
$('#TPE_Packs_'+type).append('<option value="'+value[type]+'" data-name="'+key+'">'+key+'</option>');
});
$('#TPE_Packs_'+type).append('</optgroup>');
});
$('#TP_ShowPreviewAll').after('<div style="position:absolute; right:0; margin:-10px 12px 0 0; font-size:12px;" title="Load all links from an extra texture pack.\nYou also need to click &quot;Import Textures&quot; to save/use them in a game."<span>Load Complete &quot;Extra&quot; Pack: </span><select id="TP_ExtraPacks" style="width:20px; color:black; border-radius:4px;"><option>- Select -</option></select></div>');
$.each(extraPacks, function(key, value) {
$('#TP_ExtraPacks').append('<option value="'+key+'"'+(value.author?' title="Created by '+value.author+'"':'')+'>'+key+'</option>');
});
$('#TP_ExtraPacks').on('change', function() {
var val = this.value;
$.each($('#custom').find('input[type="text"]'), function() {
$('#'+this.id).val(extraPacks[val][this.id]);
});
updateFloorTilesPreview();
});
$.each(myPacks, function(key, value) {
createNewPackIcon(key);
});
};
/*-------------------------------------------------------------------------------*/
var updateFloorTilesPreview = function() {
var ctx = $("#TPE_FloorTiles_Preview").get(0).getContext("2d");
var img = document.createElement('img');
img.onload = function() {
ctx.clearRect(0, 0, 40, 40);
drawFloorTile(ctx, img);
img = null;
};
img.crossOrigin = 'Anonymous';
img.src = $('#tiles').val();
};
var updateBallPreviews = function() {
if (options.redball.modify) {
var redctx = $("#TPE_Red_Ball_Preview").get(0).getContext("2d");
redctx.clearRect(0, 0, 40, 40);
drawBall(redctx, 'redball');
if (options.redball.shapes_overlay) drawOverlay(redctx, 'redball');
if (options.redball.border_width > 0) drawBorder(redctx, 'redball');
if (options.redball.shapes_arc) drawArc(redctx, 'redball');
if (options.redball.shapes_star) drawStar(redctx, 'redball');
}
if (options.blueball.modify) {
var bluectx = $("#TPE_Blue_Ball_Preview").get(0).getContext("2d");
bluectx.clearRect(0, 0, 40, 40);
drawBall(bluectx, 'blueball');
if (options.blueball.shapes_overlay) drawOverlay(bluectx, 'blueball');
if (options.blueball.border_width > 0) drawBorder(bluectx, 'blueball');
if (options.blueball.shapes_arc) drawArc(bluectx, 'blueball');
if (options.blueball.shapes_star) drawStar(bluectx, 'blueball');
}
};
var updateAllPreviews = function() {
updateBGPreview();
updateFloorTilesPreview();
updateBallPreviews();
};
/*-------------------------------------------------------------------------------*/
// Define the preset values...
/*-------------------------------------------------------------------------------*/
var presets = {
all: {
containerId: ['TPE_MySavedOptions'],
presets: {
Cleared: {},
MAF: {"gameoptions":{"ball_transparency":"0","fading_splats":true,"transparent_background":true,"filters_brightness":true,"filters_brightness_value":"80"},"ballglow":{"modify":false,"red_color":"#ff4040","red_opacity":"60","blue_color":"#5555ff","blue_opacity":"70"},"sbpl":{"modify":true,"x":"18","y":"18","color":"#ffd700","opacity":"60"},"gamewallpaper":{"type":"gradient","imagedata":"","stretch":true,"gradient_type":"team","gradient_preset":"green","color":"#000040","color1":"#4a0000","color2":"#00003e"},"altSpawnShadow":{"modify":true,"red_color":"#ff4040","blue_color":"#5555ff"},"modify_TP":{"modify":true,"line_color":"#00ff00","line_opacity":"100","line_width":"2","line_radius":"21","fill_color":"#00ff00","fill_opacity":"0"},"modify_RB":{"modify":true,"line_color":"#ffff00","line_opacity":"100","line_width":"5","line_radius":"14","fill_color":"#ffff00","fill_opacity":"0","speed":"45"},"modify_JJ":{"modify":true,"line_color":"#235957","fill_color":"#40a8a5","x":"5","y":"35","radius":"5"},"textures":{"tiles":"http://i.imgur.com/4mDfMIH.png","speedpad":"http://i.imgur.com/6h2Fna8.png","speedpadRed":"http://i.imgur.com/pF4l9SO.png","speedpadBlue":"http://i.imgur.com/NlepAuW.png","portal":"http://i.imgur.com/f0HY7Tu.png","splats":"http://i.imgur.com/2kLd2Rn.png","gravityWell":"http://i.imgur.com/zPdBr5d.png"},"floortiles":{"modify":true,"plain":true,"tint_color":"#414141","tint_opacity":"50","transparency":"0","margin":"1","specks":true,"specks_color":"#000000","specks_length":"20","specks_width":"10","specks_angle":"0","specks_count":"37","specks_opacity":"6","checkered":true,"checkered_random":false,"checkered_altTintColor":"#80ff00","checkered_altTintOpacity":"8","grids_square":true,"grids_square_size":"36","grids_square_color":"#ffffff","grids_square_linewidth":"1","grids_square_opacity":"20","grids_square_dashed":false,"grids_diagonal":false,"grids_diagonal_size":"40","grids_diagonal_color":"#ffffff","grids_diagonal_opacity":"12","grids_diagonal_dashed":false,"checkered_stripes":false,"grids_square_altSides":false,"grids_square_altColor":"#838383"},"shapes":{"centerline":true,"centerline_color":"#00ff00","centerline_width":"2","centerline_dashsize":"5","centerline_opacity":"80","circle":true,"circle_red_color":"#ff0f0f","circle_blue_color":"#0000f9","circle_yellow_color":"#ffff00","circle_width":"20","circle_radius":"360","circle_opacity":"50","octagon":false,"octagon_red_color":"#ff4040","octagon_blue_color":"#5555ff","octagon_yellow_color":"#ffff00","octagon_width":"6","octagon_radius":"80","octagon_opacity":"80","octagon_sides":"8","octagon_fillopacity":"0","cross":false,"cross_red_color":"#ff4040","cross_blue_color":"#5555ff","cross_yellow_color":"#ffff00","cross_width":"5","cross_radius_inner":"35","cross_radius_outer":"140","cross_opacity":"80","baseradius":false,"baseradius_red_color":"#ff4040","baseradius_blue_color":"#5555ff","baseradius_opacity":"65","baseradius_width":"4","baseradius_dashsize":"40","basefill":false,"basefill_red_color":"#ffffff","basefill_blue_color":"#ffffff","basefill_opacity":"15"},"walls":{"modify":true,"color":"#9fff9f","opacity":"12"},"spikes":{"modify":false,"color":"#ff8877","opacity":"60","floortint":true,"floortint_color":"#ff80ff","floortint_stroke":true,"floortint_opacity":"40","floortint_rounded":"8","floortint_margin":"4","floortint_dash":"0","floortint_fill":true,"floortint_fillopacity":"25"},"bombs":{"modify":false,"color":"#bb00bb","opacity":"60","floortint":false,"floortint_color":"#bb00bb","floortint_stroke":true,"floortint_opacity":"100","floortint_margin":"4","floortint_dash":"2","floortint_fill":true,"floortint_fillopacity":"20"},"redball":{"modify":true,"color":"#ff0000","size":"10","opacity":"50","gradient":false,"gradient_color":"#550000","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"3","shapes_arc_position":"16","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#ff0000","shapes_arc_transparent":true,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#222222","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#535353","shapes_arc_color":"#000000"},"blueball":{"modify":true,"color":"#0080ff","size":"10","opacity":"50","gradient":false,"gradient_color":"#003a75","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"3","shapes_arc_position":"16","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#0080ff","shapes_arc_color":"#ffffff","shapes_arc_transparent":true,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"}},
C1: {"gameoptions":{"ball_transparency":"0","fading_splats":true,"transparent_background":true,"filters_brightness":false,"filters_brightness_value":"80"},"ballglow":{"modify":false,"red_color":"#ff4040","red_opacity":"60","blue_color":"#5555ff","blue_opacity":"70"},"sbpl":{"modify":true,"x":"18","y":"18","color":"#ff80ff","opacity":"60"},"gamewallpaper":{"type":"color","imagedata":"","stretch":true,"gradient_type":"ellipse","gradient_preset":"blue","color":"#2c2c2c","color1":"#444455","color2":"#222255"},"altSpawnShadow":{"modify":true,"red_color":"#ff4040","blue_color":"#5555ff"},"modify_TP":{"modify":true,"line_color":"#00ff00","line_opacity":"100","line_width":"2","line_radius":"21","fill_color":"#00ff00","fill_opacity":"0"},"modify_RB":{"modify":true,"line_color":"#ffff00","line_opacity":"100","line_width":"2","line_radius":"19","fill_color":"#ff8040","fill_opacity":"75","speed":"50"},"modify_JJ":{"modify":true,"line_color":"#235957","fill_color":"#40a8a5","x":"5","y":"35","radius":"5"},"textures":{"tiles":"http://i.imgur.com/7AxkC9G.png","speedpad":"http://i.imgur.com/6h2Fna8.png","speedpadRed":"http://i.imgur.com/pF4l9SO.png","speedpadBlue":"http://i.imgur.com/NlepAuW.png","portal":"http://i.imgur.com/f0HY7Tu.png","splats":"http://i.imgur.com/2kLd2Rn.png","gravityWell":"http://i.imgur.com/zPdBr5d.png"},"floortiles":{"modify":false,"plain":true,"tint_color":"#141414","tint_opacity":"30","transparency":"0","margin":"0","specks":false,"specks_color":"#aeaeae","specks_length":"20","specks_width":"2","specks_angle":"0","specks_count":"20","specks_opacity":"20","checkered":true,"checkered_random":false,"checkered_altTintColor":"#000000","checkered_altTintOpacity":"20","grids_diagonal":false,"grids_diagonal_color":"#585858","grids_diagonal_dashed":false,"grids_diagonal_opacity":"19","grids_diagonal_size":"70","grids_square":true,"grids_square_color":"#ffffff","grids_square_dashed":false,"grids_square_opacity":"10","grids_square_size":"38","checkered_stripes":false,"grids_square_altSides":true,"grids_square_altColor":"#696969","grids_square_linewidth":"1"},"shapes":{"centerline":true,"centerline_color":"#00ff00","centerline_width":"3","centerline_dashsize":"0","centerline_opacity":"40","circle":true,"circle_red_color":"#ff4040","circle_blue_color":"#5555ff","circle_yellow_color":"#ffff00","circle_width":"3","circle_radius":"140","circle_opacity":"100","octagon":true,"octagon_red_color":"#ff4040","octagon_blue_color":"#5555ff","octagon_yellow_color":"#ffff00","octagon_width":"3","octagon_radius":"40","octagon_opacity":"80","octagon_sides":"8","octagon_fillopacity":"20","cross":true,"cross_red_color":"#ff4040","cross_blue_color":"#5555ff","cross_yellow_color":"#ffff00","cross_width":"3","cross_radius_inner":"45","cross_radius_outer":"140","cross_opacity":"80","baseradius":true,"baseradius_red_color":"#ff4040","baseradius_blue_color":"#5555ff","baseradius_opacity":"80","baseradius_width":"4","baseradius_dashsize":"5","basefill":true,"basefill_red_color":"#ffffff","basefill_blue_color":"#ffffff","basefill_opacity":"6"},"walls":{"modify":true,"color":"#ffff00","opacity":"10"},"spikes":{"modify":false,"color":"#ff8877","opacity":"60","floortint":false,"floortint_color":"#cccccc","floortint_stroke":true,"floortint_opacity":"50","floortint_rounded":"3","floortint_margin":"2","floortint_dash":"0","floortint_fill":false,"floortint_fillopacity":"12"},"bombs":{"modify":false,"color":"#bb00bb","opacity":"60","floortint":false,"floortint_color":"#bb00bb","floortint_stroke":true,"floortint_opacity":"50","floortint_margin":"1","floortint_dash":"0","floortint_fill":false,"floortint_fillopacity":"12"},"redball":{"modify":true,"color":"#ff0000","size":"16","opacity":"65","gradient":false,"gradient_color":"#550000","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"2","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffc6c6","border_color":"#b30000","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#000000","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},"blueball":{"modify":true,"color":"#0080ff","size":"16","opacity":"65","gradient":false,"gradient_color":"#003a75","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"4","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#bfdfff","border_color":"#0058b0","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"}},
T1: {"gameoptions":{"ball_transparency":"0","fading_splats":true,"transparent_background":true,"filters_brightness":false,"filters_brightness_value":"80"},"ballglow":{"modify":false,"red_color":"#ff4040","red_opacity":"60","blue_color":"#5555ff","blue_opacity":"70"},"sbpl":{"modify":false,"x":"18","y":"18","color":"#ffd700","opacity":"60"},"gamewallpaper":{"type":"gradient","imagedata":"","stretch":true,"gradient_type":"team","gradient_preset":"light","color":"#000040","color1":"#DDDDDD","color2":"#777777"},"altSpawnShadow":{"modify":false,"red_color":"#ff4040","blue_color":"#5555ff"},"modify_TP":{"modify":true,"line_color":"#00ff00","line_opacity":"100","line_width":"2","line_radius":"21","fill_color":"#80ff80","fill_opacity":"20"},"modify_RB":{"modify":true,"line_color":"#ffff00","line_opacity":"100","line_width":"5","line_radius":"14","fill_color":"#ffff00","fill_opacity":"0","speed":"45"},"modify_JJ":{"modify":true,"line_color":"#235957","fill_color":"#40a8a5","x":"5","y":"35","radius":"5"},"textures":{"tiles":"http://i.imgur.com/x8mUxdq.png","speedpad":"http://i.imgur.com/6h2Fna8.png","speedpadRed":"http://i.imgur.com/pF4l9SO.png","speedpadBlue":"http://i.imgur.com/NlepAuW.png","portal":"http://i.imgur.com/qpg0wCt.png","splats":"http://i.imgur.com/ABTYq4t.png","gravityWell":"http://i.imgur.com/zPdBr5d.png"},"floortiles":{"modify":true,"plain":true,"tint_color":"#ffff80","tint_opacity":"100","transparency":"0","margin":"20","specks":false,"specks_color":"#ffff80","specks_length":"2","specks_width":"1","specks_angle":"0","specks_count":"50","specks_opacity":"100","checkered":false,"checkered_random":false,"checkered_altTintColor":"#737373","checkered_altTintOpacity":"7","grids_square":true,"grids_square_size":"40","grids_square_color":"#617c74","grids_square_linewidth":"1","grids_square_opacity":"25","grids_square_dashed":false,"grids_diagonal":false,"grids_diagonal_size":"70","grids_diagonal_color":"#c0c0c0","grids_diagonal_opacity":"10","grids_diagonal_dashed":false,"checkered_stripes":false,"grids_square_altSides":false,"grids_square_altColor":"#6c6c6c"},"shapes":{"centerline":true,"centerline_color":"#00ff00","centerline_width":"2","centerline_dashsize":"5","centerline_opacity":"80","circle":true,"circle_red_color":"#ff0f0f","circle_blue_color":"#0053a6","circle_yellow_color":"#ffff00","circle_width":"20","circle_radius":"360","circle_opacity":"50","octagon":false,"octagon_red_color":"#ff4040","octagon_blue_color":"#5555ff","octagon_yellow_color":"#ffff00","octagon_width":"6","octagon_radius":"80","octagon_opacity":"80","octagon_sides":"8","octagon_fillopacity":"0","cross":true,"cross_red_color":"#ff4040","cross_blue_color":"#5555ff","cross_yellow_color":"#ffff00","cross_width":"5","cross_radius_inner":"35","cross_radius_outer":"120","cross_opacity":"80","baseradius":false,"baseradius_red_color":"#ff4040","baseradius_blue_color":"#5555ff","baseradius_opacity":"65","baseradius_width":"4","baseradius_dashsize":"40","basefill":false,"basefill_red_color":"#ffffff","basefill_blue_color":"#ffffff","basefill_opacity":"15"},"walls":{"modify":false,"color":"#000000","opacity":"40"},"spikes":{"modify":true,"color":"#a74fff","opacity":"35","floortint":true,"floortint_color":"#ffffff","floortint_stroke":true,"floortint_opacity":"100","floortint_rounded":"16","floortint_margin":"4","floortint_dash":"3","floortint_fill":false,"floortint_fillopacity":"25"},"bombs":{"modify":false,"color":"#bb00bb","opacity":"60","floortint":false,"floortint_color":"#bb00bb","floortint_stroke":true,"floortint_opacity":"100","floortint_margin":"4","floortint_dash":"3","floortint_fill":true,"floortint_fillopacity":"20"},"redball":{"modify":true,"color":"#ff0000","size":"10","opacity":"50","gradient":false,"gradient_color":"#550000","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"3","shapes_arc_position":"16","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#ff0000","shapes_arc_transparent":true,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#222222","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#535353","shapes_arc_color":"#000000"},"blueball":{"modify":true,"color":"#0080ff","size":"10","opacity":"50","gradient":false,"gradient_color":"#003a75","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":false,"shapes_arc_width":"3","shapes_arc_position":"16","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#0080ff","shapes_arc_color":"#ffffff","shapes_arc_transparent":true,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"}},
}
}, floortiles: {
keys: ['floortiles'],
containerId: ['TPE_Presets_FloorTiles'],
presets: {
a: {"modify":true,"plain":true,"tint_color":"#000000","tint_opacity":"100","transparency":"0","margin":"0","specks":true,"specks_color":"#77ffff","specks_length":"2","specks_width":"1","specks_angle":"0","specks_count":"50","specks_opacity":"30","checkered":false,"checkered_random":false,"checkered_altTintColor":"#737373","checkered_altTintOpacity":"7","grids_diagonal":false,"grids_diagonal_color":"#c0c0c0","grids_diagonal_dashed":false,"grids_diagonal_opacity":"10","grids_diagonal_size":"70","grids_square":false,"grids_square_color":"#ffffff","grids_square_dashed":false,"grids_square_opacity":"24","grids_square_size":"38","checkered_stripes":false,"grids_square_linewidth":"2","grids_square_altSides":true,"grids_square_altColor":"#9d9d9d"},
b: {"modify":true,"plain":true,"tint_color":"#000000","tint_opacity":"100","transparency":"0","margin":"0","specks":true,"specks_color":"#ff0080","specks_length":"20","specks_width":"3","specks_angle":"0","specks_count":"20","specks_opacity":"14","checkered":false,"checkered_random":true,"checkered_altTintColor":"#111111","checkered_altTintOpacity":"20","grids_diagonal":true,"grids_diagonal_color":"#ffffff","grids_diagonal_dashed":false,"grids_diagonal_opacity":"5","grids_diagonal_size":"80","grids_square":false,"grids_square_color":"#ffffff","grids_square_dashed":false,"grids_square_opacity":"10","grids_square_size":"40","checkered_stripes":false,"grids_square_linewidth":"1","grids_square_altSides":false,"grids_square_altColor":"#ffffff"},
c: {"modify":true,"plain":true,"tint_color":"#666666","tint_opacity":"50","transparency":"0","margin":"0","specks":true,"specks_color":"#000000","specks_length":"20","specks_width":"1","specks_angle":"90","specks_count":"10","specks_opacity":"10","checkered":false,"checkered_random":false,"checkered_altTintColor":"#000000","checkered_altTintOpacity":"5","grids_diagonal":false,"grids_diagonal_color":"#777777","grids_diagonal_dashed":false,"grids_diagonal_opacity":"50","grids_diagonal_size":"40","grids_square":true,"grids_square_color":"#ffffff","grids_square_dashed":true,"grids_square_opacity":"15","grids_square_size":"65","checkered_stripes":false,"grids_square_linewidth":"1","grids_square_altSides":false,"grids_square_altColor":"#ffffff"},
d: {"modify":true,"plain":true,"tint_color":"#000000","tint_opacity":"100","transparency":"0","margin":"0","specks":false,"specks_color":"#777777","specks_length":"57","specks_width":"1","specks_angle":"45","specks_count":"20","specks_opacity":"10","checkered":true,"checkered_random":false,"checkered_altTintColor":"#7700ff","checkered_altTintOpacity":"12","grids_diagonal":true,"grids_diagonal_color":"#777777","grids_diagonal_dashed":false,"grids_diagonal_opacity":"8","grids_diagonal_size":"80","grids_square":true,"grids_square_color":"#ffffff","grids_square_dashed":false,"grids_square_opacity":"10","grids_square_size":"40","checkered_stripes":false,"grids_square_linewidth":"1","grids_square_altSides":false,"grids_square_altColor":"#ffffff"},
e: {"modify":true,"plain":true,"tint_color":"#333333","tint_opacity":"100","transparency":"0","margin":"0","specks":true,"specks_color":"#000000","specks_length":"20","specks_width":"1","specks_angle":"0","specks_count":"20","specks_opacity":"10","checkered":true,"checkered_random":true,"checkered_altTintColor":"#111111","checkered_altTintOpacity":"20","grids_diagonal":true,"grids_diagonal_color":"#777777","grids_diagonal_dashed":false,"grids_diagonal_opacity":"7","grids_diagonal_size":"80","grids_square":true,"grids_square_color":"#000000","grids_square_dashed":false,"grids_square_opacity":"30","grids_square_size":"40","checkered_stripes":false,"grids_square_linewidth":"1","grids_square_altSides":false,"grids_square_altColor":"#ffffff"},
f: {"modify":true,"plain":true,"tint_color":"#50706b","tint_opacity":"50","transparency":"0","margin":"0","specks":true,"specks_color":"#000000","specks_length":"20","specks_width":"1","specks_angle":"0","specks_count":"20","specks_opacity":"10","checkered":true,"checkered_random":false,"checkered_altTintColor":"#000000","checkered_altTintOpacity":"9","grids_diagonal":false,"grids_diagonal_color":"#80ff00","grids_diagonal_dashed":false,"grids_diagonal_opacity":"15","grids_diagonal_size":"60","grids_square":true,"grids_square_color":"#000000","grids_square_dashed":false,"grids_square_opacity":"30","grids_square_size":"38","checkered_stripes":false,"grids_square_linewidth":"1","grids_square_altSides":true,"grids_square_altColor":"#ffffff"},
g: {"modify":true,"plain":true,"tint_color":"#706b50","tint_opacity":"50","transparency":"0","margin":"0","specks":true,"specks_color":"#aeaeae","specks_length":"20","specks_width":"1","specks_angle":"315","specks_count":"20","specks_opacity":"20","checkered":false,"checkered_random":false,"checkered_altTintColor":"#000000","checkered_altTintOpacity":"9","grids_diagonal":false,"grids_diagonal_color":"#80ff00","grids_diagonal_dashed":false,"grids_diagonal_opacity":"15","grids_diagonal_size":"60","grids_square":true,"grids_square_color":"#ffffff","grids_square_dashed":false,"grids_square_opacity":"30","grids_square_size":"19","checkered_stripes":true,"grids_square_altSides":true,"grids_square_altColor":"#000000","grids_square_linewidth":"1"},
h: {"modify":true,"plain":true,"tint_color":"#b5b5b5","tint_opacity":"50","transparency":"0","margin":"0","specks":false,"specks_color":"#000000","specks_length":"20","specks_width":"1","specks_angle":"0","specks_count":"20","specks_opacity":"10","checkered":false,"checkered_random":false,"checkered_altTintColor":"#000000","checkered_altTintOpacity":"9","grids_diagonal":false,"grids_diagonal_color":"#ffffff","grids_diagonal_dashed":false,"grids_diagonal_opacity":"12","grids_diagonal_size":"40","grids_square":true,"grids_square_color":"#ffffff","grids_square_dashed":true,"grids_square_opacity":"10","grids_square_size":"54","checkered_stripes":false,"grids_square_altSides":false,"grids_square_altColor":"#000000","grids_square_linewidth":"40"},
i: {"modify":true,"plain":true,"tint_color":"#413f43","tint_opacity":"50","transparency":"0","margin":"1","specks":true,"specks_color":"#000000","specks_length":"20","specks_width":"10","specks_angle":"0","specks_count":"37","specks_opacity":"6","checkered":true,"checkered_random":false,"checkered_altTintColor":"#49b683","checkered_altTintOpacity":"13","grids_square":true,"grids_square_size":"36","grids_square_color":"#ffffff","grids_square_linewidth":"1","grids_square_opacity":"20","grids_square_dashed":false,"grids_diagonal":false,"grids_diagonal_size":"40","grids_diagonal_color":"#ffffff","grids_diagonal_opacity":"12","grids_diagonal_dashed":false,"checkered_stripes":false,"grids_square_altSides":false,"grids_square_altColor":"#838383"},
}
}, redball: {
keys: ['redball'],
containerId: ['TPE_Presets_RedBall'],
presets: {
a: {"modify":true,"color":"#ff0000","size":"19","opacity":"100","gradient":true,"gradient_color":"#550000","gradient_position":"20","border_width":"1","border_segments":"4","shapes_arc":true,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#d2d2d2","border_color":"#bb0000","gradient_start":"5","gradient_stop":"25","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#222222","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},
b: {"modify":true,"color":"#ff0000","size":"13","opacity":"100","gradient":true,"gradient_color":"#400000","gradient_position":"12","border_width":"3","border_segments":"6","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"4","shapes_star_spikes":"2","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#ff0000","gradient_start":"5","gradient_stop":"32","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#000000","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},
c: {"modify":true,"color":"#ff0000","size":"5","opacity":"100","gradient":true,"gradient_color":"#550000","gradient_position":"20","border_width":"1","border_segments":"8","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"2","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#ff0000","gradient_start":"1","gradient_stop":"5","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#000000","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},
d: {"modify":true,"color":"#ff0000","size":"19","opacity":"100","gradient":true,"gradient_color":"#550000","gradient_position":"17","border_width":"1","border_segments":"0","shapes_arc":true,"shapes_arc_width":"1","shapes_arc_position":"6","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"1","shapes_star_spikes":"4","shapes_star_inner":"1","shapes_star_outer":"14","shapes_overlay":true,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#000000","gradient_start":"5","gradient_stop":"25","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#333333","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},
e: {"modify":true,"color":"#ff0000","size":"13","opacity":"100","gradient":false,"gradient_color":"#550000","gradient_position":"17","border_width":"4","border_segments":"2","shapes_arc":false,"shapes_arc_width":"1","shapes_arc_position":"6","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"1","shapes_star_spikes":"5","shapes_star_inner":"3","shapes_star_outer":"11","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#ff0000","gradient_start":"5","gradient_stop":"25","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#000000","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#333333"},
f: {"modify":true,"color":"#b70000","size":"14","opacity":"65","gradient":false,"gradient_color":"#550000","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":true,"shapes_arc_width":"1","shapes_arc_position":"19","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"2","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffc6c6","border_color":"#ff0000","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_overlay_type":"earth1","shapes_star_color":"#000000","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#535353","shapes_arc_color":"#000000"},
}
}, blueball: {
keys: ['blueball'],
containerId: ['TPE_Presets_BlueBall'],
presets: {
a: {"modify":true,"color":"#0080ff","size":"19","opacity":"100","gradient":true,"gradient_color":"#000055","gradient_start":"5","gradient_stop":"25","gradient_position":"20","border_width":"1","border_segments":"4","shapes_arc":true,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"3","shapes_star_spikes":"4","shapes_star_inner":"2","shapes_star_outer":"9","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#d2d2d2","border_color":"#0080ff","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":true,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"},
b: {"modify":true,"color":"#0080ff","size":"13","opacity":"100","gradient":true,"gradient_color":"#bfdfff","gradient_start":"5","gradient_stop":"32","gradient_position":"12","border_width":"3","border_segments":"6","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"4","shapes_star_spikes":"4","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#0080ff","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"},
c: {"modify":true,"color":"#0080ff","size":"5","opacity":"100","gradient":true,"gradient_color":"#003a75","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"1","border_segments":"8","shapes_arc":false,"shapes_arc_width":"2","shapes_arc_position":"13","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"4","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#0080ff","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"},
d: {"modify":true,"color":"#0080ff","size":"19","opacity":"100","gradient":true,"gradient_color":"#000055","gradient_start":"5","gradient_stop":"25","gradient_position":"17","border_width":"1","border_segments":"0","shapes_arc":true,"shapes_arc_width":"1","shapes_arc_position":"6","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"1","shapes_star_spikes":"4","shapes_star_inner":"1","shapes_star_outer":"14","shapes_overlay":true,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#000000","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#aaaaaa","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"},
e: {"modify":true,"color":"#0080ff","size":"13","opacity":"100","gradient":false,"gradient_color":"#000055","gradient_start":"5","gradient_stop":"25","gradient_position":"17","border_width":"4","border_segments":"2","shapes_arc":false,"shapes_arc_width":"1","shapes_arc_position":"6","shapes_arc_size":"18","shapes_star":true,"shapes_star_width":"1","shapes_star_spikes":"5","shapes_star_inner":"3","shapes_star_outer":"11","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#ffffff","border_color":"#0080ff","shapes_arc_color":"#aaaaaa","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"},
f: {"modify":true,"color":"#0080ff","size":"14","opacity":"65","gradient":false,"gradient_color":"#003a75","gradient_start":"1","gradient_stop":"5","gradient_position":"20","border_width":"2","border_segments":"8","shapes_arc":true,"shapes_arc_width":"2","shapes_arc_position":"19","shapes_arc_size":"18","shapes_star":false,"shapes_star_width":"4","shapes_star_spikes":"4","shapes_star_inner":"0","shapes_star_outer":"10","shapes_overlay":false,"shapes_overlay_transparency":"20","border_alt_color":"#bfdfff","border_color":"#2b95ff","shapes_arc_color":"#000000","shapes_arc_transparent":false,"shapes_overlay_base64":"","shapes_star_color":"#ffffff","shapes_star_transparent":false,"shapes_star_fill":false,"shapes_star_fill_color":"#b9b9b9","shapes_overlay_type":"earth1"}
}
},
ballshapes: {
keys: ['redball', 'blueball'],
containerId: ['TPE_Presets_Shapes_RedBall', 'TPE_Presets_Shapes_BlueBall'],
presets: {
'square': { 'shapes_star_width': 2, 'shapes_star_spikes': 4, 'shapes_star_inner': 8, 'shapes_star_outer': 12, 'shapes_star_fill': false },
'plus': { 'shapes_star_width': 4, 'shapes_star_spikes': 4, 'shapes_star_inner': 0, 'shapes_star_outer': 10, 'shapes_star_fill': false },
'minus': { 'shapes_star_width': 4, 'shapes_star_spikes': 2, 'shapes_star_inner': 0, 'shapes_star_outer': 8, 'shapes_star_fill': false },
'merc': { 'shapes_star_width': 2, 'shapes_star_spikes': 3, 'shapes_star_inner': 7, 'shapes_star_outer': 1, 'shapes_star_fill': true, 'shapes_star_fill_color': '#FFFFFF' },
'star4': { 'shapes_star_width': 3, 'shapes_star_spikes': 4, 'shapes_star_inner': 2, 'shapes_star_outer': 9, 'shapes_star_fill': false },
}
}
};
/*-------------------------------------------------------------------------------*/
var loadPresets = function() {
$.each(presets, function(key, value) {
if (!value.containerId) return true;
$.each(value.containerId, function(ke, va) {
var thiskey = '';
if (value.keys) thiskey = value.keys[ke];
$.each(value.presets, function(k, v) {
let title = 'Load this preset';
let displayName = k;
if (va === 'TPE_MySavedOptions') {
if (v.hasOwnProperty('textures') && ((v.textures.tiles) || (v.textures.speedpad) || (v.textures.speedpadRed) || (v.textures.speedpadBlue) || (v.textures.portal) || (v.textures.splats) || (v.textures.gravityWell)) ) {
title += ' (includes texture links)';
displayName = '<span style="color:mediumorchid">*</span>' + k;
}
}
$('#'+va).append('<div class="TPE_Preset" data-preset="'+key+'.'+k+'" data-color="'+thiskey+'" title="'+title+'">'+displayName+'</div>');
});
let x = 12;
let y = 7;
let yd = 15;
let w = 12;
let h = 12;
let fs = 8;
if (va === 'TPE_MySavedOptions') {
x = 30;
y = 15;
yd = 19;
w = 15;
h = 15;
fs = 10;
}
$('#'+va).append('<div class="TPE_Import_Presets" data-key="'+key+'" data-keys="'+thiskey+'" title="Import a JSON formatted string for '+key+' options" style="position:absolute; width:'+w+'px; height:'+h+'px; margin:0px 0 '+(y+yd)+'px '+x+'px; padding:1px; bottom:0; left:0; opacity:0.2; text-align:center; font-size:'+fs+'px; color:white; background:midnightblue; border:1px solid dodgerblue; border-radius:4px; cursor:pointer">I</div>');
$('#'+va).append('<div class="TPE_Export_Presets" data-key="'+key+'" data-keys="'+thiskey+'" title="Export '+key+' options to a JSON formatted string" style="position:absolute; width:'+w+'px; height:'+h+'px; margin:0 0 '+y+'px '+x+'px; padding:1px; bottom:0; left:0; opacity:0.2; text-align:center; font-size:'+fs+'px; color:white; background:blueviolet; border:1px solid skyblue; border-radius:4px; cursor:pointer">E</div>');
});
});
};
var loadPreset = function(preset, color) {
if (!preset || !preset.includes('.')) return;
var index = preset.split('.');
if (!presets[index[0]].presets[index[1]]) return;
if (index[0] === 'all') {
if (presets.all.presets.hasOwnProperty([index[1]])) {
options = $.extend(true, {}, defaultOptions, presets.all.presets[index[1]]);
GM_setValue('options', options);
loadOptionsValues(false);
//updateFloorTilesPreview();
}
} else {
$.each(presets[index[0]].presets[index[1]], function(key, value) {
var newValue;
var selectedColor;
if (typeof value !== 'object') {
if (color) key = color + '.' + key;
newValue = { [key]: value };
} else {
selectedColor = color;
newValue = value;
}
$.each(newValue, function(k, v) {
if ((index[0] === 'ballshapes')) { //(index[0] === 'balls') ||
if (!color || (selectedColor && k !== selectedColor)) { // || k !== color
return true;
}
if (typeof value === 'object') {
k = color + '.' + key;
v = value[color];
}
} else if (!k.includes('.')) {
k = key + '.' + k;
}
var element = $('#TPE_Container, #TPE_Container_Balls').find('[data-saveto="'+k+'"]');
if ((v === true) || (v === false)) {
element.prop('checked', v);
} else if ($(element).attr('type') === 'radio') {
$('#TPE_Container, #TPE_Container_Balls').find('[data-type="'+value+'"]').prop('checked', true);
} else {
element.val(v);
}
var group = $(element).data('group');
var rgroup = $(element).data('rgroup');
if (group) {
if ((v === true) || (v > 0)) $('.' + group).slideDown(400);
else $('.' + group).slideUp(400);
}
if (rgroup) {
if ((v === true) || (v > 0)) $('.' + rgroup).slideUp(400);
else $('.' + rgroup).slideDown(400);
}
});
});
}
saveValues();
if (index[0] === 'all') {
updateAllPreviews();
} else if (index[0] === 'floortiles') {
updateFloorTilesPreview();
} else if ((index[0] === 'redball') || (index[0] === 'blueball') || (index[0] === 'ballshapes')) {
updateBallPreviews();
}
};
/*-------------------------------------------------------------------------------*/
// Create the new page elements & menus...
/*-------------------------------------------------------------------------------*/
//Add new elements to the "Import Custom" tab...
$('#TP_ShowPreviewAll').remove(); //remove the built-in "Preview All"
$('#custom').find('.TP_ShowPreview').remove(); //remove the built-in link previews
$('#custom').find('input').parent('div').prepend('<span class="TP_ShowPreview" style="margin:4px 5px 0 0; padding:2px 5px; font-size:12px; color:white; background:#444; border:1px dashed #aaa; border-radius:5px; float:right; cursor:default;">Preview</span>');
$('#custom-textures-btn').before('<span id="TP_ShowPreviewAll" style="position:absolute; right:0; margin:30px 16px 0 0; padding:2px 5px; font-size:16px; color:white; background:#444; border:1px dashed #aaa; border-radius:5px; cursor:default;">Preview All</span>');
$('#custom-textures-btn').after('<div id="TPE_MySavedPacks" style="display:flex; margin:15px 5px 0; flex-flow:row wrap; align-items:center; justify-content:center; background:#333; border:1px solid #444; border-radius:5px;"></div>');
$('#TPE_MySavedPacks').append('<div id="TPE_SaveMyPack" title="Save the current texture links as a new pack" style="margin:2px 13px; padding:6px 0; width:38px; height:38px; opacity:0.6; text-align:center; font-size:18px; color:white; background:limegreen; border: 1px dashed white; border-radius:10px; cursor:pointer">&#10133;</div>');
//Create "Options" tab...
$('ul.tab-list').append('<li data-target="#TPE_Container"><a>Game Options</a></li>');
$('div.tab-content').append('<div id="TPE_Container" class="tab-pane" style="padding:10px; font-size:12px;"></div>');
//Add Ball Editor Tab...
$('ul.tab-list').append('<li data-target="#TPE_Container_Balls"><a>Ball Editor</a></li>');
$('div.tab-content').append('<div id="TPE_Container_Balls" class="tab-pane" style="padding:10px; font-size:12px;"></div>');
/*******************/
//Game Options...
$('#TPE_Container').append('<div id="TPE_GameOptions" style="display:flex; align-items:flex-start; justify-content:center; width:100%;"></div>');
$('#TPE_GameOptions').append('<div id="TPE_Options" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; margin:10px 5px; padding:6px; width:350px; border:1px solid #777; border-radius:10px;"></div>');
$('#TPE_Options').append('<label title="0=Solid Color. 100=Invisible!" style="display:flex; justify-content:flex-start; align-items:center; white-space:nowrap;"><span>Ball Transparency: </span><span style="margin:0 10px"><input type="range" id="TPE_TransparentBall" min="0" max="100" data-saveto="gameoptions.ball_transparency" style="width:80px"></span><span id="TPE_TransparentBallValue">'+(options.gameoptions.ball_transparency)+'</span>%</label>');
$('#TPE_Options').append('<label title="Splats will fade out after 5 seconds"><input type="checkbox" id="TPE_FadingSplats" data-saveto="gameoptions.fading_splats">Use Fading Splats</label>');
$('#TPE_Options').append('<label title="Remove the black background behind the map"><input type="checkbox" id="TPE_TransparentBackground" data-saveto="gameoptions.transparent_background">Transparent Game Background</label>');
$('#TPE_Options').append('<label title="Modify the &quot;TagPro&quot; powerup effect"><input type="checkbox" data-saveto="modify_TP.modify" data-group="TPE_Group_ModifyTP">Modify TagPro</label>' +
'<div class="TPE_Group_ModifyTP TPE_SubGroup">' +
' <div><label title="">Line Color: <input type="color" data-saveto="modify_TP.line_color"></label>' +
' <label title="TagPro default is: 100">Line Opacity: <input type="number" min="0" max="100" data-saveto="modify_TP.line_opacity"></label>' +
' <label title="TagPro default is: 3">Line Width: <input type="number" min="0" max="20" data-saveto="modify_TP.line_width"></label></div>' +
' <div><label title="">Fill Color: <input type="color" data-saveto="modify_TP.fill_color"></label>' +
' <label title="TagPro default is: 15">Fill Opacity: <input type="number" min="0" max="100" data-saveto="modify_TP.fill_opacity"></label></div>' +
' <div><label title="TagPro default is: 20">Radius: <input type="number" min="1" max="30" data-saveto="modify_TP.line_radius"></label></div>' +
'</div>');
$('#TPE_Options').append('<label title="Modify the &quot;Rolling Bomb&quot; powerup effect"><input type="checkbox" data-saveto="modify_RB.modify" data-group="TPE_Group_ModifyRB">Modify Rolling Bomb</label>' +
'<div class="TPE_Group_ModifyRB TPE_SubGroup">' +
' <div><label title="">Line Color: <input type="color" data-saveto="modify_RB.line_color"></label>' +
' <label title="TagPro default is: 0 (0 = no line)">Line Opacity: <input type="number" min="0" max="100" data-saveto="modify_RB.line_opacity"></label>' +
' <label title="TagPro default is: 0 (0 = no line)">Line Width: <input type="number" min="0" max="20" data-saveto="modify_RB.line_width"></label></div>' +
' <div><label title="">Fill Color: <input type="color" data-saveto="modify_RB.fill_color"></label>' +
' <label title="TagPro default is: 75 (0 = no fill)">Fill Opacity: <input type="number" min="0" max="100" data-saveto="modify_RB.fill_opacity"></label></div>' +
' <div><label title="TagPro default is: 20">Radius: <input type="number" min="1" max="30" data-saveto="modify_RB.line_radius"></label>' +
' <label title="TagPro default is: 150 (lower is faster flashing)">Flashing Speed: <input type="number" min="20" max="200" step="5" data-saveto="modify_RB.speed"></label></div>' +
'</div>');
$('#TPE_Options').append('<label title="Modify the &quot;Juke Juice&quot; powerup\n(Replaces the JJ icon with circle => no icon lag with live player position script!)"><input type="checkbox" data-saveto="modify_JJ.modify" data-group="TPE_Group_ModifyJJ">Modify Juke Juice</label>' +
'<div class="TPE_Group_ModifyJJ TPE_SubGroup">' +
' <label title="">Line Color: <input type="color" data-saveto="modify_JJ.line_color"></label>' +
' <label title="">Fill Color: <input type="color" data-saveto="modify_JJ.fill_color"></label>' +
' <div><label title="TagPro default is: ~8\n(Left is 0, Center is 20, Right is 40)">X: <input type="number" min="0" max="40" data-saveto="modify_JJ.x"></label>' +
' <label title="TagPro default is: ~32\n(Top is 0, Center is 20, Bottom is 40)">Y: <input type="number" min="0" max="40" data-saveto="modify_JJ.y"></label>' +
' <label title="TagPro default is: ~5">Radius: <input type="number" min="2" max="10" data-saveto="modify_JJ.radius"></label></div>' +
'</div>');
$('#TPE_Options').append('<label title="Use an alternate spawn shadow (dead ball face)"><input type="checkbox" data-saveto="altSpawnShadow.modify" data-group="TPE_Group_AltSpawnShadow">Alternate Spawn Shadow</label>' +
'<div class="TPE_Group_AltSpawnShadow TPE_SubGroup">' +
' <label title="">"Red" Color: <input type="color" data-saveto="altSpawnShadow.red_color"></label>' +
' <label title="">"Blue" Color: <input type="color" data-saveto="altSpawnShadow.blue_color"></label>' +
'</div>');
$('#TPE_Options').append('<label title="Changes the brightness of *everyone elses* ball so yours stands out better (only works if &quot;Modify Balls&quot; is enabled in the &quot;Ball Editor&quot; tab)"><input type="checkbox" data-saveto="gameoptions.filters_brightness" data-group="TPE_Group_FilterBrightness">Make Me Special</label>' +
'<div class="TPE_Group_FilterBrightness TPE_SubGroup">' +
' <label title="100 = Normal; <100 = Darker; >100 = Brighter">Brightness: <input type="number" min="0" max="200" data-saveto="gameoptions.filters_brightness_value"></label>' +
'</div>');
$('#TPE_Options').append('<div class="TPE_Divider"></div>');
$('#TPE_Options').append('<label title="Shows the current scoreboard position for each player on their ball"><input type="checkbox" id="TPE_AddSBPosLabels" data-saveto="sbpl.modify" data-group="TPE_Group_SBPL">Add Scoreboard Position Labels</label>' +
'<div class="TPE_Group_SBPL TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="sbpl.color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="sbpl.opacity"></label>' +
' <label title="0 = Ball Centre. Less than 0 = Left. Greater than 0 = Right.">X: <input type="number" min="-40" max="40" data-saveto="sbpl.x"></label>' +
' <label title="0 = Ball Centre. Less than 0 = Up. Greater than 0 = Down.">Y: <input type="number" min="-40" max="40" data-saveto="sbpl.y"></label>' +
'</div>');
$('#TPE_Options').append('<label title="Ball Glow works best when either the Floor Tiles have some transparency, or the Floor File margin is > 0 (so you can see the glow). Tile transparency needs more GPU processing though!)"><input type="checkbox" data-saveto="ballglow.modify" data-group="TPE_Group_BallGlow">Add Ball Glow</label>' +
'<div class="TPE_Group_BallGlow TPE_SubGroup">' +
' <div><label title="">"Red": <input type="color" data-saveto="ballglow.red_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="ballglow.red_opacity"></label></div>' +
' <div><label title="">"Blue": <input type="color" data-saveto="ballglow.blue_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="ballglow.blue_opacity"></label></div>' +
'</div>');
//Tints...
$('#TPE_Options').append('<div class="TPE_Divider"></div>');
$('#TPE_Options').append('<label title="Tint the walls from your texture pack"><input type="checkbox" data-saveto="walls.modify" data-group="TPE_Group_TintWalls">Tint Walls</label>' +
'<div class="TPE_Group_TintWalls TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="walls.color"></label>' +
' <label title="0=No Tint, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="walls.opacity"></label>' +
'</div>');
$('#TPE_Options').append('<label title="Tint the spikes from your texture pack"><input type="checkbox" data-saveto="spikes.modify" data-group="TPE_Group_TintSpikes">Tint Spikes</label>' +
'<div class="TPE_Group_TintSpikes TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="spikes.color"></label>' +
' <label title="0=No Tint, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="spikes.opacity"></label>' +
'</div>');
$('#TPE_Options').append('<label title="Tint the bombs from your texture pack"><input type="checkbox" data-saveto="bombs.modify" data-group="TPE_Group_TintBombs">Tint Bombs</label>' +
'<div class="TPE_Group_TintBombs TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="bombs.color"></label>' +
' <label title="0=No Tint, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="bombs.opacity"></label>' +
'</div>');
$('#TPE_Options').append('<label title="Tint the floor tile under the spikes"><input type="checkbox" data-saveto="spikes.floortint" data-group="TPE_Group_SpikesFloorTint">Highlight Spike Tiles</label>' +
'<div class="TPE_Group_SpikesFloorTint TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="spikes.floortint_color"></label>' +
' <div><label title="">Stroke: <input type="checkbox" data-saveto="spikes.floortint_stroke"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="spikes.floortint_opacity"></label>' +
' <label title="">Rounded: <input type="number" min="0" max="40" data-saveto="spikes.floortint_rounded"></label>' +
' <label title="">Margin: <input type="number" min="0" max="10" data-saveto="spikes.floortint_margin"></label>' +
' <label title="">Dash: <input type="number" min="0" max="20" data-saveto="spikes.floortint_dash"></label></div>' +
' <div><label title="">Fill: <input type="checkbox" data-saveto="spikes.floortint_fill"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="spikes.floortint_fillopacity"></label></div>' +
'</div>');
$('#TPE_Options').append('<label title="Tint the floor tile under the bombs"><input type="checkbox" data-saveto="bombs.floortint" data-group="TPE_Group_BombsFloorTint">Highlight Bomb Tiles</label>' +
'<div class="TPE_Group_BombsFloorTint TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="bombs.floortint_color"></label>' +
' <div><label title="">Stroke: <input type="checkbox" data-saveto="bombs.floortint_stroke"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="bombs.floortint_opacity"></label>' +
' <label title="">Margin: <input type="number" min="0" max="10" data-saveto="bombs.floortint_margin"></label>' +
' <label title="">Dash: <input type="number" min="0" max="20" data-saveto="bombs.floortint_dash"></label></div>' +
' <div><label title="">Fill: <input type="checkbox" data-saveto="bombs.floortint_fill"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="bombs.floortint_fillopacity"></label></div>' +
'</div>');
/*******************/
//Tiles...
$('#TPE_GameOptions').append('<div id="TPE_Tile_Options" style="display:flex; align-items:flex-start; justify-content:center; width:340px;"></div>');
//Floor Tiles...
$('#TPE_Tile_Options').append('<div id="TPE_FloorTiles" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; margin:10px 5px; padding:6px; width:260px; border:1px solid #777; border-radius:10px;">' +
' <div id="TPE_FloorTiles_Preview_Container" style="position:absolute; top:5px; right:5px; z-index:1; border:1px dashed rgba(128,220,128,0.6); padding:2px; height:46px; border-radius:4px;"><canvas id="TPE_FloorTiles_Preview" width="40" height="40"></canvas></div>' +
'</div>');
$('#TPE_FloorTiles').append('<label title=""><input type="checkbox" data-saveto="floortiles.modify" data-group="TPE_Group_ModifyFloorTiles">Modify Floor Tiles</label>' +
'<div class="TPE_Group_ModifyFloorTiles TPE_SubGroup">' +
' <div><label title="This will replace the Floor tiles in your texture pack with a plain square tile"><input type="checkbox" data-saveto="floortiles.plain" data-rgroup="TPE_Group_Tiles_Plain">Use Plain Tiles</label></div>' +
' <div><label title="Tint the floor tiles with this color">Tint Color: <input type="color" data-saveto="floortiles.tint_color"></label></div>' +
' <div class="TPE_Group_Tiles_Plain"><label title="0=No Tint, 100=Solid Color">Tint Opacity: <input type="number" min="0" max="100" data-saveto="floortiles.tint_opacity"></label></div>' +
' <div><label title="This is the transparency of your texture pack floor floortiles. 0=Solid Color, 100=Transparent\nNote that older systems may struggle with transparency - set to 0 for best performance.">Tiles Transparency: <input type="number" min="0" max="100" data-saveto="floortiles.transparency"></label></div>' +
' <div><label title="Reduces the tile size by this much (e.g.: 2 = 38px floor tile size, 20 = No Tile)">Tile Margin: <input type="number" min="0" max="20" data-saveto="floortiles.margin"></label></div>' +
'</div>');
//Specks...
$('#TPE_FloorTiles').append('<label title=""><input type="checkbox" data-saveto="floortiles.specks" data-group="TPE_Group_Tiles_Specks">Add Randoms</label>' +
'<div class="TPE_Group_Tiles_Specks TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="floortiles.specks_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="floortiles.specks_opacity"></label>' +
' <label title="">Length: <input type="number" min="1" max="40" data-saveto="floortiles.specks_length"></label>' +
' <label title="">Width: <input type="number" min="1" max="20" data-saveto="floortiles.specks_width"></label>' +
' <label title="0=Random Angles">Angle: <input type="number" min="0" max="360" value="315" data-saveto="floortiles.specks_angle"></label>' +
' <label title="The total number of randoms to draw">Count: <input type="number" min="1" max="300" data-saveto="floortiles.specks_count"></label>' +
'</div>');
//Checkered...
$('#TPE_FloorTiles').append('<label title="Checkered Tiles works best when...\n- The 2 Tint Colors are the same (or very similar), and/or\n- The 2 Tint Opacity values are close together (1-10 difference is good)\n- If you\'re using &quot;Plain Tiles&quot; the Opacity values should be high (90-100), otherwise they will be transparent"><input type="checkbox" data-saveto="floortiles.checkered" data-group="TPE_Group_CheckeredTiles">Checkered Tiles</label>' +
'<div class="TPE_Group_CheckeredTiles TPE_SubGroup">' +
' <label title="Tint the alternate floor tiles with this color" style="margin-left:10px">Alt Tint Color: <input type="color" data-saveto="floortiles.checkered_altTintColor"></label>' +
' <label title="0=No Tint, 100=Solid Color" style="margin-left:10px">Alt Tint Opacity: <input type="number" min="0" max="100" data-saveto="floortiles.checkered_altTintOpacity"></label>' +
' <label title="Use a random pattern instead of a checkered pattern" style="margin-left:10px"><input type="checkbox" data-saveto="floortiles.checkered_random">Randomize Pattern</label>' +
' <label title="" style="margin-left:10px"><input type="checkbox" data-saveto="floortiles.checkered_stripes">Stripes</label>' +
'</div>');
//Grids...
$('#TPE_FloorTiles').append('<label title=""><input type="checkbox" data-saveto="floortiles.grids_square" data-group="TPE_Group_Grids_Square">Square Grid</label>' +
'<div class="TPE_Group_Grids_Square TPE_SubGroup">' +
' <label title="">Size: <input type="number" min="1" max="80" data-saveto="floortiles.grids_square_size"></label>' +
' <label title="">Color: <input type="color" data-saveto="floortiles.grids_square_color"></label>' +
' <label title="">Linewidth: <input type="number" min="1" max="40" data-saveto="floortiles.grids_square_linewidth"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="floortiles.grids_square_opacity"></label>' +
' <label title="">Dashed: <input type="checkbox" data-saveto="floortiles.grids_square_dashed"></label>' +
' <label title="">Alt Side: <input type="checkbox" data-saveto="floortiles.grids_square_altSides" data-group="TPE_Group_Grids_Square_AltSides"></label>' +
' <label title="Color for the bottom & right edges. If darker than grid color, the tile appears raised. If lighter, the tile appears sunken." class="TPE_Group_Grids_Square_AltSides">Color: <input type="color" data-saveto="floortiles.grids_square_altColor"></label>' +
'</div>');
$('#TPE_FloorTiles').append('<label><input type="checkbox" data-saveto="floortiles.grids_diagonal" data-group="TPE_Group_Grids_Diagonal">Diagonal Grid</label>' +
'<div class="TPE_Group_Grids_Diagonal TPE_SubGroup">' +
' <label title="">Size: <input type="number" min="1" max="80" data-saveto="floortiles.grids_diagonal_size"></label>' +
' <label title="">Color: <input type="color" data-saveto="floortiles.grids_diagonal_color"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="floortiles.grids_diagonal_opacity"></label>' +
' <label title="">Dashed: <input type="number" min="0" max="40" data-saveto="floortiles.grids_diagonal_dashed"></label>' +
'</div>');
//Floor Presets...
$('#TPE_FloorTiles').append('<div id="TPE_Presets_FloorTiles" class="TPE_Presets" style="text-align:center; margin-top:5px; width:100%; border:1px solid #555; border-radius:3px; padding:5px 0;" title="Floor Tile Presets"></div>');
//Base Shapes...
$('#TPE_GameOptions').append('<div id="TPE_Shapes" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; margin:10px 5px; width:340px;"></div>');
$('#TPE_Shapes').append('<div id="TPE_ShapesOptions" style="display:flex; flex-flow:column wrap; width:100%; padding:10px; border:1px solid #777; border-radius:10px;"></div>');
$('#TPE_ShapesOptions').append('<label title="Draws a line down the center of the map"><input type="checkbox" data-saveto="shapes.centerline" data-group="TPE_Group_ShapesCenterLine">Map Center Line</label>' +
'<div class="TPE_Group_ShapesCenterLine TPE_SubGroup">' +
' <label title="">Color: <input type="color" data-saveto="shapes.centerline_color"></label>' +
' <label title="">Line Width: <input type="number" min="1" max="40" data-saveto="shapes.centerline_width"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.centerline_opacity"></label>' +
' <label title="0=Solid Line">Dash Size: <input type="number" min="0" max="39" data-saveto="shapes.centerline_dashsize"></label>' +
'</div>');
$('#TPE_ShapesOptions').append('<label title="Draws a circle around the flags (will be drawn on floor tiles only - make as big as you want!)"><input type="checkbox" data-saveto="shapes.circle" data-group="TPE_Group_ShapesCircle">Circle Around Flags</label>' +
'<div class="TPE_Group_ShapesCircle TPE_SubGroup">' +
' <label title="">"R": <input type="color" data-saveto="shapes.circle_red_color"></label>' +
' <label title="">"B": <input type="color" data-saveto="shapes.circle_blue_color"></label>' +
' <label title="">"Y": <input type="color" data-saveto="shapes.circle_yellow_color"></label>' +
' <label title="Line Width">Width: <input type="number" min="1" max="100" data-saveto="shapes.circle_width"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.circle_opacity"></label>' +
' <label title="">Radius: <input type="number" min="1" max="400" data-saveto="shapes.circle_radius"></label>' +
'</div>');
$('#TPE_ShapesOptions').append('<label title="Draws a n-sided polygon around the flags (will be drawn over walls if too big - less than 140 radius is good)"><input type="checkbox" data-saveto="shapes.octagon" data-group="TPE_Group_ShapesOctagon">Polygon Around Flags</label>' +
'<div class="TPE_Group_ShapesOctagon TPE_SubGroup">' +
' <label title="">"R": <input type="color" data-saveto="shapes.octagon_red_color"></label>' +
' <label title="">"B": <input type="color" data-saveto="shapes.octagon_blue_color"></label>' +
' <label title="">"Y": <input type="color" data-saveto="shapes.octagon_yellow_color"></label>' +
' <label title="">#Sides: <input type="number" min="3" max="30" data-saveto="shapes.octagon_sides"></label>' +
' <label title="">Radius: <input type="number" min="40" max="200" data-saveto="shapes.octagon_radius"></label>' +
' <label title="Line Width">Line Width: <input type="number" min="1" max="40" data-saveto="shapes.octagon_width"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.octagon_opacity"></label>' +
' <label title="0=No Fill. 100=Solid Color (can\'t see flag)">Fill Opacity: <input type="number" min="0" max="100" data-saveto="shapes.octagon_fillopacity"></label>' +
'</div>');
$('#TPE_ShapesOptions').append('<label title="Draws a cross around the flags (will be drawn over walls if too big - less than 140 outer radius is good)"><input type="checkbox" data-saveto="shapes.cross" data-group="TPE_Group_ShapesCross">Cross Around Flags</label>' +
'<div class="TPE_Group_ShapesCross TPE_SubGroup">' +
' <label title="">"R": <input type="color" data-saveto="shapes.cross_red_color"></label>' +
' <label title="">"B": <input type="color" data-saveto="shapes.cross_blue_color"></label>' +
' <label title="">"Y": <input type="color" data-saveto="shapes.cross_yellow_color"></label>' +
' <label title="Line Width">Width: <input type="number" min="1" max="80" data-saveto="shapes.cross_width"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.cross_opacity"></label>' +
' <label title="Inner Radius (will be drawn over flag if too small - 35-60 is good)">Inner: <input type="number" min="0" max="100" data-saveto="shapes.cross_radius_inner"></label>' +
' <label title="Outer Radius (will be drawn over walls if too big - less than 140 is good)">Outer: <input type="number" min="1" max="200" data-saveto="shapes.cross_radius_outer"></label>' +
'</div>');
$('#TPE_ShapesOptions').append('<div class="TPE_Divider"></div>');
$('#TPE_ShapesOptions').append('<label title="Draws a line around the red/blue bases"><input type="checkbox" data-saveto="shapes.baseradius" data-group="TPE_Group_BaseRadius">Base Radius Line</label>' +
'<div class="TPE_Group_BaseRadius TPE_SubGroup">' +
' <label title="">"Red": <input type="color" data-saveto="shapes.baseradius_red_color"></label>' +
' <label title="">"Blue": <input type="color" data-saveto="shapes.baseradius_blue_color"></label>' +
' <div><label title="">Line Width: <input type="number" min="1" max="40" data-saveto="shapes.baseradius_width"></label>' +
' <label title="0=Solid Line">Dash Size: <input type="number" min="0" max="39" data-saveto="shapes.baseradius_dashsize"></label>' +
' <label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.baseradius_opacity"></label></div>' +
'</div>');
$('#TPE_ShapesOptions').append('<label title="Tints the floor tiles of the red/blue bases"><input type="checkbox" data-saveto="shapes.basefill" data-group="TPE_Group_BaseFill">Base Fill</label>' +
'<div class="TPE_Group_BaseFill TPE_SubGroup">' +
' <label title="">"Red": <input type="color" data-saveto="shapes.basefill_red_color"></label>' +
' <label title="">"Blue": <input type="color" data-saveto="shapes.basefill_blue_color"></label>' +
' <div><label title="0=Transparent, 100=Solid Color">Opacity: <input type="number" min="0" max="100" data-saveto="shapes.basefill_opacity"></label></div>' +
'</div>');
//Wallpaper Options...
$('#TPE_GameOptions').append('<div id="TPE_Wallpaper" style="display:flex; flex-flow:column wrap; align-items:center; margin:10px 5px; padding:10px; width:260px; border:1px solid #777; border-radius:10px;"></div>');
$('#TPE_Wallpaper').append('<span>Game Background: <select id="TPE_WP" style="color:black" data-saveto="gamewallpaper.type">' +
' <option value="none">None</option>' +
' <option value="color">Color</option>' +
' <option value="gradient">Gradient</option>' +
' <option value="image">Image</option>' +
'</select></span>');
$('#TPE_Wallpaper').append('<div id="TPE_DropZone_Outer" style="display:flex; align-items:center; margin:10px; width:220px; height:165px; text-align:center; border:2px dotted silver;"><div id="TPE_DropZone" style="width:100%; height:100%"></div></div>');
$('#TPE_Wallpaper').append('<div class="TPE_WPG_Image" style="margin:-10px 0 5px; font-size:12px; font-style:italic">(Drag & Drop Backgrounds Here)</div>');
$('#TPE_Wallpaper').append('<div class="TPE_WPG_Image" style="margin:-10px 0 5px; font-size:12px;">Stored Image Size: <span id="TPE_WPG_Image_Size"></span></div>');
$('#TPE_Wallpaper').append('<label class="TPE_WPG_Image"><input type="checkbox" data-saveto="gamewallpaper.stretch">Stretch Wallpaper to Fit</label>');
$('#TPE_Wallpaper').append('<input type="hidden" data-saveto="gamewallpaper.imagedata">');
$('#TPE_Wallpaper').append('<span class="TPE_WPG_Color">Color: <input type="color" id="TPE_WPG_Color" data-saveto="gamewallpaper.color"></span>');
$('#TPE_Wallpaper').append('<div class="TPE_WPG_Gradient" style="text-align:center;">' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="red" data-saveto="gamewallpaper.gradient_preset" data-c1="#554444" data-c2="#552222">Red</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="green" data-saveto="gamewallpaper.gradient_preset" data-c1="#445544" data-c2="#225522">Green</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="blue" data-saveto="gamewallpaper.gradient_preset" data-c1="#444455" data-c2="#222255">Blue</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="orange" data-saveto="gamewallpaper.gradient_preset" data-c1="#665400" data-c2="#512400">Orange</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="light" data-saveto="gamewallpaper.gradient_preset" data-c1="#DDDDDD" data-c2="#777777">Light</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="dark" data-saveto="gamewallpaper.gradient_preset" data-c1="#222222" data-c2="#090909">Dark</label>' +
' <label><input type="radio" name="TPE_GradientPresets" data-type="redblue" data-saveto="gamewallpaper.gradient_preset" data-c1="#aa0000" data-c2="#0055aa">Red/Blue</label>' +
'</div>');
$('#TPE_Wallpaper').append('<div class="TPE_WPG_Gradient"><span>Color 1: <input type="color" id="TPE_GameWallPaper_Color1" data-saveto="gamewallpaper.color1"></span><span style="margin-left:20px;">Color 2: <input type="color" id="TPE_GameWallPaper_Color2" data-saveto="gamewallpaper.color2"></span></div>');
$('#TPE_Wallpaper').append('<span class="TPE_WPG_Gradient" style="margin-top:5px;">Gradient Type: <select id="TPE_GradientTypes" style="color:black" data-saveto="gamewallpaper.gradient_type">' +
' <option value="horizontal">Horizontal</option>' +
' <option value="vertical">Vertical</option>' +
' <option value="circle">Circle</option>' +
' <option value="ellipse">Ellipse</option>' +
' <option value="team" title="Color1 is on the Red side of the screen, Color2 is on the Blue side.">Team</option>' +
'</select></span>');
$('#TPE_Container').append('<div id="TPE_MySavedOptions" style="display:flex; margin:15px 5px 0; padding:0 20px; flex-flow:row wrap; align-items:center; justify-content:center; background:#333; border:1px solid #444; border-radius:5px;"></div>');
$('#TPE_MySavedOptions').append('<div id="TPE_MySavedOptionsButtons" style="position:relative"></div>');
$('#TPE_MySavedOptionsButtons').append('<div id="TPE_SaveMyOptions" title="Save the current options as a new set" style="margin:2px 13px; padding:6px 0; width:38px; height:38px; opacity:0.6; text-align:center; font-size:18px; color:white; background:limegreen; border:1px dashed white; border-radius:10px; cursor:pointer">&#10133;</div>');
/*******************/
//Custom Ball Options...
$('#TPE_Container_Balls').append('<div id="TPE_Ball_Options" style="display:flex; align-items:flex-start; justify-content:center; width:100%;"></div>');
//Red...
$('#TPE_Ball_Options').append('<div id="TPE_Red_Balls" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; margin:10px 5px; padding:6px; width:275px; border:1px solid #777; border-radius:10px;"></div>');
$('#TPE_Red_Balls').append('<label title=""><input type="checkbox" id="TPE_ModifyRed" data-saveto="redball.modify" data-group="TPE_Group_RedBall">Modify "Red" Balls</label>');
$('#TPE_Red_Balls').append('<div id="TPE_Balls_Red" class="TPE_Group_RedBall" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; padding:4px 10px; width:100%; margin-left:6px;"></div>');
$('#TPE_Balls_Red').append('<label title="">Ball Color: <input type="color" data-saveto="redball.color"></label>');
$('#TPE_Balls_Red').append('<label title="Ball Radius (default is 19)">Ball Size: <input type="number" min="0" max="19" data-saveto="redball.size"></label>');
$('#TPE_Balls_Red').append('<label title="0=Transparent, 100=Solid Color">Ball Opacity: <input type="number" min="0" max="100" data-saveto="redball.opacity"></label>');
$('#TPE_Balls_Red').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Red').append('<label title="Fill with a Radial Gradient"><input type="checkbox" data-saveto="redball.gradient" data-group="TPE_RedBall_Gradient_Group">Use Gradient</label>' +
'<div class="TPE_RedBall_Gradient_Group TPE_SubGroup">' +
' <label title="Outer Gradient Color">Outer Color: <input type="color" data-saveto="redball.gradient_color"></label>' +
' <label title="Gradient Start (Inner)">Gradient Start: <input type="number" min="0" max="40" data-saveto="redball.gradient_start"></label>' +
' <label title="Gradient Stop (Outer)">Gradient Stop: <input type="number" min="0" max="40" data-saveto="redball.gradient_stop"></label>' +
' <label title="Position of Gradient (Ball Center is 20)">Gradient Position: <input type="number" min="1" max="20" data-saveto="redball.gradient_position"></label>' +
'</div>');
$('#TPE_Balls_Red').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Red').append('<label title="Width of border (0 to disable)">Border Width: <input type="number" min="0" max="19" data-saveto="redball.border_width" data-group="TPE_RedBall_Border_Group"></label>' +
'<div class="TPE_RedBall_Border_Group TPE_SubGroup">' +
' <label title="Color of ball\'s outer border">Border Color: <input type="color" data-saveto="redball.border_color"></label>' +
' <label title=""># Segments: <input type="number" min="0" max="20" step="2" data-saveto="redball.border_segments" data-group="TPE_RedBall_BorderSegments_Group"></label>' +
' <label class="TPE_RedBall_BorderSegments_Group TPE_SubGroup" title="">Alt Border Color: <input type="color" data-saveto="redball.border_alt_color"></label>' +
'</div>');
$('#TPE_Balls_Red').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Red').append('<div style="display:flex; flex-flow:column wrap; align-items:flex-start; width:100%; padding:2px; border:1px dotted #444; border-radius:3px; font-size:11px;">' +
' <label title=""><input type="checkbox" data-saveto="redball.shapes_arc" data-group="TPE_RedBall_Shapes_Arc_Group" style="margin:1px; width:11px; height:11px;">Arc</label>' +
' <div class="TPE_RedBall_Shapes_Arc_Group TPE_SubGroup">' +
' <div><label title="">Color: <input type="color" data-saveto="redball.shapes_arc_color"></label>' +
' <label title="">Transparent: <input type="checkbox" data-saveto="redball.shapes_arc_transparent" style="width:11px; height:11px;"></label></div>' +
' <label title="">Line Width: <input type="number" min="1" max="19" data-saveto="redball.shapes_arc_width"></label>' +
' <label title="">Position: <input type="number" min="1" max="19" data-saveto="redball.shapes_arc_position"></label>' +
' <label title="">Size: <input type="number" min="1" max="18" data-saveto="redball.shapes_arc_size"></label>' +
' </div>' +
'<div class="TPE_Divider"></div>' +
' <label title=""><input type="checkbox" data-saveto="redball.shapes_star" data-group="TPE_RedBall_Shapes_Star_Group" style="margin:1px; width:11px; height:11px;">Shapes</label>' +
' <div class="TPE_RedBall_Shapes_Star_Group TPE_SubGroup">' +
' <div><label title="">Color: <input type="color" data-saveto="redball.shapes_star_color"></label>' +
' <label title="">Transparent: <input type="checkbox" data-saveto="redball.shapes_star_transparent" style="width:11px; height:11px;"></label></div>' +
' <div><label title="">Fill: <input type="checkbox" data-saveto="redball.shapes_star_fill" data-group="TPE_Group_RedBall_Shapes_Star_Fill" style="width:11px; height:11px;"></label>' +
' <label class="TPE_Group_RedBall_Shapes_Star_Fill" title="">Fill Color: <input type="color" data-saveto="redball.shapes_star_fill_color"></label></div>' +
' <label title="">Line Width: <input type="number" min="0" max="10" data-saveto="redball.shapes_star_width"></label>' +
' <label title="">Spikes: <input type="number" min="2" max="20" data-saveto="redball.shapes_star_spikes"></label>' +
' <div><label title="">Inner: <input type="number" min="0" max="20" data-saveto="redball.shapes_star_inner"></label>' +
' <label title="">Outer: <input type="number" min="1" max="20" data-saveto="redball.shapes_star_outer"></label></div>' +
' <div id="TPE_Presets_Shapes_RedBall" style="text-align:center; margin-top:5px;"></div>' +
' </div>' +
'<div class="TPE_Divider"></div>' +
' <label title=""><input type="checkbox" data-saveto="redball.shapes_overlay" data-group="TPE_RedBall_Shapes_Overlay_Group" style="margin:1px; width:11px; height:11px;">Overlays</label>' +
' <div class="TPE_RedBall_Shapes_Overlay_Group" style="text-align:center;">' +
' <div>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="marble1">Marble#1</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="marble2">Marble#2</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="earth1">Earth#1</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="earth2">Earth#2</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="swirl1">Swirl#1</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="donald">Donald</label>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="lucky">Lucky</label>' +
' </div>' +
' <label title=""><input type="radio" name="TPE_RedBall_Shapes_Overlay_Type" data-saveto="redball.shapes_overlay_type" data-type="custom">Custom (Base64)</label>' +
' <label title="Copy a Base64 Encoded string here (use https://www.base64-image.de/ to encode your image)"><input type="text" id="TPE_RedBall_Shapes_Overlay_Base64" data-saveto="redball.shapes_overlay_base64" style="margin:1px; width:220px; color:black;"></label>' +
' <label title="">Transparency: <input type="number" min="0" max="100" data-saveto="redball.shapes_overlay_transparency"></label>' +
' </div>' +
'</div');
$('#TPE_Balls_Red').append('<div id="TPE_Presets_RedBall" style="text-align:center; margin-top:5px; width:100%; border:1px solid #cc0000; border-radius:3px; padding:5px 0;" title="Red Ball Presets"></div>');
//Blue...
$('#TPE_Ball_Options').append('<div id="TPE_Blue_Balls" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; margin:10px 5px; padding:6px; width:275px; border:1px solid #777; border-radius:10px;"></div>');
$('#TPE_Blue_Balls').append('<label title=""><input type="checkbox" id="TPE_ModifyBlue" data-saveto="blueball.modify" data-group="TPE_Group_BlueBall">Modify "Blue" Balls</label>');
$('#TPE_Blue_Balls').append('<div id="TPE_Balls_Blue" class="TPE_Group_BlueBall" style="position:relative; display:flex; flex-flow:column wrap; align-items:flex-start; padding:4px 10px; width:100%; margin-left:6px;"></div>');
$('#TPE_Balls_Blue').append('<label title="">Ball Color: <input type="color" data-saveto="blueball.color"></label>');
$('#TPE_Balls_Blue').append('<label title="Ball Radius (default is 19)">Ball Size: <input type="number" min="0" max="19" data-saveto="blueball.size"></label>');
$('#TPE_Balls_Blue').append('<label title="0=Transparent, 100=Solid Color">Ball Opacity: <input type="number" min="0" max="100" data-saveto="blueball.opacity"></label>');
$('#TPE_Balls_Blue').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Blue').append('<label title="Fill with a Radial Gradient"><input type="checkbox" data-saveto="blueball.gradient" data-group="TPE_BlueBall_Gradient_Group">Use Gradient</label>' +
'<div class="TPE_BlueBall_Gradient_Group TPE_SubGroup">' +
' <label title="Outer Gradient Color">Outer Color: <input type="color" data-saveto="blueball.gradient_color"></label>' +
' <label title="Gradient Start (Inner)">Gradient Start: <input type="number" min="0" max="40" data-saveto="blueball.gradient_start"></label>' +
' <label title="Gradient Stop (Outer)">Gradient Stop: <input type="number" min="0" max="40" data-saveto="blueball.gradient_stop"></label>' +
' <label title="Position of Gradient (Ball Center is 20)">Gradient Position: <input type="number" min="1" max="20" data-saveto="blueball.gradient_position"></label>' +
'</div>');
$('#TPE_Balls_Blue').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Blue').append('<label title="Width of border (0 to disable)">Border Width: <input type="number" min="0" max="19" data-saveto="blueball.border_width" data-group="TPE_BlueBall_Border_Group"></label>' +
'<div class="TPE_BlueBall_Border_Group TPE_SubGroup">' +
' <label title="Color of ball\'s outer border">Border Color: <input type="color" data-saveto="blueball.border_color"></label>' +
' <label title=""># Segments: <input type="number" min="0" max="20" step="2" data-saveto="blueball.border_segments" data-group="TPE_BlueBall_BorderSegments_Group"></label>' +
' <label class="TPE_BlueBall_BorderSegments_Group TPE_SubGroup" title="">Alt Border Color: <input type="color" data-saveto="blueball.border_alt_color"></label>' +
'</div>');
$('#TPE_Balls_Blue').append('<div class="TPE_Divider2"></div>');
$('#TPE_Balls_Blue').append('<div style="display:flex; flex-flow:column wrap; align-items:flex-start; width:100%; padding:2px; border:1px dotted #444; border-radius:3px; font-size:11px;">' +
' <label title=""><input type="checkbox" data-saveto="blueball.shapes_arc" data-group="TPE_BlueBall_Shapes_Arc_Group" style="margin:1px; width:11px; height:11px;">Arc</label>' +
' <div class="TPE_BlueBall_Shapes_Arc_Group TPE_SubGroup">' +
' <div><label title="">Color: <input type="color" data-saveto="blueball.shapes_arc_color"></label>' +
' <label title="">Transparent: <input type="checkbox" data-saveto="blueball.shapes_arc_transparent" style="width:11px; height:11px;"></label></div>' +
' <label title="">Line Width: <input type="number" min="1" max="19" data-saveto="blueball.shapes_arc_width"></label>' +
' <label title="">Position: <input type="number" min="1" max="19" data-saveto="blueball.shapes_arc_position"></label>' +
' <label title="">Size: <input type="number" min="1" max="18" data-saveto="blueball.shapes_arc_size"></label>' +
' </div>' +
'<div class="TPE_Divider"></div>' +
' <label title=""><input type="checkbox" data-saveto="blueball.shapes_star" data-group="TPE_BlueBall_Shapes_Star_Group" style="margin:1px; width:11px; height:11px;">Shapes</label>' +
' <div class="TPE_BlueBall_Shapes_Star_Group TPE_SubGroup">' +
' <div><label title="">Color: <input type="color" data-saveto="blueball.shapes_star_color"></label>' +
' <label title="">Transparent: <input type="checkbox" data-saveto="blueball.shapes_star_transparent" style="width:11px; height:11px;"></label></div>' +
' <div><label title="">Fill: <input type="checkbox" data-saveto="blueball.shapes_star_fill" data-group="TPE_Group_BlueBall_Shapes_Star_Fill" style="width:11px; height:11px;"></label>' +
' <label class="TPE_Group_BlueBall_Shapes_Star_Fill" title="">Fill Color: <input type="color" data-saveto="blueball.shapes_star_fill_color"></label></div>' +
' <label title="">Line Width: <input type="number" min="0" max="10" data-saveto="blueball.shapes_star_width"></label>' +
' <label title="">Spikes: <input type="number" min="2" max="20" data-saveto="blueball.shapes_star_spikes"></label>' +
' <label title="">Inner: <input type="number" min="0" max="20" data-saveto="blueball.shapes_star_inner"></label>' +
' <label title="">Outer: <input type="number" min="1" max="20" data-saveto="blueball.shapes_star_outer"></label>' +
' <div id="TPE_Presets_Shapes_BlueBall" style="text-align:center; margin-top:5px;"></div>' +
' </div>' +
'<div class="TPE_Divider"></div>' +
' <label title=""><input type="checkbox" data-saveto="blueball.shapes_overlay" data-group="TPE_BlueBall_Shapes_Overlay_Group" style="margin:1px; width:11px; height:11px;">Overlays</label>' +
' <div class="TPE_BlueBall_Shapes_Overlay_Group" style="text-align:center;">' +
' <div>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="marble1">Marble#1</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="marble2">Marble#2</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="earth1">Earth#1</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="earth2">Earth#2</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="swirl1">Swirl#1</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="donald">Donald</label>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="lucky">Lucky</label>' +
' </div>' +
' <label title=""><input type="radio" name="TPE_BlueBall_Shapes_Overlay_Type" data-saveto="blueball.shapes_overlay_type" data-type="custom">Custom (Base64)</label>' +
' <label title="Copy a Base64 Encoded string here (use https://www.base64-image.de/ to encode your image)"><input type="text" id="TPE_BlueBall_Shapes_Overlay_Base64" data-saveto="blueball.shapes_overlay_base64" style="margin:1px; width:220px; color:black;"></label>' +
' <label title="">Transparency: <input type="number" min="0" max="100" data-saveto="blueball.shapes_overlay_transparency"></label>' +
' </div>' +
'</div');
$('#TPE_Balls_Blue').append('<div id="TPE_Presets_BlueBall" style="text-align:center; margin-top:5px; width:100%; border:1px solid dodgerblue; border-radius:3px; padding:5px 0;" title="Blue Ball Presets"></div>');
$('#TPE_Red_Balls').append('<div class="TPE_Group_RedBall" style="position:absolute; top:5px; right:5px;"><canvas id="TPE_Red_Ball_Preview" width="40" height="40"></canvas></div>');
$('#TPE_Blue_Balls').append('<div class="TPE_Group_BlueBall" style="position:absolute; top:5px; right:5px;"><canvas id="TPE_Blue_Ball_Preview" width="40" height="40"></canvas></div>');
loadPresets();
loadCustomValues();
loadOptionsValues(true);
setTimeout(updateAllPreviews, 500);
GM_addStyle('#TPE_Container label, #TPE_Container_Balls label { margin:1px 2px 0; font-weight:normal; }');
GM_addStyle('#TPE_Container input[type="checkbox"], #TPE_Container_Balls input[type="checkbox"] { margin:4px 3px 3px 0; }');
GM_addStyle('#TPE_Container input[type="radio"], #TPE_Container_Balls input[type="radio"] { margin:2px 1px 2px 5px; width:11px; height:11px; }');
GM_addStyle('#TPE_Container input[type="number"], #TPE_Container_Balls input[type="number"] { color:black; width:46px; height:18px; margin:0 2px 0; }');
GM_addStyle('#TPE_Container input[type="color"], #TPE_Container_Balls input[type="color"] { margin:2px; padding:0px 3px; height:18px; }');
GM_addStyle('.TPE_MySavedPack { position:relative; margin:5px; padding:5px; color:black; background:#ccc; font-size:15px; font-weight:bold; border-radius:5px; cursor:pointer; }'); //border:1px solid #777; margin:5px; padding:0 12px 0 3px;
GM_addStyle('.TPE_DeleteSavedPack { display:none; position:absolute; width:15px; height:15px; top:0px; right:0px; color:white; background:red; opacity:0.7; font-size:11px; text-align:center; border-radius:50%; cursor:pointer; }');
GM_addStyle('.TPE_MySavedPackLabel { position:absolute; bottom:6px; left:50px; background:#22bb22; padding:0 3px; border-radius:3px; font:11px Arial; color:white; }');
GM_addStyle('.TPE_MySavedOptions { position:relative; color:black; background:#ccc; font-size:14px; font-weight:bold; border-radius:5px; cursor:pointer; border:1px solid #777; margin:5px; padding:1px 20px; }');
GM_addStyle('.TPE_DeleteSavedOptions { display:none; position:absolute; width:12px; height:13px; top:0px; right:0px; color:white; background:red; opacity:0.5; font-size:9px; text-align:center; border-radius:30%; cursor:pointer; }');
GM_addStyle('.TPE_Preset, .TPE_Shape_Preset, .TPE_FloorTile_Preset { display:inline-block; border:1px solid #777; border-radius:3px; margin:1px 2px; padding:1px 2px; min-width:12px; cursor:pointer; }');
GM_addStyle('.TPE_Preset:hover, .TPE_Shape_Preset:hover, .TPE_FloorTile_Preset:hover { background:#444; border:1px solid #FFF; }');
GM_addStyle('.TPE_SubGroup { margin-left:13px; }');
GM_addStyle('.TPE_Divider { border-top:1px dashed #555; width:100%; margin-top:5px; }');
GM_addStyle('.TPE_Divider2 { width:100%; margin-top:12px; margin-bottom:3px; }');
GM_addStyle('.texture-packs .texture-choice .name { font-size:15px; }');
GM_addStyle('.texture-packs .texture-choice .author { font-size:13px; }');
/*-------------------------------------------------------------------------------*/
// Bind events...
/*-------------------------------------------------------------------------------*/
$('#TPE_FloorTiles_Preview_Container').hoverIntent(function() {
var tilesImg = new Image();
var speedpadImg = new Image();
var portalImg = new Image();
var redBallImg, blueBallImg;
if (options.redball.modify) redBallImg = $('#TPE_Red_Ball_Preview')[0];
if (options.blueball.modify) blueBallImg = $('#TPE_Blue_Ball_Preview')[0];
$('#TPE_FloorTiles_Preview_Container').append('<div id="TP_PreviewerAll" style="position:absolute; display:inline-block; top:60px; left:-100px; padding:10px 10px 8px 10px; background:#111; box-shadow:0px 0px 9px white; border:1px solid #666; border-radius:5px; z-index:9999;">Generating Preview...</div>');
tilesImg.onload = function() {
let bg = createAllModsPreview(tilesImg, previewCanvas).toDataURL('image/png');
let bgColor = '#111';
if (options.gamewallpaper.type === 'color') {
bgColor = options.gamewallpaper.color;
} else if (options.gamewallpaper.type === 'gradient') {
let gradienttype = 'ellipse';
bgColor = 'rgba(0,0,0,0)';
if ((options.gamewallpaper.gradient_type === 'circle') || (options.gamewallpaper.gradient_type === 'ellipse')) {
$('#TP_PreviewerAll').css('background', 'radial-gradient('+options.gamewallpaper.gradient_type+' farthest-corner at 600px 40px , '+options.gamewallpaper.color1+' 0%, '+options.gamewallpaper.color2+' 100%)'); //options.gamewallpaper.color1;
} else if (options.gamewallpaper.gradient_type === 'horizontal') {
$('#TP_PreviewerAll').css('background', 'linear-gradient(to right, ' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color1 + ' 60%, ' + options.gamewallpaper.color2 + ')');
} else if (options.gamewallpaper.gradient_type === 'vertical') {
$('#TP_PreviewerAll').css('background', 'linear-gradient(' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ' 33%, ' + options.gamewallpaper.color2 + ')');
} else if (options.gamewallpaper.gradient_type === 'team') {
$('#TP_PreviewerAll').css('background', 'linear-gradient(135deg, ' + options.gamewallpaper.color1 + ', ' + options.gamewallpaper.color2 + ')');
}
} else if (options.gamewallpaper.type === 'image' && options.gamewallpaper.imagedata) {
bgColor = 'rgba(0,0,0,0)';
$('#TP_PreviewerAll').css('background', 'url('+options.gamewallpaper.imagedata+')');
} else if (options.gamewallpaper.type === 'none') {
bgColor = 'rgba(0,0,0,0)';
$('#TP_PreviewerAll').css('background', '#000 url("/images/background.jpg") center center / cover no-repeat');
} else {
bgColor = '#000000';
}
$('#TP_PreviewerAll').text('').append('<canvas id="TTM_BG_Preview" width="640" height="440" style="background:'+bgColor+' url('+bg+');"></canvas>');
initAnimation();
animatePreview(tilesImg, speedpadImg, portalImg, redBallImg, blueBallImg);
};
tilesImg.crossOrigin = "Anonymous";
tilesImg.src = $('#tiles').val();
speedpadImg.crossOrigin = 'Anonymous';
speedpadImg.src = $('#speedpad').val();
portalImg.crossOrigin = 'Anonymous';
portalImg.src = $('#portal').val();
}, function() {
$('#TP_PreviewerAll').remove();
});
var preview_map = {"info":{"width":16,"height":11},"data":{"0_5":{"id":9.1,"x":0,"y":5,"tx":520,"ty":120},"0_6":{"id":9.1,"x":0,"y":6,"tx":520,"ty":120},"1_1":{"id":2,"x":1,"y":1,"tx":520,"ty":160},"1_2":{"id":2,"x":1,"y":2,"tx":520,"ty":160},"1_3":{"id":2,"x":1,"y":3,"tx":520,"ty":160},"1_4":{"id":2,"x":1,"y":4,"tx":520,"ty":160},"1_5":{"id":2,"x":1,"y":5,"tx":520,"ty":160},"1_6":{"id":2,"x":1,"y":6,"tx":520,"ty":160},"1_7":{"id":2,"x":1,"y":7,"tx":520,"ty":160},"1_8":{"id":2,"x":1,"y":8,"tx":520,"ty":160},"1_9":{"id":2,"x":1,"y":9,"tx":520,"ty":160},"1_10":{"id":2,"x":1,"y":10,"tx":520,"ty":160},"2_1":{"id":2,"x":2,"y":1,"tx":520,"ty":160},"2.2":{"id":2,"x":2,"y":2,"tx":520,"ty":160},"2_3":{"id":2,"x":2,"y":3,"tx":520,"ty":160},"2_4":{"id":2,"x":2,"y":4,"tx":520,"ty":160},"2_5":{"id":2,"x":2,"y":5,"tx":520,"ty":160},"2_6":{"id":2,"x":2,"y":6,"tx":520,"ty":160},"2_7":{"id":2,"x":2,"y":7,"tx":520,"ty":160},"2_8":{"id":2,"x":2,"y":8,"tx":520,"ty":160},"2.9":{"id":2,"x":2,"y":9,"tx":520,"ty":160},"2_10":{"id":2,"x":2,"y":10,"tx":520,"ty":160},"3_0":{"id":9.2,"x":3,"y":0,"tx":560,"ty":120},"3_1":{"id":2,"x":3,"y":1,"tx":520,"ty":160},"3_2":{"id":2,"x":3,"y":2,"tx":520,"ty":160},"3_3":{"id":2,"x":3,"y":3,"tx":520,"ty":160},"3_4":{"id":2,"x":3,"y":4,"tx":520,"ty":160},"3_5":{"id":2,"x":3,"y":5,"tx":520,"ty":160},"3_6":{"id":2,"x":3,"y":6,"tx":520,"ty":160},"3_7":{"id":2,"x":3,"y":7,"tx":520,"ty":160},"3_8":{"id":2,"x":3,"y":8,"tx":520,"ty":160},"3_9":{"id":2,"x":3,"y":9,"tx":520,"ty":160},"3_10":{"id":2,"x":3,"y":10,"tx":520,"ty":160},"4_0":{"id":9.2,"x":4,"y":0,"tx":560,"ty":120},"4_1":{"id":2,"x":4,"y":1,"tx":520,"ty":160},"4_2":{"id":2,"x":4,"y":2,"tx":520,"ty":160},"4_3":{"id":2,"x":4,"y":3,"tx":520,"ty":160},"4_4":{"id":2,"x":4,"y":4,"tx":520,"ty":160},"4_5":{"id":2,"x":4,"y":5,"tx":520,"ty":160},"4_6":{"id":2,"x":4,"y":6,"tx":520,"ty":160},"4_7":{"id":2,"x":4,"y":7,"tx":520,"ty":160},"4_8":{"id":2,"x":4,"y":8,"tx":520,"ty":160},"4_9":{"id":2,"x":4,"y":9,"tx":520,"ty":160},"4_10":{"id":2,"x":4,"y":10,"tx":520,"ty":160},"5_1":{"id":2,"x":5,"y":1,"tx":520,"ty":160},"5_2":{"id":2,"x":5,"y":2,"tx":520,"ty":160},"5_3":{"id":2,"x":5,"y":3,"tx":520,"ty":160},"5_4":{"id":2,"x":5,"y":4,"tx":520,"ty":160},"5_5":{"id":2,"x":5,"y":5,"tx":520,"ty":160},"5_6":{"id":2,"x":5,"y":6,"tx":520,"ty":160},"5_7":{"id":2,"x":5,"y":7,"tx":520,"ty":160},"5_8":{"id":2,"x":5,"y":8,"tx":520,"ty":160},"5_9":{"id":2,"x":5,"y":9,"tx":520,"ty":160},"5_10":{"id":2,"x":5,"y":10,"tx":520,"ty":160},"6_1":{"id":2,"x":6,"y":1,"tx":520,"ty":160},"6_2":{"id":2,"x":6,"y":2,"tx":520,"ty":160},"6_3":{"id":2,"x":6,"y":3,"tx":520,"ty":160},"6_4":{"id":2,"x":6,"y":4,"tx":520,"ty":160},"6.5":{"id":2,"x":6,"y":5,"tx":520,"ty":160},"6_5":{"id":7,"x":6,"y":5,"tx":480,"ty":0},"6.6":{"id":2,"x":6,"y":6,"tx":520,"ty":160},"6_6":{"id":7,"x":6,"y":6,"tx":480,"ty":0},"6_7":{"id":2,"x":6,"y":7,"tx":520,"ty":160},"6_8":{"id":2,"x":6,"y":8,"tx":520,"ty":160},"6_9":{"id":2,"x":6,"y":9,"tx":520,"ty":160},"6_10":{"id":2,"x":6,"y":10,"tx":520,"ty":160},"7_0":{"id":2,"x":7,"y":0,"tx":520,"ty":160},"7_1":{"id":2,"x":7,"y":1,"tx":520,"ty":160},"7_2":{"id":2,"x":7,"y":2,"tx":520,"ty":160},"7.3":{"id":2,"x":7,"y":3,"tx":520,"ty":160},"7_3":{"id":8,"x":7,"y":3,"tx":520,"ty":240},"7_4":{"id":2,"x":7,"y":4,"tx":520,"ty":160},"7_6":{"id":11,"x":7,"y":6,"tx":560,"ty":160},"7_7":{"id":11,"x":7,"y":7,"tx":560,"ty":160},"7_8":{"id":2,"x":7,"y":8,"tx":520,"ty":160},"7_9":{"id":2,"x":7,"y":9,"tx":520,"ty":160},"7_10":{"id":2,"x":7,"y":10,"tx":520,"ty":160},"8_0":{"id":2,"x":8,"y":0,"tx":520,"ty":160},"8_1":{"id":2,"x":8,"y":1,"tx":520,"ty":160},"8_2":{"id":9,"x":8,"y":2,"tx":480,"ty":120},"8_3":{"id":9,"x":8,"y":3,"tx":480,"ty":120},"8_4":{"id":9,"x":8,"y":4,"tx":480,"ty":120},"8_6":{"id":11,"x":8,"y":6,"tx":560,"ty":160},"8_7":{"id":11,"x":8,"y":7,"tx":560,"ty":160},"8_8":{"id":11,"x":8,"y":8,"tx":560,"ty":160},"8_9":{"id":2,"x":8,"y":9,"tx":520,"ty":160},"8_10":{"id":2,"x":8,"y":10,"tx":520,"ty":160},"9_0":{"id":2,"x":9,"y":0,"tx":520,"ty":160},"9_1":{"id":2,"x":9,"y":1,"tx":520,"ty":160},"9_2":{"id":12,"x":9,"y":2,"tx":600,"ty":160},"9_3":{"id":9,"x":9,"y":3,"tx":480,"ty":120},"9_4":{"id":9,"x":9,"y":4,"tx":480,"ty":120},"9_6":{"id":18,"x":9,"y":6,"tx":600,"ty":200},"9_7":{"id":11,"x":9,"y":7,"tx":560,"ty":160},"9_8":{"id":11,"x":9,"y":8,"tx":560,"ty":160},"9_9":{"id":11,"x":9,"y":9,"tx":560,"ty":160},"9_10":{"id":2,"x":9,"y":10,"tx":520,"ty":160},"10_0":{"id":2,"x":10,"y":0,"tx":520,"ty":160},"10_1":{"id":2,"x":10,"y":1,"tx":520,"ty":160},"10_2":{"id":12,"x":10,"y":2,"tx":600,"ty":160},"10_3":{"id":12,"x":10,"y":3,"tx":600,"ty":160},"10_4":{"id":9,"x":10,"y":4,"tx":480,"ty":120},"10_6":{"id":18,"x":10,"y":6,"tx":600,"ty":200},"10_7":{"id":18,"x":10,"y":7,"tx":600,"ty":200},"10_8":{"id":11,"x":10,"y":8,"tx":560,"ty":160},"10_9":{"id":11,"x":10,"y":9,"tx":560,"ty":160},"10_10":{"id":11,"x":10,"y":10,"tx":560,"ty":160},"11_0":{"id":2,"x":11,"y":0,"tx":520,"ty":160},"11_1":{"id":2,"x":11,"y":1,"tx":520,"ty":160},"11_2":{"id":2,"x":11,"y":2,"tx":520,"ty":160},"11_3":{"id":12,"x":11,"y":3,"tx":600,"ty":160},"11_4":{"id":12,"x":11,"y":4,"tx":600,"ty":160},"11_7":{"id":18,"x":11,"y":7,"tx":600,"ty":200},"11_8":{"id":18,"x":11,"y":8,"tx":600,"ty":200},"11_9":{"id":11,"x":11,"y":9,"tx":560,"ty":160},"11_10":{"id":11,"x":11,"y":10,"tx":560,"ty":160},"12_0":{"id":2,"x":12,"y":0,"tx":520,"ty":160},"12_1":{"id":2,"x":12,"y":1,"tx":520,"ty":160},"12_2":{"id":2,"x":12,"y":2,"tx":520,"ty":160},"12_3":{"id":2,"x":12,"y":3,"tx":520,"ty":160},"12_4":{"id":2,"x":12,"y":4,"tx":520,"ty":160},"12.5":{"id":2,"x":12,"y":5,"tx":520,"ty":160},"12_5":{"id":10,"x":12,"y":5,"tx":480,"ty":40},"12_7":{"id":18,"x":12,"y":7,"tx":600,"ty":200},"12_8":{"id":18,"x":12,"y":8,"tx":600,"ty":200},"12_9":{"id":18,"x":12,"y":9,"tx":600,"ty":200},"12_10":{"id":18,"x":12,"y":10,"tx":600,"ty":200},"13_0":{"id":2,"x":13,"y":0,"tx":520,"ty":160},"13_1":{"id":2,"x":13,"y":1,"tx":520,"ty":160},"13_2":{"id":2,"x":13,"y":2,"tx":520,"ty":160},"13_3":{"id":2,"x":13,"y":3,"tx":520,"ty":160},"13_4":{"id":2,"x":13,"y":4,"tx":520,"ty":160},"13_5":{"id":2,"x":13,"y":5,"tx":520,"ty":160},"13.6":{"id":2,"x":13,"y":6,"tx":520,"ty":160},"13_6":{"id":10,"x":13,"y":6,"tx":480,"ty":40},"13_8":{"id":18,"x":13,"y":8,"tx":600,"ty":200},"13_9":{"id":18,"x":13,"y":9,"tx":600,"ty":200},"13_10":{"id":18,"x":13,"y":10,"tx":600,"ty":200},"14.0":{"id":2,"x":14,"y":0,"tx":520,"ty":160},"14_0":{"id":7,"x":14,"y":0,"tx":480,"ty":0},"14.1":{"id":2,"x":14,"y":1,"tx":520,"ty":160},"14_2":{"id":2,"x":14,"y":2,"tx":520,"ty":160},"14_3":{"id":2,"x":14,"y":3,"tx":520,"ty":160},"14_4":{"id":2,"x":14,"y":4,"tx":520,"ty":160},"14_5":{"id":2,"x":14,"y":5,"tx":520,"ty":160},"14_6":{"id":2,"x":14,"y":6,"tx":520,"ty":160},"14_8":{"id":9.3,"x":14,"y":8,"tx":600,"ty":120},"14_9":{"id":9.3,"x":14,"y":9,"tx":600,"ty":120},"14_10":{"id":9.3,"x":14,"y":10,"tx":600,"ty":120},"15.0":{"id":2,"x":15,"y":0,"tx":520,"ty":160},"15.1":{"id":2,"x":15,"y":1,"tx":520,"ty":160},"15_1":{"id":7,"x":15,"y":1,"tx":480,"ty":0},"15_2":{"id":2,"x":15,"y":2,"tx":520,"ty":160},"15_3":{"id":2,"x":15,"y":3,"tx":520,"ty":160},"15_4":{"id":2,"x":15,"y":4,"tx":520,"ty":160},"15_5":{"id":2,"x":15,"y":5,"tx":520,"ty":160},"15_6":{"id":2,"x":15,"y":6,"tx":520,"ty":160},"15_8":{"id":2,"x":15,"y":8,"tx":520,"ty":160},"15_9":{"id":2,"x":15,"y":9,"tx":520,"ty":160},"15_10":{"id":2,"x":15,"y":10,"tx":520,"ty":160}}};
var preview_pups = {"jukejuice":{"id":6.1,"x":14,"y":1,"tx":480,"ty":160}, "rollingbomb":{"id":6.2,"x":2,"y":2,"tx":480,"ty":200}, "tagpro":{"id":6.3,"x":15,"y":0,"tx":480,"ty":240}, "placeholder":{"id":6.5,"x":2,"y":9,"tx":480,"ty":320} };
var preview_walls = {"0":{"q":0,"x":0,"y":0,"tx":0,"ty":280},"1":{"q":1,"x":0,"y":0,"tx":220,"ty":200},"2":{"q":2,"x":0,"y":0,"tx":220,"ty":220},"3":{"q":3,"x":0,"y":0,"tx":0,"ty":220},"4":{"q":0,"x":0,"y":1,"tx":0,"ty":200},"5":{"q":1,"x":0,"y":1,"tx":220,"ty":240},"6":{"q":2,"x":0,"y":1,"tx":300,"ty":340},"7":{"q":3,"x":0,"y":1,"tx":0,"ty":220},"8":{"q":0,"x":0,"y":2,"tx":0,"ty":200},"9":{"q":1,"x":0,"y":2,"tx":300,"ty":360},"10":{"q":2,"x":0,"y":2,"tx":460,"ty":220},"11":{"q":3,"x":0,"y":2,"tx":0,"ty":220},"12":{"q":0,"x":0,"y":3,"tx":0,"ty":200},"13":{"q":1,"x":0,"y":3,"tx":460,"ty":200},"14":{"q":2,"x":0,"y":3,"tx":460,"ty":220},"15":{"q":3,"x":0,"y":3,"tx":0,"ty":220},"16":{"q":0,"x":0,"y":4,"tx":0,"ty":200},"17":{"q":1,"x":0,"y":4,"tx":460,"ty":200},"18":{"q":2,"x":0,"y":4,"tx":460,"ty":300},"19":{"q":3,"x":0,"y":4,"tx":0,"ty":300},"20":{"q":0,"x":0,"y":7,"tx":0,"ty":280},"21":{"q":1,"x":0,"y":7,"tx":460,"ty":280},"22":{"q":2,"x":0,"y":7,"tx":460,"ty":220},"23":{"q":3,"x":0,"y":7,"tx":0,"ty":220},"24":{"q":0,"x":0,"y":8,"tx":0,"ty":200},"25":{"q":1,"x":0,"y":8,"tx":460,"ty":200},"26":{"q":2,"x":0,"y":8,"tx":460,"ty":220},"27":{"q":3,"x":0,"y":8,"tx":0,"ty":220},"28":{"q":0,"x":0,"y":9,"tx":0,"ty":200},"29":{"q":1,"x":0,"y":9,"tx":460,"ty":200},"30":{"q":2,"x":0,"y":9,"tx":60,"ty":340},"31":{"q":3,"x":0,"y":9,"tx":0,"ty":220},"32":{"q":0,"x":0,"y":10,"tx":0,"ty":200},"33":{"q":1,"x":0,"y":10,"tx":60,"ty":360},"34":{"q":2,"x":0,"y":10,"tx":220,"ty":220},"35":{"q":3,"x":0,"y":10,"tx":0,"ty":220},"36":{"q":0,"x":0,"y":11,"tx":0,"ty":200},"37":{"q":1,"x":0,"y":11,"tx":220,"ty":240},"38":{"q":2,"x":0,"y":11,"tx":340,"ty":420},"39":{"q":3,"x":0,"y":11,"tx":0,"ty":300},"40":{"q":0,"x":1,"y":0,"tx":240,"ty":200},"41":{"q":1,"x":1,"y":0,"tx":220,"ty":200},"42":{"q":2,"x":1,"y":0,"tx":340,"ty":300},"43":{"q":3,"x":1,"y":0,"tx":240,"ty":220},"44":{"q":0,"x":1,"y":1,"tx":240,"ty":400},"45":{"q":1,"x":1,"y":1,"tx":340,"ty":320},"46":{"q":3,"x":1,"y":1,"tx":320,"ty":340},"47":{"q":0,"x":1,"y":10,"tx":80,"ty":360},"48":{"q":2,"x":1,"y":10,"tx":100,"ty":380},"49":{"q":3,"x":1,"y":10,"tx":240,"ty":340},"50":{"q":0,"x":1,"y":11,"tx":240,"ty":240},"51":{"q":1,"x":1,"y":11,"tx":100,"ty":400},"52":{"q":2,"x":1,"y":11,"tx":340,"ty":420},"53":{"q":3,"x":1,"y":11,"tx":360,"ty":420},"54":{"q":0,"x":2,"y":0,"tx":240,"ty":200},"55":{"q":1,"x":2,"y":0,"tx":460,"ty":280},"56":{"q":2,"x":2,"y":0,"tx":460,"ty":300},"57":{"q":3,"x":2,"y":0,"tx":360,"ty":300},"58":{"q":0,"x":2,"y":11,"tx":120,"ty":400},"59":{"q":1,"x":2,"y":11,"tx":220,"ty":200},"60":{"q":2,"x":2,"y":11,"tx":340,"ty":420},"61":{"q":3,"x":2,"y":11,"tx":360,"ty":420},"62":{"q":0,"x":3,"y":11,"tx":240,"ty":200},"63":{"q":1,"x":3,"y":11,"tx":220,"ty":200},"64":{"q":2,"x":3,"y":11,"tx":340,"ty":420},"65":{"q":3,"x":3,"y":11,"tx":360,"ty":420},"66":{"q":0,"x":4,"y":11,"tx":240,"ty":200},"67":{"q":1,"x":4,"y":11,"tx":220,"ty":200},"68":{"q":2,"x":4,"y":11,"tx":340,"ty":420},"69":{"q":3,"x":4,"y":11,"tx":360,"ty":420},"70":{"q":0,"x":5,"y":0,"tx":0,"ty":280},"71":{"q":1,"x":5,"y":0,"tx":220,"ty":200},"72":{"q":2,"x":5,"y":0,"tx":340,"ty":420},"73":{"q":3,"x":5,"y":0,"tx":0,"ty":300},"74":{"q":0,"x":5,"y":11,"tx":240,"ty":200},"75":{"q":1,"x":5,"y":11,"tx":220,"ty":200},"76":{"q":2,"x":5,"y":11,"tx":340,"ty":420},"77":{"q":3,"x":5,"y":11,"tx":360,"ty":420},"78":{"q":0,"x":6,"y":0,"tx":240,"ty":200},"79":{"q":1,"x":6,"y":0,"tx":220,"ty":200},"80":{"q":2,"x":6,"y":0,"tx":380,"ty":420},"81":{"q":3,"x":6,"y":0,"tx":360,"ty":420},"82":{"q":0,"x":6,"y":11,"tx":240,"ty":200},"83":{"q":1,"x":6,"y":11,"tx":220,"ty":200},"84":{"q":2,"x":6,"y":11,"tx":340,"ty":420},"85":{"q":3,"x":6,"y":11,"tx":360,"ty":420},"86":{"q":0,"x":7,"y":0,"tx":280,"ty":200},"87":{"q":1,"x":7,"y":0,"tx":300,"ty":200},"88":{"q":3,"x":7,"y":0,"tx":400,"ty":420},"89":{"q":0,"x":7,"y":5,"tx":0,"ty":280},"90":{"q":1,"x":7,"y":5,"tx":220,"ty":200},"91":{"q":2,"x":7,"y":5,"tx":340,"ty":300},"92":{"q":3,"x":7,"y":5,"tx":0,"ty":220},"93":{"q":0,"x":7,"y":6,"tx":0,"ty":240},"94":{"q":1,"x":7,"y":6,"tx":340,"ty":320},"95":{"q":3,"x":7,"y":6,"tx":200,"ty":300},"96":{"q":0,"x":7,"y":11,"tx":240,"ty":200},"97":{"q":1,"x":7,"y":11,"tx":220,"ty":200},"98":{"q":2,"x":7,"y":11,"tx":340,"ty":420},"99":{"q":3,"x":7,"y":11,"tx":360,"ty":420},"100":{"q":0,"x":8,"y":5,"tx":240,"ty":200},"101":{"q":1,"x":8,"y":5,"tx":220,"ty":200},"102":{"q":2,"x":8,"y":5,"tx":340,"ty":420},"103":{"q":3,"x":8,"y":5,"tx":360,"ty":300},"104":{"q":0,"x":8,"y":11,"tx":240,"ty":200},"105":{"q":1,"x":8,"y":11,"tx":220,"ty":200},"106":{"q":2,"x":8,"y":11,"tx":340,"ty":420},"107":{"q":3,"x":8,"y":11,"tx":360,"ty":420},"108":{"q":0,"x":9,"y":5,"tx":240,"ty":200},"109":{"q":1,"x":9,"y":5,"tx":220,"ty":200},"110":{"q":2,"x":9,"y":5,"tx":340,"ty":420},"111":{"q":3,"x":9,"y":5,"tx":360,"ty":420},"112":{"q":0,"x":9,"y":11,"tx":240,"ty":200},"113":{"q":1,"x":9,"y":11,"tx":220,"ty":200},"114":{"q":2,"x":9,"y":11,"tx":340,"ty":420},"115":{"q":3,"x":9,"y":11,"tx":360,"ty":420},"116":{"q":0,"x":10,"y":5,"tx":240,"ty":200},"117":{"q":1,"x":10,"y":5,"tx":220,"ty":200},"118":{"q":2,"x":10,"y":5,"tx":380,"ty":300},"119":{"q":3,"x":10,"y":5,"tx":360,"ty":420},"120":{"q":0,"x":10,"y":11,"tx":240,"ty":200},"121":{"q":1,"x":10,"y":11,"tx":220,"ty":200},"122":{"q":2,"x":10,"y":11,"tx":340,"ty":420},"123":{"q":3,"x":10,"y":11,"tx":360,"ty":420},"124":{"q":0,"x":11,"y":5,"tx":240,"ty":200},"125":{"q":1,"x":11,"y":5,"tx":460,"ty":280},"126":{"q":2,"x":11,"y":5,"tx":300,"ty":380},"127":{"q":3,"x":11,"y":5,"tx":400,"ty":300},"128":{"q":0,"x":11,"y":6,"tx":400,"ty":320},"129":{"q":1,"x":11,"y":6,"tx":300,"ty":400},"130":{"q":2,"x":11,"y":6,"tx":100,"ty":300},"131":{"q":3,"x":11,"y":6,"tx":0,"ty":300},"132":{"q":0,"x":11,"y":11,"tx":240,"ty":200},"133":{"q":1,"x":11,"y":11,"tx":220,"ty":200},"134":{"q":2,"x":11,"y":11,"tx":340,"ty":420},"135":{"q":3,"x":11,"y":11,"tx":360,"ty":420},"136":{"q":0,"x":12,"y":6,"tx":320,"ty":400},"137":{"q":1,"x":12,"y":6,"tx":460,"ty":280},"138":{"q":2,"x":12,"y":6,"tx":300,"ty":380},"139":{"q":3,"x":12,"y":6,"tx":120,"ty":300},"140":{"q":0,"x":12,"y":7,"tx":120,"ty":320},"141":{"q":1,"x":12,"y":7,"tx":380,"ty":160},"142":{"q":2,"x":12,"y":7,"tx":60,"ty":420},"143":{"q":0,"x":12,"y":11,"tx":240,"ty":200},"144":{"q":1,"x":12,"y":11,"tx":220,"ty":200},"145":{"q":2,"x":12,"y":11,"tx":340,"ty":420},"146":{"q":3,"x":12,"y":11,"tx":360,"ty":420},"147":{"q":0,"x":13,"y":7,"tx":320,"ty":400},"148":{"q":1,"x":13,"y":7,"tx":220,"ty":200},"149":{"q":2,"x":13,"y":7,"tx":340,"ty":420},"150":{"q":3,"x":13,"y":7,"tx":80,"ty":420},"151":{"q":0,"x":13,"y":11,"tx":240,"ty":200},"152":{"q":1,"x":13,"y":11,"tx":220,"ty":200},"153":{"q":2,"x":13,"y":11,"tx":340,"ty":420},"154":{"q":3,"x":13,"y":11,"tx":360,"ty":420},"155":{"q":0,"x":14,"y":7,"tx":240,"ty":200},"156":{"q":1,"x":14,"y":7,"tx":220,"ty":200},"157":{"q":2,"x":14,"y":7,"tx":340,"ty":420},"158":{"q":3,"x":14,"y":7,"tx":360,"ty":420},"159":{"q":0,"x":14,"y":11,"tx":240,"ty":200},"160":{"q":1,"x":14,"y":11,"tx":220,"ty":200},"161":{"q":2,"x":14,"y":11,"tx":340,"ty":420},"162":{"q":3,"x":14,"y":11,"tx":360,"ty":420},"163":{"q":0,"x":15,"y":7,"tx":240,"ty":200},"164":{"q":1,"x":15,"y":7,"tx":220,"ty":200},"165":{"q":2,"x":15,"y":7,"tx":380,"ty":300},"166":{"q":3,"x":15,"y":7,"tx":360,"ty":420},"167":{"q":0,"x":15,"y":11,"tx":240,"ty":200},"168":{"q":1,"x":15,"y":11,"tx":140,"ty":400},"169":{"q":2,"x":15,"y":11,"tx":340,"ty":420},"170":{"q":3,"x":15,"y":11,"tx":360,"ty":420},"171":{"q":0,"x":16,"y":7,"tx":240,"ty":200},"172":{"q":1,"x":16,"y":7,"tx":460,"ty":280},"173":{"q":2,"x":16,"y":7,"tx":460,"ty":220},"174":{"q":3,"x":16,"y":7,"tx":400,"ty":300},"175":{"q":0,"x":16,"y":8,"tx":400,"ty":320},"176":{"q":1,"x":16,"y":8,"tx":460,"ty":200},"177":{"q":2,"x":16,"y":8,"tx":460,"ty":220},"178":{"q":3,"x":16,"y":8,"tx":0,"ty":220},"179":{"q":0,"x":16,"y":9,"tx":0,"ty":200},"180":{"q":1,"x":16,"y":9,"tx":460,"ty":200},"181":{"q":2,"x":16,"y":9,"tx":460,"ty":220},"182":{"q":3,"x":16,"y":9,"tx":0,"ty":220},"183":{"q":0,"x":16,"y":10,"tx":0,"ty":200},"184":{"q":1,"x":16,"y":10,"tx":460,"ty":200},"185":{"q":2,"x":16,"y":10,"tx":460,"ty":220},"186":{"q":3,"x":16,"y":10,"tx":160,"ty":380},"187":{"q":0,"x":16,"y":11,"tx":160,"ty":400},"188":{"q":1,"x":16,"y":11,"tx":460,"ty":200},"189":{"q":2,"x":16,"y":11,"tx":460,"ty":300},"190":{"q":3,"x":16,"y":11,"tx":360,"ty":420}};
previewCanvas.width = preview_map.info.width * 40;
previewCanvas.height = preview_map.info.height * 40;
var createAllModsPreview = function(tilesImage) {
var previewCtx = previewCanvas.getContext("2d");
previewCtx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
var tileCanvas = document.createElement('canvas');
tileCanvas.width = 40;
tileCanvas.height = 40;
var tileCtx = tileCanvas.getContext('2d');
//tiles...
tileCanvas.width = 40;
tileCanvas.height = 40;
//floor, objects..
$.each(preview_map.data, function(key, value) {
tileCtx.clearRect(0, 0, tileCanvas.width, tileCanvas.height);
evenX = (Math.floor(value.x) % 2 === 0 ? true : false);
evenY = (Math.floor(value.y) % (options.floortiles.checkered && options.floortiles.checkered_stripes ? 0 : 2) === 0 ? true : false);
if (value.id === 2) {
drawFloorTile(tileCtx, tilesImage, evenX, evenY);
if (options.spikes.floortint && options.spikes.floortint_opacity > 0) {
let newKey = key.replace('.', '_');
if (preview_map.data.hasOwnProperty(newKey) && preview_map.data[newKey].id === 7) {
let margin = +options.spikes.floortint_margin;
tileCtx.translate(-0.5, -0.5);
tileCtx.lineWidth = 1;
tileCtx.strokeStyle = hexToRgbA(options.spikes.floortint_color, options.spikes.floortint_opacity / 100);
tileCtx.fillStyle = hexToRgbA(options.spikes.floortint_color, options.spikes.floortint_fillopacity / 100);
if (options.spikes.floortint_dash) tileCtx.setLineDash([options.spikes.floortint_dash]);
roundedRect(tileCtx, margin, margin, 41-margin*2, 41-margin*2, +options.spikes.floortint_rounded, options.spikes.floortint_stroke, options.spikes.floortint_fill);
if (options.spikes.floortint_dash) tileCtx.setLineDash([]);
tileCtx.translate(0.5, 0.5);
}
}
if (options.bombs.floortint && options.bombs.floortint_opacity > 0) {
let newKey = key.replace('.', '_');
if (preview_map.data.hasOwnProperty(newKey) && preview_map.data[newKey].id === 10) {
let margin = +options.bombs.floortint_margin;
tileCtx.save();
tileCtx.translate(-0.5, -0.5);
tileCtx.lineWidth = 1;
tileCtx.strokeStyle = hexToRgbA(options.bombs.floortint_color, options.bombs.floortint_opacity / 100);
tileCtx.fillStyle = hexToRgbA(options.bombs.floortint_color, options.bombs.floortint_fillopacity / 100);
if (options.bombs.floortint_dash) tileCtx.setLineDash([options.bombs.floortint_dash]);
roundedRect(tileCtx, margin, margin, 41-margin*2, 41-margin*2, 0, options.bombs.floortint_stroke, options.bombs.floortint_fill);
if (options.bombs.floortint_dash) tileCtx.setLineDash([]);
//tileCtx.translate(0.5, 0.5);
tileCtx.restore();
}
}
if (options.shapes.basefill && (value.x > 12) && (value.y < 2)) {
tileCtx.fillStyle = hexToRgbA(options.shapes.basefill_red_color, options.shapes.basefill_opacity / 100);
tileCtx.fillRect(0, 0, 40, 40);
}
if (options.shapes.baseradius) {
let doTranslate = (options.shapes.baseradius_width % 2 !== 0);
tileCtx.strokeStyle = hexToRgbA(options.shapes.baseradius_red_color, options.shapes.baseradius_opacity / 100);
tileCtx.lineWidth = options.shapes.baseradius_width;
if (options.shapes.baseradius_dashsize > 0) {
tileCtx.setLineDash([options.shapes.baseradius_dashsize]);
if (doTranslate) tileCtx.translate(0.5, 0.5);
}
tileCtx.beginPath();
if (value.x === 12 && (value.y === 0 || value.y === 1)) {
tileCtx.moveTo(20, 0);
tileCtx.lineTo(20, 40);
} else if (value.x === 12 && (value.y === 2)) {
tileCtx.moveTo(20, 0);
tileCtx.arcTo(20, 20, 40, 20, 20);
} else if ((value.x === 13 || value.x === 14 || value.x === 15) && (value.y === 2)) {
tileCtx.moveTo(0, 20);
tileCtx.lineTo(40, 20);
}
tileCtx.stroke();
if (options.shapes.baseradius_dashsize > 0) {
if (doTranslate) tileCtx.translate(-0.5, -0.5);
tileCtx.setLineDash([]);
}
}
if (options.shapes.centerline && value.y === Math.floor(preview_map.info.height / 2)) {
let doTranslate = (options.shapes.centerline_width % 2 !== 0);
tileCtx.strokeStyle = hexToRgbA(options.shapes.centerline_color, options.shapes.centerline_opacity / 100);
tileCtx.lineWidth = options.shapes.centerline_width;
if (options.shapes.centerline_dashsize > 0) {
tileCtx.setLineDash([options.shapes.centerline_dashsize]);
if (doTranslate) tileCtx.translate(0.5, 0.5);
}
tileCtx.beginPath();
tileCtx.moveTo(0, 20);
tileCtx.lineTo(40, 20);
tileCtx.stroke();
if (options.shapes.centerline_dashsize > 0) {
if (doTranslate) tileCtx.translate(-0.5, -0.5);
tileCtx.setLineDash([]);
}
}
previewCtx.drawImage(tileCanvas, (value.x*40), (value.y*40));
} else if ((value.id === 11) || (value.id === 12) || (value.id === 17) || (value.id === 18) || (value.id === 9) || (value.id === 9.1) || (value.id === 9.2) || (value.id === 9.3)) {
tileCtx.drawImage(tilesImage, value.tx,value.ty,40,40, 0,0,40,40);
previewCtx.drawImage(tileCanvas, (value.x*40), (value.y*40));
} else if (value.id === 7 && options.spikes.modify) {
tileCtx.drawImage(tilesImage, value.tx,value.ty,40,40, 0,0,40,40);
setTint(tileCanvas, options.spikes.color, options.spikes.opacity/100);
previewCtx.drawImage(tileCanvas, (value.x*40), (value.y*40));
} else if (value.id === 10 && options.bombs.modify) {
tileCtx.drawImage(tilesImage, value.tx,value.ty,40,40, 0,0,40,40);
setTint(tileCanvas, options.bombs.color, options.bombs.opacity/100);
previewCtx.drawImage(tileCanvas, (value.x*40), (value.y*40));
} else {
previewCtx.drawImage(tilesImage, value.tx,value.ty,40,40, (value.x*40),(value.y*40),40,40);
}
});
//pups..
$.each(preview_pups, function(key, value) {
tileCtx.clearRect(0, 0, tileCanvas.width, tileCanvas.height);
tileCtx.drawImage(tilesImage, value.tx,value.ty,40,40, 0,0,40,40);
previewCtx.drawImage(tileCanvas, (value.x*40), (value.y*40));
});
//walls...
tileCanvas.width = 20;
tileCanvas.height = 20;
var rgbks;
var wallsCanvas = document.createElement('canvas');
wallsCanvas.width = 480;
wallsCanvas.height = 440;
var wallsCtx = wallsCanvas.getContext('2d');
wallsCtx.drawImage(tilesImage, 0,0,480,440, 0,0,480,440);
if (options.walls.modify) setTint(wallsCanvas, options.walls.color, options.walls.opacity/100);
$.each(preview_walls, function(key, value) {
if (value.q >= 0) {
var xoffset = 0, yoffset = 0;
tileCtx.clearRect(0, 0, tileCanvas.width, tileCanvas.height);
if ((value.q === 1) || (value.q === 2)) xoffset = 20;
if ((value.q === 0) || (value.q === 1)) yoffset = -20;
tileCtx.drawImage(wallsCanvas, value.tx,value.ty,20,20, 0,0,20,20);
previewCtx.drawImage(tileCanvas, (value.x*40)+xoffset, (value.y*40)+yoffset+20);
}
});
wallsCanvas = null;
tileCanvas = null;
return previewCanvas;
};
//"Import Custom" previews...
$('#custom').append('<div id="TP_PreviewerSingle" style="position:absolute; display:none; background:#000 url(\'/textures/classic/tiles.png\') center / contain no-repeat; width:640px; height:440px; top:64px; right:0px; box-shadow:0px 0px 9px white; border-radius:5px; z-index:9998;"></div>');
$('#custom').find('.TP_ShowPreview').hoverIntent(function() {
var id = $(this).siblings('input').attr('id');
var value = $(this).siblings('input').val();
var width = '640px';
var height = '40px';
if (!value || (!value.startsWith('http') && !value.startsWith('/')) || !value.endsWith('.png')) value = '/textures/classic/'+id+'.png';
if (id === 'tiles') height = '440px';
else if (id === 'splats') height = '240px';
$('#TP_Previewer').show();
$(this).before( $('#TP_PreviewerSingle') );
$('#TP_PreviewerSingle').css({ 'background':'#000 url(\''+value+'\') center / contain no-repeat', 'width':width, 'height':height });
$('#TP_PreviewerSingle').fadeIn(50);
}, function() {
$('#TP_PreviewerSingle').fadeOut(50);
});
$('#TP_ShowPreviewAll').hoverIntent(function() {
var tilesImg = new Image();
var speedpadImg = new Image();
var portalImg = new Image();
$('#TP_ShowPreviewAll').append('<div id="TP_PreviewerAll" style="position:absolute; display:inline-block; bottom:20px; right:-10px; padding:10px; background:#111; box-shadow:0px 0px 9px white; border:1px solid #666; border-radius:5px; z-index:9999;">Generating Preview...</div>');
tilesImg.onload = function() {
let bg = createPreview(tilesImg).toDataURL('image/png');
$('#TP_PreviewerAll').text('').append('<canvas id="TTM_BG_Preview" width="640" height="440" style="background-image: url('+bg+');"></canvas>');
initAnimation();
animatePreview(tilesImg, speedpadImg, portalImg);
};
tilesImg.crossOrigin = "Anonymous";
tilesImg.src = $('#tiles').val();
speedpadImg.crossOrigin = 'Anonymous';
speedpadImg.src = $('#speedpad').val();
portalImg.crossOrigin = 'Anonymous';
portalImg.src = $('#portal').val();
}, function() {
$('#TP_PreviewerAll').remove();
});
/*-------------------------------------------------------------------------------*/
var createPreview = function(img, isThumbnail=false) {
let ctx = previewCanvas.getContext("2d");
//floor, objects..
$.each(preview_map.data, function(key, value) {
ctx.drawImage(img, value.tx, value.ty, 40, 40, value.x*40, value.y*40, 40, 40);
});
//pups..
$.each(preview_pups, function(key, value) {
ctx.drawImage(img, value.tx, value.ty, 40, 40, value.x*40, value.y*40, 40, 40);
});
//walls...
$.each(preview_walls, function(key, value) {
if (value.q >= 0) {
var xoffset = 0, yoffset = 0;
if ((value.q === 1) || (value.q === 2)) xoffset = 20;
if ((value.q === 0) || (value.q === 1)) yoffset = -20;
ctx.drawImage(img, value.tx, value.ty, 20, 20, value.x*40+xoffset, value.y*40+yoffset+20, 20, 20);
}
});
if (isThumbnail) {
let tempCanvas = document.createElement('canvas');
tempCanvas.width = 200;
tempCanvas.height = 138;
let tempCtx = tempCanvas.getContext("2d");
tempCtx.drawImage(previewCanvas, 0,0,640,440, 0,0,200,138);
return tempCanvas;
} else {
return previewCanvas;
}
};
var drawPop, popStartSize, popStep, extraAnimFramePos, frameCount, animObjects;
var initAnimation = function() {
drawPop = 0;
popStartSize = 100;
popStep = 10;
extraAnimFramePos = 0;
frameCount = 0;
animObjects = {
rball: { p0:{x:840, y:-200}, p1:{x:40, y:40}, p2:{x:40, y:400}, p3:{x:540, y:390}, tx:560, ty:0, speed:0.003, t:0 },
bball: { p0:{x:680, y:-160}, p1:{x:-40, y:130}, p2:{x:0, y:540}, p3:{x:405, y:270}, tx:600, ty:0, speed:0.003, t:0 },
yflag: { p0:{x:120, y:94}, p1:{x:352, y:346}, p2:{x:352, y:346}, p3:{x:352, y:346}, tx:520, ty:40, speed:0.0015, t:0, offx:13, offy:-32 },
};
};
var animatePreview = function(tilesImg, speedpadImg, portalImg, redBallImg, blueBallImg) {
if (!$('#TTM_BG_Preview').length) return;
var bgCtx = document.getElementById('TTM_BG_Preview').getContext('2d');
bgCtx.clearRect(0, 0, previewCanvas.width, previewCanvas.height);
bgCtx.fillStyle = 'rgba(255,128,0,0.1)';
for (var key in animObjects) {
let value = animObjects[key];
let draw = true;
var pt;
if (key === 'yflag') {
pt = { x:animObjects.bball.x + value.offx, y:animObjects.bball.y + value.offy };
if ((value.speed < 0 && value.t < 0.5) || (value.speed > 0 && value.t > 0.5)) draw = false;
if (draw && pt.x > 370 && pt.y > 230) draw = false;
} else {
pt = calcBezierPoint(value.t, value.p0, value.p1, value.p2, value.p3);
value.x = pt.x;
value.y = pt.y;
if (key === 'rball') {
if (value.speed < 0) draw = false;
if (drawPop === 0 && pt.x+39 > value.p3.x && pt.y > 230 && value.speed < 0) drawPop = popStartSize;
}
}
if (draw) {
if (key === 'rball') {
bgCtx.save();
bgCtx.translate(pt.x, pt.y);
bgCtx.rotate(200+(50*value.t));
bgCtx.globalAlpha = ((100 - options.gameoptions.ball_transparency) / 100);
if (options.gameoptions.filters_brightness) bgCtx.filter = 'brightness('+options.gameoptions.filters_brightness_value+'%) ';
if (redBallImg) bgCtx.drawImage(redBallImg, 0,0,40,40, -20,-20,40,40);
else bgCtx.drawImage(tilesImg, value.tx,value.ty,40,40, -20,-20,40,40);
bgCtx.translate(-pt.x, -pt.y);
bgCtx.globalAlpha = 1;
bgCtx.restore();
} else if (key === 'bball' && blueBallImg) {
bgCtx.globalAlpha = ((100 - options.gameoptions.ball_transparency) / 100);
bgCtx.drawImage(blueBallImg, 0,0,40,40, pt.x,pt.y,40,40);
bgCtx.globalAlpha = 1;
} else {
bgCtx.drawImage(tilesImg, value.tx,value.ty,40,40, pt.x,pt.y,40,40);
}
}
value.t += value.speed;
if (value.t > 1 || value.t < 0) value.speed *= -1;
}
if (drawPop > 0) {
bgCtx.beginPath();
bgCtx.arc(540,390,popStartSize-drawPop, 0, Math.PI*2, false);
bgCtx.fill();
drawPop-=popStep;
} else {
drawPop = 0;
}
if (speedpadImg) {
bgCtx.drawImage(speedpadImg, extraAnimFramePos,0,40,40, 440,80,40,40);
}
if (portalImg) {
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,320,40,40);
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,360,40,40);
bgCtx.drawImage(portalImg, extraAnimFramePos,0,40,40, 600,400,40,40);
}
if (frameCount % 8 === 0) extraAnimFramePos+=40;
if (extraAnimFramePos >= 160) extraAnimFramePos = 0;
frameCount++;
window.requestAnimationFrame(function() { animatePreview(tilesImg, speedpadImg, portalImg, redBallImg, blueBallImg); });
};
var calcBezierPoint = function(t, p0, p1, p2, p3) {
var data = [p0, p1, p2, p3];
var at = 1 - t;
for (var i = 1; i < data.length; i++) {
for (var k = 0; k < data.length - i; k++) {
data[k] = {
x: data[k].x * at + data[k + 1].x * t,
y: data[k].y * at + data[k + 1].y * t
};
}
}
return data[0];
};
/*-------------------------------------------------------------------------------*/
$('.texture-choice').on('click', function() {
var currentTiles = $('#tiles').val();
var clearableCounter = 0;
var clearable = setInterval(function() {
clearableCounter+=50;
if (clearableCounter > 2000) {
clearInterval(clearable);
}
if ($('#tiles').val() !== currentTiles) {
clearInterval(clearable);
updateFloorTilesPreview();
}
}, 50);
});
$('#TPE_DeleteAllOptions').on('click', function() {
if (!confirm('All saved options sets will be deleted and this page will reload\n\nOK to continue?\n\n')) return;
GM_deleteValue('myOptions');
window.location.reload();
}).hover(function() {
$(this).css('opacity', '1');
}, function() {
$(this).css('opacity', '0.2');
});
$('.TPE_Import_Presets').on('click', function() {
var what = this.dataset.key;
var response = prompt('Enter JSON string to import ' + what + ' options from...');
var optionsJSON = {};
if (!response) return;
try {
if (what === 'all') {
optionsJSON = JSON.parse(response);
} else {
optionsJSON[what] = JSON.parse(response);
}
} catch(e) {
alert('An error has occurred. Data string must be in JSON format.\n\n');
return;
}
options = $.extend(true, options, optionsJSON);
GM_setValue('options', options);
loadOptionsValues(false);
updateAllPreviews();
}).hover(function() {
$(this).css('opacity', '1');
}, function() {
$(this).css('opacity', '0.2');
});
$('.TPE_Export_Presets').on('click', function() {
checkOptions();
var key = this.dataset.key;
var aux = document.createElement("input");
var values = '';
if (key === 'all') {
options.textures.tiles = $('#tiles').val();
options.textures.speedpad = $('#speedpad').val();
options.textures.speedpadRed = $('#speedpadRed').val();
options.textures.speedpadBlue = $('#speedpadBlue').val();
options.textures.portal = $('#portal').val();
options.textures.splats = $('#splats').val();
options.textures.gravityWell = $('#gravityWell').val();
aux.setAttribute("value", JSON.stringify(options));
} else if (this.dataset.keys) {
var keysArray = this.dataset.keys.split(',');
var newObject = {};
for (var i in keysArray) {
if (options.hasOwnProperty(keysArray[i])) {
newObject = options[keysArray[i]];
}
}
aux.setAttribute("value", JSON.stringify(newObject));
} else {
aux.setAttribute("value", JSON.stringify(options[key]));
}
document.body.appendChild(aux);
aux.select();
document.execCommand("copy");
document.body.removeChild(aux);
alert('Done - ' + key + ' options have been saved in the clipboard as a JSON sting.\n\n');
}).hover(function() {
$(this).css('opacity', '1');
}, function() {
$(this).css('opacity', '0.2');
});
$('#TPE_SaveMyPack').on('click', function() {
var name = prompt('Texture pack name:');
if (name) {
var myPacks = GM_getValue('myPacks', {});
var currentPack = getCurrentPack();
var isNewPack = true;
if (myPacks.hasOwnProperty(name)) {
if (!confirm('"'+name+'" already exists - OK to overwrite?\n\n')) return;
isNewPack = false;
}
myPacks[name] = currentPack;
GM_setValue('myPacks', myPacks);
if (isNewPack) {
createNewPackIcon(name);
$.each($('#custom').find('input[type="text"]'), function() {
$('#TPE_MyPacks_OptGroup_'+this.id).after('<option value="'+myPacks[name][this.id]+'" data-name="'+name+'">'+name+'</option>');
});
}
$('#custom-textures-btn').trigger('click');
}
}).hover(function() {
$(this).css('opacity', '1');
}, function() {
$(this).css('opacity', '0.7');
});
$('#TPE_MySavedPacks').on('click', '.TPE_MySavedPack', function() {
var myPacks = GM_getValue('myPacks', {});
var name = $(this).data('name');
if (myPacks.hasOwnProperty(name)) {
$.each(myPacks[name], function(key, value) {
$('#'+key).val(value);
});
$('#custom-textures-btn').trigger('click');
}
});
$('#TPE_MySavedPacks').on('mouseenter', '.TPE_MySavedPack', function() {
$(this).css('box-shadow', '0 0 15px #ccc');
$(this).find('.TPE_DeleteSavedPack').show();
}).on('mouseleave', '.TPE_MySavedPack', function() {
$(this).css('box-shadow', 'none');
$(this).find('.TPE_DeleteSavedPack').hide();
});
$('#TPE_MySavedPacks').on('click', '.TPE_DeleteSavedPack', function(e) {
e.stopPropagation();
e.preventDefault();
var myPacks = GM_getValue('myPacks', {});
var name = $(this).parent().data('name');
if (name && myPacks.hasOwnProperty(name)) {
if (!confirm('Delete saved pack "'+name+'?\n\n')) return;
delete myPacks[name];
GM_setValue('myPacks', myPacks);
var $this = $(this).parent();
$this.fadeOut(600, function() { $this.remove(); });
$('#custom').find('select').find('option[data-name="'+name+'"]').remove();
}
});
$('#TPE_MySavedPacks').on('mouseenter', '.TPE_DeleteSavedPack', function() {
$(this).css('opacity', '1');
}).on('mouseleave', '.TPE_DeleteSavedPack', function() {
$(this).css('opacity', '0.7');
});
$('.TPE_Packs').on('change', function() {
$(this).siblings('input[type="text"]').val($(this).val());
});
/*-------------------------------------------------------------------------------*/
$('#TPE_SaveMyOptions').on('click', function() {
var saveTextures = confirm('Save the texture links too\n\n(Cancel for No)?\n\n');
var name = prompt('Options save name:');
if (name) {
var myOptions = GM_getValue('myOptions', {});
var isNewOptions = true;
if (myOptions.hasOwnProperty(name)) {
if (!confirm('"'+name+'" already exists - OK to overwrite?\n\n')) return;
isNewOptions = false;
}
myOptions[name] = options;
if (saveTextures) {
if (!myOptions[name].hasOwnProperty('textures')) myOptions[name].textures = {};
myOptions[name].textures.tiles = $('#tiles').val();
myOptions[name].textures.speedpad = $('#speedpad').val();
myOptions[name].textures.speedpadRed = $('#speedpadRed').val();
myOptions[name].textures.speedpadBlue = $('#speedpadBlue').val();
myOptions[name].textures.portal = $('#portal').val();
myOptions[name].textures.splats = $('#splats').val();
myOptions[name].textures.gravityWell = $('#gravityWell').val();
$('#custom-textures-btn').trigger('click');
} else {
delete myOptions[name].textures;
}
GM_setValue('myOptions', myOptions);
if (isNewOptions) {
createNewOptionsIcon(name);
}
}
}).hover(function() {
$(this).css('opacity', '1');
}, function() {
$(this).css('opacity', '0.7');
});
$('#TPE_MySavedOptions').on('click', '.TPE_MySavedOptions', function() {
var myOptions = GM_getValue('myOptions', {});
var name = $(this).data('name');
if (myOptions.hasOwnProperty(name)) {
options = $.extend(true, {}, defaultOptions, myOptions[name]);
GM_setValue('options', options);
loadOptionsValues(false);
updateAllPreviews();
}
});
$('#TPE_MySavedOptions').on('mouseenter', '.TPE_MySavedOptions', function() {
$(this).css('box-shadow', '0 0 10px #aaa');
$(this).find('.TPE_DeleteSavedOptions').show();
}).on('mouseleave', '.TPE_MySavedOptions', function() {
$(this).css('box-shadow', 'none');
$(this).find('.TPE_DeleteSavedOptions').hide();
});
$('#TPE_MySavedOptions').on('click', '.TPE_DeleteSavedOptions', function(e) {
e.stopPropagation();
e.preventDefault();
var myOptions = GM_getValue('myOptions', {});
var name = $(this).parent().data('name');
if (name && myOptions.hasOwnProperty(name)) {
if (!confirm('Delete saved options "'+name+'?\n\n')) return;
delete myOptions[name];
GM_setValue('myOptions', myOptions);
var $this = $(this).parent();
$this.fadeOut(600, function() { $this.remove(); });
}
});
$('#TPE_MySavedOptions').on('mouseenter', '.TPE_DeleteSavedOptions', function() {
$(this).css('opacity', '1');
}).on('mouseleave', '.TPE_DeleteSavedOptions', function() {
$(this).css('opacity', '0.5');
});
$('#TPE_ApplyQuickTints').on('click', function() {
var red = options.quick_tint.red_color;
var blue = options.quick_tint.blue_color;
var yellow = options.quick_tint.yellow_color;
$('#TPE_Container').find('input[data-saveto="altSpawnShadow.red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="altSpawnShadow.blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="ballglow_Red_Color"]').val(red);
$('#TPE_Container').find('input[data-saveto="ballglow_Blue_Color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="flags.red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="flags.blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="flags.yellow_color"]').val(yellow);
$('#TPE_Container').find('input[data-saveto="shapes.circle_red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="shapes.circle_blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="shapes.circle_yellow_color"]').val(yellow);
$('#TPE_Container').find('input[data-saveto="shapes.octagon_red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="shapes.octagon_blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="shapes.octagon_yellow_color"]').val(yellow);
$('#TPE_Container').find('input[data-saveto="shapes.cross_red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="shapes.cross_blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="shapes.cross_yellow_color"]').val(yellow);
$('#TPE_Container').find('input[data-saveto="shapes.baseradius_red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="shapes.baseradius_blue_color"]').val(blue);
$('#TPE_Container').find('input[data-saveto="shapes.basefill_red_color"]').val(red);
$('#TPE_Container').find('input[data-saveto="shapes.basefill_blue_color"]').val(blue);
$('#TPE_Container_Balls').find('input[data-saveto="redball.Color"]').val(red);
$('#TPE_Container_Balls').find('input[data-saveto="blueball.Color"]').val(blue);
saveValues();
updateAllPreviews();
});
$('#TPE_ApplyQuickTints_Header').on('click', function() {
$('#TPE_ApplyQuickTints_Content').slideToggle();
});
/*-------------------------------------------------------------------------------*/
$('.tab-list li').on('click', function() {
$(this).parents('.tab-list').find('li').removeClass('active');
$(this).parents('.tab-list').parent().find('.tab-pane').removeClass('active');
$(this).addClass('active');
$( $(this).data('target') ).addClass('active');
});
$('#TPE_Wallpaper').find('input[type="radio"]').on('click', function() {
$('#TPE_GameWallPaper_Color1').val(this.dataset.c1);
$('#TPE_GameWallPaper_Color2').val(this.dataset.c2);
options.gamewallpaper.color1 = this.dataset.c1;
options.gamewallpaper.color2 = this.dataset.c2;
GM_setValue('options', options);
});
$('#TPE_TransparentBall').on('input', function() {
$('#TPE_TransparentBallValue').text(this.value);
saveValue(this);
});
var hideshowGroups = function(that) {
var saveto = that.dataset.saveto;
var type = that.dataset.type;
var group = that.dataset.group;
var rgroup = that.dataset.rgroup;
var index = saveto.split('.');
/*
if (saveto === 'addBallGlow') {
if ( $(that).is(':checked') ) $('#TPE_Container').find('.TPE_Group_BallGlow').fadeIn();
else $('#TPE_Container').find('.TPE_Group_BallGlow').fadeOut();
}*/
if (type === 'custom') {
$('input[data-saveto="'+index[0]+'.shapes_overlay_base64"]').fadeIn();
} else {
$('input[data-saveto="'+index[0]+'.shapes_overlay_base64"]').fadeOut();
}
if (group) {
if ( $(that).is(':checked') || ($(that).val() > 0) ) $('#TPE_Container, #TPE_Container_Balls').find('.'+group).fadeIn();
else $('#TPE_Container, #TPE_Container_Balls').find('.'+group).fadeOut();
}
if (rgroup) {
if ( $(that).is(':checked') || ($(that).val() > 0) ) $('#TPE_Container, #TPE_Container_Balls').find('.'+rgroup).fadeOut();
else $('#TPE_Container, #TPE_Container_Balls').find('.'+rgroup).fadeIn();
}
};
$('#TPE_Container, #TPE_Container_Balls').find('input[type="checkbox"], input[type="number"], input[type="radio"]').on('click', function() {
hideshowGroups(this);
saveValue(this);
updateAllPreviews();
});
$('#TPE_Container, #TPE_Container_Balls').find('input[type="color"], select').on('change', function() {
hideshowGroups(this);
saveValue(this);
updateAllPreviews();
});
$('.TPE_Preset').on('click', function() {
loadPreset(this.dataset.preset, this.dataset.color);
});
/*-------------------------------------------------------------------------------*/
// Drag/Drop events...
$(document).on('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
$('#TPE_DropZone_Outer').css({border:'2px dotted yellow'});
}).on('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
$('#TPE_DropZone_Outer').css({border:'2px dashed silver'});
});
$('#TPE_DropZone_Outer').on('dragover', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({background:'lime', opacity:0.3});
}).on('dragleave', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({background:'', opacity:1});
}).on('drop', function(e) {
e.stopPropagation();
e.preventDefault();
$(this).css({border:'2px dotted silver', background:'', opacity:1});
handleDrop(e, 'wallpaper');
}).on('dblclick', function(e) {
e.stopPropagation();
e.preventDefault();
if ($('#TPE_WP').val() === 'image') {
if (!confirm('Remove Custom Wallpaper?')) return;
options.gamewallpaper.imagedata = '';
$('#TPE_DropZone').css({ 'background': '#000 url("/images/background.jpg") center center / cover no-repeat' });
}
});
} //...not in a game
}); //tagpro.ready()
if (window.location.port) {
/*-------------------------------------------------------------------------------*/
//This allows us to modifiy the tiles before they get drawn. It is based around code by snaps...
/**
* Executes `fn` when the relevant parts of the `tagpro` object have
* been initialized.
* @param {Function} fn - The function to execute.
*/
var waitForInitialized = function (fn) {
if (!tagpro || !tagpro.tiles || !tagpro.tiles.draw || !tagpro.renderer) {
setTimeout(function() {
waitForInitialized(fn);
}, 10);
} else {
// Only override if we load early enough.
if (!tagpro.renderer.layers.backgroundDrawn) {
fn();
}
}
};
waitForInitialized(function() {
var stdDraw = tagpro.tiles.draw;
// ids of the tiles we're interested in changing.
var floorTiles = [2]; //[2, 11, 12, 17, 18]
var prefix = "__tinted__";
/**
* Creates the tinted texture for the tile of the given id and sets
* the relevant values such that the returned value will function in
* the original `tagpro.tiles.draw` function.
* @param {(number|string)} tileId - The original id of the tile to set information for.
* @return {string} - The new id to use for the tile.
**/
var setTintedTexture = function(tileId, suffix, forceDrawTiles=false) {
var originalTileId = tileId;
suffix = suffix || '';
tileId = prefix + originalTileId + suffix;
//we're drawing several versions of a tile with 'specks' so a uniform pattern isn't obvious...
if ( (options.floortiles.specks && (originalTileId == 2) ) ) {
suffix += '_v'+Math.floor(Math.random()*8);
tileId = prefix + originalTileId + suffix;
}
if (!tagpro.tiles[tileId] || !PIXI.TextureCache[tileId] || forceDrawTiles) {
var tile = tagpro.tiles[originalTileId];
tagpro.tiles[tileId] = tile;
var elt = document.createElement("canvas");
elt.width = tile.size || 40;
elt.height = tile.size || 40;
var ctx = elt.getContext("2d");
var spread = tile.spread || 0;
var sx = tile.x * 40 - spread;
var sy = tile.y * 40 - spread;
var tileSize = (tile.size || 40) + spread * 2;
if (doTintWall) {
ctx.drawImage(tagpro.tiles.image, sx, sy, tileSize, tileSize, 0, 0, tileSize, tileSize);
let color = options.walls.color;
let opacity = options.walls.opacity / 100;
setTint(elt, color, opacity);
PIXI.TextureCache[tileId] = PIXI.Texture.fromCanvas(elt);
return tileId;
}
if (originalTileId == 2) {
drawFloorTile(ctx, tagpro.tiles.image, evenX, evenY, true);
if (doBaseFill && baseTintColor) {
ctx.fillStyle = hexToRgbA(baseTintColor, options.shapes.basefill_opacity / 100);
ctx.fillRect(0, 0, tileSize, tileSize);
}
if (doBaseCircle && baseCircle) {
ctx.beginPath();
ctx.lineWidth = baseCircle.linewidth || options.shapes.circle_width;
ctx.strokeStyle = hexToRgbA(baseCircle.color, baseCircle.opacity || options.shapes.circle_opacity / 100);
ctx.arc(baseCircle.x, baseCircle.y, baseCircle.radius || options.shapes.circle_radius, 0,Math.PI*2, false);
ctx.closePath();
ctx.stroke();
}
if (doSpikeTileFill) {
let margin = +options.spikes.floortint_margin;
ctx.translate(-0.5, -0.5);
ctx.lineWidth = 1;
ctx.strokeStyle = hexToRgbA(options.spikes.floortint_color, options.spikes.floortint_opacity / 100);
ctx.fillStyle = hexToRgbA(options.spikes.floortint_color, options.spikes.floortint_fillopacity / 100);
if (options.spikes.floortint_dash) ctx.setLineDash([options.spikes.floortint_dash]);
roundedRect(ctx, margin, margin, 41-margin*2, 41-margin*2, +options.spikes.floortint_rounded, options.spikes.floortint_stroke, options.spikes.floortint_fill);
if (options.spikes.floortint_dash) ctx.setLineDash([]);
ctx.translate(0.5, 0.5);
}
if (doBombTileFill) {
let margin = +options.bombs.floortint_margin;
ctx.translate(-0.5, -0.5);
ctx.lineWidth = 1;
ctx.strokeStyle = hexToRgbA(options.bombs.floortint_color, options.bombs.floortint_opacity / 100);
ctx.fillStyle = hexToRgbA(options.bombs.floortint_color, options.bombs.floortint_fillopacity / 100);
if (options.spikes.floortint_dash) ctx.setLineDash([options.bombs.floortint_dash]);
roundedRect(ctx, margin, margin, 41-margin*2, 41-margin*2, 0, options.bombs.floortint_stroke, options.bombs.floortint_fill);
if (options.bombs.floortint_dash) ctx.setLineDash([]);
ctx.translate(0.5, 0.5);
}
if (doBaseRadius && baseTintColor) {
let doTranslate = (options.shapes.centerline_width % 2 !== 0);
ctx.strokeStyle = hexToRgbA(baseTintColor, options.shapes.baseradius_opacity / 100);
ctx.lineWidth = options.shapes.baseradius_width;
if (options.shapes.baseradius_dashsize > 0) {
ctx.setLineDash([options.shapes.baseradius_dashsize]);
if (doTranslate) ctx.translate(0.5, 0.5);
}
ctx.beginPath();
if (baseRadiusDirection === 'top') {
ctx.moveTo(0, 20);
ctx.lineTo(40, 20);
} else if (baseRadiusDirection === 'side') {
ctx.moveTo(20, 0);
ctx.lineTo(20, 40);
} else if (baseRadiusDirection === 'corner-nw') {
ctx.moveTo(20, 40);
ctx.arcTo(20, 20, 40, 20, 20);
} else if (baseRadiusDirection === 'corner-ne') {
ctx.moveTo(0, 20);
ctx.arcTo(20, 20, 20, 40, 20);
} else if (baseRadiusDirection === 'corner-se') {
ctx.moveTo(20, 0);
ctx.arcTo(20, 20, 0, 20, 20);
} else if (baseRadiusDirection === 'corner-sw') {
ctx.moveTo(40, 20);
ctx.arcTo(20, 20, 20, 0, 20);
}
ctx.stroke();
if (options.shapes.baseradius_dashsize > 0) {
if (doTranslate) ctx.translate(-0.5, -0.5);
ctx.setLineDash([]);
}
}
if (centerLineTint) {
let doTranslate = (options.shapes.centerline_width % 2 !== 0);
ctx.strokeStyle = hexToRgbA(options.shapes.centerline_color, options.shapes.centerline_opacity / 100);
ctx.lineWidth = options.shapes.centerline_width;
if (options.shapes.centerline_dashsize > 0) {
ctx.setLineDash([options.shapes.centerline_dashsize]);
if (doTranslate) ctx.translate(0.5, 0.5);
}
ctx.beginPath();
if (centerLineTint === 'vertical') {
ctx.moveTo(20, 0);
ctx.lineTo(20, 40);
} else if (centerLineTint === 'horizontal') {
ctx.moveTo(0, 20);
ctx.lineTo(40, 20);
}
ctx.stroke();
if (options.shapes.centerline_dashsize > 0) {
if (doTranslate) ctx.translate(-0.5, -0.5);
ctx.setLineDash([]);
}
}
} else if (options.spikes.modify && originalTileId == 7) {
ctx.drawImage(tagpro.tiles.image, sx, sy, tileSize, tileSize, 0, 0, tileSize, tileSize);
let color = options.spikes.color || '#FFFFFF';
let opacity = options.spikes.opacity / 100;
setTint(elt, color, opacity);
} else if (options.bombs.modify && ((originalTileId == 10) || (originalTileId == '10.1')) ) {
ctx.drawImage(tagpro.tiles.image, sx, sy, tileSize, tileSize, 0, 0, tileSize, tileSize);
let color = options.bombs.color || '#FFFFFF';
let opacity = options.bombs.opacity / 100;
setTint(elt, color, opacity);
}
PIXI.TextureCache[tileId] = PIXI.Texture.fromCanvas(elt);
elt = null;
}
return tileId;
};
// Override `tagpro.tiles.draw`.
tagpro.tiles.draw = function() {
if (tagpro.tiles.draw.caller === tagpro.tiles.drawLayers) { // Only make changes when drawing background tiles.
let loc = arguments[2];
let floorTile = ( (typeof arguments[1] !== "object") && (arguments[1] === 2) && loc);
let wallTile = ( options.walls.modify && (typeof(arguments[1]) === 'string') && (arguments[1].startsWith('1.')) && loc);
let random = 0;
let suffix = '';
doTintWall = false;
if (wallTile) {
doTintWall = true;
suffix += '9' + arguments[1];
arguments[1] = setTintedTexture(arguments[1], suffix, false);
} else if (floorTile) {
let locX = Math.floor(loc.x / 40);
let locY = Math.floor(loc.y / 40);
let floorColor = options.floortiles.tint_color;
let floorOpacity = options.floortiles.modify ? options.floortiles.tint_opacity / 100 : 0;
let evenTile = false;
evenX = (locX % 2 === 0);
evenY = (locY % (options.floortiles.checkered && options.floortiles.checkered_stripes ? 0 : 2) === 0 ? true : false);
if ((evenX && evenY) || (!evenX && !evenY)) {
evenTile = true;
suffix += '7';
} else {
suffix += '8';
}
if (options.floortiles.grids_square) {
if (evenX && !evenY) {
suffix += 'TL';
} else if (!evenX && !evenY) {
suffix += 'TR';
} else if (!evenX && evenY) {
suffix += 'BL';
} else if (evenX && evenY) {
suffix += 'BR';
}
}
if (options.floortiles.checkered) {
if (evenTile || (options.floortiles.checkered_random && Math.floor(Math.random()*3))) {
floorColor = options.floortiles.checkered_altTintColor;
floorOpacity = options.floortiles.checkered_altTintOpacity / 100;
}
}
TINT_COLOR = floorColor;
OPACITY = floorOpacity;
doBaseFill = false;
doBaseRadius = false;
doBaseCircle = false;
doSpikeTileFill = false;
doBombTileFill = false;
baseRadiusDirection = '';
centerLineTint = '';
if (flagRadius && options.shapes.basefill && options.shapes.basefill_opacity > 0) {
if ( (Math.abs(arguments[2].x - flagLocs.red.x) < flagRadius) && (Math.abs(arguments[2].y - flagLocs.red.y) < flagRadius) ) {
doBaseFill = true;
baseTintColor = options.shapes.basefill_red_color;
suffix += '1';
} else if ( (Math.abs(arguments[2].x - flagLocs.blue.x) < flagRadius) && (Math.abs(arguments[2].y - flagLocs.blue.y) < flagRadius) ) {
doBaseFill = true;
baseTintColor = options.shapes.basefill_blue_color;
suffix += '2';
}
}
if (options.shapes.circle && options.shapes.circle_opacity > 0) {
let rect = { x:loc.x, y:loc.y, w:40, h:40 };
if (flagLocs.yellow.x && flagLocs.yellow.y) {
let circleYellow = { x:flagLocs.yellow.x+20, y:flagLocs.yellow.y+20, r:options.shapes.circle_radius };
if (isCircleIntersectingRect(circleYellow, rect, options.shapes.circle_width)) {
doBaseCircle = true;
baseCircle = { color:options.shapes.circle_yellow_color, opacity:options.shapes.circle_opacity/100, x:flagLocs.yellow.x-loc.x+20, y:flagLocs.yellow.y-loc.y+20, radius:options.shapes.circle_radius, linewidth:options.shapes.circle_width };
suffix += 'BCY'+loc.x+loc.y;
}
} else {
let circleRed = { x:flagLocs.red.x+20, y:flagLocs.red.y+20, r:options.shapes.circle_radius };
let circleBlue = { x:flagLocs.blue.x+20, y:flagLocs.blue.y+20, r:options.shapes.circle_radius };
if (isCircleIntersectingRect(circleRed, rect, options.shapes.circle_width)) {
doBaseCircle = true;
baseCircle = { color:options.shapes.circle_red_color, opacity:options.shapes.circle_opacity/100, x:flagLocs.red.x-loc.x+20, y:flagLocs.red.y-loc.y+20, radius:options.shapes.circle_radius, linewidth:options.shapes.circle_width };
suffix += 'BCR'+loc.x+loc.y;
} else {
if (isCircleIntersectingRect(circleBlue, rect, options.shapes.circle_width)) {
doBaseCircle = true;
baseCircle = { color:options.shapes.circle_blue_color, opacity:options.shapes.circle_opacity/100, x:flagLocs.blue.x-loc.x+20, y:flagLocs.blue.y-loc.y+20, radius:options.shapes.circle_radius, linewidth:options.shapes.circle_width };
suffix += 'BCB'+loc.x+loc.y;
}
}
}
}
if (options.spikes.floortint && options.spikes.floortint_opacity > 0) { //!doBaseFill &&
if (tagpro.map[locX][locY] === 7) {
doSpikeTileFill = true;
suffix += 'SFT'+loc.x+loc.y;
}
}
if (options.bombs.floortint && options.bombs.floortint_opacity > 0) { //!doBaseFill &&
if ((tagpro.map[locX][locY] === 10) || (tagpro.map[locX][locY] === '10.1')) {
doBombTileFill = true;
suffix += 'BFT'+loc.x+loc.y;
}
}
if (flagRadius && options.shapes.baseradius && options.shapes.baseradius_opacity > 0) {
if ( (Math.abs(arguments[2].x - flagLocs.red.x) === flagRadius) && (Math.abs(arguments[2].y - flagLocs.red.y) < flagRadius) ) {
doBaseRadius = true; //left, right
baseTintColor = options.shapes.baseradius_red_color;
baseRadiusDirection = 'side';
suffix += 'A';
} else if ( (Math.abs(arguments[2].x - flagLocs.red.x) < flagRadius) && (Math.abs(arguments[2].y - flagLocs.red.y) === flagRadius) ) {
doBaseRadius = true; //top, bottom
baseTintColor = options.shapes.baseradius_red_color;
baseRadiusDirection = 'top';
suffix += 'B';
} else if ( (Math.abs(arguments[2].x - flagLocs.red.x) === flagRadius) && (Math.abs(arguments[2].y - flagLocs.red.y) === flagRadius) ) {
doBaseRadius = true; //corner
baseTintColor = options.shapes.baseradius_red_color;
if ((arguments[2].x < flagLocs.red.x) && (arguments[2].y < flagLocs.red.y)) {
baseRadiusDirection = 'corner-nw';
suffix += 'AB.1';
} else if ((arguments[2].x < flagLocs.red.x) && (arguments[2].y > flagLocs.red.y)) {
baseRadiusDirection = 'corner-sw';
suffix += 'AB.2';
} else if ((arguments[2].x > flagLocs.red.x) && (arguments[2].y < flagLocs.red.y)) {
baseRadiusDirection = 'corner-ne';
suffix += 'AB.3';
} else if ((arguments[2].x > flagLocs.red.x) && (arguments[2].y > flagLocs.red.y)) {
baseRadiusDirection = 'corner-se';
suffix += 'AB.4';
}
} else if ( (Math.abs(arguments[2].x - flagLocs.blue.x) === flagRadius) && (Math.abs(arguments[2].y - flagLocs.blue.y) < flagRadius) ) {
doBaseRadius = true;
baseTintColor = options.shapes.baseradius_blue_color;
baseRadiusDirection = 'side';
suffix += 'C';
} else if ( (Math.abs(arguments[2].x - flagLocs.blue.x) < flagRadius) && (Math.abs(arguments[2].y - flagLocs.blue.y) === flagRadius) ) {
doBaseRadius = true;
baseTintColor = options.shapes.baseradius_blue_color;
baseRadiusDirection = 'top';
suffix += 'D';
} else if ( (Math.abs(arguments[2].x - flagLocs.blue.x) === flagRadius) && (Math.abs(arguments[2].y - flagLocs.blue.y) === flagRadius) ) {
doBaseRadius = true;
baseTintColor = options.shapes.baseradius_blue_color;
if ((arguments[2].x < flagLocs.blue.x) && (arguments[2].y < flagLocs.blue.y)) {
baseRadiusDirection = 'corner-nw';
suffix += 'CD.1';
} else if ((arguments[2].x < flagLocs.blue.x) && (arguments[2].y > flagLocs.blue.y)) {
baseRadiusDirection = 'corner-sw';
suffix += 'CD.2';
} else if ((arguments[2].x > flagLocs.blue.x) && (arguments[2].y < flagLocs.blue.y)) {
baseRadiusDirection = 'corner-ne';
suffix += 'CD.3';
} else if ((arguments[2].x > flagLocs.blue.x) && (arguments[2].y > flagLocs.blue.y)) {
baseRadiusDirection = 'corner-se';
suffix += 'CD.4';
}
}
}
if (options.shapes.centerline && options.shapes.centerline_opacity > 0) {
if (arguments[2].x === halfwayX) {
centerLineTint = 'vertical';
suffix += '3';
} else if (arguments[2].y === halfwayY) {
centerLineTint = 'horizontal';
suffix += '4';
}
}
arguments[1] = setTintedTexture(arguments[1], '_'+suffix, arguments[2], false);
}
} else if (tagpro.tiles.draw.caller === tagpro.renderer.drawDynamicTile) {
let loc = arguments[2];
let bombTile = ( options.bombs.modify && (typeof arguments[1] !== "object") && ([10, 10.1].indexOf(arguments[1]) !== -1) && loc);
let spikeTile = ( options.spikes.modify && (typeof arguments[1] !== "object") && ([7].indexOf(arguments[1]) !== -1) && loc);
let suffix = '';
doTintWall = false;
doBaseFill = false;
doBaseRadius = false;
doBaseCircle = false;
doSpikeTileFill = false;
doBombTileFill = false;
baseRadiusDirection = '';
centerLineTint = '';
if (bombTile || spikeTile) {
let locX = Math.floor(loc.x / 40);
let locY = Math.floor(loc.y / 40);
evenX = (locX % 2 === 0);
evenY = (locY % (options.floortiles.checkered && options.floortiles.checkered_stripes ? 0 : 2) === 0 ? true : false);
if (arguments[1] == '10') {
suffix = 'BOMB';
} else if (arguments[1] == '10.1') {
suffix = 'BAMB';
} else if (arguments[1] == '7') {
suffix = 'SPK';
}
arguments[1] = setTintedTexture(arguments[1], '_'+suffix, arguments[2], false);
}
}
return stdDraw.apply(null, arguments);
};
}); //waitForInitialized()
} //if window.location.port
//-----------------------------------------------
//functions for drawing modified tiles & balls...
//-----------------------------------------------
function drawBall(ctx, tileId) {
if (!ctx || !tileId) return;
let ballSize = Number(options[tileId].size);
let ballColor = options[tileId].color;
let ballOpacity = options[tileId].opacity / 100;
let ballUseGradient = options[tileId].gradient;
let ballGradientColor = options[tileId].gradient_color;
let ballGradientStart = Number(options[tileId].gradient_start) || 5;
let ballGradientStop = Number(options[tileId].gradient_stop) || 25;
let ballGradientPosition = Number(options[tileId].gradient_position) || 20;
let ballBorderWidth = Number(options[tileId].border_width) || 0;
let ballBorderWidth2 = ballBorderWidth;
let ballBorderColor = options[tileId].border_color;
let ballBorderSegments = Number(options[tileId].border_segments) || 0;
let ballBorderAltColor = options[tileId].border_alt_color;
if (ballBorderWidth) {
if ((ballBorderWidth >= 1) && (ballSize === 19)) ballSize = 18;
}
if (ballOpacity > 0) {
ballColor = hexToRgbA(ballColor, ballOpacity);
ballGradientColor = hexToRgbA(ballGradientColor, ballOpacity);
}
if (ballUseGradient) {
let gradient = ctx.createRadialGradient(ballGradientPosition,ballGradientPosition,ballGradientStart, ballGradientPosition,ballGradientPosition,ballGradientStop);
gradient.addColorStop(0, ballColor);
gradient.addColorStop(1, ballGradientColor);
ctx.fillStyle = gradient;
} else {
ctx.fillStyle = ballColor;
}
ctx.beginPath();
ctx.arc(20, 20, ballSize, 0, Math.PI*2);
ctx.closePath();
ctx.fill();
}
function drawBorder(ctx, tileId) {
if (!ctx || !tileId) return;
let ballBorderWidth = Number(options[tileId].border_width) || 0;
let ballBorderColor = options[tileId].border_color;
let ballBorderSegments = Number(options[tileId].border_segments) || 0;
let ballBorderAltColor = options[tileId].border_alt_color;
if (ballBorderWidth < 1) return;
ctx.lineWidth = ballBorderWidth;
if (ballBorderSegments === 0) ballBorderSegments = 1;
if ((ballBorderSegments > 1) && (ballBorderSegments % 2)) ballBorderSegments++;
let percent = 100 / ballBorderSegments;
let endAngle = Math.PI * 2;
let lastAngle = 0;
for (var i=0; i<ballBorderSegments; i++) {
let color = i % 2 === 0 ? ballBorderColor : ballBorderAltColor;
let currentSegment = endAngle * (percent/100);
let currentAngle = currentSegment + lastAngle;
ctx.beginPath();
ctx.arc(20, 20, (18 - ballBorderWidth / 2 + 0.5), lastAngle, currentAngle, false);
ctx.strokeStyle = color;
ctx.stroke();
ctx.closePath();
lastAngle = lastAngle + currentSegment;
}
}
function drawArc(ctx, tileId) {
if (!ctx || !tileId) return;
let color = options[tileId].shapes_arc_color || 'white';
let linewidth = Number(options[tileId].shapes_arc_width) || 2;
let position = Number(options[tileId].shapes_arc_position) || 14;
let size = Number(options[tileId].shapes_arc_size) || 4;
var x = 10 * (Math.PI*2/180) * size;
if (options[tileId].shapes_arc_transparent) ctx.globalCompositeOperation = "destination-out";
ctx.strokeStyle = color;
ctx.lineWidth = linewidth;
ctx.beginPath();
ctx.arc(20, 20, position, 0, x);
ctx.stroke();
ctx.closePath();
if (options[tileId].shapes_arc_transparent) ctx.globalCompositeOperation = "source-over";
}
function drawStar(ctx, tileId) {
if (!ctx || !tileId) return;
let cx = 20;
let cy = 20;
let color = options[tileId].shapes_star_color || 'white';
let transparent = options[tileId].shapes_star_transparent || false;
let linewidth = Number(options[tileId].shapes_star_width >= 0 ? options[tileId].shapes_star_width : 2);
let spikes = Number(options[tileId].shapes_star_spikes) || 4;
let innerRadius = Number(options[tileId].shapes_star_inner >= 0 ? options[tileId].shapes_star_inner : 5);
let outerRadius = Number(options[tileId].shapes_star_outer >= 0 ? options[tileId].shapes_star_outer : 12);
let fill = options[tileId].shapes_star_fill || false;
let fillColor = options[tileId].shapes_star_fill_color || 'white';
let rot = Math.PI/2*3;
let x = cx;
let y = cy;
let step = Math.PI/spikes;
if (options[tileId].shapes_star_transparent) ctx.globalCompositeOperation = "destination-out";
ctx.beginPath();
ctx.moveTo(cx,cy-outerRadius);
for(i=0; i<spikes; i++){
x = cx+Math.cos(rot)*outerRadius;
y = cy+Math.sin(rot)*outerRadius;
ctx.lineTo(x,y);
rot += step;
x = cx+Math.cos(rot)*innerRadius;
y = cy+Math.sin(rot)*innerRadius;
ctx.lineTo(x,y);
rot += step;
}
ctx.lineTo(cx,cy-outerRadius);
ctx.closePath();
ctx.lineWidth = linewidth;
ctx.strokeStyle = color;
if (linewidth) ctx.stroke();
if (fill) {
ctx.fillStyle = fillColor;
ctx.fill();
}
ctx.closePath();
if (options[tileId].shapes_star_transparent) ctx.globalCompositeOperation = "source-over";
}
function drawOverlay(ctx, tileId) {
if (!ctx || !tileId) return;
let type = options[tileId].shapes_overlay_type;
let alpha = ((100 - Number(options[tileId].shapes_overlay_transparency) || 0) / 100);
if (!type) return;
var overlays = {};
overlays.marble1 = 'data:image/png;base64,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'; //by Professor Tag
overlays.marble2 = 'data:image/png;base64,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';
overlays.earth1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAAB3RJTUUH4QEVFzkMVTCY/gAAAAlwSFlzAAALEwAACxMBAJqcGAAAAARnQU1BAACxjwv8YQUAAASiSURBVHja1VhpTxRBEC0QdBcQBOT24PK+NUZRE4/EaPy3fvCrH4wXKsSgJAqIGEHlEgSP9QCsR79m22F6tmfVRCt5WZjp7npdXVePyD8uG4qcV68oU3wvMK5bcUpRzbGf/zbBrKJOcVHRpFhSLChWPON3Kxo5p0OxnUQX/jTBjKJTUa5oVtSQbJuiQjHhWfu4GEtb2aTYpmhVzCu+/AmCsMJWjp1RTCteKHZSeU7xKmZeDeeWeE6iXfFN8T5JeZkkSw2tk6OlDtKKtxR9ijOKUmd8CS0E5Y0ecpBPiru0IuYvF0vwA39rqQy/Q7RmJ99tdMidFeObUDqmGFSc5glYgd/edtaG/zbwdNb5ciGCwsXPc5ejikXFBTGOb63cwF8Qvy7GT3vEBEVUx4BDzsoiN7VUDMFWKgbg1JN8jqPsouXO81mv4oeiks/t+rDMd1p7lmu5ZHI+5SFBAkJvabEBEoAPIVV0k4hFq+R90BWM71fs4DogNx+gOzjNfCFJNy0s0VJbnGc4pmxkLiyHgEK0NpDom0C9qRK1WzV20RrDtGIhHbBqjuPnUugM8sE4KSWx1hTjoSvoWKO7SyPIhT2S972NgfMeiolUZIL9JLoUMtESLJeEZElBmbosJhemERC5T4LXxORJRP8c3zXyXSLBdinsG6gizSnJQXC8lTQAAu21mJPoIjnkWWSGjxKTqC3BQ2JqbLR9quWYHRxTjKDe3hFzrIvEPIktctNoOqYkph2zQVJFKw6TJHZ9jpOR9SekOFnhmtFEDII3+Xcfx8W2bLbQo53aozjK/5slf5wIhJYiCb4UU4995IFlD7kKlyCOsZxWzNDc2Pkd/r9MSya2RjEyW+TGIDUuQbsDpI4rYnq9x2IcF10GWny4QTadjoJXAp/Ytm2NoLsQ0skJxVUx0WfLEqI8J/72Pk5S30HE1OpLQreyUQyLZSIDQRTRixQAP3qqGFE857OmAGUIwvGUBDeTC+aOWoK2n4sT3MhssyC0II59kotVJCjDmsvcUBX1fJLkogCrI+euZg9LMCv+SMViT2T9cX0mcTSlvtZeJF85cKvbRowkjD/MMbj3zFkffJcwATuZ9rzDvBuKZxIeEPBrXw+wl4CsNsaWIDK6r9ThGMsTFMKKAyQa0gBAp69ktvEX6eyjSxAy6pkEZz0SoLhawrsjX5uGDa64XFyCY+K/SOMG11VA6a5AckmCDeI01u7ZLkGwH0yYfEzMcccJrNwm4TIT8wwpDXl2SBxXKY0MQu30BQTGtnveNcaslSQNkf+R91Ac4Hu/FILoonj5QEyLFCeZmGdIC+dSkINEm9591L3uE0rcrpFI70l8Mo2WOfhMR0pykM2SD6haroFPIetKoy/q7L0XfuUmYVSTKUcJ/LJO0gvWhL/hyoqjfSSeXJyUFkAQPtHijIOP2g8+B4q0nhWsi666V/JlNBVBCJLlOK2EmjtC6+Jm1/4b5CCIZHwlS7wLhSRWBMwYf+EjOJqTki5qXfkqJtf1iz8Y1yT04m7vFnYOrFidkhhcZpT4ETqpJHRgjMDB0anUkyxSkK3ZaBxyJIW2H4U/9VeF/0J+AgBDBp2zseZgAAAAAElFTkSuQmCC';
overlays.earth2 = 'data:image/png;base64,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';
overlays.swirl1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAAAAACpleexAAAALHRFWHRDcmVhdGlvbiBUaW1lAFR1ZSAyNiBBcHIgMjAxNiAxMToxODo0MyArMTIwMBPMDBYAAAAHdElNRQfgBBkXEyaoin5tAAAACXBIWXMAAAsSAAALEgHS3X78AAAABGdBTUEAALGPC/xhBQAABh9JREFUeNoN1NlTG/cBAODf7m+1h7SSWN0HEkiIQ4CRwcE2IpA6vnDGxzhpnE7dMtN0pu1TZvrah/ahb52+9CGd6XTaaZNOMm6S4qRu6tgYMBiCAZPYCHMEgZCQQBJotVqJXe3Zfn/Eh7wY+/S96qD9xaFuEJOloR1QHWUXiz1LXRkggtIoN/33XwVbfvtGGMXs1AGZpgnKIO5/frJQ9THEXJJKdORWAVPb+p3z9UuLgjDySEGl14f/XVNnhi5ShbG3msjA6vCOrSEO5hfsZs5y6vu50LWMXPLlAca5ApKKwweddsNvFExDi8LGQWi2OdFm+hDodfrss6bz4zftsbvwpsVSnxiAWg5pQDReybmaSssx83rv4Er4vJf+mvGaLI9Ou4n7sIkMcXOVdoysKzUDTy9dsuxrkrIbU4Rw1UPrj+P1luPnzoEn0PqK4kTH21FV0giqWEoMy5uCFyk15SKcwc+I+vZJTH52Rg6i5BoLYpHf81xB53cFSxOog/TXNPQ7JYkTbL3NK3LBa13hnWjPC0x0nAy/L/kNZNJfOUKNW6d/jINKhK4slLu4gH8VtzUm+DLanxJ1qstdXqEQvFWQgUwzBkSQjVJVpd/7xM+61+qCOy1raOHVaRX1R6/+tSLLvU4Ut9tOrMpKGaf8PP3O7pbXIGNZJph7jhbhzsEKZdHxxxgZMcOyUaarQie2UWp8rbHZR9QsulCl5TSDYqEC1MtNMFgWlH0f7XkJ+xTKdekRetDa6T8W8ushBHxnnHmM8kDPVGSdUcIWJeHpdX8M7PGJQhu+uLNdZOI2xRZX5pwW6y2UJCDl2pEKbLfMy/+Jdsnz5XPVTWx08aM/fbw2vRPtV/MsX44CFGcdVgwIJk8NIJX67NnLdw5st/+5K/zC+Y2XcntseH22USgH83AEvOwDVOVpR1jQTUaZtVH/iKjBe0F3j3N+STuqbY9F2qqpmAgHjrCIflB+dl11VNIaRKz9xXuBfvFLs8dxy53h1pUrCPnB2+Qm/OEB4mFNKWOHsPJ+ZmGxjdQursy5TX2fsVY4HI0OdKLI1BUWScELq0Nk2TFxDRMnRzrsbQ9yocz31M+D4TMPs2HR6LCKpqMuVS8Y4anCoFZKV16B4/Fmc2dM4abtfC/1Ych1nf80FdArxkPiKQPGr0FfzLKN8xZPyWSRCmqrm1EfUKvdvR+dkGyvJe8mOGbPevwwMWKE4TcMvOvBDTRrFe/TAdExJIAxPxuz/tHs8sQd8vbdx5P7zacQGf7anOVSx2Guhn7ZEickdr0thEyZt8+avnIYkQ5Xu/1EOBi3Ov4Gb1IbvvmYPhfMF39QFUuW0qTDVU9ElHO16R4zH3QoxnbCmv7iFhxl1XKxn8B89y9IyspzwzYkW4S9EC57+T9fRXbrV1y8uJC/YYO3E/SmIZBpXEp2F8vTLSJqobx0YS9S7VOytZhG7aJ2yRUl62gKsElvDmC8slViseVju6CvF20qFGYp8qhMKGDvwGAFfyGwZE+FVVO96eXGeoNNtdKNvMLTmRPZ/YG81kVoeN0AUbnUI2Fd7MTpMkkYFA/OBqHPlgN5CxA7lUOcQ4ckDKVru85twjGBQY4bVPL1fWusSG8DUmEOYdNSZ3k5JL38JQSUYK5vTvI+NIzVMLPPYG/QRNxfMjPGY21yZHfPs2EKPPopWQVj63yD2CRRRBVjptoBgMeY/K1ms3pUMPWzw6lX+crQk5tM9rOViFy4T0QHSb+AJXMXNYFmeS3kA6BC/rc/tdTBf3N16d3qB+WBYQSK391Zf5eDEKM1gCkG3XDo0VDB9EkLmRrJb76zeGNzPOqRSMog1y/PSM0uDeOO/9+jXDeVk2FV+kO8b6bDPBdd/tGkHM9U6q4eK9gitoDHzMOR9S7J5skA9l/ywp3bjVlj7zN3/uo8R+TS5ysWjJPDa2iiG2BwdAqya61Gzgw3yJ9TyMPrGTx7Pblrx89Wd77IWxqyk28KTweMNLy8hF9oVUu4wPSFnYdP3tYKco/phf3pm1MzLTH8q3sH/JGlIU0D+BN9o7/SYc27vA2uo5dnfKljKT5rO/Le83UzAeYcHAsgPey0i/4fdWIEXCu2brUAAAAASUVORK5CYII=';
overlays.donald = 'data:image/png;base64,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';
overlays.lucky = 'data:image/png;base64,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';
overlays.custom = options[tileId].shapes_overlay_base64;
var ballSize = Number(options[tileId].Size)*2;
var offset = (40 - ballSize) / 2;
var img = new Image();
img.src = overlays[type];
var overlay = document.createElement("canvas");
overlay.width = 40;
overlay.height = 40;
var overlayCtx = overlay.getContext("2d");
overlayCtx.globalAlpha = alpha;
overlayCtx.drawImage(img, 0, 0);
ctx.globalCompositeOperation = "source-atop";
ctx.drawImage(overlay, 0, 0);
ctx.globalCompositeOperation = "source-over";
overlay = null;
}
function addGridToTile(ctx, size, lineWidth, color, opacity, dashed, evenX, evenY, isStriped, altSides, globalCompositeOperation="source-over") {
if (!ctx) return;
if (!size) size = 40;
size = Number(size);
ctx.globalCompositeOperation = globalCompositeOperation;
ctx.lineWidth = lineWidth;
ctx.strokeStyle = hexToRgbA(color, opacity);
if (dashed) ctx.setLineDash([2, 2]);
if (size > 40) {
let j = size / 2;
let i = 40 - j;
if (evenX && !evenY) { //TL
ctx.beginPath();
ctx.moveTo(i, 40);
ctx.lineTo(i, i);
ctx.lineTo(40, i);
ctx.stroke();
ctx.closePath();
} else if (!evenX && !evenY) { //TR
ctx.beginPath();
ctx.moveTo(0, i);
ctx.lineTo(j, i);
ctx.lineTo(j, 40);
ctx.stroke();
ctx.closePath();
} else if (!evenX && evenY) { //BR
ctx.beginPath();
ctx.moveTo(j, 0);
ctx.lineTo(j, j);
ctx.lineTo(0, j);
ctx.stroke();
ctx.closePath();
} else if (evenX && evenY) { //BL
ctx.beginPath();
ctx.moveTo(40, j);
ctx.lineTo(i, j);
ctx.lineTo(i, 0);
ctx.stroke();
ctx.closePath();
}
} else {
let loops = Math.floor(40 / size);
let margin = (40 % size) / 2;
let adj = 1; //(lineWidth/2);
ctx.translate(0.5, 0.5);
ctx.lineWidth = lineWidth;
for (var i=0; i<loops; i++) {
let x = i*size+margin;
for (var j=0; j<loops; j++) {
let y = j*size+margin;
ctx.strokeStyle = hexToRgbA(color, opacity);
ctx.beginPath();
ctx.moveTo(x, y+size-margin);
ctx.lineTo(x, y);
ctx.lineTo(x+size-margin, y);
ctx.stroke();
ctx.closePath();
if (altSides) {
ctx.strokeStyle = hexToRgbA(options.floortiles.grids_square_altColor, opacity);
ctx.beginPath();
ctx.moveTo(x-adj+margin, y+size-adj);
ctx.lineTo(x+size-adj, y+size-adj);
ctx.lineTo(x+size-adj, y-adj+margin);
ctx.stroke();
ctx.closePath();
}
}
}
ctx.translate(-0.5, -0.5);
}
ctx.setLineDash([]);
ctx.globalCompositeOperation = "source-over";
}
function addXToTile(ctx, size, lineWidth, color, opacity, dashed, evenTile, translate=false, globalCompositeOperation="source-over") {
if (!ctx) return;
if (!size) size = 40;
size = Number(size);
let startX = 0;
let startY = 0;
ctx.globalCompositeOperation = globalCompositeOperation;
if (size > 40) {
if (evenTile) {
let j = size / 2;
let i = 20 - (j - 20);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = hexToRgbA(color, opacity);
if (dashed > 0) ctx.setLineDash([dashed]);
if (translate) ctx.translate(0.5, 0.5);
ctx.beginPath();
ctx.moveTo(i-0.5, i-0.5);
ctx.lineTo(j-0.5, j-0.5);
ctx.closePath();
ctx.stroke();
if (translate) ctx.translate(-0.5, -0.5);
ctx.beginPath();
ctx.moveTo(j, i);
ctx.lineTo(i, j);
ctx.closePath();
ctx.stroke();
}
} else {
var pattern = document.createElement('canvas');
pattern.width = size;
pattern.height = size;
var pctx = pattern.getContext('2d');
pctx.lineWidth = lineWidth;
pctx.strokeStyle = hexToRgbA(color, opacity);
if (dashed) pctx.setLineDash([dashed]);
if (translate) pctx.translate(0.5, 0.5);
pctx.beginPath();
pctx.moveTo(0-0.5, 0-0.5);
pctx.lineTo(size-0.5, size-0.5);
pctx.closePath();
pctx.stroke();
if (translate) pctx.translate(-0.5, -0.5);
pctx.beginPath();
pctx.moveTo(size, 0);
pctx.lineTo(0, size);
pctx.closePath();
pctx.stroke();
var patt = ctx.createPattern(pattern, "repeat");
ctx.fillStyle = patt;
ctx.fillRect(0, 0, 40, 40);
pattern = null;
}
ctx.setLineDash([]);
ctx.globalCompositeOperation = "source-over";
}
function addSpecksToTile(ctx, count, color, opacity, width=1, length=1, angle=315) {
if (!ctx) return;
let a = angle * Math.PI / 180;
ctx.fillStyle = hexToRgbA(color, opacity);
ctx.strokeStyle = hexToRgbA(color, opacity);
for (var i=0; i<count; i++) {
if (angle === '0') a = Math.random() * Math.PI * 2;
let sx = Math.random()*40;
let sy = Math.random()*40;
let d = Math.random()*length;
let dx = sx + Math.cos(a) * d;
let dy = sy + Math.sin(a) * d;
ctx.lineWidth = Math.random()*width;
ctx.beginPath();
ctx.moveTo(sx, sy);
ctx.lineTo(dx, dy);
ctx.closePath();
ctx.stroke();
}
}
function drawFloorTile(ctx, image, evenX, evenY, drawExtras=true) {
if (!ctx) return;
let tilesColor = options.floortiles.tint_color;
let tilesTintOpacity = (options.floortiles.modify && options.floortiles.tint_opacity > 0) ? options.floortiles.tint_opacity / 100 : 0;
let tilesTransparency = 0;
let evenTile = false;
if (drawExtras) {
if ((evenX && evenY) || (!evenX && !evenY)) {
evenTile = true;
}
if (options.floortiles.checkered) {
if (evenTile || (options.floortiles.checkered_random && Math.floor(Math.random()*3))) {
tilesColor = options.floortiles.checkered_altTintColor;
tilesTintOpacity = options.floortiles.checkered_altTintOpacity / 100;
}
}
}
if (options.floortiles.modify && options.floortiles.plain) {
let margin = options.floortiles.margin;
tilesTransparency = (options.floortiles.modify && options.floortiles.transparency > 0) ? (100 - options.floortiles.transparency) / 100 : 1;
//if (margin === '20' || tilesTransparency === '100') return;
ctx.fillStyle = hexToRgbA(options.floortiles.tint_color, tilesTransparency);
ctx.fillRect(margin, margin, 40-margin*2, 40-margin*2);
if (options.floortiles.checkered) {
setTint(ctx.canvas, tilesColor, tilesTintOpacity);
}
} else if (image) {
if (options.floortiles.modify && options.floortiles.transparency === '100') tilesTransparency = 1;
else if (options.floortiles.modify && options.floortiles.transparency === '0') tilesTransparency = 1; //
else tilesTransparency = (100 - options.floortiles.transparency) / 100;
if (options.floortiles.modify && tilesTransparency > 0) ctx.globalAlpha = tilesTransparency;
ctx.drawImage(image, 520, 160, 40, 40, 0, 0, 40, 40);
if (tilesTintOpacity > 0) setTint(ctx.canvas, tilesColor, tilesTintOpacity);
ctx.globalAlpha = 1;
} else {
return;
}
if (drawExtras) {
if (options.floortiles.specks) {
let specksCount = options.floortiles.specks_count;
let specksColor = options.floortiles.specks_color;
let specksOpacity = options.floortiles.specks_opacity / 100;
let specksWidth = options.floortiles.specks_width;
let specksLength = options.floortiles.specks_length;
let specksAngle = options.floortiles.specks_angle;
addSpecksToTile(ctx, specksCount, specksColor, specksOpacity, specksWidth, specksLength, specksAngle);
}
if (options.floortiles.grids_square) {
addGridToTile(ctx, options.floortiles.grids_square_size, options.floortiles.grids_square_linewidth, options.floortiles.grids_square_color, options.floortiles.grids_square_opacity / 100, options.floortiles.grids_square_dashed, evenX, evenY, options.floortiles.checkered_stripes, options.floortiles.grids_square_altSides);
}
if (options.floortiles.grids_diagonal) {
addXToTile(ctx, options.floortiles.grids_diagonal_size, 1, options.floortiles.grids_diagonal_color, options.floortiles.grids_diagonal_opacity / 100, options.floortiles.grids_diagonal_dashed, evenTile, true);
}
}
}
/* Helper functions... */
const hexToRgb = hex =>
hex.replace(/^#?([a-f\d])([a-f\d])([a-f\d])$/i, (m, r, g, b) => '#' + r + r + g + g + b + b)
.substring(1).match(/.{2}/g)
.map(x => parseInt(x, 16));
function hexToRgbA(hex, alpha=1){
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 (!$.isNumeric(alpha) || (alpha < 0) || (alpha > 1)) alpha = 1;
return 'rgba(' + [(c>>16)&255, (c>>8)&255, c&255].join(', ') + ', ' + alpha + ')';
}
}
function colorLuminance(hex, lum) {
hex = String(hex).replace(/[^0-9a-f]/gi, '');
if (hex.length < 6) {
hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
}
lum = lum || 0;
var rgb = "#", c, i;
for (i = 0; i < 3; i++) {
c = parseInt(hex.substr(i*2,2), 16);
c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
rgb += ("00"+c).substr(c.length);
}
return rgb;
}
function clamp(number, min, max) { return Math.max(min, Math.min(number, max)); }
function loop(number, min, max) { return number < min ? max : (number > max ? min : number); }
function isCircleIntersectingRect(circle, rect, circlelineWidth=0) {
circlelineWidth = circlelineWidth/2;
// Find the vertical & horizontal (distX/distY) distances between the circle’s center and the rectangle’s center
let rectWC = rect.w/2;
let rectHC = rect.h/2;
let distX = Math.abs(circle.x - rect.x-rectWC);
let distY = Math.abs(circle.y - rect.y-rectHC);
// If the distance is greater than halfCircle + halfRect, then they are too far apart to be colliding
if (distX > (rectWC + Number(circle.r))) { return false; }
if (distY > (rectHC + Number(circle.r))) { return false; }
// Find the closest point to the circle within the rectangle
let closestX = clamp(circle.x, rect.x, rect.x+rect.w);
let closestY = clamp(circle.y, rect.y, rect.y+rect.h);
let farthestX = loop(circle.x, rect.x, rect.x+rect.w);
let farthestY = loop(circle.y, rect.y, rect.y+rect.h);
// Calculate the distance between the circle's center and this closest point
let distanceX = circle.x - closestX;
let distanceY = circle.y - closestY;
let distanceX2 = circle.x - farthestX;
let distanceY2 = circle.y - farthestY;
// If the distance is less than the circle's radius, an intersection occurs
let distanceSquared = (distanceX * distanceX) + (distanceY * distanceY);
let distanceSquared2 = (distanceX2 * distanceX2) + (distanceY2 * distanceY2);
let circleSquared = (+circle.r+circlelineWidth) * (+circle.r+circlelineWidth);
let circleSquared2 = (+circle.r-circlelineWidth) * (+circle.r-circlelineWidth);
return (distanceSquared <= circleSquared && distanceSquared2 >= circleSquared2);
}
/**
* Set tint of a given canvas element.
* @param {HTMLElement} image - Canvas element holding the image to tint.
* @param {string} [color="#000000"] - Color string to tint the tiles, like "#FF0000".
* @param {number} [opacity="0.01"] - How much to preserve the original image.
**/
function setTint(image, color, opacity, globalCompositeOperation="destination-atop") {
// Adapted from: http://stackoverflow.com/a/4231508/1698058
var tint = document.createElement("canvas");
tint.width = image.width;
tint.height = image.height;
var tintCtx = tint.getContext("2d");
tintCtx.fillStyle = hexToRgbA(color || "#000000", opacity);
tintCtx.fillRect(0, 0, tint.width, tint.height);
tintCtx.globalCompositeOperation = globalCompositeOperation; //destination-atop
//tintCtx.globalAlpha = opacity || 0.01;
tintCtx.drawImage(image, 0, 0);
var imageCtx = image.getContext("2d");
//imageCtx.globalAlpha = opacity || 0.01;
imageCtx.drawImage(tint, 0, 0);
tint = null;
}
function roundedRect(ctx, x, y, width, height, radius, stroke, fill) {
ctx.save();
ctx.beginPath();
ctx.moveTo(x+radius,y);
ctx.arcTo(x+width,y,x+width,y+radius,radius);
ctx.arcTo(x+width,y+height,x+width-radius,y+height,radius);
ctx.arcTo(x,y+height,x,y+height-radius,radius);
ctx.arcTo(x,y,x+radius,y,radius);
if (stroke) ctx.stroke();
if (fill) ctx.fill();
ctx.restore();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment