Compare commits

...

35 Commits

Author SHA1 Message Date
L7NEG cf2e354173 Expand legacy heist tools and refresh offsets
Add heist cut and payout controls, safer finale actions, loot options, and teleport menus. Refresh legacy offsets and move event and business controls to tunables, with compatibility and menu-guard updates.
2026-09-30 11:40:18 +03:00
L7NEG 2c7b12720b Update YimMenu and Nenyoo preview and remove donation options
its optional to donate since btc and eth are banned in egypt btw...
again thank you all for all support
2026-09-27 09:29:11 +03:00
L7NEG 034c9e4bef Merge pull request #90 from Sys0xdbg/feat/nenyoo-support
Polish Nenyoo release package
2026-09-20 01:13:42 +03:00
Debugger e6d5d3a245 Remove Nenyoo development tests 2026-09-19 18:09:49 -04:00
Debugger b3ebc25a43 Polish Nenyoo documentation 2026-09-19 18:08:00 -04:00
L7NEG b77c81bc48 Merge pull request #89 from Sys0xdbg/feat/nenyoo-support
Add Nenyoo support for GTA V Legacy
2026-09-19 12:05:49 +03:00
Debugger e8adcde6e2 Keep offset loader out of script listings 2026-09-17 02:14:43 -04:00
Debugger b54f4c48c5 Store edition offsets as data files 2026-09-17 02:13:34 -04:00
Debugger d868876d70 Add GTA V Enhanced support to Nenyoo 2026-09-17 01:58:42 -04:00
Debugger e4a41668ee preview 2026-09-17 01:31:58 -04:00
Debugger 9ca89413c9 Centralize GTA globals and script locals 2026-09-17 01:22:58 -04:00
Debugger c45c7f03fc Preserve collectible help text in Nenyoo information panel 2026-09-14 19:21:42 -04:00
Debugger 624c607185 Show Ultimate Menu information in companion panel 2026-09-14 19:06:36 -04:00
Debugger a7120f68e7 Clarify offline menu check 2026-09-14 18:38:24 -04:00
Debugger 4dd2ec689c Keep offline notices out of selectable menu rows 2026-09-14 18:37:37 -04:00
Debugger b7625dfbe1 Document correct Nenyoo install path and in-game checks 2026-09-14 12:13:27 -04:00
Debugger 5ff45873e2 Keep dynamic weapon actions bound to their labels 2026-09-14 12:04:03 -04:00
Debugger 720816f826 Add Nenyoo Legacy adapter for YimMenu Ultimate Menu 2026-09-14 11:15:47 -04:00
L7NEG c06a2ff411 Harden legacy config file handling
Use the native io.exists helper and return nil when config reads fail instead of raising fatal errors, allowing callers to handle missing or unreadable configuration files gracefully.
2026-09-14 15:42:45 +03:00
L7NEG 96e20e98e1 feat(Kortz Center Heist Menu): refactor UI, fix payouts & autos
Refactor Kortz Center heist UI and logic: add helper functions (SetKortzTarget, KortzReloadBoard, KortzSkipCooldown, RainbowInfo, ToggleBitDropdown), simplify messages, and reorganize ImGui layout. Fix payout off-by-one by adjusting getCurrentPayout/setPayout to use the correct global index and fallback to base payouts. Harden auto-hack loop and detection for data crack / fingerprint / vault door. Consolidate many prep toggles into dropdowns, inline glass progress read, and various UX/tooltip improvements.
2026-08-27 05:01:59 +03:00
L7NEG 2e74762235 fix(locals): fix lasers local 2026-08-24 06:28:07 +03:00
L7NEG 307d6e07ca Fixes missing functions and lua formatted code
fixed missing set_bools and set_globals credits: SilentSalo/SilentNight-Script

formatted lua code style using stylua
2026-08-14 04:18:28 +03:00
L7NEG 9583689be9 feat: add Trick or Treat and Snowmen collectible event toggles
feat: add Trick or Treat and Snowmen collectible event toggles
2026-08-13 21:31:26 +03:00
L7NEG c679209178 Updated globals for halloween weather and updated all events menu
thx to pr#86 @Pyxalon and https://github.com/UltimateMenu/UltimateMenu/issues/85 @mylifereading6666-oss
2026-08-13 21:30:10 +03:00
Pyxalon c6ea3a97c0 Update Ultimate_Menu_Legacy.lua 2026-08-13 10:28:30 -04:00
L7NEG 306c771a78 Fix typo in SNOWMEN_COLLECTIBLES variable 2026-08-13 17:16:20 +03:00
Pyxalon 11b079a49e Update Ultimate_Menu_Legacy.lua 2026-08-13 10:04:06 -04:00
Pyxalon 335cf29d97 Update Ultimate_Menu_Legacy.lua 2026-08-12 17:12:26 -04:00
L7NEG a28c577c2a feat(Heist): Kortz Center Complete Revamp/Addons
Revamped Kortz Center Heist With much Cleaner UI

Added Custom payout and multiplier thx to imaginenothing on ukc https://www.unknowncheats.me/forum/4746347-post762.html

Now Kortz Heist is ultimate ready for modifications yay

removed all local function() and replaced with direct function() call since local call exceeded 200 so i freed up some for now :D

enjoy :3
2026-08-03 04:33:26 +03:00
L7NEG 362e626393 Fixes And feats
Added Kortz solo exhibit b2 in mission cracker submenu credits goes to [tidmouth](https://www.unknowncheats.me/forum/members/5823999.html) on [ukc](https://www.unknowncheats.me/forum/4745112-post761.html)

Added glass cutter and auto doors hack thx to imaginenothing for the locals/globals on ukc :3 

Fixed Data crack locals (Thx to imaginenothing on ukc for the help

Revamped UI in Kortz Center Heist > Mission cracker submenu

Added back Camlist to Cayo Heist in Remove All CCTV's

soon more addons/fixes :D
2026-08-03 00:18:50 +03:00
L7NEG b6e598c4f7 Fixes and Updates
fixed Cayo Perico Cuts Globals thx to xt95 aka Void • Vortex on discord

removed auto cracker its useless for now and it has some bugs

fixed data cracker bug thx to imaginenothing on unknowncheats.me  for the help :3

some other little changes you can view on the commit line changes enjoy <3
2026-08-01 05:54:02 +03:00
L7NEG 150f423ed7 Fix Kortz Center Bag Size Global
thx to @opadopaosas123-cell for reporting the issue https://github.com/UltimateMenu/UltimateMenu/issues/84
2026-07-31 17:25:47 +03:00
L7NEG 63f0ea1488 Add AHDg global for heist difficulty adjustment
Fixed missing globals thx to @mtsadiq https://github.com/YimMenu-Lua/UltimateMenuRevived/issues/2 for reporting them
2026-07-28 01:59:25 +03:00
L7NEG ff7def525b Update SMC6 value and comment in Ultimate_Menu_Legacy 2026-07-28 01:45:01 +03:00
L7NEG 29965eeb59 Refactor Diamond Casino Heist UI & behavior
Rework Diamond Casino Heist UI and related behavior in Ultimate_Menu_Legacy.lua:

- Consolidate all prep dropdowns into a single ImGui block so controls render in the correct order; add offline checks.
- Make Loadout and Vehicles combos filtered by selected Gunman/Driver respectively; reset dependent indices on change.
- Replace legacy menu controls/buttons with ImGui.Buttons for Apply/Reset Preps and Reload/Solo/Kill Cooldown, keeping previous logic.
- Convert Cuts UI to ImGui: add checkbox to remove crew cuts, integer inputs for 4 player cuts, and preset selector (including auto max-payout preset). Preserve preset behavior and SetDiamondMaxPayout usage.
- Add state variables for UI inputs (casinoCrewCuts_enabled, casinoPc*_val) and a looped script that applies/removes crew cut tunables based on the checkbox.
- Minor formatting and naming cleanups (preset and names arrays, removed redundant separators/text).

This change improves layout consistency, UX, and keeps functionality intact while preparing the UI for more dynamic interactions.
2026-07-28 00:05:37 +03:00
11 changed files with 17316 additions and 5098 deletions
+21
View File
@@ -0,0 +1,21 @@
# Ultimate Menu for Nenyoo
Ultimate Menu runs in Nenyoo on GTA V Legacy and Enhanced with the same menu structure and controls as the YimMenu edition.
## Install
1. Copy this folder to `%LOCALAPPDATA%\Nenyoo\Plus\Scripts\User\UltimateMenu\`.
2. Keep `Ultimate_Menu.lua` and the `lib` folder together.
3. In Nenyoo, open **Scripts** and select `Ultimate_Menu.lua`.
Online features become available after joining GTA Online.
## Supported builds
- GTA V Legacy 3889
- GTA V Enhanced 1158.13
The correct offset catalog is selected automatically. Build-specific globals and locals are stored in:
- `lib/game_offsets_legacy.offsets`
- `lib/game_offsets_enhanced.offsets`
+49
View File
@@ -0,0 +1,49 @@
-- @nenyoo-menu
-- Ultimate Menu for Nenyoo (GTA V Legacy and Enhanced).
-- Install this package under %LOCALAPPDATA%\Nenyoo\Plus\Scripts\User\UltimateMenu.
local source = debug.getinfo(1, "S").source
assert(source:sub(1, 1) == "@", "Ultimate Menu must be loaded from a file")
local directory = source:sub(2):match("^(.*[\\/])")
assert(directory, "Could not locate the Ultimate Menu package")
-- The YimResupplier config belongs to this package, not the GTA working directory.
local script_io = setmetatable({
open = function(name, mode)
if name == "YimResupplier.json" then name = directory .. name end
return io.open(name, mode)
end,
}, {__index = io})
-- Keep compatibility overrides inside this package; other Nenyoo scripts use
-- the original native, memory, network, and script tables.
local environment = setmetatable({
io = script_io,
memory = setmetatable({}, {__index = memory}),
network = setmetatable({}, {__index = network or {}}),
script = setmetatable({}, {__index = script or {}}),
NETSHOPPING = setmetatable({}, {__index = NETSHOPPING}),
PAD = setmetatable({}, {__index = PAD}),
HUD = setmetatable({}, {__index = HUD}),
ENTITY = setmetatable({}, {__index = ENTITY}),
CUTSCENE = setmetatable({}, {__index = CUTSCENE}),
}, {__index = _ENV})
local function run(path)
local chunk, message = loadfile(path, "t", environment)
assert(chunk, message)
return chunk()
end
local offsets = run(directory .. "lib\\game_offsets.offsets")
for _, group in ipairs({offsets.globals, offsets.locals, offsets.scripts}) do
for name, value in pairs(group) do environment[name] = value end
end
environment.ULTIMATE_MENU_OFFSETS = offsets
environment.ULTIMATE_MENU_EDITION = offsets.edition
environment.ULTIMATE_MENU_BUILD = offsets.build
local compatibility = run(directory .. "lib\\yim_compat.lua")
run(directory .. "lib\\Ultimate_Menu_Legacy.lua")
run(directory .. "lib\\info_panel.lua")(compatibility)
compatibility.materialize_imgui()
return compatibility
File diff suppressed because it is too large Load Diff
+13
View File
@@ -0,0 +1,13 @@
-- Select the build-specific GTA address catalog at runtime.
local source = debug.getinfo(1, "S").source
assert(source:sub(1, 1) == "@", "Offset catalog must be loaded from a file")
local directory = assert(source:sub(2):match("^(.*[\\/])"), "Could not locate offset catalogs")
local edition = "Legacy"
if ctx and type(ctx.edition) == "function" then
local reported = tostring(ctx.edition())
if reported:lower() == "enhanced" then edition = "Enhanced" end
end
local filename = edition == "Enhanced" and "game_offsets_enhanced.offsets" or "game_offsets_legacy.offsets"
return assert(loadfile(directory .. filename, "t", _ENV))()
+278
View File
@@ -0,0 +1,278 @@
-- GTA V Enhanced build 1158.13 globals and script locals used by Ultimate Menu.
-- Update addresses here when a game build changes; feature code should not
-- contain raw global or local addresses.
local FREEMODE_TUNABLES = 262145
local globals = {
FMg = 262145, -- freemode tunables base
CSg1 = 1575048, -- session type
CSg2 = 1574589, -- session switch
CSg3 = 1574591, -- session quit
ACg1 = 1936408, -- apartment cut: player 1
ACg2 = 1936409, -- apartment cut: player 2
ACg3 = 1936410, -- apartment cut: player 3
ACg4 = 1936411, -- apartment cut: player 4
ACg5 = 1941383, -- apartment local-player cut
AUAJg1 = 271333, -- Fleeca job root hash
AUAJg2 = 271338, -- Prison Break root hash
AUAJg3 = 271345, -- Humane Labs root hash
AUAJg4 = 271351, -- Series A root hash
AUAJg5 = 271357, -- Pacific Standard root hash
ACDg = 2686124, -- apartment cooldown/player-data base
AHDg = 4722363, -- apartment heist difficulty
DCCg1 = 1976088, -- casino cut: player 1
DCCg2 = 1976089, -- casino cut: player 2
DCCg3 = 1976090, -- casino cut: player 3
DCCg4 = 1976091, -- casino cut: player 4
CPCg1 = 1981458, -- Cayo cut: player 1
CPCg2 = 1981459, -- Cayo cut: player 2
CPCg3 = 1981460, -- Cayo cut: player 3
CPCg4 = 1981461, -- Cayo cut: player 4
DCg1 = 1969934, -- Doomsday cut: player 1
DCg2 = 1969935, -- Doomsday cut: player 2
DCg3 = 1969936, -- Doomsday cut: player 3
DCg4 = 1969937, -- Doomsday cut: player 4
GCg = 2692915, -- generic heist cut multiplier
KCBGL = 300182, -- Kortz bag size
KCWMG = 300344, -- Kortz weekly multiplier
KCCDG = 300247, -- Kortz normal cooldown
KCCD2G = 300248, -- Kortz hard cooldown
KCLDG = 1935711, -- Kortz lasers disabled
KCSECONDARY_BASE = 5009911, -- Kortz secondary-target array
KCPAYOUT_BASE = 300149, -- Kortz primary-target payouts
HGLs1 = 4722361, -- heist launch state 1
HGLs2 = 4722364, -- heist launch state 2
HGLs3 = 4722365, -- heist launch state 3
HGLs4 = 4915256, -- heist launch state 4
SNOW = 266558,
halloweatherAddress = 294894,
yetihuntAddress = 297763,
TRICK_OR_TREAT = 294663,
SNOWMEN_COLLECTIBLES = 295964,
GVADg = 296039, -- Gun Van armour discount
GVWDg = 296020, -- Gun Van weapon discount
GVTDg = 296031, -- Gun Van throwable discount
CCBL0 = 288788, -- casino chip buy limit 1
CCBL1 = 288789, -- casino chip buy limit 2
CPBg = 291483, -- Cayo bag size
PSV = 291735, -- Panther Statue value
PDIAMOND = 291733, -- Pink Diamond value
BB = 291732, -- Bearer Bonds value
RN = 291731, -- Ruby Necklace value
TEQUILA = 291730, -- Tequila value
AG = 4525224, -- achievement unlock selector
current_objectives_global = 2359296,
weekly_objectives_global = 2732247,
objectives_state_global = 1574746,
CARGO1 = 284730,
CARGO2 = 284731,
CARGO3 = 284732,
CARGO4 = 284733,
CARGO5 = 284734,
CARGO6 = 284735,
CARGO7 = 284736,
CARGO8 = 284737,
CARGO9 = 284738,
CEO1 = 277970, -- special cargo sale threshold
CEO2 = 277737, -- special cargo buy cooldown
CEO3 = 277738, -- special cargo sell cooldown
SafeCapacity = 23773, -- nightclub safe capacity tunable offset
IncomeStart = 23750, -- nightclub income range start
IncomeEnd = 23769, -- nightclub income range end
main_global = 1673814, -- YimResupplier business-state base
TRANSACTION_ERROR_GLOBAL_1 = 4516981,
TRANSACTION_ERROR_GLOBAL_2 = 4516982,
TRANSACTION_ERROR_GLOBAL_3 = 4516983,
GUN_VAN_LOCATION_GLOBAL = 2655290,
PLAYER_RP_MULTIPLIER_GLOBAL = 262146,
AIR_CARGO_RP_MULTIPLIER_GLOBAL = 284713,
NIGHTCLUB_CASH_BONUS_1 = 279564,
NIGHTCLUB_CASH_BONUS_2 = 279570,
NIGHTCLUB_CASH_BASE = 279558,
NIGHTCLUB_COKE_BONUS_1 = 279565,
NIGHTCLUB_COKE_BONUS_2 = 279571,
NIGHTCLUB_COKE_BASE = 279559,
NIGHTCLUB_METH_BONUS_1 = 279566,
NIGHTCLUB_METH_BONUS_2 = 279572,
NIGHTCLUB_METH_BASE = 279560,
NIGHTCLUB_WEED_BONUS_1 = 279567,
NIGHTCLUB_WEED_BONUS_2 = 279573,
NIGHTCLUB_WEED_BASE = 279561,
NIGHTCLUB_DOCUMENTS_BONUS_1 = 279563,
NIGHTCLUB_DOCUMENTS_BONUS_2 = 279569,
NIGHTCLUB_DOCUMENTS_BASE = 279557,
NIGHTCLUB_BUNKER_BONUS_1 = 283494,
NIGHTCLUB_BUNKER_BONUS_2 = 283493,
NIGHTCLUB_BUNKER_BASE = 283492,
NIGHTCLUB_ACID_BONUS = 279568,
NIGHTCLUB_ACID_BASE = 279562,
}
function globals.DAILY_OBJECTIVE_CURRENT(index)
return globals.current_objectives_global + 1 + 681 + 4248 + 1 + (index * 3)
end
function globals.DAILY_OBJECTIVE_STATE(index)
return globals.objectives_state_global + 1 + 1 + index
end
function globals.WEEKLY_OBJECTIVE_STATE()
return globals.weekly_objectives_global + 1 + 1
end
function globals.WEEKLY_OBJECTIVE_CURRENT()
return globals.weekly_objectives_global + 1 + 2
end
function globals.NIGHTCLUB_SAFE_VALUE(player_id)
return 1845347 + player_id + 260 + 364 + 5
end
function globals.APARTMENT_COOLDOWN(player_id)
return globals.ACDg + 1 + (player_id * 77) + 76
end
function globals.APARTMENT_HEIST_TYPE(player_id)
return globals.ACDg + (player_id * 77) + 24 + 2
end
function globals.HEIST_SOLO_LAUNCH(heist_type)
return 794989 + 4 + 1 + (heist_type * 95) + 75
end
function globals.APARTMENT_FORCE_READY(player_index)
return 2658294 + 1 + ((player_index - 1) * 468) + 270
end
function globals.LEGACY_HEIST_FORCE_READY(player_index)
return 1882717 + 1 + ((player_index - 1) * 315) + 43 + 11 + player_index
end
function globals.CAYO_FORCE_READY(player_index)
return 1981147 + 1 + ((player_index - 1) * 27) + 7 + player_index
end
function globals.KORTZ_SECONDARY_TARGET(player_index, offset)
return globals.KCSECONDARY_BASE + (player_index * 333) + offset
end
function globals.KORTZ_SECONDARY_PRIMARY(player_index)
return globals.KORTZ_SECONDARY_TARGET(player_index, 68)
end
function globals.KORTZ_SECONDARY_SECONDARY(player_index)
return globals.KORTZ_SECONDARY_TARGET(player_index, 143)
end
function globals.KORTZ_PAYOUT(target_index)
return globals.KCPAYOUT_BASE + target_index + 1
end
function globals.YIM_RESUPPLIER_SLOT(slot_index)
return globals.main_global + slot_index + 1
end
local locals = {
AIFl1 = 20412, -- apartment instant finish 1
AIFl2 = 21474,
AIFl3 = 22153,
AIFl4 = 23098,
AIFl5 = 29327,
AIFl6 = 32854,
AFHl = 12263, -- Fleeca hack
AFDl = 10538, -- Fleeca drill
AFPl = 10233, -- Pacific hack
AHSo = 20414, -- apartment checkpoint bitset
AHLIVESL = 28164, -- apartment team lives
DCRBl = 219, -- casino planning reload
DCAg = 10713, -- casino autograbber state
DCAs = 10727, -- casino autograbber speed
DCFHl = 55028, -- casino fingerprint hack
DCKHl = 56098, -- casino keypad hack
DCDVDl1 = 10534, -- casino vault drill result
DCDVDl2 = 10564, -- casino vault drill progress
DCLIVESL = 28164, -- casino team lives
DCXf1 = 20412,
DCXf2 = 21474,
DCXf3 = 22153,
DCXf4 = 23098,
DCXf5 = 29327,
DCXf6 = 32854,
CPRSl = 1580, -- Cayo planning reload
CPFHl = 26619, -- Cayo fingerprint hack
CPPCCl = 32754, -- Cayo plasma cutter
CPSTCl = 31511, -- Cayo drainage pipe
CPXf1 = 56504,
CPXf2 = 58281,
CPLIVESL = 64395, -- Cayo team lives
DDSHl = 1449, -- Doomsday scenario hack
DDIF1 = 20412,
DDIF2 = 22153,
DDIF3 = 29327,
DDIF4 = 32854,
DDIF5 = 32882,
DDLIVESL = 28164, -- Doomsday team lives
KCBRL = 599, -- Kortz planning reload
KCDCL = 1388, -- Kortz data crack base
KCFHL = 26866, -- Kortz fingerprint hack
KCAC_BASE = 32819, -- Kortz access-code base
KCLGL = 71006, -- Kortz lasers
KCVLL = 27914, -- Kortz vault door
KCCGL_BASE = 32856, -- Kortz cut-glass base
KCCGL_OFFSET = 3,
KCPT_STATE = 29366, -- Kortz primary target state
KCST_STATE = 29366, -- Kortz secondary target state
KCLIVESL = 65159, -- Kortz team lives
KCIf1 = 57251,
KCIf2 = 59027,
AGFl1 = 56505, -- Agency instant finish 1
AGFl2 = 58281,
ASIFl1 = 56505, -- Auto Shop instant finish 1
ASIFl2 = 58281,
ASRBl = 418, -- Auto Shop planning reload
SYRl1 = 547, -- Salvage Yard planning reload
HGGs1 = 20230, -- fmmc_launcher heist type
HGGs2 = 20211, -- fmmc_launcher minimum players
IHPB = 56504,
IHPL = 58281,
NLCl = 267, -- nightclub cutscene state
slots_random_results_table = 1381,
prize_wheel_win_state = 311,
prize_wheel_prize = 14,
prize_wheel_prize_state = 45,
SMC1 = 577,
SMC2 = 583,
SMC3 = 1160,
SMC4 = 631,
SMC5 = 1171,
SMC6 = 591,
SMC7 = 772,
SMC8 = 773,
SMC9 = 639,
SMC10 = 635,
SMC11 = 825,
SMC12 = 826,
SCRIPT_STATE = 2,
GUNCLUB_LIVERY = 955,
}
function locals.KORTZ_DATA_CRACK(index)
return locals.KCDCL + 1 + (index * 4)
end
function locals.KORTZ_ACCESS_CODE(index)
return locals.KCAC_BASE + (index * 2)
end
function locals.KORTZ_CUT_GLASS(index)
return locals.KCCGL_BASE + (index * 13) + locals.KCCGL_OFFSET
end
local scripts = {
FMC = "fm_mission_controller",
FMMCL = "fmmc_launcher",
FMC2020 = "fm_mission_controller_2020",
HIP = "heist_island_planning",
CASINO_SLOTS = "casino_slots",
CASINO_LUCKY_WHEEL = "casino_lucky_wheel",
GUNCLUB_SHOP = "gunclub_shop",
}
return {edition = "Enhanced", build = "1158.13", globals = globals, locals = locals, scripts = scripts}
+303
View File
@@ -0,0 +1,303 @@
-- GTA V Legacy build 3889 globals and script locals used by Ultimate Menu.
-- Update addresses here when a game build changes; feature code should not
-- contain raw global or local addresses.
local FREEMODE_TUNABLES = 262145
local globals = {
FMg = FREEMODE_TUNABLES, -- freemode tunables base
CSg1 = 1575046, -- session type
CSg2 = 1574589, -- session switch
CSg3 = 1574589 + 2, -- session quit
ACg1 = 1935929 + 1 + 1, -- apartment cut: player 1
ACg2 = 1935929 + 1 + 2, -- apartment cut: player 2
ACg3 = 1935929 + 1 + 3, -- apartment cut: player 3
ACg4 = 1935929 + 1 + 4, -- apartment cut: player 4
ACg5 = 1937897 + 3008 + 1, -- apartment local-player cut
ACg6 = 1937897 + 3008 + 2, -- apartment cut: player 2 (actual)
ACg7 = 1937897 + 3008 + 3, -- apartment cut: player 3 (actual)
ACg8 = 1937897 + 3008 + 4, -- apartment cut: player 4 (actual)
AUAJg1 = FREEMODE_TUNABLES + 9184, -- Fleeca job root hash
AUAJg2 = FREEMODE_TUNABLES + 9189, -- Prison Break root hash
AUAJg3 = FREEMODE_TUNABLES + 9196, -- Humane Labs root hash
AUAJg4 = FREEMODE_TUNABLES + 9202, -- Series A root hash
AUAJg5 = FREEMODE_TUNABLES + 9208, -- Pacific Standard root hash
ACDg = 2686119, -- apartment cooldown/player-data base
AFRg = 2658293, -- apartment force ready global
AHDg = 4718592 + 3771, -- apartment heist difficulty
DCCg1 = 1972483 + 1497 + 736 + 92 + 1, -- casino cut: player 1
DCCg2 = 1972483 + 1497 + 736 + 92 + 2, -- casino cut: player 2
DCCg3 = 1972483 + 1497 + 736 + 92 + 3, -- casino cut: player 3
DCCg4 = 1972483 + 1497 + 736 + 92 + 4, -- casino cut: player 4
CFRg = 1976846, -- casino force ready global
CPCg1 = 1979291 + 831 + 56 + 1, -- Cayo cut: player 1
CPCg2 = 1979291 + 831 + 56 + 2, -- Cayo cut: player 2
CPCg3 = 1979291 + 831 + 56 + 3, -- Cayo cut: player 3
CPCg4 = 1979291 + 831 + 56 + 4, -- Cayo cut: player 4
CYFRg = 1980404, -- Cayo force ready global
DCg1 = 1968511 + 812 + 50 + 1, -- Doomsday cut: player 1
DCg2 = 1968511 + 812 + 50 + 2, -- Doomsday cut: player 2
DCg3 = 1968511 + 812 + 50 + 3, -- Doomsday cut: player 3
DCg4 = 1968511 + 812 + 50 + 4, -- Doomsday cut: player 4
DDFRg = 1882652, -- Doomsday force ready global
GCg = 2686119 + 6791, -- generic heist cut multiplier
KCBGL = FREEMODE_TUNABLES + 37438, -- Kortz bag size
KCWMG = FREEMODE_TUNABLES + 37600, -- Kortz weekly multiplier
KCCDG = FREEMODE_TUNABLES + 37503, -- Kortz normal cooldown
KCCD2G = FREEMODE_TUNABLES + 37504, -- Kortz hard cooldown
KCLDG = 1935234, -- Kortz lasers disabled
KCSECONDARY_BASE = 4980736 + 1 + 29174, -- Kortz secondary-target array
KCPAYOUT_BASE = FREEMODE_TUNABLES + 37405, -- Kortz primary-target payouts
HGLs1 = 4718592 + 3769, -- heist launch state 1
HGLs2 = 4718592 + 3772, -- heist launch state 2
HGLs3 = 4718592 + 3773, -- heist launch state 3
HGLs4 = 4718592 + 190163 + 1, -- heist launch state 4
SNOW = FREEMODE_TUNABLES + 4413,
halloweatherAddress = FREEMODE_TUNABLES + 32247,
yetihuntAddress = FREEMODE_TUNABLES + 35041,
TRICK_OR_TREAT = FREEMODE_TUNABLES + 32173,
SNOWMEN_COLLECTIBLES = FREEMODE_TUNABLES + 33317,
GVADg = FREEMODE_TUNABLES + 33392, -- Gun Van armour discount
GVWDg = FREEMODE_TUNABLES + 33373, -- Gun Van weapon discount
GVTDg = FREEMODE_TUNABLES + 33384, -- Gun Van throwable discount
CCBL0 = FREEMODE_TUNABLES + 26623, -- casino chip buy limit 1
CCBL1 = FREEMODE_TUNABLES + 26624, -- casino chip buy limit 2
CPBg = FREEMODE_TUNABLES + 29300, -- Cayo bag size
PSV = FREEMODE_TUNABLES + 29552, -- Panther Statue value
PDIAMOND = FREEMODE_TUNABLES + 29550, -- Pink Diamond value
BB = FREEMODE_TUNABLES + 29549, -- Bearer Bonds value
RN = FREEMODE_TUNABLES + 29548, -- Ruby Necklace value
TEQUILA = FREEMODE_TUNABLES + 29547, -- Tequila value
AG = 4525223 + 1, -- achievement unlock selector
current_objectives_global = 2359296,
weekly_objectives_global = 2732111,
objectives_state_global = 1574746,
CARGO1 = FREEMODE_TUNABLES + 22581,
CARGO2 = FREEMODE_TUNABLES + 22582,
CARGO3 = FREEMODE_TUNABLES + 22583,
CARGO4 = FREEMODE_TUNABLES + 22584,
CARGO5 = FREEMODE_TUNABLES + 22585,
CARGO6 = FREEMODE_TUNABLES + 22586,
CARGO7 = FREEMODE_TUNABLES + 22587,
CARGO8 = FREEMODE_TUNABLES + 22588,
CARGO9 = FREEMODE_TUNABLES + 22589,
CEO1 = FREEMODE_TUNABLES + 15821, -- special cargo sale threshold
CEO2 = FREEMODE_TUNABLES + 15588, -- special cargo buy cooldown
CEO3 = FREEMODE_TUNABLES + 15589, -- special cargo sell cooldown
SafeCapacity = 23769, -- nightclub safe capacity tunable offset
IncomeStart = 23746, -- nightclub income range start
IncomeEnd = 23765, -- nightclub income range end
main_global = 1673807, -- YimResupplier business-state base
TRANSACTION_ERROR_GLOBAL_1 = 4516981,
TRANSACTION_ERROR_GLOBAL_2 = 4516982,
TRANSACTION_ERROR_GLOBAL_3 = 4516983,
GUN_VAN_LOCATION_GLOBAL = 2652581 + 2706,
PLAYER_RP_MULTIPLIER_GLOBAL = FREEMODE_TUNABLES + 1,
AIR_CARGO_RP_MULTIPLIER_GLOBAL = FREEMODE_TUNABLES + 22564,
NIGHTCLUB_CASH_BONUS_1 = FREEMODE_TUNABLES + 17415,
NIGHTCLUB_CASH_BONUS_2 = FREEMODE_TUNABLES + 17421,
NIGHTCLUB_CASH_BASE = FREEMODE_TUNABLES + 17409,
NIGHTCLUB_COKE_BONUS_1 = FREEMODE_TUNABLES + 17416,
NIGHTCLUB_COKE_BONUS_2 = FREEMODE_TUNABLES + 17422,
NIGHTCLUB_COKE_BASE = FREEMODE_TUNABLES + 17410,
NIGHTCLUB_METH_BONUS_1 = FREEMODE_TUNABLES + 17417,
NIGHTCLUB_METH_BONUS_2 = FREEMODE_TUNABLES + 17423,
NIGHTCLUB_METH_BASE = FREEMODE_TUNABLES + 17411,
NIGHTCLUB_WEED_BONUS_1 = FREEMODE_TUNABLES + 17418,
NIGHTCLUB_WEED_BONUS_2 = FREEMODE_TUNABLES + 17424,
NIGHTCLUB_WEED_BASE = FREEMODE_TUNABLES + 17412,
NIGHTCLUB_DOCUMENTS_BONUS_1 = FREEMODE_TUNABLES + 17414,
NIGHTCLUB_DOCUMENTS_BONUS_2 = FREEMODE_TUNABLES + 17420,
NIGHTCLUB_DOCUMENTS_BASE = FREEMODE_TUNABLES + 17408,
NIGHTCLUB_BUNKER_BONUS_1 = FREEMODE_TUNABLES + 21345,
NIGHTCLUB_BUNKER_BONUS_2 = FREEMODE_TUNABLES + 21344,
NIGHTCLUB_BUNKER_BASE = FREEMODE_TUNABLES + 21343,
NIGHTCLUB_ACID_BONUS = FREEMODE_TUNABLES + 17419,
NIGHTCLUB_ACID_BASE = FREEMODE_TUNABLES + 17413,
}
function globals.DAILY_OBJECTIVE_CURRENT(index)
return globals.current_objectives_global + 1 + 681 + 4248 + 1 + (index * 3)
end
function globals.DAILY_OBJECTIVE_STATE(index)
return globals.objectives_state_global + 1 + 1 + index
end
function globals.WEEKLY_OBJECTIVE_STATE()
return globals.weekly_objectives_global + 1 + 1
end
function globals.WEEKLY_OBJECTIVE_CURRENT()
return globals.weekly_objectives_global + 1 + 2
end
function globals.NIGHTCLUB_SAFE_VALUE(player_id)
return 1845298 + player_id + 260 + 364 + 5
end
function globals.APARTMENT_COOLDOWN(player_id)
return globals.ACDg + 1 + (player_id * 77) + 76
end
function globals.APARTMENT_HEIST_TYPE(player_id)
return globals.ACDg + (player_id * 77) + 24 + 2
end
function globals.HEIST_SOLO_LAUNCH(heist_type)
return 794989 + 4 + 1 + (heist_type * 95) + 75
end
function globals.APARTMENT_FORCE_READY(player_index)
return 2658293 + 1 + ((player_index - 1) * 468) + 270
end
function globals.LEGACY_HEIST_FORCE_READY(player_index)
return 1882572 + 1 + ((player_index - 1) * 315) + 43 + 11 + player_index
end
function globals.CAYO_FORCE_READY(player_index)
return 1979868 + 1 + ((player_index - 1) * 27) + 7 + player_index
end
function globals.KORTZ_SECONDARY_TARGET(player_index, offset)
return globals.KCSECONDARY_BASE + (player_index * 333) + offset
end
function globals.KORTZ_SECONDARY_PRIMARY(player_index)
return globals.KORTZ_SECONDARY_TARGET(player_index, 68)
end
function globals.KORTZ_SECONDARY_SECONDARY(player_index)
return globals.KORTZ_SECONDARY_TARGET(player_index, 143)
end
function globals.KORTZ_PAYOUT(target_index)
return globals.KCPAYOUT_BASE + target_index + 1
end
function globals.YIM_RESUPPLIER_SLOT(slot_index)
return globals.main_global + slot_index + 1
end
local locals = {
AIFl1 = 19808, -- apartment instant finish 1
AIFl2 = 19808 + 1062,
AIFl3 = 19808 + 1740 + 1,
AIFl4 = 19808 + 2686,
AIFl5 = 28722 + 1,
AIFl6 = 31981 + 1 + 68,
AFHl = 11837 + 24, -- Fleeca hack
AFDl = 10125 + 11, -- Fleeca drill
AFPl = 9831, -- Pacific hack
AHSo = 19808 + 2, -- apartment checkpoint bitset
AHLIVESL = 26234 + 1325 + 1, -- apartment team lives
DCRBl = 217, -- casino planning reload
DCAg = 10311, -- casino autograbber state
DCAs = 10311 + 14, -- casino autograbber speed
DCFHl = 54118, -- casino fingerprint hack
DCKHl = 55188, -- casino keypad hack
DCDVDl1 = 10125 + 7, -- casino vault drill result
DCDVDl2 = 10125 + 37, -- casino vault drill progress
DCLIVESL = 26234 + 1325 + 1, -- casino team lives
DCXf1 = 19808,
DCXf2 = 19808 + 1062,
DCXf3 = 19808 + 1740 + 1,
DCXf4 = 19808 + 2686,
DCXf5 = 28722 + 1,
DCXf6 = 31981 + 1 + 68,
CPRSl = 1578, -- Cayo planning reload
CPFHl = 26217, -- Cayo fingerprint hack
CPPCCl = 32349 + 3, -- Cayo plasma cutter
CPSTCl = 31109, -- Cayo drainage pipe
CPXf1 = 56070,
CPXf2 = 56070 + 1776 + 1,
CPLIVESL = 62851 + 1109 + 1, -- Cayo team lives
CPMantrap1 = 68939 + (0 * 293) + 236, -- Cayo solo mantrap dual keycard 1
CPMantrap2 = 20813, -- Cayo solo mantrap dual keycard 2
CPSecondary = 28971 + 11, -- Cayo secondary target state
CPLootTake = 59552 + 1376 + 60, -- Cayo loot take
DDSHl = 1312 + 135, -- Doomsday scenario hack
DDIF1 = 19808,
DDIF2 = 19808 + 1740 + 1,
DDIF3 = 28722 + 1,
DDIF4 = 31981 + 1 + 68,
DDIF5 = 31981 + 97,
DDIF6 = 19808 + 1062, -- Doomsday Act III passed flag
DDLIVESL = 26234 + 1325 + 1, -- Doomsday team lives
KCBRL = 597, -- Kortz planning reload
KCDCL = 1386, -- Kortz data crack base
KCFHL = 26464, -- Kortz fingerprint hack
KCAC_BASE = 32416 + 1, -- Kortz access-code base
KCLGL = 70472, -- Kortz lasers
KCVLL = 27512, -- Kortz vault door
KCLDIF1 = 1058, -- Kortz lasers difficulty 1
KCLDIF2 = 1059, -- Kortz lasers difficulty 2
KCNoDmg = 1060, -- Kortz no-damage lasers
KCLootTake = 60203 + 1376 + 60, -- Kortz loot take
KCCGL_BASE = 32453 + 1, -- Kortz cut-glass base
KCCGL_OFFSET = 3,
KCPT_STATE = 28953 + 11, -- Kortz primary target state
KCST_STATE = 28953 + 11, -- Kortz secondary target state
KCLIVESL = 63515 + 1109 + 1, -- Kortz team lives
KCIf1 = 56716 + 1,
KCIf2 = 56716 + 1776 + 1,
AGFl1 = 56070 + 1, -- Agency instant finish 1
AGFl2 = 56070 + 1776 + 1,
ASIFl1 = 56070 + 1, -- Auto Shop instant finish 1
ASIFl2 = 56070 + 1776 + 1,
ASRBl = 416, -- Auto Shop planning reload
SYRl1 = 545, -- Salvage Yard planning reload
LSAIFl1 = 7879 + 1306, -- LSA operations instant finish 1
LSAIFl2 = 7741 + 1, -- LSA operations instant finish 2
HGGs1 = 20194 + 34, -- fmmc_launcher heist type
HGGs2 = 20194 + 15, -- fmmc_launcher minimum players
IHPB = 56070,
IHPL = 56070 + 1776 + 1,
NLCl = 213 + 32 + 19 + 1, -- nightclub cutscene state
slots_random_results_table = 1379,
prize_wheel_win_state = 309,
prize_wheel_prize = 14,
prize_wheel_prize_state = 45,
SMC1 = 574 + 1,
SMC2 = 574 + 7,
SMC3 = 574 + 584,
SMC4 = 574 + 55,
SMC5 = 574 + 595,
SMC6 = 589,
SMC7 = 770,
SMC8 = 771,
SMC9 = 632 + 5,
SMC10 = 632 + 1,
SMC11 = 632 + 191,
SMC12 = 632 + 192,
SCRIPT_STATE = 2,
GUNCLUB_LIVERY = 206 + 747,
}
function locals.KORTZ_DATA_CRACK(index)
return locals.KCDCL + 1 + (index * 4)
end
function locals.KORTZ_ACCESS_CODE(index)
return locals.KCAC_BASE + (index * 2)
end
function locals.KORTZ_CUT_GLASS(index)
return locals.KCCGL_BASE + (index * 13) + locals.KCCGL_OFFSET
end
local scripts = {
FMC = "fm_mission_controller",
FMMCL = "fmmc_launcher",
FMC2020 = "fm_mission_controller_2020",
FMCV3 = "fm_mission_controller_v3",
FMMLASERS = "fmmc_lasers",
HIP = "heist_island_planning",
CASPL = "gb_casino_heist_planning",
GANGPL = "gb_gang_ops_planning",
KORTZPL = "kortz_planning",
TUNERPL = "tuner_planning",
SMUGOPS = "fm_content_smuggler_ops",
CASINO_SLOTS = "casino_slots",
CASINO_LUCKY_WHEEL = "casino_lucky_wheel",
GUNCLUB_SHOP = "gunclub_shop",
}
return {edition = "Legacy", build = "3889", globals = globals, locals = locals, scripts = scripts}
+138
View File
@@ -0,0 +1,138 @@
-- Companion information panel for the Nenyoo edition of Ultimate Menu.
-- The menu adapter publishes text on the script thread. Draw only the
-- published strings here; overlay.on_draw runs on Nenyoo's render thread.
return function(compat)
local scroll_by_page = {}
local last_page
local function clamp(value, low, high)
return math.max(low, math.min(high, value))
end
local function wrap_paragraph(value, max_width, output, heading, color)
local line = ""
for word in value:gmatch("%S+") do
local candidate = line == "" and word or line .. " " .. word
if line ~= "" and text.width(font.small, candidate) > max_width then
output[#output + 1] = {text = line, heading = heading, color = color}
line = word
else
line = candidate
end
end
if line ~= "" then output[#output + 1] = {text = line, heading = heading, color = color} end
end
local function make_lines(rows, max_width)
local lines = {}
for _, row in ipairs(rows) do
local value = tostring(row.text or ""):gsub("\r", "")
if value == "" then
lines[#lines + 1] = {gap = 8}
else
local compact = value:gsub("%s+", " "):match("^%s*(.-)%s*$")
local heading = #compact <= 38 and (compact:sub(-1) == ":" or compact == "Preps")
for paragraph in (value .. "\n"):gmatch("(.-)\n") do
if paragraph:match("%S") then wrap_paragraph(paragraph, max_width, lines, heading, row.color)
else lines[#lines + 1] = {gap = 8} end
end
lines[#lines + 1] = {gap = heading and 7 or 11}
end
if row.tooltip then
wrap_paragraph(row.tooltip:gsub("%s+", " "), max_width, lines, false, nil)
lines[#lines + 1] = {gap = 11}
end
end
while #lines > 0 and lines[#lines].gap do lines[#lines] = nil end
return lines
end
overlay.on_draw("ultimate_menu_information", function()
if not menu.is_visible() then return end
local id = menu.page_id()
local info = compat.info_for_page(id)
if not info or #info.rows == 0 then return end
local sw, sh = ctx.screen_w(), ctx.screen_h()
local bx, by, bw = menu.bounds()
if not bw or bw <= 0 then return end
local gap, pad, header_h = 14, 14, 36
local width = math.min(420, math.max(280, sw * 0.30))
local side = bx + bw + gap + width <= sw - 8 or bx - gap - width >= 8
if not side then width = math.min(600, sw - 16) end
local x
if side and bx + bw + gap + width <= sw - 8 then x = bx + bw + gap
elseif side then x = bx - gap - width
else x = clamp(bx + (bw - width) * 0.5, 8, sw - width - 8) end
local lines = make_lines(info.rows, width - pad * 2)
if #lines == 0 then return end
local line_h = text.height(font.small) + 4
local content_h = 0
for _, line in ipairs(lines) do content_h = content_h + (line.gap or line_h) end
local desired_h = header_h + pad * 2 + content_h
local height = math.min(desired_h, sh - 16, 650)
local y = clamp(by, 8, sh - height - 8)
if not side then
local _, content_y, _, content_height = menu.content_rect()
local below = content_y + content_height + 56
local space_below = sh - below - 8
if content_height > 0 and space_below >= 170 then
y = below
height = math.min(height, space_below)
elseif by >= 180 then
height = math.min(height, by - 16)
y = by - height - 8
end
end
local viewport_h = height - header_h - pad * 2
if viewport_h <= line_h then return end
if last_page ~= id then scroll_by_page[id] = 0; last_page = id end
local max_scroll = math.max(0, content_h - viewport_h)
local scroll = clamp(scroll_by_page[id] or 0, 0, max_scroll)
local mx, my = input.mouse_x(), input.mouse_y()
if mx >= x and mx <= x + width and my >= y and my <= y + height then
scroll = clamp(scroll - input.mouse_wheel() * line_h * 3, 0, max_scroll)
end
scroll_by_page[id] = scroll
local ar, ag, ab = theme.accent()
draw.rect(x, y, x + width, y + height, 12, 15, 22, 232, 7)
draw.rect(x, y, x + width, y + header_h, 24, 32, 44, 245, 7)
draw.rect(x, y + header_h - 2, x + width, y + header_h, ar, ag, ab, 255)
draw.rect_outline(x, y, x + width, y + height, ar, ag, ab, 125, 7)
text.draw_ellipsis(font.item, x + pad, y + (header_h - text.height(font.item)) * 0.5,
240, 245, 250, 255, info.title, width - pad * 2)
local top = y + header_h + pad
draw.push_clip(x + pad, top, x + width - pad, top + viewport_h)
local cursor = top - scroll
for _, line in ipairs(lines) do
if line.gap then cursor = cursor + line.gap
else
if cursor + line_h >= top and cursor <= top + viewport_h then
local r, g, b = 220, 228, 238
if line.heading then r, g, b = ar, ag, ab end
if line.color then
local function channel(value)
value = value or 1
return clamp(math.floor((value <= 1 and value * 255 or value) + 0.5), 0, 255)
end
r, g, b = channel(line.color[1]), channel(line.color[2]), channel(line.color[3])
end
text.draw(font.small, x + pad, cursor, r, g, b, 245, line.text)
end
cursor = cursor + line_h
end
end
draw.pop_clip()
if max_scroll > 0 then
local track_top, track_height = top, viewport_h
local thumb_h = math.max(22, track_height * viewport_h / content_h)
local thumb_y = track_top + (track_height - thumb_h) * scroll / max_scroll
draw.rect(x + width - 5, thumb_y, x + width - 2, thumb_y + thumb_h,
ar, ag, ab, 190, 2)
end
end)
end
+665
View File
@@ -0,0 +1,665 @@
-- YimMenu API compatibility for Ultimate Menu on Nenyoo.
-- Loaded by the Nenyoo entry script on Nenyoo's script thread.
local nv = native_invoker
local stat_out = memory.alloc_int()
local float_out = memory.alloc_float()
local scan_context
local function invoke(hash, args, result)
nv.begin_call()
for _, arg in ipairs(args) do
local kind, value = arg[1], arg[2]
if kind == "float" then nv.push_arg_float(value)
elseif kind == "bool" then nv.push_arg_bool(value)
elseif kind == "ptr" then nv.push_arg_pointer(value)
else nv.push_arg_int(value) end
end
nv.end_call(hash)
if result == "bool" then return nv.get_return_value_bool() end
if result == "int" then return nv.get_return_value_int() end
if result == "float" then return nv.get_return_value_float() end
if result == "vector3" then return nv.get_return_value_vector3() end
end
local function stat_hash(name) return util.joaat(name) end
stats = {}
function stats.get_int(name)
local ok = invoke("767FBC2AC802EF3D", {{"int", stat_hash(name)}, {"ptr", stat_out}, {"int", -1}}, "bool")
return ok and memory.read_int(stat_out) or 0
end
function stats.get_float(name)
local ok = invoke("D7AE6C9C9C6AC54C", {{"int", stat_hash(name)}, {"ptr", float_out}, {"int", -1}}, "bool")
return ok and memory.read_float(float_out) or 0.0
end
function stats.get_bool(name)
local ok = invoke("11B5E6D2AE73F48E", {{"int", stat_hash(name)}, {"ptr", stat_out}, {"int", -1}}, "bool")
return ok and memory.read_bool(stat_out) or false
end
function stats.set_int(name, value)
if scan_context then return false end
return invoke("B3271D7AB655B441", {{"int", stat_hash(name)}, {"int", value}, {"bool", true}}, "bool")
end
function stats.set_float(name, value)
if scan_context then return false end
return invoke("4851997F37FE9B3C", {{"int", stat_hash(name)}, {"float", value}, {"bool", true}}, "bool")
end
function stats.set_bool(name, value)
if scan_context then return false end
return invoke("4B33C4243DE0C432", {{"int", stat_hash(name)}, {"bool", value}, {"bool", true}}, "bool")
end
function stats.get_masked_int(name, offset, width)
local ok = invoke("655185A06D9EEAAB", {
{"int", stat_hash(name)}, {"ptr", stat_out}, {"int", offset}, {"int", width}, {"int", -1},
}, "bool")
return ok and memory.read_int(stat_out) or 0
end
function stats.set_masked_int(name, value, offset, width)
if scan_context then return false end
return invoke("7BBB1B54583ED410", {
{"int", stat_hash(name)}, {"int", value}, {"int", offset}, {"int", width}, {"bool", true},
}, "bool")
end
function stats.set_bool_masked(name, value, bit)
if scan_context then return false end
return invoke("5BC62EC1937B9E5B", {
{"int", stat_hash(name)}, {"bool", value}, {"int", bit}, {"bool", true},
}, "bool")
end
local function character_slot() return stats.get_int("MPPLY_LAST_MP_CHAR") end
function stats.set_packed_stat_bool(index, value)
if scan_context then return false end
invoke("DB8A58AEAA67CD07", {{"int", index}, {"bool", value}, {"int", character_slot()}})
end
function stats.set_packed_stat_int(index, value)
if scan_context then return false end
invoke("1581503AE529CD2E", {{"int", index}, {"int", value}, {"int", character_slot()}})
end
globals = {}
local function global_addr(index)
local addr = memory.script_global(index)
return addr and addr ~= 0 and addr or nil
end
function globals.get_int(index)
local addr = global_addr(index)
return addr and memory.read_int(addr) or 0
end
function globals.set_int(index, value)
if scan_context then return false end
local addr = global_addr(index)
if addr then memory.write_int(addr, value); return true end
return false
end
function globals.set_float(index, value)
if scan_context then return false end
local addr = global_addr(index)
if addr then memory.write_float(addr, value); return true end
return false
end
function globals.set_string(index, value, size)
if scan_context then return false end
local addr = global_addr(index)
if not addr then return false end
if memory.write_string then memory.write_string(addr, value or "") return true end
return false
end
locals = {}
local function local_addr(script_name, index)
local addr = memory.script_local(util.joaat(script_name), index)
return addr and addr ~= 0 and addr or nil
end
function locals.get_int(script_name, index)
local addr = local_addr(script_name, index)
return addr and memory.read_int(addr) or 0
end
function locals.get_float(script_name, index)
local addr = local_addr(script_name, index)
return addr and memory.read_float(addr) or 0.0
end
function locals.set_int(script_name, index, value)
if scan_context then return false end
local addr = local_addr(script_name, index)
if addr then memory.write_int(addr, value); return true end
return false
end
function locals.set_float(script_name, index, value)
if scan_context then return false end
local addr = local_addr(script_name, index)
if addr then memory.write_float(addr, value); return true end
return false
end
tunables = {}
local function tunable_addr(name)
local addr = memory.tunable(name)
return addr and addr ~= 0 and addr or nil
end
function tunables.get_int(name)
local addr = tunable_addr(name)
return addr and memory.read_int(addr) or 0
end
function tunables.get_float(name)
local addr = tunable_addr(name)
return addr and memory.read_float(addr) or 0.0
end
function tunables.set_int(name, value)
if scan_context then return false end
local addr = tunable_addr(name)
if addr then memory.write_int(addr, value); return true end
return false
end
function tunables.set_float(name, value)
if scan_context then return false end
local addr = tunable_addr(name)
if addr then memory.write_float(addr, value); return true end
return false
end
function tunables.set_bool(name, value)
if scan_context then return false end
local addr = tunable_addr(name)
if addr then memory.write_bool(addr, value); return true end
return false
end
network = network or {}
function network.is_session_started()
return invoke("9DE624D2FC4B603F", {}, "bool")
end
function network.force_script_host(name)
if scan_context then return false end
return __ny_request_script_host(name)
end
-- Yim's generated native binding returns an output argument as a second Lua
-- value. Nenyoo's generic named-native wrapper only returns the native result.
-- Preserve the transaction ID required by Ultimate Menu's weapon unlocks.
NETSHOPPING.NET_GAMESERVER_BEGIN_SERVICE = function(_, category, item, action, value, flags)
if scan_context then return false, 0 end
memory.write_int(stat_out, 0)
local ok = invoke("3C5FD37B5499582E", {
{"ptr", stat_out}, {"int", category}, {"int", item},
{"int", action}, {"int", value}, {"int", flags},
}, "bool")
return ok, memory.read_int(stat_out)
end
NETSHOPPING.NET_GAMESERVER_BASKET_IS_ACTIVE = function()
return invoke("A65568121DF2EA26", {}, "bool")
end
local disable_control_action = PAD.DISABLE_CONTROL_ACTION
PAD.DISABLE_CONTROL_ACTION = function(...)
if not scan_context then return disable_control_action(...) end
end
-- The generated native.call wrappers return one integer; blip coordinates are
-- a three-float native result used by several Resupplier teleport actions.
HUD.GET_BLIP_COORDS = function(blip)
return invoke("586AFE3FF72D996E", {{"int", blip}}, "vector3")
end
HUD.DOES_BLIP_EXIST = function(blip)
return invoke("A6DB27D19ECBB7DA", {{"int", blip}}, "bool")
end
ENTITY.DOES_ENTITY_EXIST = function(entity)
return invoke("7239B21A38F536BA", {{"int", entity}}, "bool")
end
CUTSCENE.IS_CUTSCENE_PLAYING = function()
return invoke("D3C2E180A40F031E", {}, "bool")
end
joaat = util.joaat
vec3 = {new = function(_, x, y, z) return {x = x, y = y, z = z} end}
log = {
info = function(message) if util.log then util.log(message) end end,
warning = function(message) if util.log then util.log(message) end end,
debug = function(message) if util.log then util.log(message) end end,
}
entities = {
get_all_objects_as_handles = function()
return __stand_get_all(false, false, true)
end,
}
local function pattern_at(addr)
return {
is_null = function() return addr:is_null() end,
add = function(_, offset) return pattern_at(addr:add(offset)) end,
rip = function() return pattern_at(addr:rip()) end,
get_string = function() return addr:read_string() end,
}
end
memory.scan_pattern = function(pattern) return pattern_at(mem.scan_address(pattern)) end
self = {
get_id = function() return PLAYER.PLAYER_ID() end,
get_ped = function() return PLAYER.PLAYER_PED_ID() end,
}
weapons = {}
local weapon_names = {}
local weapon_catalog_loaded, next_weapon_lookup = false, 0
local function readable_weapon_name(value)
return value:gsub("^WEAPON_", ""):gsub("_", " "):lower():gsub("(%a)([%w']*)", function(first, rest)
return first:upper() .. rest
end)
end
function weapons.get_weapon_display_name(value)
if value == nil or value == "" or value == 0 then return "" end
if not weapon_catalog_loaded and __stand_get_weapons and os.clock() >= next_weapon_lookup then
local catalog = __stand_get_weapons()
weapon_catalog_loaded = #catalog > 0
next_weapon_lookup = os.clock() + 1
for _, entry in ipairs(catalog) do
local name = entry.d or readable_weapon_name(entry.n)
weapon_names[entry.n] = name
weapon_names[util.joaat(entry.n)] = name
end
end
if weapon_names[value] then return weapon_names[value] end
if type(value) == "string" and value:match("^WEAPON_[%w_]+$") then
return readable_weapon_name(value)
end
return ""
end
local tab_methods = {}
local imgui_sections = {}
local info_pages = {}
local tab_mt = {__index = tab_methods}
local function page_id(ref)
return util.joaat("Stand#" .. tostring(type(ref) == "table" and ref.id or ref))
end
local function info_page(ref, title)
local id = page_id(ref)
if not info_pages[id] then info_pages[id] = {title = title or "Information", static = {}} end
return info_pages[id], id
end
local function text_input(parent, label, help, callback, value)
if menu.text_input then
return menu.text_input(parent, label, {}, help, callback, value)
end
return __smenu.text_input(type(parent) == "table" and parent.id or parent, label, {}, help, callback, value)
end
local function tab(ref, path)
info_page(ref, path:match("([^/]+)$") or path)
return setmetatable({ref = ref, path = path}, tab_mt)
end
gui = {}
function gui.get_tab(name)
return tab(menu.list(menu.my_root(), name, {}, "Ultimate Menu for Nenyoo"), name)
end
function gui.show_message(title, message) util.toast(tostring(title) .. ": " .. tostring(message)) end
gui.show_success = gui.show_message
gui.show_error = gui.show_message
function gui.add_notification(message) util.toast(tostring(message)) end
function tab_methods:add_tab(name)
return tab(menu.list(self.ref, name, {}, ""), self.path .. "/" .. name)
end
function tab_methods:add_button(label, callback)
return menu.action(self.ref, label, {}, "", callback)
end
function tab_methods:add_checkbox(label, default_value)
local ref = menu.toggle(self.ref, label, {}, "", function() end, default_value or false)
return {
is_enabled = function() return menu.get_value(ref) and true or false end,
set_enabled = function(_, value) menu.set_value(ref, value and true or false) end,
}
end
function tab_methods:add_input_int(label, default_value)
local obj = {value = default_value or 0}
text_input(self.ref, label, "Enter an integer", function(text)
local number = tonumber(text)
if number then obj.value = math.tointeger(number) or math.floor(number) end
end, tostring(obj.value))
function obj:get_value() return self.value end
function obj:set_value(value) self.value = value end
return obj
end
function tab_methods:add_text(label)
local page = info_page(self.ref)
page.static[#page.static + 1] = {text = tostring(label or "")}
end
function tab_methods:add_separator() return menu.divider(self.ref, "") end
function tab_methods:add_sameline() end
function tab_methods:add_imgui(callback)
imgui_sections[#imgui_sections + 1] = {parent = self.ref, path = self.path, callback = callback}
end
script = script or {}
-- The upstream script also calls script:sleep() directly from one menu action.
function script.sleep(_, ms) util.yield(ms) end
local fiber_script = {
yield = function(_, ms) util.yield(ms) end,
sleep = function(_, ms) util.yield(ms) end,
}
function script.register_looped(_, callback)
return util.create_thread(function()
while true do
callback(fiber_script)
util.yield()
end
end)
end
function script.run_in_fiber(callback)
return util.create_thread(function() callback(fiber_script) end)
end
function script.execute_as_script(name, callback)
if scan_context then return false end
return __ny_execute_as_script(name, callback)
end
local current_section, current_event, building, widget_index, widget_occurrences, separator_occurrences, parent_stack
local function current_parent() return parent_stack[#parent_stack] end
local function push_parent(ref) parent_stack[#parent_stack + 1] = ref end
local function pop_parent() if #parent_stack > 1 then parent_stack[#parent_stack] = nil end end
local function ancestors(extra)
local out = {}
for _, ref in ipairs(parent_stack) do
out[type(ref) == "table" and ref.id or ref] = true
end
if extra then out[type(extra) == "table" and extra.id or extra] = true end
return out
end
local function source_key(counters, fallback, label)
for level = 3, 12 do
local info = debug.getinfo(level, "Sl")
if not info then break end
if info.source and info.source:find("Ultimate_Menu_Legacy.lua", 1, true) then
local line = info.currentline
local key = tostring(line)
if label ~= nil then key = key .. ":" .. tostring(label) end
counters[key] = (counters[key] or 0) + 1
return key .. ":" .. counters[key]
end
end
return fallback
end
local function next_id(label)
widget_index = widget_index + 1
return source_key(widget_occurrences, tostring(widget_index), label)
end
local function label_for_menu(label)
if label:sub(1, 2) ~= "##" then return label:gsub("##.*$", "") end
if current_section.last_text and current_section.last_text ~= "" then return current_section.last_text end
return label:sub(3):gsub("_", " "):gsub("(%l)(%u)", "%1 %2")
end
local function replay(section, event)
current_section, current_event = section, event
building, widget_index, widget_occurrences, separator_occurrences, parent_stack = false, 0, {}, {}, {section.parent}
section.info_rows = {}
section.callback()
current_section, current_event, parent_stack = nil, nil, nil
end
local function event_for(id, value)
return current_event and current_event.id == id and current_event.value == value
end
local function register_action(label, value)
local id = next_id(label)
local section = current_section
if not section.widget_refs[id] then
local path = ancestors()
section.widget_refs[id] = menu.action(current_parent(), label_for_menu(label), {}, "", function()
replay(section, {id = id, value = value, ancestors = path})
end)
end
section.last_ref = section.widget_refs[id]
section.last_info_row = nil
return event_for(id, value)
end
ImGui = {}
function ImGui.Button(label) return register_action(label, true) end
function ImGui.Selectable(label) return register_action(label, true) end
function ImGui.Checkbox(label, value)
local id = next_id(label)
local section = current_section
if not section.widget_refs[id] then
local path = ancestors()
section.widget_refs[id] = menu.toggle(current_parent(), label_for_menu(label), {}, "", function(on)
replay(section, {id = id, value = on, ancestors = path})
end, value and true or false)
end
section.last_ref = section.widget_refs[id]
section.last_info_row = nil
if current_event and current_event.id == id then return current_event.value, true end
return value, false
end
local function numeric_input(label, value, as_float)
local id = next_id(label)
local section = current_section
if not section.widget_refs[id] then
local path = ancestors()
section.widget_refs[id] = text_input(current_parent(), label_for_menu(label), "Enter a number", function(text)
local number = tonumber(text)
if number then
if not as_float then number = math.tointeger(number) or math.floor(number) end
replay(section, {id = id, value = number, ancestors = path})
end
end, tostring(value or 0))
end
section.last_ref = section.widget_refs[id]
section.last_info_row = nil
if current_event and current_event.id == id then return current_event.value, true end
return value, false
end
function ImGui.InputInt(label, value) return numeric_input(label, value, false) end
function ImGui.InputFloat(label, value) return numeric_input(label, value, true) end
function ImGui.DragInt(label, value) return numeric_input(label, value, false) end
function ImGui.SliderInt(label, value, min_value, max_value)
local id = next_id(label)
local section = current_section
if not section.widget_refs[id] then
local path = ancestors()
section.widget_refs[id] = menu.slider(current_parent(), label_for_menu(label), {}, "", min_value, max_value, value, 1, function(selected)
replay(section, {id = id, value = selected, ancestors = path})
end)
end
section.last_ref = section.widget_refs[id]
section.last_info_row = nil
if current_event and current_event.id == id then return current_event.value, true end
return value, false
end
function ImGui.InputText(label, value)
local id = next_id(label)
local section = current_section
if not section.widget_refs[id] then
local path = ancestors()
section.widget_refs[id] = text_input(current_parent(), label_for_menu(label), "", function(text)
replay(section, {id = id, value = text, ancestors = path})
end, value or "")
end
section.last_ref = section.widget_refs[id]
section.last_info_row = nil
if current_event and current_event.id == id then return current_event.value, true end
return value, false
end
function ImGui.Combo(label, selected, choices, count)
local id = next_id(label)
local section = current_section
local menu_label = label_for_menu(label)
if not section.containers_by_id[id] then
local list = menu.list(current_parent(), menu_label, {}, "")
section.containers_by_id[id] = list
section.containers[#section.containers + 1] = list
local path = ancestors(list)
for i = 1, count or #choices do
local choice = choices[i] or tostring(i)
local choice_index = i - 1
menu.action(list, choice, {}, "", function()
replay(section, {id = id, value = choice_index, ancestors = path})
end)
end
end
section.last_ref = section.containers_by_id[id]
section.last_info_row = nil
local current_choice = choices[(selected or 0) + 1]
if current_choice then
local display = menu_label .. ": " .. tostring(current_choice)
if menu.get_menu_name(section.last_ref) ~= display then menu.set_menu_name(section.last_ref, display) end
end
if current_event and current_event.id == id then return current_event.value, true end
return selected, false
end
local function record_text(value, color)
if value == nil or value == "" then return end
local label = tostring(value)
if current_section.tooltip then
if current_section.last_info_row then
local row = current_section.last_info_row
if row.text == "[?]" then row.text = label
else row.tooltip = label end
elseif current_section.last_ref then
menu.set_help_text(current_section.last_ref, label)
end
return
end
local compact = label:gsub("%s+", " "):match("^%s*(.-)%s*$")
local _, id = info_page(current_parent())
local rows = current_section.info_rows[id]
if not rows then rows = {}; current_section.info_rows[id] = rows end
local row = {text = label, color = color}
rows[#rows + 1] = row
current_section.last_info_row = row
current_section.last_ref = nil
if compact ~= "[?]" and #compact <= 60 then
current_section.last_text = compact:gsub(":$", "")
end
end
ImGui.Text = record_text
ImGui.TextUnformatted = ImGui.Text
ImGui.TextWrapped = ImGui.Text
function ImGui.TextColored(r, g, b, a, value)
record_text(value, {r, g, b, a})
end
function ImGui.Separator()
local id = source_key(separator_occurrences, "separator:" .. tostring(widget_index))
if not current_section.separator_refs[id] then
current_section.separator_refs[id] = menu.divider(current_parent(), "")
end
end
function ImGui.Spacing() end
function ImGui.SameLine() end
function ImGui.Dummy() end
function ImGui.ProgressBar(fraction, _, _, overlay)
ImGui.Text(overlay or string.format("%d%%", math.floor(math.max(0, math.min(1, fraction or 0)) * 100)))
end
function ImGui.SetTooltip(message)
if current_section.last_info_row then
local row = current_section.last_info_row
if row.text == "[?]" then row.text = tostring(message)
else row.tooltip = tostring(message) end
elseif current_section.last_ref then
menu.set_help_text(current_section.last_ref, tostring(message))
end
end
function ImGui.BeginTooltip() current_section.tooltip = true; return true end
function ImGui.EndTooltip() current_section.tooltip = false end
function ImGui.IsItemHovered() return true end
function ImGui.IsItemActive() return false end
function ImGui.GetFontSize() return 14 end
function ImGui.PushStyleColor() end
function ImGui.PopStyleColor() end
function ImGui.PushTextWrapPos() end
function ImGui.PopTextWrapPos() end
function ImGui.PushItemWidth() end
function ImGui.SetNextItemWidth() end
function ImGui.SetNextWindowSize() end
function ImGui.OpenPopup() end
function ImGui.CloseCurrentPopup()
-- The Gun Van editor is a Nenyoo submenu. Keep its source branch active
-- after closing so re-entering the submenu does not leave inert controls.
weapon_editor_popup = true
menu.go_back()
end
function ImGui.BeginTabBar() return true end
function ImGui.BeginTabItem(label)
local id = next_id(label)
local ref = current_section.containers_by_id[id]
if not ref then
ref = menu.list(current_parent(), label, {}, "")
info_page(ref, label)
current_section.containers[#current_section.containers + 1] = ref
current_section.containers_by_id[id] = ref
end
if not ref then return false end
if current_event and not current_event.ancestors[ref.id] then return false end
current_section.last_info_row = nil
push_parent(ref)
return true
end
function ImGui.EndTabItem() pop_parent() end
function ImGui.BeginListBox(label)
return ImGui.BeginTabItem(label)
end
function ImGui.EndListBox() pop_parent() end
function ImGui.TreeNode(label)
return ImGui.BeginTabItem(label)
end
function ImGui.TreePop() pop_parent() end
function ImGui.BeginPopupModal(label)
return ImGui.BeginTabItem(label)
end
function ImGui.EndPopup() pop_parent() end
function ImGui.EndTabBar() end
ImGuiCol = {Text = 0}
ImGuiTabBarFlags = {None = 0}
ImGuiWindowFlags = {Modal = 0, NoCollapse = 0, NoMove = 0, NoResize = 0}
local compat = {imgui_sections = imgui_sections, info_pages = info_pages}
function compat.info_for_page(id)
local page = info_pages[id]
if not page then return nil end
local rows, last_label = {}, nil
local function append(row)
local label = row.text:gsub("%s+", " "):match("^%s*(.-)%s*$")
if label == "" then
if #rows > 0 and rows[#rows].text ~= "" then rows[#rows + 1] = {text = ""} end
last_label = nil
elseif label ~= last_label then
rows[#rows + 1] = row
last_label = label
end
end
for _, row in ipairs(page.static) do append(row) end
for _, section in ipairs(imgui_sections) do
local live = section.info_rows and section.info_rows[id]
if live then for _, row in ipairs(live) do append(row) end end
end
return {title = page.title, rows = rows}
end
function compat.materialize_imgui()
for _, section in ipairs(imgui_sections) do
section.widget_refs, section.separator_refs = {}, {}
section.info_rows = {}
section.containers, section.containers_by_id = {}, {}
section.tooltip, section.last_ref, section.last_text = false, nil, nil
current_section, current_event = section, nil
building, widget_index, widget_occurrences, separator_occurrences, parent_stack = true, 0, {}, {}, {section.parent}
scan_context = section.path:find("Story Mode", 1, true) and "story" or "online"
section.callback()
scan_context = nil
end
current_section, current_event, parent_stack = nil, nil, nil
if __smenu and __smenu.node_in_viewport then
util.create_thread(function()
while true do
for _, section in ipairs(imgui_sections) do
local parent = section.parent
local visible = __smenu.node_in_viewport(type(parent) == "table" and parent.id or parent)
if not visible then
for _, ref in ipairs(section.containers) do
if __smenu.node_in_viewport(type(ref) == "table" and ref.id or ref) then
visible = true
break
end
end
end
if visible then replay(section, nil) end
end
util.yield()
end
end)
end
end
return compat
Binary file not shown.

After

Width:  |  Height:  |  Size: 541 KiB

+13 -51
View File
@@ -17,14 +17,18 @@
--- ---
<h2 align="center">📸 Preview (Legacy)</h2> <h2 align="center">📸 YimMenu Preview (Legacy)</h2>
<p align="center"> <p align="center">
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/15.png" alt="Ultimate Menu Preview"> <img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/15.png" alt="Ultimate Menu Preview">
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/16.png" alt="Ultimate Menu Preview"> </p>
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/17.png" alt="Ultimate Menu Preview">
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/18.png" alt="Ultimate Menu Preview"> ---
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/19.png" alt="Ultimate Menu Preview">
<h2 align="center">📸 Nenyoo Preview (Legacy)</h2>
<p align="center">
<img src="Nenyoo/preview.jpg" alt="Ultimate Menu running in Nenyoo on GTA V Legacy">
</p> </p>
--- ---
@@ -40,6 +44,9 @@
- For **YimMenuV2 Enhanced**: - For **YimMenuV2 Enhanced**:
Coming Soon (WIP) Coming Soon (WIP)
- For **Nenyoo GTA V Legacy or Enhanced**:
Copy the contents of [`Nenyoo`](Nenyoo) to `%LOCALAPPDATA%\Nenyoo\Plus\Scripts\User\UltimateMenu\`. In Nenyoo, open `Scripts` and select `Ultimate_Menu.lua` to load its menu page. The `lib` folder must stay beside the entry script. Join GTA Online before using online actions.
Supported builds: Legacy 3889 and Enhanced 1158.13. The matching offsets are selected automatically.
</details> </details>
--- ---
@@ -49,6 +56,7 @@
- **Ultimate Menu for ModestMenu**: Last updated on **Dec 12, 2024** *(Final Update)* - **Ultimate Menu for ModestMenu**: Last updated on **Dec 12, 2024** *(Final Update)*
- **Ultimate Menu for YimMenu Legacy**: Last updated on **Jul 24, 2026** - **Ultimate Menu for YimMenu Legacy**: Last updated on **Jul 24, 2026**
- **Ultimate Menu for YimMenu Enhanced**: **Might Not Coming Soon (WIP Waiting for completion of YimMenuV2 Lua API)** - **Ultimate Menu for YimMenu Enhanced**: **Might Not Coming Soon (WIP Waiting for completion of YimMenuV2 Lua API)**
- **Ultimate Menu for Nenyoo**: Legacy and Enhanced support
--- ---
@@ -64,52 +72,6 @@ Credits For Everything I Used Is Included In The Script.
--- ---
## ☕ Support & Donations
<details>
<summary><strong>Click to show donation options</strong></summary>
If you'd like to support this project or say thanks you can use one of the below options:
<p align="center">
<a href="https://www.buymeacoffee.com/L7NEG" target="_blank">
<img src="https://img.shields.io/badge/Buy%20Me%20a%20Coffee-yellow?logo=buy-me-a-coffee&logoColor=white" alt="Buy Me A Coffee">
</a>
</p>
<p align="center">
<strong>Binance ID:</strong><br>
<code>810214888</code>
</p>
<p align="center">
<strong>Phantom Profile:</strong><br>
https://phantom.com/user/l7neg
</p>
<p align="center">
<strong>BTC Address:</strong><br>
<code>12U6pLzGtSPivFGvP4rKz9AtesxjDP3fe7</code>
</p>
<p align="center">
<strong>BTC (Taproot) Address:</strong><br>
<code>bc1pp8vc4zsfsz7z66f3e75s73kk5q7catugfflfu6n8craylq7r35wsrsa820</code>
</p>
<p align="center">
<strong>BTC (Native Segwit) Address:</strong><br>
<code>bc1qxq3c376ewt0xn8994q50zd7kmzv4trhx46f8xa</code>
</p>
<p align="center"><em>Any support is greatly appreciated! :3.</em></p>
</details>
---
---
<h2 align="left">💬 Discord Server</h2> <h2 align="left">💬 Discord Server</h2>
<p align="left"> <p align="left">
File diff suppressed because it is too large Load Diff