Compare commits
4 Commits
eb216fd0e4
...
ed94c65172
Author | SHA1 | Date |
---|---|---|
|
ed94c65172 | |
|
546d17c76b | |
|
43b5b1b016 | |
|
3f3ad1a185 |
1
build.js
1
build.js
|
@ -56,6 +56,7 @@ script = script.replace(/\bS\[(\d+)\]/g, (_match, index) => `"${stringArray[inde
|
||||||
const modUtils = new ModUtils(minifyCode(script));
|
const modUtils = new ModUtils(minifyCode(script));
|
||||||
|
|
||||||
import applyPatches from './patches/main.js';
|
import applyPatches from './patches/main.js';
|
||||||
|
console.log("Applying patches...");
|
||||||
applyPatches(modUtils);
|
applyPatches(modUtils);
|
||||||
|
|
||||||
// for versions ^1.99.5.2
|
// for versions ^1.99.5.2
|
||||||
|
|
54
modUtils.js
54
modUtils.js
|
@ -5,6 +5,8 @@ import UglifyJS from 'uglify-js';
|
||||||
const escapeRegExp = (/** @type {string} */ string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
const escapeRegExp = (/** @type {string} */ string) => string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&');
|
||||||
|
|
||||||
export function minifyCode(/** @type {string} */ script) {
|
export function minifyCode(/** @type {string} */ script) {
|
||||||
|
// "return" statements outside of a function throw a parse error
|
||||||
|
script = "()=>{" + script + "}";
|
||||||
const output = UglifyJS.minify(script, {
|
const output = UglifyJS.minify(script, {
|
||||||
compress: false,
|
compress: false,
|
||||||
mangle: false
|
mangle: false
|
||||||
|
@ -12,7 +14,10 @@ export function minifyCode(/** @type {string} */ script) {
|
||||||
if (output.error) throw output.error;
|
if (output.error) throw output.error;
|
||||||
if (output.warnings) throw (output.warnings);
|
if (output.warnings) throw (output.warnings);
|
||||||
if (output.warnings) console.warn(output.warnings);
|
if (output.warnings) console.warn(output.warnings);
|
||||||
return output.code;
|
let code = output.code;
|
||||||
|
if (code.endsWith(";")) code = code.slice(0, -1);
|
||||||
|
code = code.slice(5, -1); // unwrap from function
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ModUtils {
|
class ModUtils {
|
||||||
|
@ -34,6 +39,8 @@ class ModUtils {
|
||||||
this.matchRawCode = this.matchRawCode.bind(this);
|
this.matchRawCode = this.matchRawCode.bind(this);
|
||||||
this.replaceCode = this.replaceCode.bind(this);
|
this.replaceCode = this.replaceCode.bind(this);
|
||||||
this.waitForMinification = this.waitForMinification.bind(this);
|
this.waitForMinification = this.waitForMinification.bind(this);
|
||||||
|
this.matchCode = this.matchCode.bind(this);
|
||||||
|
this.insertCode = this.insertCode.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {RegExp} expression */
|
/** @param {RegExp} expression */
|
||||||
|
@ -71,11 +78,13 @@ class ModUtils {
|
||||||
// Return value example:
|
// Return value example:
|
||||||
// When replaceRawCode or matchRawCode are called with "var1=var2+1;" as the code
|
// When replaceRawCode or matchRawCode are called with "var1=var2+1;" as the code
|
||||||
// and this matches "a=b+1;", the returned value will be the object: { var1: "a", var2: "b" }
|
// and this matches "a=b+1;", the returned value will be the object: { var1: "a", var2: "b" }
|
||||||
|
/** @param {{ [x: string]: string; }} [nameMappings] */
|
||||||
replaceRawCode(/** @type {string} */ raw, /** @type {string} */ result, nameMappings) {
|
replaceRawCode(/** @type {string} */ raw, /** @type {string} */ result, nameMappings) {
|
||||||
const { expression, groups } = this.generateRegularExpression(raw, false, nameMappings);
|
const { expression, groups } = this.generateRegularExpression(raw, false, nameMappings);
|
||||||
let localizerCount = 0;
|
let localizerCount = 0;
|
||||||
let replacementString = result.replaceAll("$", "$$").replaceAll("__L()", "__L)").replaceAll("__L(", "__L,")
|
let replacementString = result.replaceAll("$", "$$").replaceAll("__L()", "__L)").replaceAll("__L(", "__L,")
|
||||||
.replace(/\w+/g, match => {
|
.replace(/\w+/g, match => {
|
||||||
|
if (nameMappings !== undefined && nameMappings.hasOwnProperty(match)) return nameMappings[match];
|
||||||
// these would get stored as "___localizer1", "___localizer2", ...
|
// these would get stored as "___localizer1", "___localizer2", ...
|
||||||
if (match === "__L") match = "___localizer" + (++localizerCount);
|
if (match === "__L") match = "___localizer" + (++localizerCount);
|
||||||
return groups.hasOwnProperty(match) ? "$" + groups[match] : match;
|
return groups.hasOwnProperty(match) ? "$" + groups[match] : match;
|
||||||
|
@ -90,8 +99,14 @@ class ModUtils {
|
||||||
}
|
}
|
||||||
matchRawCode(/** @type {string} */ raw, nameMappings) {
|
matchRawCode(/** @type {string} */ raw, nameMappings) {
|
||||||
const { expression, groups } = this.generateRegularExpression(raw, false, nameMappings);
|
const { expression, groups } = this.generateRegularExpression(raw, false, nameMappings);
|
||||||
const expressionMatchResult = this.matchOne(expression);
|
try {
|
||||||
return Object.fromEntries(Object.entries(groups).map(([identifier, groupNumber]) => [identifier, expressionMatchResult[groupNumber]]));
|
const expressionMatchResult = this.matchOne(expression);
|
||||||
|
return Object.fromEntries(Object.entries(groups).map(
|
||||||
|
([identifier, groupNumber]) => [identifier, expressionMatchResult[groupNumber]]
|
||||||
|
));
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error("matchRawCode match error:\n\n" + e + "\n\nRaw code: " + raw + "\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
generateRegularExpression(/** @type {string} */ code, /** @type {boolean} */ isForDictionary, nameMappings) {
|
generateRegularExpression(/** @type {string} */ code, /** @type {boolean} */ isForDictionary, nameMappings) {
|
||||||
const groups = {};
|
const groups = {};
|
||||||
|
@ -119,9 +134,38 @@ class ModUtils {
|
||||||
let expression = new RegExp(isForDictionary ? raw.replaceAll("@@", "@") : raw, "g");
|
let expression = new RegExp(isForDictionary ? raw.replaceAll("@@", "@") : raw, "g");
|
||||||
return { expression, groups };
|
return { expression, groups };
|
||||||
}
|
}
|
||||||
replaceCode(code, replacement, options) {
|
|
||||||
return this.replaceRawCode(minifyCode(code), replacement);
|
/**
|
||||||
|
* @typedef {{ dictionary?: { [x: string]: string } }} BaseOptions
|
||||||
|
* @typedef {BaseOptions & { addToDictionary?: string[] }} MatchCodeOptions
|
||||||
|
*/
|
||||||
|
matchCode(code, /** @type {MatchCodeOptions=} */ options) {
|
||||||
|
const result = this.matchRawCode(minifyCode(code));
|
||||||
|
if (options?.addToDictionary !== undefined) {
|
||||||
|
options.addToDictionary.forEach(varName => {
|
||||||
|
if (result[varName] === undefined)
|
||||||
|
throw new Error(`matchCode addToDictionary error: ${varName} was undefined in the match results`)
|
||||||
|
this.addToDictionary(varName, result[varName]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
replaceCode(/** @type {string} */ code, /** @type {string} */ replacement, /** @type {BaseOptions=} */ options) {
|
||||||
|
return this.replaceRawCode(minifyCode(code), replacement, options?.dictionary);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} code
|
||||||
|
* @param {string} codeToInsert
|
||||||
|
* @param {BaseOptions} [options]
|
||||||
|
*/
|
||||||
|
insertCode(code, codeToInsert, options) {
|
||||||
|
const insertionPoint = "/* here */";
|
||||||
|
if (!code.includes(insertionPoint)) throw new Error("insertCode: No insertion point found");
|
||||||
|
return this.replaceCode(code.replace(insertionPoint, ""), code.replace(insertionPoint, codeToInsert), options);
|
||||||
|
}
|
||||||
|
|
||||||
waitForMinification(/** @type {Function} */ handler) {
|
waitForMinification(/** @type {Function} */ handler) {
|
||||||
this.postMinifyHandlers.push(handler);
|
this.postMinifyHandlers.push(handler);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,17 @@
|
||||||
import ModUtils from '../modUtils.js';
|
import ModUtils from '../modUtils.js';
|
||||||
|
|
||||||
// Custom lobby patches
|
// Custom lobby patches
|
||||||
export default (/** @type {ModUtils} */ { replaceCode, replaceRawCode, dictionary: dict, waitForMinification }) => {
|
export default (/** @type {ModUtils} */ { insertCode, replaceRawCode, dictionary: dict, waitForMinification }) => {
|
||||||
|
|
||||||
// set player id correctly
|
// set player id correctly
|
||||||
replaceCode(`function aBG(aBE) {
|
insertCode(`function aBG(aBE) {
|
||||||
if (!Lobby.aAl) { return -1; }
|
if (!Lobby.aAl) { return -1; }
|
||||||
|
/* here */
|
||||||
var s = aBE.length;
|
var s = aBE.length;
|
||||||
var qu = Lobby.aAl.qu;
|
var qu = Lobby.aAl.qu;
|
||||||
for (var i = 0; i < s; i++) { if (aBE[i].qu === qu) { return i; } }
|
for (var i = 0; i < s; i++) { if (aBE[i].qu === qu) { return i; } }
|
||||||
return -1;
|
return -1;
|
||||||
}`, `function aBG(aBE) {
|
}`, `if (__fx.customLobby.isActive()) return __fx.customLobby.getPlayerId();`);
|
||||||
if (!Lobby.aAl) { return -1; }
|
|
||||||
if (__fx.customLobby.isActive()) return __fx.customLobby.getPlayerId();
|
|
||||||
var s = aBE.length;
|
|
||||||
var qu = Lobby.aAl.qu;
|
|
||||||
for (var i = 0; i < s; i++) { if (aBE[i].qu === qu) { return i; } }
|
|
||||||
return -1;
|
|
||||||
}`);
|
|
||||||
|
|
||||||
waitForMinification(() => {
|
waitForMinification(() => {
|
||||||
replaceRawCode("this.aHm=function(){i___.rX(),aM.a7U(0),aM.init()}",
|
replaceRawCode("this.aHm=function(){i___.rX(),aM.a7U(0),aM.init()}",
|
||||||
|
@ -42,10 +36,10 @@ export default (/** @type {ModUtils} */ { replaceCode, replaceRawCode, dictionar
|
||||||
wR===1 && __fx.customLobby.isActive() && ${dict.MenuManager}.${dict.getState}() !== 6 && __fx.customLobby.setActive(false);
|
wR===1 && __fx.customLobby.isActive() && ${dict.MenuManager}.${dict.getState}() !== 6 && __fx.customLobby.setActive(false);
|
||||||
if(8===i.pz&&0===wR)if(4211===d)wS(d);`)
|
if(8===i.pz&&0===wR)if(4211===d)wS(d);`)
|
||||||
// when leaving a game
|
// when leaving a game
|
||||||
replaceRawCode("this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),ap.ky.zt(),this.vH=0,bU.zu(),m.n.setState(0),zs||bJ.df.show(),aN.setState(0),2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}",
|
replaceRawCode("this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),ap.ky.zt(),this.vH=0,bU.zu(),m.n.setState(0),aN.setState(0),zs||bJ.df.show(),2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}",
|
||||||
`this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),
|
`this.wl=function(zs){a1.gZ||az.oO.a11.length||(az.oO.a11=az.a12.vd()),
|
||||||
__fx.customLobby.isActive() === false && ap.ky.zt(),
|
__fx.customLobby.isActive() === false && ap.ky.zt(),
|
||||||
this.vH=0,bU.zu(),m.n.setState(0),zs||bJ.df.show(),aN.setState(0);
|
this.vH=0,bU.zu(),m.n.setState(0),aN.setState(0),zs||bJ.df.show();
|
||||||
if (__fx.customLobby.isActive()) __fx.customLobby.rejoinLobby(); else 2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}`)
|
if (__fx.customLobby.isActive()) __fx.customLobby.rejoinLobby(); else 2===this.a3D?i.ky.a3U():1===this.a3D?i.j(19):i.j(5,5)}`)
|
||||||
// do not display lobby UI
|
// do not display lobby UI
|
||||||
replaceRawCode(`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),`,
|
replaceRawCode(`(sV.style.backdropFilter="blur(4px)",sV.style.webkitBackdropFilter="blur(4px)"),`,
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
export default (/** @type {import('../modUtils.js').default} */ { insertCode, replaceCode, matchCode }) => {
|
||||||
|
|
||||||
|
const { mainCanvas, x, y } = insertCode(`this.te = function() {
|
||||||
|
if (!this.b()) { return; }
|
||||||
|
mainCanvas.drawImage(canvas, x, this.y);
|
||||||
|
/* here */
|
||||||
|
}`, `if (__fx.settings.keybindButtons) __fx.mobileKeybinds.draw(mainCanvas, x, this.y);`)
|
||||||
|
|
||||||
|
const { h, redraw } = insertCode(`a6k = Math.floor(3 * this.h / 2);
|
||||||
|
a4M = c.pZ.rN(1, Math.floor(0.5 * this.h));
|
||||||
|
canvas = document.createElement("canvas");
|
||||||
|
canvas.width = w;
|
||||||
|
/* here */
|
||||||
|
canvas.height = this.h;
|
||||||
|
ctx = canvas.getContext("2d", { alpha: true });
|
||||||
|
ctx.font = a4M;
|
||||||
|
c.pZ.textBaseline(ctx, 1);
|
||||||
|
c.pZ.textAlign(ctx, 1);
|
||||||
|
this.a6m();
|
||||||
|
redraw();
|
||||||
|
`, `__fx.mobileKeybinds.setSize(w, this.h, mainCanvas)`, { dictionary: { mainCanvas } })
|
||||||
|
|
||||||
|
const { ba, gap } = matchCode(`this.h = Math.floor(0.066 * h___.pb); w = h___.w - 4 * ba.gap - this.h;`);
|
||||||
|
|
||||||
|
const { bd, requestRepaint } = insertCode(`this.gm = function(kt, ku) {
|
||||||
|
if (!this.b()) { return false; }
|
||||||
|
/* here */
|
||||||
|
if (!a.a0n(kt, ku)) { return false; }
|
||||||
|
aR.mC = false;
|
||||||
|
if (a6w(this, kt, ku)) { bd.requestRepaint = true; }
|
||||||
|
return true;
|
||||||
|
};`,
|
||||||
|
`if (__fx.settings.keybindButtons && ku > this.y - Math.floor(ba.gap / 4) - this.h && ku < this.y - Math.floor(ba.gap / 4) && __fx.mobileKeybinds.click(kt - x)) return true;`,
|
||||||
|
{ dictionary: { x, y, h, ba, gap } }
|
||||||
|
)
|
||||||
|
|
||||||
|
insertCode(
|
||||||
|
`var a6l = 11 / 12; /* here */`,
|
||||||
|
`__fx.keybindFunctions.repaintAttackPercentageBar = function() { redraw(); bd.requestRepaint = true; };`,
|
||||||
|
{ dictionary: { redraw, bd, requestRepaint } }
|
||||||
|
)
|
||||||
|
|
||||||
|
// fix to correctly display peace vote menu and game messages (prevent overlap with keybind buttons)
|
||||||
|
replaceCode(`if (a.a4y(aM.a4u())) {
|
||||||
|
if (au.b) { return a.y - a.h - 2 * a4a; }
|
||||||
|
else { return a.y - a4a; }
|
||||||
|
}`, `if (a.a4y(aM.a4u())) {
|
||||||
|
if (au.b) { return __fx.settings.keybindButtons ? a.y - 2 * a.h - 3 * a4a : a.y - a.h - 2 * a4a; }
|
||||||
|
else { return __fx.settings.keybindButtons ? a.y - a.h - 2 * a4a : a.y - a4a; }
|
||||||
|
}`)
|
||||||
|
insertCode(
|
||||||
|
`if (a.a4y(aM.a4u())) { return /* here */ a.y - h - ba.gap; }`,
|
||||||
|
`__fx.settings.keybindButtons ? a.y - 2 * (h + ba.gap) : `
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
|
@ -1,7 +1,10 @@
|
||||||
const playerDataProperties = ["playerTerritories", "playerBalances", "rawPlayerNames"];
|
const playerDataProperties = ["playerTerritories", "playerBalances", "rawPlayerNames"];
|
||||||
const gameObjectProperties = ["playerId", "gIsTeamGame", "gHumans", "gLobbyMaxJoin", "gameState", "gIsSingleplayer"];
|
const gameObjectProperties = ["playerId", "gIsTeamGame", "gHumans", "gLobbyMaxJoin", "gameState", "gIsSingleplayer"];
|
||||||
|
|
||||||
export const getVar = varName => {
|
export const getVar = varName => {
|
||||||
if (playerDataProperties.includes(varName)) return window[dictionary.playerData]?.[dictionary[varName]];
|
if (playerDataProperties.includes(varName)) return window[dictionary.playerData]?.[dictionary[varName]];
|
||||||
if (gameObjectProperties.includes(varName)) return window[dictionary.game]?.[dictionary[varName]];
|
if (gameObjectProperties.includes(varName)) return window[dictionary.game]?.[dictionary[varName]];
|
||||||
return window[dictionary[varName]]
|
return window[dictionary[varName]]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getUIGap = () => Math.floor(window[dictionary.uiSizes]?.[dictionary.gap] ?? 10);
|
|
@ -1,10 +1,66 @@
|
||||||
|
import { getUIGap } from "./gameInterface.js";
|
||||||
import { getSettings } from "./settings.js";
|
import { getSettings } from "./settings.js";
|
||||||
|
|
||||||
export const keybindFunctions = { setAbsolute: () => {}, setRelative: () => {} };
|
export const keybindFunctions = {
|
||||||
|
setAbsolute: () => {},
|
||||||
|
setRelative: () => {},
|
||||||
|
repaintAttackPercentageBar: () => {}
|
||||||
|
};
|
||||||
export const keybindHandler = key => {
|
export const keybindHandler = key => {
|
||||||
const keybindData = getSettings().attackPercentageKeybinds.find(keybind => keybind.key === key);
|
const keybindData = getSettings().attackPercentageKeybinds.find(keybind => keybind.key === key);
|
||||||
if (keybindData === undefined) return false;
|
if (keybindData === undefined) return false;
|
||||||
if (keybindData.type === "absolute") keybindFunctions.setAbsolute(keybindData.value);
|
executeKeybind(keybindData);
|
||||||
else keybindFunctions.setRelative(keybindData.value);
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
function executeKeybind(keybind) {
|
||||||
|
if (keybind.type === "absolute") keybindFunctions.setAbsolute(keybind.value);
|
||||||
|
else keybindFunctions.setRelative(keybind.value);
|
||||||
|
keybindFunctions.repaintAttackPercentageBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
// mobile keybinds (keybind buttons)
|
||||||
|
|
||||||
|
let canvas;
|
||||||
|
let width = 0;
|
||||||
|
let height = 0;
|
||||||
|
const maxCount = 6;
|
||||||
|
|
||||||
|
export const mobileKeybinds = {
|
||||||
|
setSize: (w, h, mainCanvas) => {
|
||||||
|
if (getSettings().keybindButtons !== true) return;
|
||||||
|
width = w;
|
||||||
|
height = h;
|
||||||
|
|
||||||
|
// redraw
|
||||||
|
canvas = document.createElement("canvas");
|
||||||
|
canvas.width = w;
|
||||||
|
canvas.height = h;
|
||||||
|
const ctx = canvas.getContext("2d");
|
||||||
|
const fontName = mainCanvas.font.split("px ", 2)[1];
|
||||||
|
ctx.font = "bold " + h / 2 + "px " + fontName;
|
||||||
|
ctx.textAlign = "center";
|
||||||
|
ctx.textBaseline = "middle";
|
||||||
|
|
||||||
|
const keybinds = getSettings().attackPercentageKeybinds.slice(0, maxCount);
|
||||||
|
const gap = getUIGap() / 4;
|
||||||
|
const buttonWidth = (w - gap * (maxCount - 1)) / maxCount;
|
||||||
|
keybinds.forEach((keybind, i) => {
|
||||||
|
ctx.fillStyle = "rgba(0, 0, 0, 0.8)";
|
||||||
|
ctx.fillRect(i * (buttonWidth + gap), 0, buttonWidth, h);
|
||||||
|
ctx.fillStyle = "white";
|
||||||
|
const label = keybind.type === "absolute" ? (keybind.value * 100).toFixed() + "%" : "x " + Math.round(keybind.value * 100) / 100;
|
||||||
|
ctx.fillText(label, (i + 0.5) * (buttonWidth + gap), h / 2);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
click: (xRelative) => {
|
||||||
|
if (xRelative < 0 || xRelative > width) return false;
|
||||||
|
const keybinds = getSettings().attackPercentageKeybinds;
|
||||||
|
const index = Math.floor(xRelative / width * maxCount);
|
||||||
|
if (index >= keybinds.length) return false;
|
||||||
|
executeKeybind(keybinds[index]);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
draw: (mainCanvas, x, y) => {
|
||||||
|
mainCanvas.drawImage(canvas, x, y - (height + getUIGap() / 4));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
export function KeybindsInput(containerElement) {
|
export function KeybindsInput(/** @type {HTMLElement} */ containerElement) {
|
||||||
const header = document.createElement("p");
|
const header = document.createElement("p");
|
||||||
header.innerText = "Attack Percentage Keybinds";
|
header.innerText = "Attack Percentage Keybinds";
|
||||||
const keybindContainer = document.createElement("div");
|
const keybindContainer = document.createElement("div");
|
||||||
|
@ -6,6 +6,7 @@ export function KeybindsInput(containerElement) {
|
||||||
const keybindAddButton = document.createElement("button");
|
const keybindAddButton = document.createElement("button");
|
||||||
keybindAddButton.innerText = "Add";
|
keybindAddButton.innerText = "Add";
|
||||||
containerElement.append(header, keybindContainer, keybindAddButton);
|
containerElement.append(header, keybindContainer, keybindAddButton);
|
||||||
|
containerElement.className = "keybinds-input";
|
||||||
this.container = keybindContainer;
|
this.container = keybindContainer;
|
||||||
this.keys = [ "key", "type", "value" ];
|
this.keys = [ "key", "type", "value" ];
|
||||||
this.objectArray = [];
|
this.objectArray = [];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
const fx_version = '0.6.7.1'; // FX Client Version
|
const fx_version = '0.6.7.2'; // FX Client Version
|
||||||
const fx_update = 'Feb 15'; // FX Client Last Updated
|
const fx_update = 'Mar 2'; // FX Client Last Updated
|
||||||
|
|
||||||
if ("serviceWorker" in navigator) {
|
if ("serviceWorker" in navigator) {
|
||||||
navigator.serviceWorker.addEventListener("message", (e) => {
|
navigator.serviceWorker.addEventListener("message", (e) => {
|
||||||
|
@ -20,7 +20,7 @@ import winCounter from "./winCounter.js";
|
||||||
import playerList from "./playerList.js";
|
import playerList from "./playerList.js";
|
||||||
import gameScriptUtils from "./gameScriptUtils.js";
|
import gameScriptUtils from "./gameScriptUtils.js";
|
||||||
import hoveringTooltip from "./hoveringTooltip.js";
|
import hoveringTooltip from "./hoveringTooltip.js";
|
||||||
import { keybindFunctions, keybindHandler } from "./keybinds.js";
|
import { keybindFunctions, keybindHandler, mobileKeybinds } from "./keybinds.js";
|
||||||
import customLobby from './customLobby.js';
|
import customLobby from './customLobby.js';
|
||||||
|
|
||||||
window.__fx = window.__fx || {};
|
window.__fx = window.__fx || {};
|
||||||
|
@ -33,6 +33,7 @@ __fx.utils = gameScriptUtils;
|
||||||
__fx.WindowManager = WindowManager;
|
__fx.WindowManager = WindowManager;
|
||||||
__fx.keybindFunctions = keybindFunctions;
|
__fx.keybindFunctions = keybindFunctions;
|
||||||
__fx.keybindHandler = keybindHandler;
|
__fx.keybindHandler = keybindHandler;
|
||||||
|
__fx.mobileKeybinds = mobileKeybinds;
|
||||||
__fx.donationsTracker = donationsTracker;
|
__fx.donationsTracker = donationsTracker;
|
||||||
__fx.playerList = playerList;
|
__fx.playerList = playerList;
|
||||||
__fx.hoveringTooltip = hoveringTooltip;
|
__fx.hoveringTooltip = hoveringTooltip;
|
||||||
|
|
|
@ -21,6 +21,7 @@ var settings = {
|
||||||
detailedTeamPercentage: false,
|
detailedTeamPercentage: false,
|
||||||
//"customMapFileBtn": true
|
//"customMapFileBtn": true
|
||||||
customBackgroundUrl: "",
|
customBackgroundUrl: "",
|
||||||
|
keybindButtons: false,
|
||||||
attackPercentageKeybinds: [],
|
attackPercentageKeybinds: [],
|
||||||
};
|
};
|
||||||
__fx.settings = settings;
|
__fx.settings = settings;
|
||||||
|
@ -102,6 +103,10 @@ const settingsManager = new (function () {
|
||||||
"A custom image to be shown as the main menu background instead of the currently selected map.",
|
"A custom image to be shown as the main menu background instead of the currently selected map.",
|
||||||
},
|
},
|
||||||
KeybindsInput,
|
KeybindsInput,
|
||||||
|
{
|
||||||
|
for: "keybindButtons", type: "checkbox",
|
||||||
|
label: "Keybind buttons", note: "Show keybind buttons above the troop selector (max 6)"
|
||||||
|
}
|
||||||
];
|
];
|
||||||
const settingsContainer = document.querySelector(".settings .scrollable");
|
const settingsContainer = document.querySelector(".settings .scrollable");
|
||||||
var inputFields = {}; // (includes select menus)
|
var inputFields = {}; // (includes select menus)
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
border-width : 2px;
|
border-width : 2px;
|
||||||
border-width : calc(0.15 * (1vw + 1vh));
|
border-width : calc(0.15 * (1vw + 1vh));
|
||||||
font-size : 20px;
|
font-size : 20px;
|
||||||
font-size : calc(14px + ((0.5 * (1.1vw - 0.1vh)) + 0.14rem));
|
font-size : calc(13px + ((0.5 * (1.1vw - 0.1vh)) + 0.14rem));
|
||||||
max-height : 90%;
|
max-height : 90%;
|
||||||
transition : 0.2s;
|
transition : 0.2s;
|
||||||
z-index : 10;
|
z-index : 10;
|
||||||
|
@ -59,6 +59,13 @@
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.keybinds-input {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
.keybinds-input input {
|
||||||
|
width: 10em;
|
||||||
|
}
|
||||||
|
|
||||||
.flex {
|
.flex {
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue