Mobile keybinds
- Attack percentage bar is now always redrawn after each keybind use - UI changes: Slightly decreased the UI font size, adjusted the size of the inputs in the keybind settings and added a small margin under the keybind settingspull/14/head
							parent
							
								
									546d17c76b
								
							
						
					
					
						commit
						ed94c65172
					
				
								
									
									
										
											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)); | ||||
| 
 | ||||
| import applyPatches from './patches/main.js'; | ||||
| console.log("Applying patches..."); | ||||
| applyPatches(modUtils); | ||||
| 
 | ||||
| // for versions ^1.99.5.2
 | ||||
|  |  | |||
|  | @ -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 gameObjectProperties = ["playerId", "gIsTeamGame", "gHumans", "gLobbyMaxJoin", "gameState", "gIsSingleplayer"]; | ||||
| 
 | ||||
| export const getVar = varName => { | ||||
|     if (playerDataProperties.includes(varName)) return window[dictionary.playerData]?.[dictionary[varName]]; | ||||
|     if (gameObjectProperties.includes(varName)) return window[dictionary.game]?.[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"; | ||||
| 
 | ||||
| export const keybindFunctions = { setAbsolute: () => {}, setRelative: () => {} }; | ||||
| export const keybindFunctions = { | ||||
|     setAbsolute: () => {}, | ||||
|     setRelative: () => {}, | ||||
|     repaintAttackPercentageBar: () => {} | ||||
| }; | ||||
| export const keybindHandler = key => { | ||||
|     const keybindData = getSettings().attackPercentageKeybinds.find(keybind => keybind.key === key); | ||||
|     if (keybindData === undefined) return false; | ||||
|     if (keybindData.type === "absolute") keybindFunctions.setAbsolute(keybindData.value); | ||||
|     else keybindFunctions.setRelative(keybindData.value); | ||||
|     executeKeybind(keybindData); | ||||
|     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"); | ||||
|     header.innerText = "Attack Percentage Keybinds"; | ||||
|     const keybindContainer = document.createElement("div"); | ||||
|  | @ -6,6 +6,7 @@ export function KeybindsInput(containerElement) { | |||
|     const keybindAddButton = document.createElement("button"); | ||||
|     keybindAddButton.innerText = "Add"; | ||||
|     containerElement.append(header, keybindContainer, keybindAddButton); | ||||
|     containerElement.className = "keybinds-input"; | ||||
|     this.container = keybindContainer; | ||||
|     this.keys = [ "key", "type", "value" ]; | ||||
|     this.objectArray = []; | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| const fx_version = '0.6.7.1'; // FX Client Version
 | ||||
| const fx_update = 'Feb 15'; // FX Client Last Updated
 | ||||
| const fx_version = '0.6.7.2'; // FX Client Version
 | ||||
| const fx_update = 'Mar 2'; // FX Client Last Updated
 | ||||
| 
 | ||||
| if ("serviceWorker" in navigator) { | ||||
|   navigator.serviceWorker.addEventListener("message", (e) => { | ||||
|  | @ -20,7 +20,7 @@ import winCounter from "./winCounter.js"; | |||
| import playerList from "./playerList.js"; | ||||
| import gameScriptUtils from "./gameScriptUtils.js"; | ||||
| import hoveringTooltip from "./hoveringTooltip.js"; | ||||
| import { keybindFunctions, keybindHandler } from "./keybinds.js"; | ||||
| import { keybindFunctions, keybindHandler, mobileKeybinds } from "./keybinds.js"; | ||||
| import customLobby from './customLobby.js'; | ||||
| 
 | ||||
| window.__fx = window.__fx || {}; | ||||
|  | @ -33,6 +33,7 @@ __fx.utils = gameScriptUtils; | |||
| __fx.WindowManager = WindowManager; | ||||
| __fx.keybindFunctions = keybindFunctions; | ||||
| __fx.keybindHandler = keybindHandler; | ||||
| __fx.mobileKeybinds = mobileKeybinds; | ||||
| __fx.donationsTracker = donationsTracker; | ||||
| __fx.playerList = playerList; | ||||
| __fx.hoveringTooltip = hoveringTooltip; | ||||
|  |  | |||
|  | @ -21,6 +21,7 @@ var settings = { | |||
|   detailedTeamPercentage: false, | ||||
|   //"customMapFileBtn": true
 | ||||
|   customBackgroundUrl: "", | ||||
|   keybindButtons: false, | ||||
|   attackPercentageKeybinds: [], | ||||
| }; | ||||
| __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.", | ||||
|     }, | ||||
|     KeybindsInput, | ||||
|     { | ||||
|       for: "keybindButtons", type: "checkbox", | ||||
|       label: "Keybind buttons", note: "Show keybind buttons above the troop selector (max 6)" | ||||
|     } | ||||
|   ]; | ||||
|   const settingsContainer = document.querySelector(".settings .scrollable"); | ||||
|   var inputFields = {}; // (includes select menus)
 | ||||
|  |  | |||
|  | @ -28,7 +28,7 @@ | |||
| 	border-width    : 2px; | ||||
| 	border-width    : calc(0.15 * (1vw + 1vh)); | ||||
| 	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%; | ||||
| 	transition      : 0.2s; | ||||
| 	z-index         : 10; | ||||
|  | @ -59,6 +59,13 @@ | |||
| 	margin: 0px; | ||||
| } | ||||
| 
 | ||||
| .keybinds-input { | ||||
| 	margin-bottom: 1em; | ||||
| } | ||||
| .keybinds-input input { | ||||
| 	width: 10em; | ||||
| } | ||||
| 
 | ||||
| .flex { | ||||
| 	display: flex; | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue