您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Mod Menu for GeoFS flight model variables using console-modifiable input fields
// ==UserScript== // @name GeoFS Mod Menu -cool- // @namespace http://tampermonkey.net/ // @version 1.4 // @description Mod Menu for GeoFS flight model variables using console-modifiable input fields // @author Jasp // @match https://www.geo-fs.com/* // @grant none // @license MIT // ==/UserScript== (function () { 'use strict'; const presets = { "Default": { maxRPM: 2500, enginePower: 100000, fuelFlow: 0.3, dragFactor: 0.05, liftFactor: 1.0 }, "High Power": { maxRPM: 4000, enginePower: 200000, fuelFlow: 0.8, dragFactor: 0.03, liftFactor: 1.2 }, "Glider": { maxRPM: 0, enginePower: 0, fuelFlow: 0, dragFactor: 0.01, liftFactor: 1.5 }, "Heavy Jet": { maxRPM: 3200, enginePower: 150000, fuelFlow: 0.6, dragFactor: 0.07, liftFactor: 0.9 }, "Light Sport": { maxRPM: 2800, enginePower: 75000, fuelFlow: 0.4, dragFactor: 0.04, liftFactor: 1.3 } }; const variableSettings = { maxRPM: { min: 1000, max: 4000 }, minRPM: { min: 500, max: 1500 }, starterRPM: { min: 300, max: 1000 }, idleThrottle: { min: 0.01, max: 0.2 }, fuelFlow: { min: 0.1, max: 1.0 }, enginePower: { min: 50000, max: 200000 }, brakeRPM: { min: 100, max: 1000 }, wingArea: { min: 5, max: 150 }, dragFactor: { min: 0.01, max: 0.2 }, liftFactor: { min: 0.5, max: 2.0 }, CD0: { min: 0.01, max: 0.1 }, CLmax: { min: 0.5, max: 2.0 }, elevatorFactor: { min: 0.1, max: 2.0 }, rudderFactor: { min: 0.1, max: 2.0 }, aileronFactor: { min: 0.1, max: 2.0 }, mass: { min: 500, max: 50000 }, emptyWeight: { min: 500, max: 30000 }, maxWeight: { min: 1000, max: 100000 }, inertia: { min: 100, max: 50000 }, pitchMoment: { min: 10, max: 5000 }, yawMoment: { min: 10, max: 5000 }, rollMoment: { min: 10, max: 5000 }, gearDrag: { min: 0.01, max: 0.5 }, gearCompression: { min: 0.01, max: 1.0 }, gearLength: { min: 0.5, max: 5.0 } }; const explanations = { maxRPM: "Maximum revolutions per minute of the engine. Higher = more top power, but more stress. Lower = less max thrust.", minRPM: "Minimum engine RPM. Too low and the engine might stall. Too high and you lose idle control.", starterRPM: "RPM during engine startup. Higher starts faster. Too high = unrealistic.", idleThrottle: "Throttle at idle. Higher means more thrust at 0% throttle.", fuelFlow: "How fast fuel is consumed. Higher = more realistic consumption, lower = longer flights.", enginePower: "The base power of the engine. Higher = more thrust and acceleration.", brakeRPM: "RPM at which braking effect is active. Higher = faster deceleration.", wingArea: "Total wing surface. More = more lift. Too much = unrealistic flight.", dragFactor: "How much drag affects the aircraft. Higher = slower top speed.", liftFactor: "How efficiently the wings lift. Higher = easier takeoff & climb.", CD0: "Parasitic drag coefficient. Higher = more drag.", CLmax: "Max lift coefficient. Higher = more lift before stalling.", elevatorFactor: "Effectiveness of pitch control. Higher = more sensitive.", rudderFactor: "Effectiveness of yaw control. Higher = tighter turns.", aileronFactor: "Effectiveness of roll control. Higher = faster rolls.", mass: "Total aircraft mass. Higher = slower response, more stability.", emptyWeight: "Weight with no payload. Affects takeoff performance.", maxWeight: "Max takeoff weight. Higher allows more payload.", inertia: "Aircraft rotational inertia. Higher = more sluggish pitch/yaw/roll.", pitchMoment: "How much pitch resists change. Higher = smoother pitch.", yawMoment: "Yaw stability. Higher = less yaw wiggle.", rollMoment: "Roll stability. Higher = steadier rolls.", gearDrag: "Drag caused by landing gear. Higher = slower when deployed.", gearCompression: "Suspension compression. Higher = softer landings.", gearLength: "Length of gear strut. Higher = taller aircraft stance." }; const categories = { "Engine": ["maxRPM", "minRPM", "starterRPM", "idleThrottle", "fuelFlow", "enginePower", "brakeRPM"], "Aerodynamics": ["wingArea", "dragFactor", "liftFactor", "CD0", "CLmax", "elevatorFactor", "rudderFactor", "aileronFactor"], "Flight Model": ["mass", "emptyWeight", "maxWeight", "inertia", "pitchMoment", "yawMoment", "rollMoment"], "Landing Gear": ["gearDrag", "gearCompression", "gearLength"] }; const menuStyle = ` #geofsModMenu { position: fixed; top: 50px; right: 20px; background: rgba(0,0,0,0.85); color: white; padding: 15px; border-radius: 10px; z-index: 9999; max-height: 90vh; overflow-y: auto; font-family: sans-serif; font-size: 14px; display: none; width: 300px; } #geofsModMenu h2 { font-size: 16px; margin-top: 10px; border-bottom: 1px solid #ccc; } #geofsModMenu input[type="number"] { width: 80px; margin: 2px 0; background: #222; color: white; border: 1px solid #555; padding: 3px; } #geofsModMenu input[type="range"] { width: 100%; margin-bottom: 10px; } .preset-button { background: #444; color: white; padding: 4px 10px; margin: 2px; border: 1px solid #777; border-radius: 6px; cursor: pointer; font-size: 13px; } .preset-button:hover { background: #666; } #helpOverlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.95); color: white; z-index: 10000; overflow-y: scroll; padding: 30px; display: none; font-size: 15px; } #helpOverlay h1 { font-size: 24px; margin-bottom: 10px; } #closeHelp { position: absolute; top: 10px; right: 20px; font-size: 24px; cursor: pointer; color: white; } #settingsIcon { position: absolute; top: 10px; right: 10px; font-size: 18px; cursor: pointer; background: none; border: none; color: white; } `; const styleTag = document.createElement("style"); styleTag.innerHTML = menuStyle; document.head.appendChild(styleTag); const menu = document.createElement("div"); menu.id = "geofsModMenu"; const helpOverlay = document.createElement("div"); helpOverlay.id = "helpOverlay"; const closeBtn = document.createElement("div"); closeBtn.id = "closeHelp"; closeBtn.innerHTML = "✕"; closeBtn.onclick = () => { helpOverlay.style.display = "none"; menu.style.display = "block"; }; helpOverlay.appendChild(closeBtn); const helpTitle = document.createElement("h1"); helpTitle.textContent = "GeoFS Mod Menu – Variable Help"; helpOverlay.appendChild(helpTitle); for (const [key, description] of Object.entries(explanations)) { const para = document.createElement("p"); para.innerHTML = `<strong>${key}</strong>: ${description}`; helpOverlay.appendChild(para); } document.body.appendChild(helpOverlay); const settingsBtn = document.createElement("button"); settingsBtn.id = "settingsIcon"; settingsBtn.textContent = "⚙️"; settingsBtn.onclick = () => { menu.style.display = "none"; helpOverlay.style.display = "block"; }; menu.appendChild(settingsBtn); const inputsMap = {}; const presetHeader = document.createElement("h2"); presetHeader.textContent = "Presets"; menu.appendChild(presetHeader); for (const [name, values] of Object.entries(presets)) { const btn = document.createElement("button"); btn.textContent = name; btn.className = "preset-button"; btn.onclick = () => { for (const [key, val] of Object.entries(values)) { const input = inputsMap[key]?.input; const slider = inputsMap[key]?.slider; if (input && slider) { input.value = val; slider.value = val; updateModel(key, val); } } }; menu.appendChild(btn); } for (const [category, vars] of Object.entries(categories)) { const header = document.createElement("h2"); header.textContent = category; menu.appendChild(header); vars.forEach(variable => { const setting = variableSettings[variable] || { min: 0, max: 100 }; const label = document.createElement("label"); label.textContent = variable + ": "; const input = document.createElement("input"); input.type = "number"; input.step = "any"; input.value = setting.min; const slider = document.createElement("input"); slider.type = "range"; slider.min = setting.min; slider.max = setting.max; slider.step = (setting.max - setting.min) / 100; slider.value = setting.min; input.oninput = () => { slider.value = input.value; updateModel(variable, input.value); }; slider.oninput = () => { input.value = slider.value; updateModel(variable, slider.value); }; inputsMap[variable] = { input, slider }; label.appendChild(input); menu.appendChild(label); menu.appendChild(slider); menu.appendChild(document.createElement("br")); }); } document.body.appendChild(menu); function updateModel(variable, value) { try { if (geofs?.aircraft?.instance?.flightModel) { const model = geofs.aircraft.instance.flightModel; if (variable in model) { model[variable] = parseFloat(value); console.log(`[MOD MENU] Set ${variable} to ${value}`); } } } catch (err) { console.error("GeoFS mod menu error:", err); } } document.addEventListener("keydown", function (e) { if (e.key === "#") { const visible = menu.style.display === "block"; menu.style.display = visible ? "none" : "block"; helpOverlay.style.display = "none"; } }); console.log("[GeoFS Mod Menu] Loaded. Press '#' to toggle."); })();