Compare commits
3 Commits
ce2e2468fd
...
ad6f0e2f05
Author | SHA1 | Date |
---|---|---|
peshomir | ad6f0e2f05 | |
peshomir | 9e45327969 | |
peshomir | 0e4ecbb36f |
125
build.js
125
build.js
|
@ -78,7 +78,8 @@ const generateRegularExpression = (/** @type {string} */ code, /** @type {boolea
|
||||||
// this one also broke in 1.91.3 /,\w+="Player: "\+(?<playerNames>\w+)\[\w+\],\w+=\(\w\+=" Balance: "\+\w+\.\w+\((?<playerBalances>\w+)\[\w+\]\)\)\+\(" Territory: "\+\w+\.\w+\((?<playerTerritories>\w+)\[\w+\]\)\)\+\(" Coords: "/g,
|
// this one also broke in 1.91.3 /,\w+="Player: "\+(?<playerNames>\w+)\[\w+\],\w+=\(\w\+=" Balance: "\+\w+\.\w+\((?<playerBalances>\w+)\[\w+\]\)\)\+\(" Territory: "\+\w+\.\w+\((?<playerTerritories>\w+)\[\w+\]\)\)\+\(" Coords: "/g,
|
||||||
///\((?<uiOffset>\w+)=Math\.floor\(\(\w+\?\.0114:\.01296\)\*\w+\)\)/g,
|
///\((?<uiOffset>\w+)=Math\.floor\(\(\w+\?\.0114:\.01296\)\*\w+\)\)/g,
|
||||||
/(function \w+\((\w+),(\w+),(\w+),(\w+),(\w+)\){\6\.fillText\((?<playerNames>\w+)\[\2\],\4,\5\)),(\2<(?<gHumans>\w+)&&2!==(?<playerStates>\w+)\[)/g,
|
/(function \w+\((\w+),(\w+),(\w+),(\w+),(\w+)\){\6\.fillText\((?<playerNames>\w+)\[\2\],\4,\5\)),(\2<(?<gHumans>\w+)&&2!==(?<playerStates>\w+)\[)/g,
|
||||||
/,\w+=512,(?<gLobbyMaxJoin>\w+)=\w+,(?<gIsSingleplayer>\w+)&&\(\1=\w+\.\w+\(\)\),\w+=\1-\w+,\w+=0,/g
|
/,\w+=512,(?<gLobbyMaxJoin>\w+)=\w+,(?<gIsSingleplayer>\w+)&&\(\1=\w+\.\w+\(\)\),\w+=\1-\w+,\w+=0,/g,
|
||||||
|
/function \w+\(\)\{if\(2===(?<gameState>\w+)\)return 1;\w+\.\w+\(\),\1=2,\w+=\w+\}/g
|
||||||
].forEach(matchDictionaryExpression);
|
].forEach(matchDictionaryExpression);
|
||||||
|
|
||||||
const rawCodeSegments = [
|
const rawCodeSegments = [
|
||||||
|
@ -219,26 +220,35 @@ replaceOne(/(this\.\w+=function\((\w+),(\w+)\)\{)(\2===\w+&&\(\w+\.\w+\((\w+\.\w
|
||||||
"$1 donationsTracker.logDonation($2, $3, $5[0]); $4")
|
"$1 donationsTracker.logDonation($2, $3, $5[0]); $4")
|
||||||
|
|
||||||
// Display donations for a player when clicking on them in the leaderboard
|
// Display donations for a player when clicking on them in the leaderboard
|
||||||
|
// 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),
|
// match , 0 !== dG[x]) && fq.hB(x, 800, false, 0),
|
||||||
replaceOne(/,(0!==\w+\[(\w+)\]\)&&\w+\.\w+\(\2,800,!1,0\),)/g,
|
replaceOne(/,(0!==\w+\[(\w+)\])(\)&&\w+\.\w+\(\2,800,!1,0\),)/g,
|
||||||
`, ${dictionary.gIsTeamGame} && donationsTracker.displayHistory($2, ${dictionary.playerNames}, ${dictionary.gIsSingleplayer}), $1`);
|
`, ${dictionary.gIsTeamGame} && donationsTracker.displayHistory($2, ${dictionary.playerNames}, ${dictionary.gIsSingleplayer}), $1 && !isEmptySpace $3`);
|
||||||
|
|
||||||
// Reset donation history when a new game is started
|
// Reset donation history and leaderboard filter when a new game is started
|
||||||
replaceOne(new RegExp(`,${dictionary.playerBalances}=new Uint32Array\\(\\w+\\),`, "g"), "$& donationsTracker.reset(), ");
|
replaceOne(new RegExp(`,${dictionary.playerBalances}=new Uint32Array\\(\\w+\\),`, "g"), "$& donationsTracker.reset(), leaderboardFilter.reset(), ");
|
||||||
|
|
||||||
{ // Player list
|
{ // Player list and leaderboard filter tabs
|
||||||
// Draw player list button
|
// Draw player list button
|
||||||
const uiOffset = dictionary.uiSizes + "." + dictionary.gap;
|
const uiOffset = dictionary.uiSizes + "." + dictionary.gap;
|
||||||
const { groups: { drawFunction, topBarHeight } } = replaceOne(/(=1;function (?<drawFunction>\w+)\(\){[^}]+?(?<canvas>\w+)\.fillRect\(0,(?<topBarHeight>\w+),\w+,1\),(?:\3\.fillRect\([^()]+\),)+\3\.font=\w+,(\w+\.\w+)\.textBaseline\(\3,1\),\5\.textAlign\(\3,1\),\3\.fillText\(\w+\.\w+\[65\],Math\.floor\()(\w+)\/2\),(Math\.floor\(\w+\+\w+\/2\)\));/g,
|
const { groups: { drawFunction, topBarHeight } } = replaceOne(/(=1;function (?<drawFunction>\w+)\(\){[^}]+?(?<canvas>\w+)\.fillRect\(0,(?<topBarHeight>\w+),\w+,1\),(?:\3\.fillRect\([^()]+\),)+\3\.font=\w+,(\w+\.\w+)\.textBaseline\(\3,1\),\5\.textAlign\(\3,1\),\3\.fillText\(\w+\.\w+\[65\],Math\.floor\()(\w+)\/2\),(Math\.floor\(\w+\+\w+\/2\)\));/g,
|
||||||
"$1($6 + $<topBarHeight> - 22) / 2), $7; playerList.drawButton($<canvas>, 12, 12, $<topBarHeight> - 22);");
|
"$1($6 + $<topBarHeight> - 22) / 2), $7; playerList.drawButton($<canvas>, 12, 12, $<topBarHeight> - 22);");
|
||||||
const buttonBoundsCheck = `utils.isPointInRectangle($<x>, $<y>, ${uiOffset} + 12, ${uiOffset} + 12, ${topBarHeight} - 22, ${topBarHeight} - 22)`
|
const buttonBoundsCheck = `utils.isPointInRectangle($<x>, $<y>, ${uiOffset} + 12, ${uiOffset} + 12, ${topBarHeight} - 22, ${topBarHeight} - 22)`
|
||||||
// Handle player list button mouseDown
|
// Handle player list button and leaderboard tabs mouseDown
|
||||||
replaceOne(/(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){return!!\w+\(\2,\3\))&&(\(\w+=\w+\.\w+,)/g,
|
// and create a function for scrolling the leaderboard to the top
|
||||||
`$1 && (${buttonBoundsCheck} && playerList.display(${dictionary.playerNames}), true) && $4`);
|
replaceOne(/(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){return!!\w+\(\2,\3\))&&(\(\w+=\w+\.\w+,[^}]+),!0\)/g,
|
||||||
// Handle player list button hover
|
`leaderboardFilter.scrollToTop = function(){position = 0;}, $1 && ((${buttonBoundsCheck} && playerList.display(${dictionary.playerNames}), true)
|
||||||
|
&& !($<y> - ${uiOffset} > leaderboardFilter.verticalClickThreshold && leaderboardFilter.handleMouseDown($<x> - ${uiOffset})) && $4),!0)`);
|
||||||
|
// Handle player list button and leaderboard tabs hover
|
||||||
|
// and create a function for repainting the leaderboard
|
||||||
replaceOne(/(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){)(var \w+,\w+=\w+\(\3\);return \w+\?\(\w+=(\w+),\(\5=\w+\(0,\5\+=(?:[^}]+,(?<setRepaintNeeded>\w+\.\w+=!0)){2})/g,
|
replaceOne(/(this\.\w+=function\((?<x>\w+),(?<y>\w+)\){)(var \w+,\w+=\w+\(\3\);return \w+\?\(\w+=(\w+),\(\5=\w+\(0,\5\+=(?:[^}]+,(?<setRepaintNeeded>\w+\.\w+=!0)){2})/g,
|
||||||
`$1 if (${buttonBoundsCheck}) { playerList.hoveringOverButton === false && (playerList.hoveringOverButton = true, ${drawFunction}(), $<setRepaintNeeded>); } `
|
`leaderboardFilter.repaintLeaderboard = function() { ${drawFunction}(), $<setRepaintNeeded>; },
|
||||||
+ ` else { playerList.hoveringOverButton === true && (playerList.hoveringOverButton = false, ${drawFunction}(), $<setRepaintNeeded>); } $4`);
|
$1 if (${buttonBoundsCheck}) { playerList.hoveringOverButton === false && (playerList.hoveringOverButton = true, ${drawFunction}(), $<setRepaintNeeded>); }
|
||||||
|
else { playerList.hoveringOverButton === true && (playerList.hoveringOverButton = false, ${drawFunction}(), $<setRepaintNeeded>); }
|
||||||
|
if (leaderboardFilter.setHovering(
|
||||||
|
utils.isPointInRectangle($<x>, $<y>, ${uiOffset}, ${uiOffset} + leaderboardFilter.verticalClickThreshold, leaderboardFilter.windowWidth, leaderboardFilter.tabBarOffset), $<x> - ${uiOffset}
|
||||||
|
)) return; $4`);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // Display density of other players
|
{ // Display density of other players
|
||||||
|
@ -250,6 +260,97 @@ replaceOne(new RegExp(`,${dictionary.playerBalances}=new Uint32Array\\(\\w+\\),`
|
||||||
`$1 var ___id = $2; $7, $9; ${settingsSwitchNameAndBalance} && settings.showPlayerDensity && (settings.coloredDensity && ($<canvas>.fillStyle = utils.textStyleBasedOnDensity(___id)), $<canvas>.fillText(utils.getDensity(___id), $<x>, $<y> + $<fontSize>)); }`);
|
`$1 var ___id = $2; $7, $9; ${settingsSwitchNameAndBalance} && settings.showPlayerDensity && (settings.coloredDensity && ($<canvas>.fillStyle = utils.textStyleBasedOnDensity(___id)), $<canvas>.fillText(utils.getDensity(___id), $<x>, $<y> + $<fontSize>)); }`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{ // Leaderboard filter
|
||||||
|
// for the leaderboard draw function:
|
||||||
|
replaceRawCode("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[playerId]>=position&&a0Z(leaderboardPositionsById[playerId]-position,aZ.kw),0!==leaderboardPositionsById[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),",
|
||||||
|
`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 (leaderboardFilter.enabled) {
|
||||||
|
leaderboardFilter.filteredLeaderboard = leaderboardFilter.playersToInclude
|
||||||
|
.map(id => leaderboardPositionsById[id]).sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
var playerPos = (leaderboardFilter.enabled
|
||||||
|
? leaderboardFilter.filteredLeaderboard.indexOf(leaderboardPositionsById[playerId])
|
||||||
|
: leaderboardPositionsById[playerId]
|
||||||
|
);
|
||||||
|
this.playerPos = playerPos;
|
||||||
|
if (leaderboardFilter.hoveringOverTabs) a0P = -1;
|
||||||
|
if (leaderboardFilter.enabled && a0P >= leaderboardFilter.filteredLeaderboard.length) a0P = -1;
|
||||||
|
playerPos >= position && a0Z(playerPos - position, aZ.kw),
|
||||||
|
0 !== leaderboardPositionsById[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 - leaderboardFilter.tabBarOffset, a04, leaderboardFilter.tabBarOffset);
|
||||||
|
a0A.fillRect(0, y9 - leaderboardFilter.tabBarOffset, a04, leaderboardFilter.tabBarOffset);
|
||||||
|
a0A.fillStyle = aZ.gF,
|
||||||
|
a0A.fillRect(0, a0F, a04, 1),
|
||||||
|
a0A.fillRect(0, y9 - leaderboardFilter.tabBarOffset, a04, 1),
|
||||||
|
leaderboardFilter.drawTabs(a0A, a04, y9 - 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[playerId]<position+windowHeight-1?1:2;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]);",
|
||||||
|
`var hZ, eh = playerPos < position + windowHeight - 1 ? 1 : 2;
|
||||||
|
|
||||||
|
if (leaderboardFilter.enabled) {
|
||||||
|
let result = leaderboardFilter.filteredLeaderboard;
|
||||||
|
if (position !== 0 && position >= 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(",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)),",
|
||||||
|
`,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, leaderboardFilter.tabBarOffset = Math.floor(a0G * 1.3), leaderboardFilter.verticalClickThreshold = y9 - leaderboardFilter.tabBarOffset, leaderboardFilter.windowWidth = a04,
|
||||||
|
a05=aY.g0.g1(1,Math.floor(.55*a06)),`)
|
||||||
|
// 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[playerId]>=position+windowHeight-1&&(x=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 = (leaderboardFilter.enabled ? leaderboardArray[leaderboardFilter.filteredLeaderboard[a0p + position] ?? (isEmptySpace = true, leaderboardPositionsById[playerId])] : leaderboardArray[a0p + position]), a0p === windowHeight - 1 && (leaderboardFilter.enabled ? this.playerPos : leaderboardPositionsById[playerId]) >=
|
||||||
|
position + windowHeight - 1 && (x = playerId), !isEmptySpace && `);
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // Hovering tooltip
|
||||||
|
replaceRawCode("this.click=function(g8,g9,tE){var fT=aj.fU(g8),fV=aj.fW(g9),fX=aj.fY(fT,fV),fZ=aj.fa(fX);return!(!aj.fb(fT,fV)||(fT=(b7.cv.fv()?.025:.0144)*aK.fw,fV=performance.now(),Math.abs(g8-uu)>fT)||Math.abs(g9-uv)>fT||dY+500<fV)&&(dY=fV,tE?(function(g8,g9,fZ){a2.eb(fZ)||-1===(g8=ak.ff.vR(g8,g9))?k.vQ(fZ):k.vS(g8)}(g8,g9,fZ),!1)",
|
||||||
|
`hoveringTooltip.display = function(mouseX, mouseY) {
|
||||||
|
var coordX = aj.fU(mouseX), coordY = aj.fW(mouseY),
|
||||||
|
coord = aj.fY(coordX, coordY), point = aj.fa(coord);
|
||||||
|
if (coordX < 0 || coordY < 0) return;
|
||||||
|
k.vQ(point);
|
||||||
|
}
|
||||||
|
this.click = function(g8, g9, tE) {
|
||||||
|
var fT = aj.fU(g8),
|
||||||
|
fV = aj.fW(g9),
|
||||||
|
fX = aj.fY(fT, fV),
|
||||||
|
fZ = aj.fa(fX);
|
||||||
|
return !(!aj.fb(fT, fV) || (fT = (b7.cv.fv() ? .025 : .0144) * aK.fw, fV = performance.now(), Math.abs(g8 - uu) > fT) || Math.abs(g9 - uv) > fT || dY + 500 < fV) && (dY = fV, tE ? (function(g8, g9, fZ) {
|
||||||
|
a2.eb(fZ) || -1 === (g8 = ak.ff.vR(g8, g9)) ? k.vQ(fZ) : k.vS(g8)
|
||||||
|
}(g8, g9, fZ), false)`)
|
||||||
|
replaceRawCode("aK.nH=(window.devicePixelRatio||1)*aEr,",
|
||||||
|
`aK.nH = (window.devicePixelRatio || 1) * aEr, hoveringTooltip.canvasPixelScale = aK.nH,`)
|
||||||
|
}
|
||||||
|
|
||||||
// Disable built-in Territorial.io error reporting
|
// Disable built-in Territorial.io error reporting
|
||||||
replaceOne(/window\.addEventListener\("error",function (\w+)\((\w+)\){/g,
|
replaceOne(/window\.addEventListener\("error",function (\w+)\((\w+)\){/g,
|
||||||
'$& window.removeEventListener("error", $1); return alert("Error:\\n" + $2.filename + " " + $2.lineno + " " + $2.colno + " " + $2.message);');
|
'$& window.removeEventListener("error", $1); return alert("Error:\\n" + $2.filename + " " + $2.lineno + " " + $2.colno + " " + $2.message);');
|
||||||
|
|
19
readme.md
19
readme.md
|
@ -20,21 +20,22 @@ FX Client is the first Territorial.io client, targeting better User Interface an
|
||||||
|
|
||||||
## Features:
|
## Features:
|
||||||
1. It's 100% free and open source on Github
|
1. It's 100% free and open source on Github
|
||||||
2. It's Ad free and removes game's default ads.
|
2. It's ad-free and removes game's default ads.
|
||||||
3. It makes game look cooler, by replacing default assets with new ones.
|
3. It makes game look cooler, by replacing default assets with new ones.
|
||||||
4. Displays your troop density and maximum troops
|
4. Displays your troop density and maximum troops
|
||||||
5. Displays the density of players and bots
|
5. Displays the density of players and bots
|
||||||
6. Adds a win counter
|
6. Adds a "Clan" tab on the leaderboard, allowing you to easily see your clanmates
|
||||||
7. Adds a player list
|
7. Hovering tooltip: makes the territory map information (normally visible on right click) be visible constantly (on hover)
|
||||||
8. Adds the ability to view the history of who donated to a player during the game by clicking on their name in the leaderboard or the player list
|
8. Adds a player list
|
||||||
9. Can be installed as a PWA (progressive web app) ensuring maximum enjoyment on consoles, phones and even desktop devices
|
9. Adds the ability to view the history of who donated to a player during a team game by clicking on their name in the leaderboard or the player list
|
||||||
|
10. Adds a win counter
|
||||||
|
11. Can be installed as a PWA (progressive web app) ensuring maximum enjoyment on consoles, phones and even desktop devices
|
||||||
|
|
||||||
#### The client has a settings menu, from which you can:
|
#### The client has a settings menu, from which you can:
|
||||||
|
|
||||||
10. Change the game font
|
12. Make fullscreen mode trigger automatically
|
||||||
11. Make fullscreen mode trigger automatically
|
13. Set a custom main menu background
|
||||||
12. Set a custom main menu background
|
14. Create custom attack percentage keybinds
|
||||||
13. Create custom attack percentage keybinds
|
|
||||||
|
|
||||||
## Building Locally
|
## Building Locally
|
||||||
|
|
||||||
|
|
134
src/fx_core.js
134
src/fx_core.js
|
@ -1,5 +1,5 @@
|
||||||
const fx_version = '0.6.3.3'; // FX Client Version
|
const fx_version = '0.6.4.1'; // FX Client Version
|
||||||
const fx_update = 'Apr 11'; // FX Client Last Updated
|
const fx_update = 'May 20'; // FX Client Last Updated
|
||||||
|
|
||||||
if (localStorage.getItem("fx_winCount") == undefined || localStorage.getItem("fx_winCount") == null) {
|
if (localStorage.getItem("fx_winCount") == undefined || localStorage.getItem("fx_winCount") == null) {
|
||||||
var wins_counter = 0;
|
var wins_counter = 0;
|
||||||
|
@ -27,8 +27,9 @@ function KeybindsInput(containerElement) {
|
||||||
this.keys = [ "key", "type", "value" ];
|
this.keys = [ "key", "type", "value" ];
|
||||||
this.objectArray = [];
|
this.objectArray = [];
|
||||||
this.addObject = function () {
|
this.addObject = function () {
|
||||||
this.objectArray.push({ key: "", type: "absolute", value: 1 });
|
this.objectArray.push({ key: "", type: "absolute", value: 0.8 });
|
||||||
this.displayObjects();
|
this.displayObjects();
|
||||||
|
keybindAddButton.scrollIntoView(false);
|
||||||
};
|
};
|
||||||
this.update = function () {
|
this.update = function () {
|
||||||
this.objectArray = settings.attackPercentageKeybinds;
|
this.objectArray = settings.attackPercentageKeybinds;
|
||||||
|
@ -54,11 +55,15 @@ function KeybindsInput(containerElement) {
|
||||||
inputField.setAttribute("placeholder", "No key set");
|
inputField.setAttribute("placeholder", "No key set");
|
||||||
inputField.addEventListener("click", this.startKeyInput.bind(this, i, key));
|
inputField.addEventListener("click", this.startKeyInput.bind(this, i, key));
|
||||||
} else { // key === "value"
|
} else { // key === "value"
|
||||||
inputField.type = "number";
|
const isAbsolute = this.objectArray[i].type === "absolute";
|
||||||
inputField.setAttribute("step", "0.1");
|
inputField.type = isAbsolute ? "text" : "number";
|
||||||
|
if (isAbsolute) inputField.addEventListener("click", this.convertIntoNumberInput.bind(this, i, key), { once: true });
|
||||||
|
else inputField.setAttribute("step", "0.1");
|
||||||
inputField.addEventListener("input", this.updateObject.bind(this, i, key));
|
inputField.addEventListener("input", this.updateObject.bind(this, i, key));
|
||||||
}
|
}
|
||||||
inputField.value = this.objectArray[i][key];
|
if (key === "value" && this.objectArray[i].type === "absolute")
|
||||||
|
inputField.value = this.objectArray[i][key] * 100 + "%";
|
||||||
|
else inputField.value = this.objectArray[i][key];
|
||||||
// Append input field to the object div
|
// Append input field to the object div
|
||||||
objectDiv.appendChild(inputField);
|
objectDiv.appendChild(inputField);
|
||||||
}, this);
|
}, this);
|
||||||
|
@ -83,10 +88,21 @@ function KeybindsInput(containerElement) {
|
||||||
//this.displayObjects();
|
//this.displayObjects();
|
||||||
}, { once: true });
|
}, { once: true });
|
||||||
};
|
};
|
||||||
|
/** @param {PointerEvent} event */
|
||||||
|
this.convertIntoNumberInput = function (index, property, event) {
|
||||||
|
event.target.value = event.target.value.slice(0, -1);
|
||||||
|
event.target.type = "number";
|
||||||
|
event.target.addEventListener("blur", () => {
|
||||||
|
//event.target.value = this.objectArray[index][property];
|
||||||
|
this.displayObjects();
|
||||||
|
}, { once: true });
|
||||||
|
};
|
||||||
this.updateObject = function (index, property, event) {
|
this.updateObject = function (index, property, event) {
|
||||||
if (index >= this.objectArray.length) return;
|
if (index >= this.objectArray.length) return;
|
||||||
// Update the corresponding property of the object in the array
|
// Update the corresponding property of the object in the array
|
||||||
const value = property === "value" ? parseFloat(event.target.value) : property === "key" ? event.key : event.target.value;
|
const value = property === "value" ? (
|
||||||
|
this.objectArray[index].type === "absolute" ? parseFloat(event.target.value) / 100 : parseFloat(event.target.value)
|
||||||
|
) : property === "key" ? event.key : event.target.value;
|
||||||
this.objectArray[index][property] = value;
|
this.objectArray[index][property] = value;
|
||||||
if (property === "key") this.displayObjects();
|
if (property === "key") this.displayObjects();
|
||||||
};
|
};
|
||||||
|
@ -104,6 +120,7 @@ var settings = {
|
||||||
//"showBotDonations": false,
|
//"showBotDonations": false,
|
||||||
"displayWinCounter": true,
|
"displayWinCounter": true,
|
||||||
"useFullscreenMode": false,
|
"useFullscreenMode": false,
|
||||||
|
"hoveringTooltip": true,
|
||||||
//"hideAllLinks": false,
|
//"hideAllLinks": false,
|
||||||
"realisticNames": false,
|
"realisticNames": false,
|
||||||
"showPlayerDensity": true,
|
"showPlayerDensity": true,
|
||||||
|
@ -123,6 +140,8 @@ var settingsManager = new (function() {
|
||||||
note: "The win counter tracks multiplayer solo wins (not in team games)" },
|
note: "The win counter tracks multiplayer solo wins (not in team games)" },
|
||||||
{ for: "useFullscreenMode", type: "checkbox", label: "Use fullscreen mode",
|
{ for: "useFullscreenMode", type: "checkbox", label: "Use fullscreen mode",
|
||||||
note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions." },
|
note: "Note: fullscreen mode will trigger after you click anywhere on the page due to browser policy restrictions." },
|
||||||
|
{ for: "hoveringTooltip", type: "checkbox", label: "Hovering tooltip",
|
||||||
|
note: "Display map territory info constantly (on mouse hover) instead of only when right clicking on the map" },
|
||||||
//{ for: "hideAllLinks", type: "checkbox", label: "Hide Links option also hides app store links" },
|
//{ for: "hideAllLinks", type: "checkbox", label: "Hide Links option also hides app store links" },
|
||||||
{ for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" },
|
{ for: "realisticNames", type: "checkbox", label: "Realistic Bot Names" },
|
||||||
{ for: "showPlayerDensity", type: "checkbox", label: "Show player density" },
|
{ for: "showPlayerDensity", type: "checkbox", label: "Show player density" },
|
||||||
|
@ -322,6 +341,107 @@ const playerList = new (function () {
|
||||||
canvas.imageSmoothingEnabled = false;
|
canvas.imageSmoothingEnabled = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/** @param {string} name */
|
||||||
|
function parseClanFromPlayerName(name) {
|
||||||
|
const startIndex = name.indexOf("[");
|
||||||
|
// this is probably how the algorithm works, since a player with
|
||||||
|
// the name "][a]" will count as not being in a clan in the base game
|
||||||
|
return startIndex === -1 ? "" : name.slice(startIndex + 1, name.indexOf("]")).toUpperCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const leaderboardFilter = new (function() {
|
||||||
|
this.playersToInclude = [0,1,8,20,24,30,32,42,50,69,200,400,500,510,511]; // for testing
|
||||||
|
//this.playersToInclude = [];
|
||||||
|
this.tabLabels = ["ALL", "CLAN"];
|
||||||
|
// these get populated by the modified game code
|
||||||
|
this.filteredLeaderboard = [];
|
||||||
|
this.tabBarOffset = 0;
|
||||||
|
this.windowWidth = 0;
|
||||||
|
this.verticalClickThreshold = 1000;
|
||||||
|
this.hoveringOverTabs = false;
|
||||||
|
this.scrollToTop = () => {};
|
||||||
|
this.repaintLeaderboard = () => {};
|
||||||
|
|
||||||
|
this.selectedTab = 0;
|
||||||
|
this.tabHovering = -1;
|
||||||
|
//this.enabled = false;
|
||||||
|
this.enabled = true;
|
||||||
|
this.drawTabs = function(canvas, totalWidth, verticalOffset, colorForSelectedTab) {
|
||||||
|
canvas.textBaseline = "middle";
|
||||||
|
canvas.textAlign = "center";
|
||||||
|
const tabWidth = totalWidth / this.tabLabels.length;
|
||||||
|
const textOffsetY = verticalOffset + this.tabBarOffset / 2;
|
||||||
|
//console.log(verticalOffset, this.tabBarOffset, textOffsetY);
|
||||||
|
this.tabLabels.forEach((label, index) => {
|
||||||
|
if (index !== 0) canvas.fillRect(tabWidth * index, verticalOffset, 1, this.tabBarOffset);
|
||||||
|
if (this.selectedTab === index) {
|
||||||
|
canvas.fillStyle = colorForSelectedTab;
|
||||||
|
canvas.fillRect(tabWidth * index, verticalOffset, tabWidth, this.tabBarOffset);
|
||||||
|
canvas.fillStyle = "rgb(255,255,255)";
|
||||||
|
}
|
||||||
|
if (this.tabHovering === index) {
|
||||||
|
canvas.fillStyle = "rgba(255,255,255,0.3)";
|
||||||
|
canvas.fillRect(tabWidth * index, verticalOffset, tabWidth, this.tabBarOffset);
|
||||||
|
canvas.fillStyle = "rgb(255,255,255)";
|
||||||
|
}
|
||||||
|
canvas.fillText(label, tabWidth * index + tabWidth / 2, textOffsetY);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.setHovering = (isHovering, xRelative) => {
|
||||||
|
let repaintNeeded = false;
|
||||||
|
if (isHovering) {
|
||||||
|
const tab = Math.floor(xRelative / (this.windowWidth / this.tabLabels.length));
|
||||||
|
if (this.tabHovering !== tab) {
|
||||||
|
this.tabHovering = tab;
|
||||||
|
repaintNeeded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isHovering !== this.hoveringOverTabs) {
|
||||||
|
this.hoveringOverTabs = isHovering;
|
||||||
|
if (isHovering === false) this.tabHovering = -1;
|
||||||
|
if (!isHovering) repaintNeeded = true;
|
||||||
|
}
|
||||||
|
if (repaintNeeded) this.repaintLeaderboard();
|
||||||
|
return isHovering;
|
||||||
|
}
|
||||||
|
this.handleMouseDown = (xRelative) => {
|
||||||
|
//console.log("click; x: ", xRelative);
|
||||||
|
if (this.tabHovering !== this.selectedTab) {
|
||||||
|
this.selectedTab = this.tabHovering;
|
||||||
|
if (this.selectedTab === 0) this.clearFilter();
|
||||||
|
else if (this.selectedTab === 1) this.filterByOwnClan();
|
||||||
|
this.repaintLeaderboard();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
this.filterByOwnClan = () => {
|
||||||
|
this.playersToInclude = [];
|
||||||
|
const ownClan = parseClanFromPlayerName(getVar("playerNames")[getVar("playerId")]);
|
||||||
|
getVar("playerNames").forEach((name, id) => {
|
||||||
|
if (parseClanFromPlayerName(name) === ownClan) this.playersToInclude.push(id);
|
||||||
|
});
|
||||||
|
this.enabled = true;
|
||||||
|
this.scrollToTop();
|
||||||
|
};
|
||||||
|
this.clearFilter = () => { this.enabled = false; }
|
||||||
|
this.reset = () => {
|
||||||
|
this.enabled = false;
|
||||||
|
this.selectedTab = 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const hoveringTooltip = new (function() {
|
||||||
|
this.display = () => {}; // this gets populated by the modified game script
|
||||||
|
this.canvasPixelScale = 1;
|
||||||
|
document.getElementById("canvasA").addEventListener("mousemove", e => {
|
||||||
|
if (!settings.hoveringTooltip || !getVar("gameState")) return;
|
||||||
|
try {
|
||||||
|
this.display(this.canvasPixelScale * e.clientX, this.canvasPixelScale * e.clientY);
|
||||||
|
} catch (e) { console.error(e) }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
var donationsTracker = new (function(){
|
var donationsTracker = new (function(){
|
||||||
this.openedWindowPlayerID = null;
|
this.openedWindowPlayerID = null;
|
||||||
this.contentElement = document.querySelector("#donationhistory_content");
|
this.contentElement = document.querySelector("#donationhistory_content");
|
||||||
|
|
Loading…
Reference in New Issue