I made a small userscript for Fleet Dispatch that adds hotkeys for faster navigation without using buttons.
Controls:
-
Ctrl + Left/Right= decrease/increase system -
Ctrl + Up/Down= decrease/increase planet position -
Ctrl + E= set position to 16
It is designed to be lightweight and OGLight-friendly, so it does not add extra UI elements or buttons.
The script only works on the Fleet Dispatch pages and updates the fields directly, including the flight time recalculation.
Code
- // ==UserScript==
- // @name OGame Fleet II Hotkeys (Ctrl+Arrows, OGLight safe, recalc fix)
- // @namespace ogame-helper-local
- // @version 1.2
- // @description Hotkeys für System und Position in Flottenversand II, ohne Buttons
- // @match https://*.ogame.gameforge.com/game/index.php?page=ingame&component=fleetdispatch*
- // @match https://*.ogame.gameforge.com/game/index.php?page=ingame&component=movement*
- // @grant none
- // @run-at document-idle
- // ==/UserScript==
- (function () {
- 'use strict';
- function findInputByType(type) {
- const selectors = {
- system: [
- 'input[name="system"]',
- '#system',
- 'input[id*="system"]',
- 'input[class*="system"]',
- 'input[data-input="system"]'
- ],
- position: [
- 'input[name="position"]',
- '#position',
- 'input[id*="position"]',
- 'input[class*="position"]',
- 'input[data-input="position"]',
- 'input[name="planet"]',
- '#planet'
- ]
- };
- for (const sel of (selectors[type] || [])) {
- const el = document.querySelector(sel);
- if (el) return el;
- }
- const inputs = [...document.querySelectorAll('input')];
- return inputs.find(i => {
- const n = (i.name || '').toLowerCase();
- const id = (i.id || '').toLowerCase();
- const ph = (i.placeholder || '').toLowerCase();
- if (type === 'system') {
- return n.includes('system') || id.includes('system') || ph.includes('system');
- }
- if (type === 'position') {
- return (
- n.includes('position') || id.includes('position') || ph.includes('position') ||
- n.includes('planet') || id.includes('planet') || ph.includes('planet')
- );
- }
- return false;
- }) || null;
- }
- function setNativeValue(element, value) {
- const prototype = Object.getPrototypeOf(element);
- const descriptor = Object.getOwnPropertyDescriptor(prototype, 'value');
- const setter = descriptor && descriptor.set;
- if (setter) {
- setter.call(element, value);
- } else {
- element.value = value;
- }
- }
- function dispatchKeyEvent(target, type, key) {
- target.dispatchEvent(new KeyboardEvent(type, {
- key: key,
- code: key,
- bubbles: true,
- cancelable: true
- }));
- }
- function pokeFleetDispatcher() {
- try {
- if (window.fleetDispatcher) {
- if (typeof window.fleetDispatcher.refresh === 'function') {
- window.fleetDispatcher.refresh();
- }
- if (typeof window.fleetDispatcher.updateTarget === 'function') {
- window.fleetDispatcher.updateTarget();
- }
- if (typeof window.fleetDispatcher.updateDistance === 'function') {
- window.fleetDispatcher.updateDistance();
- }
- if (typeof window.fleetDispatcher.updateDuration === 'function') {
- window.fleetDispatcher.updateDuration();
- }
- }
- } catch (e) {}
- }
- function updateValue(input, newValue) {
- setNativeValue(input, String(newValue));
- input.dispatchEvent(new Event('input', { bubbles: true }));
- input.dispatchEvent(new Event('change', { bubbles: true }));
- dispatchKeyEvent(input, 'keydown', 'ArrowRight');
- dispatchKeyEvent(input, 'keyup', 'ArrowRight');
- setTimeout(() => {
- input.dispatchEvent(new Event('input', { bubbles: true }));
- input.dispatchEvent(new Event('change', { bubbles: true }));
- dispatchKeyEvent(input, 'keyup', 'ArrowRight');
- pokeFleetDispatcher();
- }, 20);
- setTimeout(() => {
- pokeFleetDispatcher();
- }, 80);
- }
- function changeSystem(delta) {
- const input = findInputByType('system');
- if (!input) return;
- const current = parseInt(input.value, 10);
- if (Number.isNaN(current)) return;
- let next = current + delta;
- if (next < 1) next = 1;
- if (next > 499) next = 499;
- updateValue(input, next);
- }
- function changePosition(delta) {
- const input = findInputByType('position');
- if (!input) return;
- const current = parseInt(input.value, 10);
- if (Number.isNaN(current)) return;
- let next = current + delta;
- if (next < 1) next = 1;
- if (next > 16) next = 16;
- updateValue(input, next);
- }
- function setPosition(value) {
- const input = findInputByType('position');
- if (!input) return;
- let next = parseInt(value, 10);
- if (Number.isNaN(next)) return;
- if (next < 1) next = 1;
- if (next > 16) next = 16;
- updateValue(input, next);
- }
- function isEditableTarget(el) {
- if (!el) return false;
- const tag = (el.tagName || '').toLowerCase();
- return (
- tag === 'input' ||
- tag === 'textarea' ||
- el.isContentEditable
- );
- }
- document.addEventListener('keydown', function (e) {
- const onFleet2 =
- location.href.includes('component=fleetdispatch') ||
- location.href.includes('component=movement');
- if (!onFleet2) return;
- if (!e.ctrlKey || e.altKey || e.shiftKey || e.metaKey) return;
- if (e.repeat) return;
- const active = document.activeElement;
- if (isEditableTarget(active)) {
- const systemInput = findInputByType('system');
- const positionInput = findInputByType('position');
- const allowed = active === systemInput || active === positionInput;
- if (!allowed) return;
- }
- switch (e.key) {
- case 'ArrowLeft':
- e.preventDefault();
- e.stopPropagation();
- changeSystem(-1);
- break;
- case 'ArrowRight':
- e.preventDefault();
- e.stopPropagation();
- changeSystem(+1);
- break;
- case 'ArrowDown':
- e.preventDefault();
- e.stopPropagation();
- changePosition(-1);
- break;
- case 'ArrowUp':
- e.preventDefault();
- e.stopPropagation();
- changePosition(+1);
- break;
- case 'e':
- case 'E':
- e.preventDefault();
- e.stopPropagation();
- setPosition(16);
- break;
- }
- }, true);
- })();
Also, could you please explain how the approval process works exactly?