From f60a896ea829d598bd0f225594d6465397690394 Mon Sep 17 00:00:00 2001 From: peshomir <80340328+peshomir@users.noreply.github.com> Date: Thu, 4 Dec 2025 19:43:56 +0200 Subject: [PATCH] Fixes for game update v2.14.4; Add modifyCode function Moved most leaderboard patches to a separate file --- build.js | 4 + modUtils.js | 25 +++++- patches/leaderboard.js | 173 +++++++++++++++++++++++++++++++++++++++++ patches/patches.js | 111 +------------------------- 4 files changed, 203 insertions(+), 110 deletions(-) create mode 100644 patches/leaderboard.js diff --git a/build.js b/build.js index 39a97cf..a3df790 100644 --- a/build.js +++ b/build.js @@ -70,6 +70,10 @@ async function patchGameCode() { str += __L(/* Strength: {10} */ [b0.rY.formatNumber(playerData.playerBalances[player])]) + " "; str += __L(/* Territory: {10} */ [b0.rY.formatNumber(playerData.playerTerritories[player])]) + " "; `, addToDictionary: ["game", "gIsReplay", "playerData", "rawPlayerNames", "playerBalances", "playerTerritories"] + }, { + code: `this.a = Math.floor(0.066 * b.c); + d = b.d - 4 * uiSizes.gap - this.a;`, + addToDictionary: ["uiSizes", "gap"] }]; codeSegments.forEach(({ code, addToDictionary }) => { modUtils.matchCode(code, { addToDictionary }) diff --git a/modUtils.js b/modUtils.js index a2cd3ae..bf02da1 100644 --- a/modUtils.js +++ b/modUtils.js @@ -51,6 +51,7 @@ class ModUtils { this.waitForMinification = this.waitForMinification.bind(this); this.matchCode = this.matchCode.bind(this); this.insertCode = this.insertCode.bind(this); + this.modifyCode = this.modifyCode.bind(this); } /** @param {RegExp} expression */ @@ -177,6 +178,23 @@ class ModUtils { return this.replaceCode(code.replace(insertionPoint, ""), code.replace(insertionPoint, codeToInsert), options); } + /** + * @param {string} annotatedCode + * @param {BaseOptions} [options] + * Currenly supports lines starting with /\*insert line:*\/ (use the `insert` helper function) + */ + modifyCode(annotatedCode, options) { + const lines = annotatedCode.split(/\r?\n/g).map(l => l.trim()) + const insertionMarker = "/*insert line:*/" + + const source = lines.filter(l => !l.startsWith(insertionMarker)).join("\n") + const replacement = lines.filter(l => { + return l.startsWith(insertionMarker) ? l.slice(insertionMarker.length) : l + }).join("\n") + if (source === replacement) throw new Error("modifyCode found no changes to apply. Did you mistype the keywords?") + return this.replaceCode(source, replacement, options); + } + waitForMinification(/** @type {Function} */ handler) { this.postMinifyHandlers.push(handler); } @@ -191,4 +209,9 @@ export default ModUtils; /** @param {(modUtils: ModUtils) => any} callback */ export function definePatch(callback) { return (/** @type {ModUtils} */ modUtils) => callback(modUtils) -} \ No newline at end of file +} +/** + * Helper for `modifyCode` + * @param {string} code +*/ +export const insert = (code) => code.split(/\r?\n/g).map(l => "/*insert line:*/" + l).join("\n"); \ No newline at end of file diff --git a/patches/leaderboard.js b/patches/leaderboard.js new file mode 100644 index 0000000..c0042aa --- /dev/null +++ b/patches/leaderboard.js @@ -0,0 +1,173 @@ +import { definePatch, insert } from "../modUtils.js"; + +export default definePatch(({ safeDictionary: dict, modifyCode, waitForMinification, matchCode, replaceOne, replaceRawCode }) => { + + // Player list and leaderboard filter tabs + + const uiOffset = dict.uiSizes + "." + dict.gap + const rawPlayerNames = dict.playerData + "." + dict.rawPlayerNames + + const { topBarHeight } = matchCode(`aAn = 0.000 * aAd; topBarHeight = Math.floor(0.45 * aAm + aAf);`) + const buttonBoundsCheck = `__fx.utils.isPointInRectangle(x, y, ${uiOffset} + 12, ${uiOffset} + 12, ${topBarHeight} - 22, ${topBarHeight} - 22)` + + // Handle player list button and leaderboard tabs mouseDown + // and create a function for scrolling the leaderboard to the top + modifyCode(`/*insert line:*/__fx.leaderboardFilter.scrollToTop = function(){position = 0;} + this.mouseDown = function(x, y) { + if (a4L(x, y)) { + /*insert line:*/ if (${buttonBoundsCheck}) return (__fx.playerList.display(${rawPlayerNames}), true) + /*insert line:*/ if (y - ${uiOffset} > __fx.leaderboardFilter.verticalClickThreshold) + /*insert line:*/ return __fx.leaderboardFilter.handleMouseDown(x - ${uiOffset}) + var aZA = aZB(y); + if (aZA >= 0) { + aYm = aF.time; + aYn = true; + aYo = aYp = aZA; + if (qr.rA()) { + aZA = iA(-1, aYp, windowHeight); + aZA = (aZA === windowHeight) ? -1 : aZA; + if (aYl !== aZA) { + aYl = aZA; + drawFunction(); + aF.requestRepaint = true; + } + } + return true; + } + if (aYq) { + aYq = false; + drawFunction(); + aF.requestRepaint = true; + } + fZ.ff(10, 0, new zU({ zW: 1 })); + return true; + } + return false; + };`) + + // Handle player list button and leaderboard tabs hover + // and create a function for repainting the leaderboard + modifyCode(`/*insert line:*/ var repaintLb = __fx.leaderboardFilter.repaintLeaderboard = function() { drawFunction(), aF.requestRepaint = true; }; + this.mouseMove = function(x, y) { + ${insert(`if (${buttonBoundsCheck}) { + __fx.playerList.hoveringOverButton === false && (__fx.playerList.hoveringOverButton = true, repaintLb()); + } else { + __fx.playerList.hoveringOverButton === true && (__fx.playerList.hoveringOverButton = false, repaintLb()); + } + if (__fx.leaderboardFilter.setHovering( + __fx.utils.isPointInRectangle( + x, y, ${uiOffset}, ${uiOffset} + __fx.leaderboardFilter.verticalClickThreshold, + __fx.leaderboardFilter.windowWidth, __fx.leaderboardFilter.tabBarOffset + ), x - ${uiOffset} + )) return;`)} + var aJ; + var aZA = aZB(y); + var aZC = a4L(x, y); + var aZD = !!(aZA < 0 && aZC && !qr.rA()); + if (aYn) { + aJ = position; + position += aYo - aZA; + position = iA(0, position, game.gMaxPlayers - windowHeight); + if (position !== aJ) { + aYq = aZD; + aYo = aZA; + aZA = iA(-1, aZA, windowHeight); + aZA = (aZA === windowHeight || !aZC) ? -1 : aZA; + aYl = aZA; + drawFunction(); + aF.requestRepaint = true; + } /*...*/ + } + };`) + + waitForMinification(() => { + // Draw player list button + replaceOne(/(="";function (?\w+)\(\){[^}]+?(?\w+)\.fillRect\(0,(?\w+),\w+,1\),(?:\3\.fillRect\([^()]+\),)+\3\.font=\w+,(\w+\.\w+)\.textBaseline\(\3,1\),\5\.textAlign\(\3,1\),\3\.fillText\(\w+,Math\.floor\()(\w+)\/2\),(Math\.floor\(\w+\+\w+\/2\)\));/g, + "$1($6 + $ - 22) / 2), $7; __fx.playerList.drawButton($, 12, 12, $ - 22);") + + { // Leaderboard filter + // for the leaderboard draw function: + replaceRawCode("function drawFunction(){a0A.clearRect(0,0,a04,y9),a0A.fillStyle=aYq?aZ.a4s:aZ.a4o,a0A.fillRect(0,0,a04,a0F),a0A.fillStyle=aZ.kZ,a0A.fillRect(0,a0F,a04,y9-a0F),leaderboardPositionsById[game.playerId]>=position&&a0Z(leaderboardPositionsById[game.playerId]-position,aZ.kw),0!==leaderboardPositionsById[game.playerId]&&0===position&&a0Z(0,aZ.lJ),-1!==a0P&&a0Z(a0P,aZ.kd),a0A.fillStyle=aZ.gF,a0A.fillRect(0,a0F,a04,1),a0A.fillRect(0,0,a04,b0.ur),a0A.fillRect(0,0,b0.ur,y9),a0A.fillRect(a04-b0.ur,0,b0.ur,y9),a0A.fillRect(0,y9-b0.ur,a04,b0.ur),", + + `var leaderboardHasChanged = true; + this.playerPos = game.playerId; + __fx.leaderboardFilter.setUpdateFlag = () => leaderboardHasChanged = true; + function updateFilteredLb() { + if (!leaderboardHasChanged) return; + __fx.leaderboardFilter.filteredLeaderboard = __fx.leaderboardFilter.playersToInclude + .map(id => leaderboardPositionsById[id]).sort((a, b) => a - b); + leaderboardHasChanged = false; + this.playerPos = __fx.leaderboardFilter.filteredLeaderboard.indexOf(leaderboardPositionsById[game.playerId]); + } + function drawFunction() { + a0A.clearRect(0, 0, a04, y9), + a0A.fillStyle = aYq ? aZ.a4s : aZ.a4o, + a0A.fillRect(0, 0, a04, a0F), + a0A.fillStyle = aZ.kZ, + a0A.fillRect(0, a0F, a04, y9 - a0F); + if (__fx.leaderboardFilter.enabled) updateFilteredLb(); + var playerPos = (__fx.leaderboardFilter.enabled + ? this.playerPos + : leaderboardPositionsById[game.playerId] + ); + if (__fx.leaderboardFilter.hoveringOverTabs) a0P = -1; + if (__fx.leaderboardFilter.enabled && a0P >= __fx.leaderboardFilter.filteredLeaderboard.length) a0P = -1; + playerPos >= position && a0Z(playerPos - position, aZ.kw), + 0 !== leaderboardPositionsById[game.playerId] && 0 === position && a0Z(0, aZ.lJ), + -1 !== a0P && a0Z(a0P, aZ.kd), + a0A.fillStyle = aZ.kZ, + //console.log("drawing", a0P), + a0A.clearRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, __fx.leaderboardFilter.tabBarOffset); + a0A.fillRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, __fx.leaderboardFilter.tabBarOffset); + a0A.fillStyle = aZ.gF, + a0A.fillRect(0, a0F, a04, 1), + a0A.fillRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, 1), + __fx.leaderboardFilter.drawTabs(a0A, a04, y9 - __fx.leaderboardFilter.tabBarOffset, aZ.kw), + a0A.fillRect(0, 0, a04, b0.ur), + a0A.fillRect(0, 0, b0.ur, y9), + a0A.fillRect(a04 - b0.ur, 0, b0.ur, y9), + a0A.fillRect(0, y9 - b0.ur, a04, b0.ur),`) + replaceRawCode("var hZ,eh=leaderboardPositionsById[game.playerId]= result.length - windowHeight) + position = (result.length > windowHeight ? result.length : windowHeight) - windowHeight; + //if (position >= result.length) position = result.length - 1; + for (a0A.font = a07, aY.g0.textAlign(a0A, 0), hZ = windowHeight - eh; 0 <= hZ; hZ--) { + const pos = result[hZ + position]; + if (pos !== undefined) + a0a(leaderboardArray[pos]), a0b(hZ, pos, leaderboardArray[pos]); + } + for (aY.g0.textAlign(a0A, 2), hZ = windowHeight - eh; 0 <= hZ; hZ--) { + const pos = result[hZ + position]; + if (pos !== undefined) + a0a(leaderboardArray[pos]), a0c(hZ, leaderboardArray[pos]); + } + } else { + for (a0A.font = a07, aY.g0.textAlign(a0A, 0), hZ = windowHeight - eh; 0 <= hZ; hZ--) + a0a(leaderboardArray[hZ + position]), a0b(hZ, hZ + position, leaderboardArray[hZ + position]); + for (aY.g0.textAlign(a0A, 2), hZ = windowHeight - eh; 0 <= hZ; hZ--) + a0a(leaderboardArray[hZ + position]), a0c(hZ, leaderboardArray[hZ + position]); + }`) + // in the leaderboard resize handler: make space for the tab buttons at the bottom of the leaderboard + replaceRawCode(",a09.height=y9,a09_ctx=a09.getContext(\"2d\",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08,a05=aY.g0.g1(1,Math.floor(.55*a06)),", + `,a09.height=y9,a09_ctx=a09.getContext("2d",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08, + a09.height = y9 += a0G, __fx.leaderboardFilter.tabBarOffset = Math.floor(a0G * 1.3), __fx.leaderboardFilter.verticalClickThreshold = y9 - __fx.leaderboardFilter.tabBarOffset, __fx.leaderboardFilter.windowWidth = a04, + a05=aY.g0.g1(1,Math.floor(.55*a06)),`) + // Set the leaderboardHasChanged flag on leaderboard updates + replaceRawCode("for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]", + `for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]; leaderboardHasChanged = true;`); + // handle clicking on a player in the leaderboard + replaceRawCode("var a0p=a0q(fJ);return ag.tQ()&&-1!==a0P&&(a0P=-1,a0Y(),b3.d1=!0),b3.dY-a0Q<350&&a0T===a0p&&-1!==(a0p=(a0p=yr(-1,a0p,windowHeight))!==windowHeight&&vU(x,y)?a0p:-1)&&(x=leaderboardArray[a0p+position],a0p===windowHeight-1&&leaderboardPositionsById[game.playerId]>=position+windowHeight-1&&(x=game.playerId),", + `var a0p = a0q(fJ); + var isEmptySpace = false; + return ag.tQ() && -1 !== a0P && (a0P = -1, a0Y(), b3.d1 = !0), b3.dY - a0Q < 350 && a0T === a0p && -1 !== (a0p = (a0p = yr(-1, a0p, windowHeight)) !== windowHeight && vU(x, y) ? a0p : -1) && (x = (__fx.leaderboardFilter.enabled ? (updateFilteredLb(), leaderboardArray[__fx.leaderboardFilter.filteredLeaderboard[a0p + position] ?? (isEmptySpace = true, leaderboardPositionsById[game.playerId])]) : leaderboardArray[a0p + position]), a0p === windowHeight - 1 && (__fx.leaderboardFilter.enabled ? this.playerPos : leaderboardPositionsById[game.playerId]) >= + position + windowHeight - 1 && (x = game.playerId), !isEmptySpace && `); + // Get clan parsing function + replaceRawCode(`this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null},`, + `this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null}, __fx.leaderboardFilter.parseClanFromPlayerName = this.uI;`); + } + }) +}) \ No newline at end of file diff --git a/patches/patches.js b/patches/patches.js index 4192d5c..fa7eec7 100644 --- a/patches/patches.js +++ b/patches/patches.js @@ -139,36 +139,14 @@ function applyPatches(/** @type {ModUtils} */ { replace, replaceOne, replaceRawC // and skip handling clicks when clicking on an empty space (see the isEmptySpace // variable in the modified leaderboard click handler from the leaderboard filter) // match , 0 !== dG[x]) && fq.hB(x, 800, false, 0), - replaceOne(/,(0!==\w+\.\w+\[(\w+)\])(\)&&\w+\.\w+\(\2,800,!1,0\),)/g, - `, ${dict.game}.${dict.gIsTeamGame} && __fx.settings.openDonationHistoryFromLb && __fx.donationsTracker.displayHistory($2, ${rawPlayerNames}, ${gIsSingleplayer}), $1 && !isEmptySpace $3`); + replaceOne(/(0!==\w+\.\w+\[(\w+)\])(\)&&\w+\.\w+\(\2,800,!1,0\),)/g, + `${dict.game}.${dict.gIsTeamGame} && __fx.settings.openDonationHistoryFromLb && __fx.donationsTracker.displayHistory($2, ${rawPlayerNames}, ${gIsSingleplayer}), $1 && !isEmptySpace $3`); // Reset donation history and leaderboard filter when a new game is started replaceRawCode(",ab.dP(),ad.a10(),b5.nZ.oJ=[],bc.dP(),this.wE=1,", `,ab.dP(),ad.a10(),b5.nZ.oJ=[],bc.dP(),this.wE=1, __fx.donationsTracker.reset(), __fx.leaderboardFilter.reset(), __fx.customLobby.isActive() && __fx.customLobby.hideWindow(),`) - { // Player list and leaderboard filter tabs - // Draw player list button - const uiOffset = dict.uiSizes + "." + dict.gap; - const { groups: { drawFunction, topBarHeight } } = replaceOne(/(="";function (?\w+)\(\){[^}]+?(?\w+)\.fillRect\(0,(?\w+),\w+,1\),(?:\3\.fillRect\([^()]+\),)+\3\.font=\w+,(\w+\.\w+)\.textBaseline\(\3,1\),\5\.textAlign\(\3,1\),\3\.fillText\(\w+,Math\.floor\()(\w+)\/2\),(Math\.floor\(\w+\+\w+\/2\)\));/g, - "$1($6 + $ - 22) / 2), $7; __fx.playerList.drawButton($, 12, 12, $ - 22);"); - const buttonBoundsCheck = `__fx.utils.isPointInRectangle($, $, ${uiOffset} + 12, ${uiOffset} + 12, ${topBarHeight} - 22, ${topBarHeight} - 22)` - // Handle player list button and leaderboard tabs mouseDown - // and create a function for scrolling the leaderboard to the top - replaceOne(/(this\.\w+=function\((?\w+),(?\w+)\){return!!\w+\(\2,\3\))&&(\(\w+=\w+\.\w+,[^}]+),!0\)/g, - `__fx.leaderboardFilter.scrollToTop = function(){position = 0;}, $1 && ((${buttonBoundsCheck} && __fx.playerList.display(${rawPlayerNames}), true) - && !($ - ${uiOffset} > __fx.leaderboardFilter.verticalClickThreshold && __fx.leaderboardFilter.handleMouseDown($ - ${uiOffset})) && $4),!0)`); - // Handle player list button and leaderboard tabs hover - // and create a function for repainting the leaderboard - replaceOne(/(this\.\w+=function\((?\w+),(?\w+)\){)(var \w+,\w+=\w+\(\3\);return \w+\?\(\w+=(\w+),\(\5=\w+\(0,\5\+=(?:[^}]+,(?\w+\.\w+=!0)){2})/g, - `__fx.leaderboardFilter.repaintLeaderboard = function() { ${drawFunction}(), $; }, - $1 if (${buttonBoundsCheck}) { __fx.playerList.hoveringOverButton === false && (__fx.playerList.hoveringOverButton = true, ${drawFunction}(), $); } - else { __fx.playerList.hoveringOverButton === true && (__fx.playerList.hoveringOverButton = false, ${drawFunction}(), $); } - if (__fx.leaderboardFilter.setHovering( - __fx.utils.isPointInRectangle($, $, ${uiOffset}, ${uiOffset} + __fx.leaderboardFilter.verticalClickThreshold, __fx.leaderboardFilter.windowWidth, __fx.leaderboardFilter.tabBarOffset), $ - ${uiOffset} - )) return; $4`); - } - { // Name rendering patches - Display density of other players & Hide bot names features const { placeBalanceAbove } = matchRawCode(`,aGH+=Math.floor(.78*fontSize),placeBalanceAbove?aGN(a7,aGJ,aGG,aGH,hT):aGM(hT,a7,aGJ,aGG,aGH,aGI)`); // Balance rendering; Renders density when the "Reverse Name/Balance" setting is off @@ -188,91 +166,6 @@ function applyPatches(/** @type {ModUtils} */ { replace, replaceOne, replaceRawC ); }`); } - { // Leaderboard filter - // for the leaderboard draw function: - replaceRawCode("function drawFunction(){a0A.clearRect(0,0,a04,y9),a0A.fillStyle=aZ.lE,a0A.fillRect(0,0,a04,a0F),a0A.fillStyle=aZ.kZ,a0A.fillRect(0,a0F,a04,y9-a0F),leaderboardPositionsById[game.playerId]>=position&&a0Z(leaderboardPositionsById[game.playerId]-position,aZ.kw),0!==leaderboardPositionsById[game.playerId]&&0===position&&a0Z(0,aZ.lJ),-1!==a0P&&a0Z(a0P,aZ.kd),a0A.fillStyle=aZ.gF,a0A.fillRect(0,a0F,a04,1),a0A.fillRect(0,0,a04,b0.ur),a0A.fillRect(0,0,b0.ur,y9),a0A.fillRect(a04-b0.ur,0,b0.ur,y9),a0A.fillRect(0,y9-b0.ur,a04,b0.ur),", - - `var leaderboardHasChanged = true; - this.playerPos = game.playerId; - __fx.leaderboardFilter.setUpdateFlag = () => leaderboardHasChanged = true; - function updateFilteredLb() { - if (!leaderboardHasChanged) return; - __fx.leaderboardFilter.filteredLeaderboard = __fx.leaderboardFilter.playersToInclude - .map(id => leaderboardPositionsById[id]).sort((a, b) => a - b); - leaderboardHasChanged = false; - this.playerPos = __fx.leaderboardFilter.filteredLeaderboard.indexOf(leaderboardPositionsById[game.playerId]); - } - function drawFunction() { - a0A.clearRect(0, 0, a04, y9), - a0A.fillStyle = aZ.lE, - a0A.fillRect(0, 0, a04, a0F), - a0A.fillStyle = aZ.kZ, - a0A.fillRect(0, a0F, a04, y9 - a0F); - if (__fx.leaderboardFilter.enabled) updateFilteredLb(); - var playerPos = (__fx.leaderboardFilter.enabled - ? this.playerPos - : leaderboardPositionsById[game.playerId] - ); - if (__fx.leaderboardFilter.hoveringOverTabs) a0P = -1; - if (__fx.leaderboardFilter.enabled && a0P >= __fx.leaderboardFilter.filteredLeaderboard.length) a0P = -1; - playerPos >= position && a0Z(playerPos - position, aZ.kw), - 0 !== leaderboardPositionsById[game.playerId] && 0 === position && a0Z(0, aZ.lJ), - -1 !== a0P && a0Z(a0P, aZ.kd), - a0A.fillStyle = aZ.kZ, - //console.log("drawing", a0P), - a0A.clearRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, __fx.leaderboardFilter.tabBarOffset); - a0A.fillRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, __fx.leaderboardFilter.tabBarOffset); - a0A.fillStyle = aZ.gF, - a0A.fillRect(0, a0F, a04, 1), - a0A.fillRect(0, y9 - __fx.leaderboardFilter.tabBarOffset, a04, 1), - __fx.leaderboardFilter.drawTabs(a0A, a04, y9 - __fx.leaderboardFilter.tabBarOffset, aZ.kw), - a0A.fillRect(0, 0, a04, b0.ur), - a0A.fillRect(0, 0, b0.ur, y9), - a0A.fillRect(a04 - b0.ur, 0, b0.ur, y9), - a0A.fillRect(0, y9 - b0.ur, a04, b0.ur),`) - replaceRawCode("var hZ,eh=leaderboardPositionsById[game.playerId]= result.length - windowHeight) - position = (result.length > windowHeight ? result.length : windowHeight) - windowHeight; - //if (position >= result.length) position = result.length - 1; - for (a0A.font = a07, aY.g0.textAlign(a0A, 0), hZ = windowHeight - eh; 0 <= hZ; hZ--) { - const pos = result[hZ + position]; - if (pos !== undefined) - a0a(leaderboardArray[pos]), a0b(hZ, pos, leaderboardArray[pos]); - } - for (aY.g0.textAlign(a0A, 2), hZ = windowHeight - eh; 0 <= hZ; hZ--) { - const pos = result[hZ + position]; - if (pos !== undefined) - a0a(leaderboardArray[pos]), a0c(hZ, leaderboardArray[pos]); - } - } else { - for (a0A.font = a07, aY.g0.textAlign(a0A, 0), hZ = windowHeight - eh; 0 <= hZ; hZ--) - a0a(leaderboardArray[hZ + position]), a0b(hZ, hZ + position, leaderboardArray[hZ + position]); - for (aY.g0.textAlign(a0A, 2), hZ = windowHeight - eh; 0 <= hZ; hZ--) - a0a(leaderboardArray[hZ + position]), a0c(hZ, leaderboardArray[hZ + position]); - }`) - // in the leaderboard resize handler: make space for the tab buttons at the bottom of the leaderboard - replaceRawCode(",a09.height=y9,a09_ctx=a09.getContext(\"2d\",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08,a05=aY.g0.g1(1,Math.floor(.55*a06)),", - `,a09.height=y9,a09_ctx=a09.getContext("2d",{alpha:!0}),a0D=.025*a04,a06=.16*a04,a0E=0*a04,a0F=Math.floor(.45*a0D+a06),a0G=(y9-a06-2*a0D-a0E)/a08, - a09.height = y9 += a0G, __fx.leaderboardFilter.tabBarOffset = Math.floor(a0G * 1.3), __fx.leaderboardFilter.verticalClickThreshold = y9 - __fx.leaderboardFilter.tabBarOffset, __fx.leaderboardFilter.windowWidth = a04, - a05=aY.g0.g1(1,Math.floor(.55*a06)),`) - // Set the leaderboardHasChanged flag on leaderboard updates - replaceRawCode("for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]", - `for(var eM=a0q-1;0<=eM;eM--)a14[eM]=jR[eM],a15[eM]=a8.f8[jR[eM]];a14[a0q]=a0l[b.ed],a15[a0q]=a8.f8[b.ed]; leaderboardHasChanged = true;`); - // handle clicking on a player in the leaderboard - replaceRawCode("var a0p=a0q(fJ);return ag.tQ()&&-1!==a0P&&(a0P=-1,a0Y(),b3.d1=!0),b3.dY-a0Q<350&&a0T===a0p&&-1!==(a0p=(a0p=yr(-1,a0p,windowHeight))!==windowHeight&&vU(x,y)?a0p:-1)&&(x=leaderboardArray[a0p+position],a0p===windowHeight-1&&leaderboardPositionsById[game.playerId]>=position+windowHeight-1&&(x=game.playerId),", - `var a0p = a0q(fJ); - var isEmptySpace = false; - return ag.tQ() && -1 !== a0P && (a0P = -1, a0Y(), b3.d1 = !0), b3.dY - a0Q < 350 && a0T === a0p && -1 !== (a0p = (a0p = yr(-1, a0p, windowHeight)) !== windowHeight && vU(x, y) ? a0p : -1) && (x = (__fx.leaderboardFilter.enabled ? (updateFilteredLb(), leaderboardArray[__fx.leaderboardFilter.filteredLeaderboard[a0p + position] ?? (isEmptySpace = true, leaderboardPositionsById[game.playerId])]) : leaderboardArray[a0p + position]), a0p === windowHeight - 1 && (__fx.leaderboardFilter.enabled ? this.playerPos : leaderboardPositionsById[game.playerId]) >= - position + windowHeight - 1 && (x = game.playerId), !isEmptySpace && `); - // Get clan parsing function - replaceRawCode(`this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null},`, - `this.uI=function(username){var uK,uJ=username.indexOf("[");return!(uJ<0)&&1<(uK=username.indexOf("]"))-uJ&&uK-uJ<=8?username.substring(uJ+1,uK).toUpperCase().trim():null}, __fx.leaderboardFilter.parseClanFromPlayerName = this.uI;`); - } - // Detailed team pie chart percentage replaceRawCode(`qr=Math.floor(100*f0+.5)+"%"`, `qr = (__fx.settings.detailedTeamPercentage ? (100*f0).toFixed(2) : Math.floor(100*f0+.5)) + "%"`)