mirror of
https://github.com/UltimateMenu/UltimateMenu.git
synced 2026-10-10 20:03:10 +08:00
Compare commits
100 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cf2e354173 | |||
| 2c7b12720b | |||
| 034c9e4bef | |||
| e6d5d3a245 | |||
| b3ebc25a43 | |||
| b77c81bc48 | |||
| e8adcde6e2 | |||
| b54f4c48c5 | |||
| d868876d70 | |||
| e4a41668ee | |||
| 9ca89413c9 | |||
| c45c7f03fc | |||
| 624c607185 | |||
| a7120f68e7 | |||
| 4dd2ec689c | |||
| b7625dfbe1 | |||
| 5ff45873e2 | |||
| 720816f826 | |||
| c06a2ff411 | |||
| 96e20e98e1 | |||
| 2e74762235 | |||
| 307d6e07ca | |||
| 9583689be9 | |||
| c679209178 | |||
| c6ea3a97c0 | |||
| 306c771a78 | |||
| 11b079a49e | |||
| 335cf29d97 | |||
| a28c577c2a | |||
| 362e626393 | |||
| b6e598c4f7 | |||
| 150f423ed7 | |||
| 63f0ea1488 | |||
| ff7def525b | |||
| 29965eeb59 | |||
| c9fe45884c | |||
| b4f01c9771 | |||
| f3778a4b21 | |||
| ba45b292db | |||
| 859a682f92 | |||
| d14b42b08e | |||
| e030c7f3f4 | |||
| 5d5b8a6de0 | |||
| 2a2d655c96 | |||
| 8e72de2936 | |||
| cc1bbd0040 | |||
| bce5cca6cf | |||
| dc127f8e19 | |||
| 3ae957323f | |||
| 7f8468d4a3 | |||
| 4548f33290 | |||
| c9381be953 | |||
| ed8de348fa | |||
| ef159a8efc | |||
| db2b8ae936 | |||
| 5c5d95f84e | |||
| bb9ab6b081 | |||
| bb3b76951b | |||
| de2144259e | |||
| a83beadfc0 | |||
| fd1064ba80 | |||
| 4ccd511e2d | |||
| dbd70e2f0e | |||
| 9abe0ad3ab | |||
| a68053e489 | |||
| 6e287087f4 | |||
| bf71acc16c | |||
| 37e5774a4c | |||
| d635ed9866 | |||
| 129a4caa90 | |||
| 86a905d7dd | |||
| 9663c47911 | |||
| d566697e8d | |||
| 875dca2969 | |||
| 54832454ca | |||
| 2a9b4d51be | |||
| 6a6e0e2d50 | |||
| c107f0bf10 | |||
| f839fd2ee5 | |||
| ed828baf8b | |||
| ee142f4564 | |||
| 473c84ac69 | |||
| 8515113297 | |||
| 5cbdbb204d | |||
| 9972459de4 | |||
| cd1edbfa64 | |||
| 1730fb5bde | |||
| ff6052e2f4 | |||
| c5dbaea207 | |||
| 24bb44eb45 | |||
| d656cf578d | |||
| 6b592202ff | |||
| 503c1f2ba3 | |||
| 97c8e8df7c | |||
| 03844850ca | |||
| 57cff43f87 | |||
| ac6176f6c4 | |||
| a3606c6577 | |||
| 561837d5ef | |||
| e0aa8504c2 |
@@ -0,0 +1,113 @@
|
|||||||
|
name: Bug report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
title: "[Bug]: "
|
||||||
|
labels: bug
|
||||||
|
type: bug
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug
|
||||||
|
description: A clear and concise description of what the bug is.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Steps To Reproduce
|
||||||
|
description: Steps to reproduce the behavior.
|
||||||
|
placeholder: |
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '...'
|
||||||
|
3. Scroll down to '...'
|
||||||
|
4. See error
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected Behavior
|
||||||
|
description: A clear and concise description of what you expected to happen.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Logs
|
||||||
|
description: |
|
||||||
|
For a bug report to be valid, you need to include the logs for YimMenu.
|
||||||
|
They can be found under `%appdata%/YimMenu/cout.log`, even if you think the log file is useless we'd still like for you to include it here.
|
||||||
|
|
||||||
|
Tip: To easily upload your log file rename the cout.log file to cout.txt, alternatively zip the cout.log file. You can then drag and drop the file here.
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Screenshots / Video
|
||||||
|
description: |
|
||||||
|
If you think the issue can be better explained with screenshots or a video then consider adding these here.
|
||||||
|
|
||||||
|
Tip: You can attach images by clicking this area to highlight it and then dragging files in.
|
||||||
|
value: |
|
||||||
|
<!-- drag and drop your images or video(s) here -->
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: Store
|
||||||
|
description: Which launcher/store do you use to launch your game?
|
||||||
|
multiple: false
|
||||||
|
options:
|
||||||
|
- Steam
|
||||||
|
- Epic Games
|
||||||
|
- Rockstar
|
||||||
|
- Other (please mention in "Additional context")
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: Language
|
||||||
|
description: Which language do you have GTA 5 set to?
|
||||||
|
multiple: false
|
||||||
|
options:
|
||||||
|
- English
|
||||||
|
- French
|
||||||
|
- Italian
|
||||||
|
- German
|
||||||
|
- Spanish
|
||||||
|
- Japanese
|
||||||
|
- Russian
|
||||||
|
- Polish
|
||||||
|
- Brazilian Portuguese
|
||||||
|
- Traditional Chinese
|
||||||
|
- Simplified Chinese
|
||||||
|
- Latin American Spanish
|
||||||
|
- Korean
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: YimMenu Language
|
||||||
|
description: Which language do you use with YimMenu?
|
||||||
|
multiple: false
|
||||||
|
options:
|
||||||
|
- English (US)
|
||||||
|
- Español (España)
|
||||||
|
- Français (FR)
|
||||||
|
- Italiano (IT)
|
||||||
|
- Portuguese (BR)
|
||||||
|
- Русский (RU)
|
||||||
|
- Chinese (CN)
|
||||||
|
- Chinese (TW)
|
||||||
|
- Korean (KR)
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: Add any other context about the problem here.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: checkboxes
|
||||||
|
attributes:
|
||||||
|
label: Release
|
||||||
|
description: We want to confirm that this issue exists on the latest **release** version of UltimateMenu, not a fork or your own version of UltimateMenu.
|
||||||
|
options:
|
||||||
|
- label: I've confirmed the issue exists on the latest **release** version of UltimateMenu
|
||||||
|
required: true
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: Website
|
||||||
|
url: https://ultimatemenu.github.io
|
||||||
|
about: Main website of UltimateMenu.
|
||||||
|
- name: Docs | wiki
|
||||||
|
url: https://github.com/UltimateMenu/UltimateMenu/wiki
|
||||||
|
about: Maybe take a look a the docs in the main wiki of UltimateMenu?
|
||||||
|
- name: Discord Server
|
||||||
|
url: https://l7neg.uk.to/discord
|
||||||
|
about: Main Discord Server of UltimateMenu.
|
||||||
|
- name: UltimateMenu profile
|
||||||
|
url: https://github.com/UltimateMenu
|
||||||
|
about: Main github Orgnization profile of UltimateMenu for other sources.
|
||||||
|
- name: UltimateMenu Org discussions
|
||||||
|
url: https://github.com/orgs/UltimateMenu/discussions
|
||||||
|
about: Main github Orgnization discussions of UltimateMenu.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
name: Enhancement request
|
||||||
|
description: Enhance an existing feature in UltimateMenu.
|
||||||
|
title: "[Enhancement]: "
|
||||||
|
labels: enhancement
|
||||||
|
type: enhancement
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Which feature
|
||||||
|
description: "Explain which feature you want to see enhanced/improved and what you'd like to be changed about it."
|
||||||
|
placeholder: "ex: I'd like to enhance/improve .... because .... ."
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reason
|
||||||
|
description: Provide Reasoning
|
||||||
|
placeholder: "Tell us why you'd want for us to improve this feature in UltimateMenu."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: |
|
||||||
|
Add any other context about the request here.
|
||||||
|
|
||||||
|
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
name: Feature request
|
||||||
|
description: Suggest an idea for this project
|
||||||
|
title: "[Request]: "
|
||||||
|
labels: feature request
|
||||||
|
type: feature request
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Problem
|
||||||
|
description: "Is your feature request related to a problem? Please describe."
|
||||||
|
placeholder: "A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]"
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Solution
|
||||||
|
description: "Describe the solution you'd like"
|
||||||
|
placeholder: "A clear and concise description of what you want to happen."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reason
|
||||||
|
description: Provide Reasoning
|
||||||
|
placeholder: "Tell us why you'd want for us to add this to UltimateMenu."
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
description: |
|
||||||
|
Add any other context about the request here.
|
||||||
|
|
||||||
|
Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in.
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
name: Autolocker
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed]
|
||||||
|
issues:
|
||||||
|
types: [closed]
|
||||||
|
|
||||||
|
permissions: write-all
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
autolock-prs:
|
||||||
|
if: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.merged }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Autolock merged PRs
|
||||||
|
steps:
|
||||||
|
- name: Autolock merged PRs
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
github.rest.issues.lock({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
lock_reason: "resolved"
|
||||||
|
});
|
||||||
|
|
||||||
|
autolock-issues:
|
||||||
|
if: ${{ github.event_name == 'issues' }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Autolock closed Issues
|
||||||
|
steps:
|
||||||
|
- name: Autolock closed Issues
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
github.rest.issues.lock({
|
||||||
|
issue_number: context.issue.number,
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
lock_reason: "resolved"
|
||||||
|
});
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -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`
|
||||||
@@ -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
@@ -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))()
|
||||||
@@ -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}
|
||||||
@@ -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}
|
||||||
@@ -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
|
||||||
@@ -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 |
@@ -1,143 +1,85 @@
|
|||||||
<div align="center">
|
<p align="center">
|
||||||
<a href="https://ghrmt.vercel.app"><img src="https://readme-typing-svg.vercel.app/?lines=Ultimate+Menu+Script;Most+Useful+Script&font=Fira%20Code&size=31¢er=true&width=380&height=50&duration=4000&pause=1000" alt="Readme Typing Svg Vercel Version By L7NEG"></a>
|
<img src="https://readme-typing-svg.vercel.app/?lines=Ultimate+Menu+Script;Most+Useful+Script&font=Fira%20Code&size=31¢er=true&width=380&height=50&duration=4000&pause=1000" alt="Typing Banner">
|
||||||
</div>
|
</p>
|
||||||
|
|
||||||
<div align="center">
|
<h1 align="center">Ultimate Menu</h1>
|
||||||
<h1><a href="https://www.unknowncheats.me/forum/grand-theft-auto-v/565688-ultimate-menu-script.html">Ultimate Menu</a></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div align="center">
|
<p align="center"><em>A powerful menu script featuring advanced recovery options, money tools, a Heist Editor, and much more.</em></p>
|
||||||
<h1><a href="https://www.unknowncheats.me/forum/grand-theft-auto-v/597103-ultimate-menu-yimmenu.html">Ultimate Menu For YimMenu</a></h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
> [!WARNING]
|
<p align="center">
|
||||||
> RIP Cargo Method
|
<a href="https://www.unknowncheats.me/forum/grand-theft-auto-v/565688-ultimate-menu-script.html">[ModestMenu UKC Thread]</a> •
|
||||||
> Yes You Heard it Right Unfotunately The Most Used Money Method Among Modders Just Got Detected So > Just Stay Away From Any Ceo 6 mil script including UltimateMenu if you want to use it just use it with your own risk
|
<a href="https://www.unknowncheats.me/forum/grand-theft-auto-v/597103-ultimate-menu-yimmenu.html">[YimMenu UKC Thread]</a> •
|
||||||
> until then you can just use nightclub safe loop or modded heists cuts
|
<a href="https://github.com/UltimateMenu/UltimateMenu?tab=readme-ov-file#-faq">[FAQ]</a>
|
||||||
> it was the beast from late 2022 when it was 10 mil per crate till it got just detected on 13/8/2024 > which is just 6 mil per crate xD gg rockstar if you really need money use this method only to sell 111 crates once fr then wait 2 weeks irl and done.
|
</p>
|
||||||
|
|
||||||
# How To Use Ultimate Menu Script
|
> [!NOTE]
|
||||||
For every Version of the ultimate menu (Kiddion/YimMenu) there is a different use and ways to fully Run It.
|
> [How To Use YimMenu After BattlEye Anticheat Update (Legacy & Enhanced)](https://github.com/UltimateMenu/UltimateMenu/wiki/How-To-Use-UM-Script-With-YimMenu-After-Battleye-Anticheat-(Legacy-&-Enhanced))
|
||||||
|
|
||||||
For Kiddions script is just puting the script into scripts directory, inside the Kiddions files.
|
---
|
||||||
|
|
||||||
For YimMenu it is actually the same way, but first before initiating the script you will need to go to Settings > Lua > Open Folder Option
|
<h2 align="center">📸 YimMenu Preview (Legacy)</h2>
|
||||||
|
|
||||||
From There Go To Scripts Folder Then Paste The Ultimate Menu In There
|
<p align="center">
|
||||||
|
<img src="https://ultimatemenu.github.io/ScreenShots/YimMenu/15.png" alt="Ultimate Menu Preview">
|
||||||
|
</p>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------
|
---
|
||||||
<div align="center">
|
|
||||||
<h1> New ScreenShots V2.3 ModestMenu</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.3/Screenshot%202024-08-22%20085243.png)
|
<h2 align="center">📸 Nenyoo Preview (Legacy)</h2>
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.3/Screenshot%202024-08-22%20094828.png)
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.3/Screenshot%202024-08-22%20070050.png)
|
|
||||||
--------------------------------------------------------------------------------------------------
|
|
||||||
<div align="center">
|
|
||||||
<h1> New ScreenShots V2.3 YimMenu</h1>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="Nenyoo/preview.jpg" alt="Ultimate Menu running in Nenyoo on GTA V Legacy">
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/YimMenu/V2.3/Screenshot%202024-08-22%20085322.png)
|
## ❓ FAQ
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/YimMenu/V2.3/Screenshot%202024-08-21%20110838.png)
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/YimMenu/V2.3/Screenshot%202024-08-21%20120222.png)
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/YimMenu/V2.3/Screenshot%202024-08-21%20120920.png)
|
|
||||||
--------------------------------------------------------------------------------------------------
|
|
||||||
<div align="center"> <h1> <details>
|
|
||||||
<summary>Old Versions ScreenShots Modest Menu</summary>
|
|
||||||
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.2/Screenshot%202024-08-14%20185938.png)
|
<details>
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.2/Screenshot%202024-08-14%20185916.png)
|
<summary><strong>How To Use?</strong></summary>
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.2/Screenshot%202024-08-14%20192524.png)
|
|
||||||
[](https://ultimatemenu.github.io/ScreenShots/ModestMenu/V2.2/Screenshot%202024-08-14%20220324.png)
|
- For **YimMenu Legacy**:
|
||||||
[](https://ibb.co/Rhzr2WC)
|
Open YimMenu → `Settings` → `Lua` → `Open Folder` → `scripts`
|
||||||
[](https://ibb.co/NY3SMjM)
|
→ Paste the `.lua` file there. That’s it!
|
||||||
[](https://i.imgur.com/M54nsX6.png)
|
|
||||||
[](https://i.imgur.com/qszJJNK.png)
|
|
||||||
[](https://i.imgur.com/A5951n9.png)
|
|
||||||
[](https://i.imgur.com/Q04ceX5.png)
|
|
||||||
[](https://i.imgur.com/J3vquqW.png)
|
|
||||||
[](https://i.imgur.com/OKD4ruV.png)
|
|
||||||
[](https://i.imgur.com/MmRIRzW.png)
|
|
||||||
[](https://i.imgur.com/tuVD0wg.png)
|
|
||||||
[](https://i.imgur.com/b2erLqZ.png)
|
|
||||||
[](https://i.imgur.com/C1nhfs6.png)
|
|
||||||
[](https://i.imgur.com/2kNARYV.png)
|
|
||||||
[](https://i.imgur.com/vfsnLz4.png)
|
|
||||||
[](https://i.imgur.com/5ovnXIS.png)
|
|
||||||
[](https://i.imgur.com/HtOYaT2.png)
|
|
||||||
[](https://i.imgur.com/wSw48p7.png)
|
|
||||||
[](https://i.imgur.com/jz13ysV.png)
|
|
||||||
[](https://i.imgur.com/NlATJNG.png)
|
|
||||||
[](https://i.imgur.com/SSf5TwH.png)
|
|
||||||
[](https://i.imgur.com/0QDgNad.png)
|
|
||||||
[](https://i.imgur.com/oBnOqdG.png)
|
|
||||||
[](https://i.imgur.com/gspkbJq.png)
|
|
||||||
[](https://i.imgur.com/fQnOyPM.png)
|
|
||||||
[](https://i.imgur.com/Zfiv9po.png)
|
|
||||||
[](https://i.imgur.com/I7QHqM8.png)
|
|
||||||
[](https://i.imgur.com/b0JmgBF.png)
|
|
||||||
[](https://i.imgur.com/qZpu6Uo.png)
|
|
||||||
[](https://i.imgur.com/EFF9efF.png)
|
|
||||||
[](https://i.imgur.com/9QRULhG.png)
|
|
||||||
[](https://i.imgur.com/bas1EOp.png)
|
|
||||||
[](https://i.imgur.com/JMkmB7X.png)
|
|
||||||
[](https://i.imgur.com/Im3W9vf.png)
|
|
||||||
[](https://i.imgur.com/qw4ir1P.png)
|
|
||||||
[](https://i.imgur.com/IZmhyCp.png)
|
|
||||||
[](https://i.imgur.com/EN7gLdh.png)
|
|
||||||
[](https://i.imgur.com/rSPdw5D.png)
|
|
||||||
[](https://i.imgur.com/KOF7T0I.png)
|
|
||||||
[](https://i.imgur.com/c6XapmD.png)
|
|
||||||
[](https://i.imgur.com/YNsHiEz.png)
|
|
||||||
[](https://i.imgur.com/D1JDwWy.png)
|
|
||||||
[](https://i.imgur.com/uRU7pEJ.png)
|
|
||||||
[](https://i.imgur.com/QqqTWhV.png)
|
|
||||||
[](https://i.imgur.com/FfeC0g0.png)
|
|
||||||
[](https://i.imgur.com/ewUvo9k.png)
|
|
||||||
[](https://i.imgur.com/aIR70Sq.png)
|
|
||||||
[](https://i.imgur.com/M33uCnH.png)
|
|
||||||
[](https://i.imgur.com/wuS93Jy.png)
|
|
||||||
[](https://i.imgur.com/IGrWFv4.png)
|
|
||||||
[](https://i.imgur.com/Wwcu6uJ.png)
|
|
||||||
[](https://i.imgur.com/Cw3lR0K.png)
|
|
||||||
[](https://i.imgur.com/sK8v823.png)
|
|
||||||
[](https://i.imgur.com/TU2a1dL.png)
|
|
||||||
[](https://i.imgur.com/I4BKPNx.png)
|
|
||||||
[](https://i.imgur.com/TfUzBnL.png)
|
|
||||||
[](https://i.imgur.com/he7jVbf.png)
|
|
||||||
[](https://i.imgur.com/2gFkwgd.png)
|
|
||||||
[](https://i.imgur.com/0JTNdeR.png)
|
|
||||||
[](https://i.imgur.com/ZOhngs0.png)
|
|
||||||
[](https://i.imgur.com/JdGNN5u.png)
|
|
||||||
[](https://i.imgur.com/g1E5tET.png)
|
|
||||||
[](https://i.imgur.com/us8pTnv.png)
|
|
||||||
[](https://i.imgur.com/UxNxSD2.png)
|
|
||||||
[](https://i.imgur.com/dsaBz9M.png)
|
|
||||||
[](https://i.imgur.com/ahzoYzX.png)
|
|
||||||
[](https://i.imgur.com/AR0fcUS.png)
|
|
||||||
[](https://i.imgur.com/4BWvVJx.png)
|
|
||||||
[](https://i.imgur.com/M5RIvvm.png)
|
|
||||||
[](https://i.imgur.com/weSH8H1.png)
|
|
||||||
|
|
||||||
</details> </h1> </div>
|
- For **YimMenuV2 Enhanced**:
|
||||||
|
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>
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------
|
---
|
||||||
<div align="center"> <h1> <details>
|
|
||||||
<summary>Old Versions ScreenShots YimMenu</summary>
|
|
||||||
|
|
||||||
|
## 📅 Update Info
|
||||||
|
|
||||||
|
- **Ultimate Menu for ModestMenu**: Last updated on **Dec 12, 2024** *(Final Update)*
|
||||||
</details> </h1> </div>
|
- **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 Nenyoo**: Legacy and Enhanced support
|
||||||
|
|
||||||
--------------------------------------------------------------------------------------------------
|
---
|
||||||
## When Your New Updates Will Be Out?
|
|
||||||
No ETA for big updates also because i don't know actually if im going to be able to continue this script (boths) because i have a life and i need to study. This is a helpfull and fun project for everyone who wants to use it, is free and you can use my script as a template.
|
|
||||||
--------------------------------------------------------------------------------------------------
|
|
||||||
## About
|
|
||||||
- By the way to anyone who ask's about the Ultimate-Menu script, is not entire mine, there is actually in credits every single person who i taked code from and who helped me with this.
|
|
||||||
## Latest Ultimate Menu Kiddions update was on: 22/08/2024
|
|
||||||
## Latest Ultimate Menu YimMenu update was on: 22/08/2024
|
|
||||||
|
|
||||||
|
## 🛠️ About
|
||||||
|
|
||||||
|
This is a fun and helpful free project for the community.
|
||||||
|
There is **no ETA** for future big updates, as I’m currently focused on studying and personal life.
|
||||||
|
|
||||||
|
You're welcome to fork, use, and build on this script for your own needs.
|
||||||
|
Treat it as a base or template if you wish.
|
||||||
|
|
||||||
|
Credits For Everything I Used Is Included In The Script.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<h2 align="left">💬 Discord Server</h2>
|
||||||
|
|
||||||
|
<p align="left">
|
||||||
|
<a href="https://dsc.gg/l7neg">
|
||||||
|
<img src="https://discord.com/api/guilds/1025804814183047218/widget.png?style=banner2" alt="L7NEG Community Discord Server">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Thanks for using Ultimate Menu Made With ❤️ By L7NEG & Contributors/Helpers**
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user