From 42710b6bdde2a62bb4a6c2f4f51204d64b43d5cd Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Mon, 23 Feb 2026 12:48:17 -0500 Subject: [PATCH 1/6] fix(YHV1): Fix initial loading of secondary targets --- SSV2/includes/features/YimHeistsV1.lua | 21 ++++++++-------- SSV2/includes/frontend/yhv1_ui.lua | 31 ++++++++++++------------ SSV2/includes/lib/translations/en-US.lua | 4 +-- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/SSV2/includes/features/YimHeistsV1.lua b/SSV2/includes/features/YimHeistsV1.lua index 5008cd8..23aa0e1 100644 --- a/SSV2/includes/features/YimHeistsV1.lua +++ b/SSV2/includes/features/YimHeistsV1.lua @@ -7,6 +7,8 @@ -- * Provide a copy of or a link to the original license (GPL-3.0 or later); see LICENSE.md or . +local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } + ---@class HeistStat ---@field public name string ---@field public val integer @@ -63,15 +65,14 @@ function YimHeists:SkipPrep(statName, statVal, notifTitle) Notifier:ShowSuccess(notifTitle, _T("YH_PREP_SKIP_NOTIF")) end --- https://www.unknowncheats.me/forum/4489469-post16.html EXCEPT setting values as that's greater risk ----@param type string I or C +-- https://www.unknowncheats.me/forum/4489469-post16.html +---@param type string ---@param index integer function YimHeists:SetSecondaryTargets(type, index) - local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } local targets = { 0, 0, 0, 0 } targets[index] = -1 - for st = 1, #secondary_targets do + for st = 1, 4 do local stat_name = _F("MPX_H4LOOT_%s_%s", secondary_targets[st], type) stats.set_int(stat_name, targets[st]) stats.set_int(stat_name .. "_SCOPED", targets[st]) @@ -83,21 +84,19 @@ end ---@return integer, integer function YimHeists:GetSecondaryTargets() - local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } - local return_i - local return_c + local loot_i, loot_c - for st = 1, #secondary_targets do + for st = 1, 4 do local stat_name = _F("MPX_H4LOOT_%s", secondary_targets[st]) if (stats.get_int(stat_name .. "_I") == -1) then - return_i = st - 1 -- ImGui indexes by 0 + loot_i = st - 1 -- ImGui indexes by 0 end if (stats.get_int(stat_name .. "_C") == -1) then - return_c = st - 1 + loot_c = st - 1 end end - return return_i or -1, return_c or -1 + return loot_i or -1, loot_c or -1 end function YimHeists:ReadPropertyData() diff --git a/SSV2/includes/frontend/yhv1_ui.lua b/SSV2/includes/frontend/yhv1_ui.lua index d0ea353..2d235b5 100644 --- a/SSV2/includes/frontend/yhv1_ui.lua +++ b/SSV2/includes/frontend/yhv1_ui.lua @@ -9,7 +9,10 @@ local YHV1 = require("includes.features.YimHeistsV1"):init() local SGSL = require("includes.services.SGSL") -local setTranslations = require("includes.frontend.helpers.set_translations") +local setTranslations = require("SSV2.includes.frontend.helpers.set_translations") +local secondary_targets = { "Cash", "Weed", "Coke", "Gold" } +local cayo_secondary_target_i, cayo_secondary_target_c + local heistNames = { "AWT_1026", -- The Cluckin' Bell Farm Raid "AWT_1109", -- No Way KnoWay @@ -106,6 +109,7 @@ local function drawBasicTab() ImGui.EndDisabled() ImGui.BeginDisabled(is_done or on_cooldown) + ImGui.SameLine() if GUI:Button(_T("SY_COMPLETE_PREPARATIONS")) then YHV1:SkipPrep(heist.stat.name, heist.stat.val, heist_name) end @@ -116,7 +120,6 @@ local function drawBasicTab() end ImGui.EndDisabled() - ImGui.SameLine() local key = heist.stat.cooldown_gvar GVars.features.yim_heists[key], _ = GUI:CustomToggle(_T("CP_HEIST_COOLDOWN_DISABLE"), @@ -134,8 +137,6 @@ local function drawBasicTab() end end -local cayo_secondary_target_i, cayo_secondary_target_c = YHV1:GetSecondaryTargets() - local function drawCayoTab() local sub = YHV1:HasSubmarine() if (not sub) then @@ -218,29 +219,27 @@ local function drawCayoTab() ImGui.Spacing() - local secondary_targets = { "Cash", "Weed", "Coke", "Gold" } - local new_secondary_target_i, secondary_target_i_click = ImGui.Combo( - _T("YH_CAYO_TARGET_SECONDARY_I"), + local secondary_target_click + cayo_secondary_target_i, secondary_target_click = ImGui.Combo( + _T "YH_CAYO_TARGET_SECONDARY_I", cayo_secondary_target_i, secondary_targets, 4 ) - if (secondary_target_i_click) then - YHV1:SetSecondaryTargets("I", new_secondary_target_i + 1) - cayo_secondary_target_i = new_secondary_target_i + if (secondary_target_click) then + YHV1:SetSecondaryTargets("I", cayo_secondary_target_i + 1) end - local new_secondary_target_c, secondary_target_c_click = ImGui.Combo( - _T("YH_CAYO_TARGET_SECONDARY_C"), + cayo_secondary_target_c, secondary_target_click = ImGui.Combo( + _T "YH_CAYO_TARGET_SECONDARY_C", cayo_secondary_target_c, secondary_targets, 4 ) - if (secondary_target_c_click) then - YHV1:SetSecondaryTargets("C", new_secondary_target_c + 1) - cayo_secondary_target_c = new_secondary_target_c + if (secondary_target_click) then + YHV1:SetSecondaryTargets("C", cayo_secondary_target_c + 1) end ImGui.Spacing() @@ -321,6 +320,8 @@ local function HeistUI() return end + cayo_secondary_target_i, cayo_secondary_target_c = YHV1:GetSecondaryTargets() + if (ImGui.BeginTabBar("##funkBar")) then ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, 10, 10) diff --git a/SSV2/includes/lib/translations/en-US.lua b/SSV2/includes/lib/translations/en-US.lua index 1b8964e..c68eb49 100644 --- a/SSV2/includes/lib/translations/en-US.lua +++ b/SSV2/includes/lib/translations/en-US.lua @@ -731,8 +731,8 @@ return { ["YH_COOLDOWN_BYPASS_TOOLTIP"] = "Disables cooldown, may result in ban. Use at your own risk!", ["YH_CAYO_REQUEST_SUB"] = "Request Submarine", ["YH_CAYO_TARGET_PRIMARY"] = "Primary Target", - ["YH_CAYO_TARGET_SECONDARY_I"] = "Secondary Target (Island)", - ["YH_CAYO_TARGET_SECONDARY_C"] = "Secondary Target (Compound)", + ["YH_CAYO_TARGET_SECONDARY_I"] = "Secondary Targets (Island)", + ["YH_CAYO_TARGET_SECONDARY_C"] = "Secondary Targets (Compound)", ["YH_CAYO_TARGET_SECONDARY_BUTTON"] = "Set All Secondary Targets", ["YH_CAYO_DIFFICULTY"] = "Hard Mode", ["YH_CAYO_WEAPONS"] = "Weapon Loadout", From 5a13602df4f167bc68ee9c081ea211ffb569cd48 Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:28:33 -0500 Subject: [PATCH 2/6] feat(YHV1): Get sub location somewhat properly --- SSV2/includes/data/globals_locals.lua | 44 +++++++++++++++++-- SSV2/includes/data/yrv3_data.lua | 2 +- SSV2/includes/features/YimHeistsV1.lua | 61 ++++++++++++++------------ SSV2/includes/frontend/yhv1_ui.lua | 32 +++++--------- SSV2/includes/modules/Game.lua | 7 ++- 5 files changed, 93 insertions(+), 53 deletions(-) diff --git a/SSV2/includes/data/globals_locals.lua b/SSV2/includes/data/globals_locals.lua index e2a0c23..416aaae 100644 --- a/SSV2/includes/data/globals_locals.lua +++ b/SSV2/includes/data/globals_locals.lua @@ -894,17 +894,53 @@ return { } }, request_services_global = { - description = "Request Services Global.", - file = "am_prostitute.c", -- definitely the right file to use I'm sure of it + description = "Request Services Global. Only used for Kosatka atm, same global for all services.", + file = "am_mp_submarine.c", LEGACY = { value = 2733002, - pattern = [[Global_(\d{7})\.f_4 = 0;]], + pattern = [[return Global_(\d{7})\.f_371;]], capture_group = 1 }, ENHANCED = { value = 2733138, - pattern = [[Global_(\d{7})\.f_4 = 0;]], + pattern = [[return Global_(\d{7})\.f_371;]], capture_group = 1 } + }, + submarine_global = { + description = "Submarine Global", + file = "am_mp_submarine.c", + LEGACY = { + value = 2658291, + pattern = [[if \(NETWORK::NETWORK_DOES_NETWORK_ID_EXIST\(Global_(\d{7})\[.*?Param0 /\*(\d+)\*/\]\.(f_\d{2})\)\)]], + capture_group = 1, + offsets = { + { + value = 468, + capture_group = 2, + description = "playerID read size." + }, + { + value = 52, + capture_group = 3 + } + } + }, + ENHANCED = { + value = 2658294, + pattern = [[if \(NETWORK::NETWORK_DOES_NETWORK_ID_EXIST\(Global_(\d{7})\[.*?Param0 /\*(\d+)\*/\]\.(f_\d{2})\)\)]], + capture_group = 1, + offsets = { + { + value = 468, + capture_group = 2, + description = "playerID read size." + }, + { + value = 52, + capture_group = 3 + } + } + } } } diff --git a/SSV2/includes/data/yrv3_data.lua b/SSV2/includes/data/yrv3_data.lua index b442b50..eff47ce 100644 --- a/SSV2/includes/data/yrv3_data.lua +++ b/SSV2/includes/data/yrv3_data.lua @@ -608,7 +608,7 @@ local RawBusinessData = { { gxt = "HD_GARNAME", coords = vec3:new(719.3386, -983.1850, 24.1402) }, }, FieldHangar = { - { gxt = "FHAN_NME_1", coords = vec3:new(2150.65, 4796.60, 41.17) }, + { gxt = "FHAN_NME_1", coords = vec3:new(2152.74, 4791.05, 41.17) }, }, CashSafes = { regular = { diff --git a/SSV2/includes/features/YimHeistsV1.lua b/SSV2/includes/features/YimHeistsV1.lua index 23aa0e1..1f2ab0f 100644 --- a/SSV2/includes/features/YimHeistsV1.lua +++ b/SSV2/includes/features/YimHeistsV1.lua @@ -7,6 +7,7 @@ -- * Provide a copy of or a link to the original license (GPL-3.0 or later); see LICENSE.md or . +local SGSL = require("includes.services.SGSL") local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } ---@class HeistStat @@ -28,6 +29,7 @@ local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } ---@class AgencyProperty : GenericProperty ---@class FieldHangarProperty : GenericProperty ---@class SubmarineProperty : GenericProperty +---@field public heading float ---@alias HEIST_TYPES table @@ -35,8 +37,9 @@ local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } ---@field private m_raw_data RawBusinessData ---@field private m_properties { agency: AgencyProperty, hangar: FieldHangarProperty, submarine: SubmarineProperty } ---@field m_tab Tab -local YimHeists = { m_raw_data = require("includes.data.yrv3_data") } -YimHeists.__index = YimHeists +local YimHeists = { m_raw_data = require("includes.data.yrv3_data") } +YimHeists.__index = YimHeists +YimHeists.__label = "YimHeists" ---@return YimHeists function YimHeists:init() @@ -45,9 +48,7 @@ function YimHeists:init() }, self) if (Game.IsOnline()) then - ThreadManager:Run(function() - instance:ReadPropertyData() - end) + instance:ReadPropertyData() end Backend:RegisterEventCallback(Enums.eBackendEvent.SESSION_SWITCH, function() @@ -99,11 +100,22 @@ function YimHeists:GetSecondaryTargets() return loot_i or -1, loot_c or -1 end +---@return ScriptGlobal +local function GetSubCoordsGlobal() + local coords_global = SGSL:Get(SGSL.data.submarine_global) + local pid_size = coords_global:GetOffset(1) + local offset2 = coords_global:GetOffset(2) + local vec_offset = 286 -- magic + + return coords_global:AsGlobal() + :At(LocalPlayer:GetPlayerID(), pid_size) + :At(offset2) + :At(vec_offset) +end + function YimHeists:ReadPropertyData() ThreadManager:Run(function() - -- a better approach to this would be to read transition state. - -- I forgot how to do that so this will do. - while (script.is_active("maintransition")) do + while (Game.IsInTransition()) do yield() end @@ -132,13 +144,11 @@ function YimHeists:ReadPropertyData() local sub_hash = stats.get_int("MPX_IH_SUB_OWNED") if (sub_hash == _J("kosatka")) then + local global = GetSubCoordsGlobal() self.m_properties.submarine = { - name = Game.GetGXTLabel("CELL_SUBMARINE"), - -- TODO: I have no idea how to properly get the location of player Kosatka - -- - -- It's an index in some global which also has offsets to show if its currently requested or not - -- I attempted to do the same for the acid lab truck but quickly got irritated - coords = Game.Ensure3DCoords(760) or vec3:zero() + name = Game.GetGXTLabel("CELL_SUBMARINE"), + coords = global:ReadVec3(), + heading = global:At(3):ReadFloat() } end end) @@ -175,19 +185,16 @@ function YimHeists:GetFieldHangarLocation() end ---@return SubmarineProperty? -function YimHeists:HasSubmarine() - return self.m_properties.submarine -end - --- ---@return vec3? --- function YimHeists:GetSubmarineLocation() --- local sub = self:HasSubmarine() --- if (not sub) then --- return --- end +function YimHeists:GetSubmarine() + local sub = self.m_properties.submarine + if (not sub) then + return + end --- sub.coords = Game.Ensure3DCoords(760) --- return sub.coords --- end + local sub_global = GetSubCoordsGlobal() + sub.coords = sub_global:ReadVec3() + sub.heading = sub_global:At(3):ReadFloat() + return sub +end return YimHeists diff --git a/SSV2/includes/frontend/yhv1_ui.lua b/SSV2/includes/frontend/yhv1_ui.lua index 2d235b5..4cee76d 100644 --- a/SSV2/includes/frontend/yhv1_ui.lua +++ b/SSV2/includes/frontend/yhv1_ui.lua @@ -96,8 +96,8 @@ local function drawBasicTab() ImGui.PushID(i) GUI:HeaderText(heist_name, { separator = true, spacing = true }) - local location = heist.get_coords() or vec3:zero() - ImGui.BeginDisabled(location:is_zero() or on_cooldown) + local location = heist.get_coords() + ImGui.BeginDisabled(not location or on_cooldown) if (GUI:Button(_T("GENERIC_TELEPORT"))) then LocalPlayer:Teleport(location, false) end @@ -118,7 +118,6 @@ local function drawBasicTab() elseif (on_cooldown) then GUI:Tooltip(_F(_T("CP_COOLDOWN_BYPASS_STATUS_FORMAT"), seconds_left / 60)) end - ImGui.EndDisabled() local key = heist.stat.cooldown_gvar @@ -138,26 +137,21 @@ local function drawBasicTab() end local function drawCayoTab() - local sub = YHV1:HasSubmarine() + local sub = YHV1:GetSubmarine() if (not sub) then ImGui.Text(_T("YH_SUBMARINE_NOT_OWNED")) return end - -- This is shitty, and only properly works when not near the sub. No idea what happens if multiple subs in session - -- TODO: Find and use the correct globals/offsets - local sub_blip = Game.Ensure3DCoords(760) local request_kosatka = SGSL:Get(SGSL.data.request_services_global):AsGlobal():At(613) local sub_requested = request_kosatka:ReadInt() == 1 - local sub_spawned = not sub.coords:is_zero() and sub_blip ~= nil - - if (sub_blip or not sub_requested) then - sub.coords = sub_blip or vec3:zero() - end + local sub_spawned = not sub.coords:is_zero() ImGui.BeginDisabled(not sub_spawned) if (GUI:Button(_T("GENERIC_TELEPORT"))) then - LocalPlayer:Teleport(sub.coords + vec3:new(0, 0, -9.8)) -- Teleport under Kosatka + local forward_angle = math.rad(sub.heading + 90) + local offset = vec3:new(math.cos(forward_angle), math.sin(forward_angle), 4) -- front of door + LocalPlayer:Teleport(sub.coords + offset) end ImGui.SameLine() @@ -166,16 +160,14 @@ local function drawCayoTab() end ImGui.EndDisabled() - local btn_label = (sub_requested) - and ImGui.TextSpinner() - or _T("YH_CAYO_REQUEST_SUB") + local btn_label = (sub_requested) and ImGui.TextSpinner() or _T("YH_CAYO_REQUEST_SUB") - ImGui.SameLine() ImGui.BeginDisabled(sub_requested or sub_spawned) + ImGui.SameLine() if (GUI:Button(btn_label)) then ThreadManager:Run(function() if (not LocalPlayer:IsOutside()) then - Notifier:ShowError("YHV1", _T("GENERIC_TP_INTERIOR_ERR")) + Notifier:ShowError(YHV1.__label, _T("GENERIC_TP_INTERIOR_ERR")) return end @@ -302,7 +294,7 @@ local function drawCayoTab() stats.set_int("MPX_H4CNF_BS_ENTR", 0) stats.set_int("MPX_H4CNF_BS_GEN", 0) stats.set_int("MPX_H4CNF_BS_ABIL", 0) - Notifier:ShowSuccess("YHV1", "All progress has been reset!") + Notifier:ShowSuccess(YHV1.__label, "All Cayo progress has been reset!") end end @@ -338,7 +330,7 @@ local function HeistUI() end end -GUI:RegisterNewTab(Enums.eTabID.TAB_ONLINE, "YimHeists", HeistUI) +GUI:RegisterNewTab(Enums.eTabID.TAB_ONLINE, YHV1.__label, HeistUI) ThreadManager:Run(function() setTranslations(tabNames) diff --git a/SSV2/includes/modules/Game.lua b/SSV2/includes/modules/Game.lua index 8a33bf9..d04bb7b 100644 --- a/SSV2/includes/modules/Game.lua +++ b/SSV2/includes/modules/Game.lua @@ -104,9 +104,14 @@ function Game.IsEnhanced() return Backend:GetAPIVersion() == Enums.eAPIVersion.V2 end +---@return boolean +function Game.IsInTransition() + return NETWORK.NETWORK_IS_IN_TRANSITION() or Backend:IsPlayerSwitchInProgress() +end + ---@return boolean function Game.IsOnline() - return network.is_session_started() and not script.is_active("maintransition") + return network.is_session_started() and not Game.IsInTransition() end ---@param handle integer From 5f8ba4b8e996757ba8bda8bd3d8e1c9a61fa166c Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Tue, 24 Feb 2026 22:17:49 -0500 Subject: [PATCH 3/6] feat(YHV1): Add Doomsday skips Skip to ACT, bypass cooldown --- SSV2/includes/data/config.lua | 1 + SSV2/includes/data/yrv3_data.lua | 42 ++++++-- SSV2/includes/features/YimHeistsV1.lua | 29 +++++- .../frontend/helpers/set_translations.lua | 20 ---- SSV2/includes/frontend/yhv1_ui.lua | 99 +++++++++++++++++-- SSV2/includes/frontend/yrv3/yrv3_ui.lua | 3 +- SSV2/includes/lib/translations/en-US.lua | 10 +- SSV2/includes/services/Translator.lua | 20 ++++ 8 files changed, 179 insertions(+), 45 deletions(-) delete mode 100644 SSV2/includes/frontend/helpers/set_translations.lua diff --git a/SSV2/includes/data/config.lua b/SSV2/includes/data/config.lua index afc01d1..28bc584 100644 --- a/SSV2/includes/data/config.lua +++ b/SSV2/includes/data/config.lua @@ -282,6 +282,7 @@ local Config = { dre_cd = false, ogfa_cd = false, cayo_cd = false, + dday_cd = false, }, yrv3 = { autofill_delay = 500, diff --git a/SSV2/includes/data/yrv3_data.lua b/SSV2/includes/data/yrv3_data.lua index eff47ce..25977d0 100644 --- a/SSV2/includes/data/yrv3_data.lua +++ b/SSV2/includes/data/yrv3_data.lua @@ -315,6 +315,17 @@ local RawBusinessData = { end end }, + ["dday_cd"] = { + dirty = false, + gstate = function() + return GVars.features.yim_heists.dday_cd + end, + onEnable = function() + if (stats.get_int("MPX_GANGOPS_FLOW_MISSION_PROG") > 0) then + stats.set_int("MPX_GANGOPS_FLOW_MISSION_PROG", 0) + end + end + }, }, SellScripts = { ["gb_smuggler"] = { -- air @@ -515,17 +526,28 @@ local RawBusinessData = { [30] = { coords = vec3:new(-3030.341797, 3334.570068, 10.105902) }, [31] = { coords = vec3:new(-3156.140625, 1376.710693, 17.073570) }, }, + Facilities = { + { gxt = "MP_DBASE_1", coords = vec3:new(1273.1376, 2835.0068, 48.0734) }, -- freemode.c func_7238 + { gxt = "MP_DBASE_2", coords = vec3:new(34.4699, 2620.9768, 84.6202) }, + { gxt = "MP_DBASE_3", coords = vec3:new(2755.9807, 3907.2722, 44.3148) }, + { gxt = "MP_DBASE_4", coords = vec3:new(3389.6028, 5508.971, 24.875) }, + { gxt = "MP_DBASE_6", coords = vec3:new(19.4492, 6825.3613, 14.4952) }, + { gxt = "MP_DBASE_7", coords = vec3:new(-2229.408, 2395.4102, 12.0106) }, + { gxt = "MP_DBASE_8", coords = vec3:new(-3.0095, 3344.4888, 40.2769) }, + { gxt = "MP_DBASE_9", coords = vec3:new(2086.0674, 1761.3461, 103.043) }, + { gxt = "MP_DBASE_10", coords = vec3:new(1864.8027, 269.0474, 163.0169) }, + }, Nightclubs = { - { name = "", coords = vec3:new(757.009, -1332.32, 26.1802) }, -- am_mp_nightclub.c func_5118 // case 102: *uParam5 is main entrance corona coords - { name = "", coords = vec3:new(345.7519, -978.8848, 28.2681) }, - { name = "", coords = vec3:new(-120.906, -1260.49, 28.2088) }, - { name = "", coords = vec3:new(5.53709, 221.35, 106.6566) }, - { name = "", coords = vec3:new(871.47, -2099.57, 29.3768) }, - { name = "", coords = vec3:new(-675.225, -2459.15, 12.8444) }, - { name = "", coords = vec3:new(195.534, -3168.88, 4.7903) }, - { name = "", coords = vec3:new(373.05, 252.13, 101.9097) }, - { name = "", coords = vec3:new(-1283.38, -649.916, 25.5198) }, - { name = "", coords = vec3:new(-1174.85, -1152.3, 4.56128) }, + { coords = vec3:new(757.009, -1332.32, 26.1802) }, -- am_mp_nightclub.c func_5118 // case 102: *uParam5 is main entrance corona coords + { coords = vec3:new(345.7519, -978.8848, 28.2681) }, + { coords = vec3:new(-120.906, -1260.49, 28.2088) }, + { coords = vec3:new(5.53709, 221.35, 106.6566) }, + { coords = vec3:new(871.47, -2099.57, 29.3768) }, + { coords = vec3:new(-675.225, -2459.15, 12.8444) }, + { coords = vec3:new(195.534, -3168.88, 4.7903) }, + { coords = vec3:new(373.05, 252.13, 101.9097) }, + { coords = vec3:new(-1283.38, -649.916, 25.5198) }, + { coords = vec3:new(-1174.85, -1152.3, 4.56128) }, }, ---@alias BusinessHubs array<{ name: string, vpu_tunable: string, max_units_tunable: string, prod_time_tunable: string }> BusinessHubs = { diff --git a/SSV2/includes/features/YimHeistsV1.lua b/SSV2/includes/features/YimHeistsV1.lua index 1f2ab0f..f6a2c86 100644 --- a/SSV2/includes/features/YimHeistsV1.lua +++ b/SSV2/includes/features/YimHeistsV1.lua @@ -27,6 +27,7 @@ local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } ---@field public coords vec3 ---@class AgencyProperty : GenericProperty +---@class FacilityProperty : GenericProperty ---@class FieldHangarProperty : GenericProperty ---@class SubmarineProperty : GenericProperty ---@field public heading float @@ -35,7 +36,7 @@ local secondary_targets = { "CASH", "WEED", "COKE", "GOLD" } ---@class YimHeists ---@field private m_raw_data RawBusinessData ----@field private m_properties { agency: AgencyProperty, hangar: FieldHangarProperty, submarine: SubmarineProperty } +---@field private m_properties { agency: AgencyProperty, hangar: FieldHangarProperty, facility: FacilityProperty, submarine: SubmarineProperty } ---@field m_tab Tab local YimHeists = { m_raw_data = require("includes.data.yrv3_data") } YimHeists.__index = YimHeists @@ -134,7 +135,7 @@ function YimHeists:ReadPropertyData() end local hangar_idx = stats.get_int("MPX_MCKENZIE_HANGAR_OWNED") - if (YRV3:IsPropertyIndexValid(hangar_idx)) then + if (hangar_idx > 0) then local hangar_ref = self.m_raw_data.FieldHangar[1] self.m_properties.hangar = { name = Game.GetGXTLabel(hangar_ref.gxt), @@ -142,6 +143,15 @@ function YimHeists:ReadPropertyData() } end + local facility_idx = stats.get_int("MPX_DBASE_OWNED") + if (facility_idx > 0) then + local facility_ref = self.m_raw_data.Facilities[facility_idx] + self.m_properties.facility = { + name = Game.GetGXTLabel(facility_ref.gxt), + coords = facility_ref.coords + } + end + local sub_hash = stats.get_int("MPX_IH_SUB_OWNED") if (sub_hash == _J("kosatka")) then local global = GetSubCoordsGlobal() @@ -184,6 +194,21 @@ function YimHeists:GetFieldHangarLocation() return hangar.coords end +---@return FacilityProperty? +function YimHeists:GetFacilityProperty() + return self.m_properties.facility +end + +---@return vec3? +function YimHeists:GetFacilityLocation() + local facility = self:GetFacilityProperty() + if (not facility) then + return + end + + return facility.coords +end + ---@return SubmarineProperty? function YimHeists:GetSubmarine() local sub = self.m_properties.submarine diff --git a/SSV2/includes/frontend/helpers/set_translations.lua b/SSV2/includes/frontend/helpers/set_translations.lua deleted file mode 100644 index e9718af..0000000 --- a/SSV2/includes/frontend/helpers/set_translations.lua +++ /dev/null @@ -1,20 +0,0 @@ --- Copyright (C) 2026 SAMURAI (xesdoog) & Contributors. --- This file is part of Samurai's Scripts. --- --- Permission is hereby granted to copy, modify, and redistribute --- this code as long as you respect these conditions: --- * Credit the owner and contributors. --- * Provide a copy of or a link to the original license (GPL-3.0 or later); see LICENSE.md or . - ----@param labels array -return function(labels) - for i = 1, #labels do - local label = labels[i] - local GXT = Game.GetGXTLabel(label) - if (string.isvalid(GXT) and GXT ~= "NULL") then - labels[i] = GXT -- get label from the game. - else - labels[i] = _T(label) -- no GXT; use our own translations - end - end -end diff --git a/SSV2/includes/frontend/yhv1_ui.lua b/SSV2/includes/frontend/yhv1_ui.lua index 4cee76d..8daaa0f 100644 --- a/SSV2/includes/frontend/yhv1_ui.lua +++ b/SSV2/includes/frontend/yhv1_ui.lua @@ -9,7 +9,6 @@ local YHV1 = require("includes.features.YimHeistsV1"):init() local SGSL = require("includes.services.SGSL") -local setTranslations = require("SSV2.includes.frontend.helpers.set_translations") local secondary_targets = { "Cash", "Weed", "Coke", "Gold" } local cayo_secondary_target_i, cayo_secondary_target_c @@ -22,6 +21,7 @@ local heistNames = { local tabNames = { "YH_BASIC_TAB", -- Basic "ISLAND_TRAVEL_T", -- Cayo Perico + "FMMC_RSTAR_MHS2", -- The Doomsday Heist } ---@type HEIST_TYPES @@ -121,7 +121,8 @@ local function drawBasicTab() ImGui.EndDisabled() local key = heist.stat.cooldown_gvar - GVars.features.yim_heists[key], _ = GUI:CustomToggle(_T("CP_HEIST_COOLDOWN_DISABLE"), + GVars.features.yim_heists[key], _ = GUI:CustomToggle( + _T("CP_HEIST_COOLDOWN_DISABLE"), GVars.features.yim_heists[key], { tooltip = _T("YH_COOLDOWN_BYPASS_TOOLTIP"), color = Color("#AA0000"), @@ -249,14 +250,15 @@ local function drawCayoTab() GUI:HeaderText(_T("GENERIC_OPTIONS_LABEL"), { separator = true, spacing = true }) - -- I'll also need to find which bits actually correspond to hard mode instead of just hard coding values and this stupid check; Bits 4, 8, 13 is the difference - local new_difficulty, difficulty_toggled = GUI:CustomToggle(_T("YH_CAYO_DIFFICULTY"), - cayo_heist_difficulty > 130000 + local new_difficulty, difficulty_toggled = GUI:CustomToggle( + _T("YH_CAYO_DIFFICULTY"), + Bit.IsBitSet(cayo_heist_difficulty, 12) ) if (difficulty_toggled) then + -- Idk what bits 3 and 7 do if (new_difficulty) then - stats.set_int("MPX_H4_PROGRESS", 131055) + stats.set_int("MPX_H4_PROGRESS", 131055) -- 126823 | 3 7 12 else stats.set_int("MPX_H4_PROGRESS", 126823) end @@ -275,7 +277,10 @@ local function drawCayoTab() stats.set_int("MPX_H4_PLAYTHROUGH_STATUS", 40000) end - GVars.features.yim_heists.cayo_cd, _ = GUI:CustomToggle(_T("CP_HEIST_COOLDOWN_DISABLE"), + ImGui.EndDisabled() -- on_cooldown + + GVars.features.yim_heists.cayo_cd, _ = GUI:CustomToggle( + _T("CP_HEIST_COOLDOWN_DISABLE"), GVars.features.yim_heists.cayo_cd, { tooltip = _T("YH_COOLDOWN_BYPASS_TOOLTIP"), color = Color("#AA0000"), @@ -297,13 +302,89 @@ local function drawCayoTab() Notifier:ShowSuccess(YHV1.__label, "All Cayo progress has been reset!") end end +end + +-- Help text and values copied from: https://www.unknowncheats.me/forum/grand-theft-auto-v/431801-cayo-perico-heist-click.html +local function drawDDayTab() + local facility = YHV1:GetFacilityProperty() + if (not facility) then + ImGui.Text(_T("YH_FACILITY_NOT_OWNED")) + return + end + + if (GUI:Button(_T("YH_TP_FACILITY"))) then + LocalPlayer:Teleport(facility.coords) + end + + ImGui.SameLine() + if (GUI:Button(_T("GENERIC_SET_WAYPOINT"))) then + Game.SetWaypointCoords(facility.coords) + end + + local dday_status = stats.get_int("MPX_GANGOPS_HEIST_STATUS") + local dday_cooldown = stats.get_int("MPX_GANGOPS_LAUNCH_TIME") + + local posix_now = Time.Epoch() + local cooldown_seconds_left = dday_cooldown - posix_now + local on_cooldown = cooldown_seconds_left > 0 + + if (on_cooldown) then + local minutes_left = cooldown_seconds_left / 60 + GUI:HeaderText(_F(_T("CP_COOLDOWN_BYPASS_STATUS_FORMAT"), minutes_left), + { separator = false, spacing = true, color = Color("#AA0000") }) + end + ImGui.BeginDisabled(on_cooldown) + GUI:HeaderText(_T("GENERIC_IMPORTANT"), { separator = true, spacing = true }) + ImGui.Text(_T("YH_DDAY_HELP1")) + local button_label = _T("YH_DDAY_FORCE") + if (GUI:Button(button_label)) then + stats.set_int("MPX_GANGOPS_HEIST_STATUS", 9999) + end + ImGui.Text(_F(_T("YH_DDAY_HELP2_FMT"), button_label)) + + GUI:HeaderText(_T("CP_HEIST_SETUP"), { separator = true, spacing = true }) + -- Final ACT 1 + ImGui.BeginDisabled(dday_status == 229383) + if (GUI:Button(Game.GetGXTLabel("HPSTRAND_IAAb"))) then -- The Data Breaches + stats.set_int("MPX_GANGOPS_FLOW_MISSION_PROG", 503) + stats.set_int("MPX_GANGOPS_HEIST_STATUS", 229383) + stats.set_int("MPX_GANGOPS_FLOW_NOTIFICATIONS", 1557) + end + ImGui.EndDisabled() + -- Final ACT 2 + ImGui.SameLine() + ImGui.BeginDisabled(dday_status == 229378) + if (GUI:Button(Game.GetGXTLabel("HPSTRAND_SUBb"))) then -- The Bogdan Problem + stats.set_int("MPX_GANGOPS_FLOW_MISSION_PROG", 240) + stats.set_int("MPX_GANGOPS_HEIST_STATUS", 229378) + stats.set_int("MPX_GANGOPS_FLOW_NOTIFICATIONS", 1557) + end + ImGui.EndDisabled() + -- Final ACT 3 + ImGui.BeginDisabled(dday_status == 229380) + if (GUI:Button(Game.GetGXTLabel("HPSTRAND_MSILb"))) then -- The Doomsday Scenario + stats.set_int("MPX_GANGOPS_FLOW_MISSION_PROG", 16368) + stats.set_int("MPX_GANGOPS_HEIST_STATUS", 229380) + stats.set_int("MPX_GANGOPS_FLOW_NOTIFICATIONS", 1557) + end + ImGui.EndDisabled() ImGui.EndDisabled() -- on_cooldown + + GVars.features.yim_heists.dday_cd, _ = GUI:CustomToggle(_T("CP_HEIST_COOLDOWN_DISABLE"), + GVars.features.yim_heists.dday_cd, { + tooltip = _T("YH_COOLDOWN_BYPASS_TOOLTIP"), + color = Color("#AA0000"), + onClick = function() + YRV3:SetCooldownStateDirty("dday_cd", true) + end + }) end local tabCallbacks = { drawBasicTab, drawCayoTab, + drawDDayTab, } local function HeistUI() @@ -333,6 +414,6 @@ end GUI:RegisterNewTab(Enums.eTabID.TAB_ONLINE, YHV1.__label, HeistUI) ThreadManager:Run(function() - setTranslations(tabNames) - setTranslations(heistNames) + Translator:TranslateGXTList(tabNames) + Translator:TranslateGXTList(heistNames) end) diff --git a/SSV2/includes/frontend/yrv3/yrv3_ui.lua b/SSV2/includes/frontend/yrv3/yrv3_ui.lua index cbf22be..eac70a0 100644 --- a/SSV2/includes/frontend/yrv3/yrv3_ui.lua +++ b/SSV2/includes/frontend/yrv3/yrv3_ui.lua @@ -9,7 +9,6 @@ local selectedTabID = 1 local colMoneyGreen = Color("#85BB65") -local setTranslations = require("includes.frontend.helpers.set_translations") local tabNames = { "GB_BOSSC", "CELL_HANGAR", @@ -136,5 +135,5 @@ end GUI:RegisterNewTab(Enums.eTabID.TAB_ONLINE, "YimResupplierV3", YRV3UI) ThreadManager:Run(function() - setTranslations(tabNames) + Translator:TranslateGXTList(tabNames) end) diff --git a/SSV2/includes/lib/translations/en-US.lua b/SSV2/includes/lib/translations/en-US.lua index c68eb49..54ba8b6 100644 --- a/SSV2/includes/lib/translations/en-US.lua +++ b/SSV2/includes/lib/translations/en-US.lua @@ -725,10 +725,9 @@ return { --#region YimHeists ["YH_BASIC_TAB"] = "Basic", - ["YH_CAYO_TAB"] = "Cayo Perico", - ["YH_SUBMARINE_NOT_OWNED"] = "Purchase a Kosatka to access the Cayo Perico Heist.", -- HIF_SUB_HELP ["YH_PREP_SKIP_NOTIF"] = "All preparation missions have been skipped. You can now start the final mission.", ["YH_COOLDOWN_BYPASS_TOOLTIP"] = "Disables cooldown, may result in ban. Use at your own risk!", + ["YH_SUBMARINE_NOT_OWNED"] = "Purchase a Kosatka to access the Cayo Perico Heist.", -- HIF_SUB_HELP ["YH_CAYO_REQUEST_SUB"] = "Request Submarine", ["YH_CAYO_TARGET_PRIMARY"] = "Primary Target", ["YH_CAYO_TARGET_SECONDARY_I"] = "Secondary Targets (Island)", @@ -737,5 +736,12 @@ return { ["YH_CAYO_DIFFICULTY"] = "Hard Mode", ["YH_CAYO_WEAPONS"] = "Weapon Loadout", ["YH_CAYO_RESET_ALL"] = "Reset ALL Progress", + ["YH_FACILITY_NOT_OWNED"] = "Purchase a Facility to access The Doomsday Heist.", -- GOPS_BASE_HELP + ["YH_TP_FACILITY"] = "Teleport to Facility", + ["YH_DDAY_FORCE"] = "FORCE ENABLE", + ["YH_DDAY_HELP1"] = + "This method is necessary if you have never played Doomsday as a host. If you have already played and completed some heists as host, skip this step.", + ["YH_DDAY_HELP2_FMT"] = + "Press the '%s' button, then call Lester to cancel all 3 heists for Doomsday.", --#endregion } diff --git a/SSV2/includes/services/Translator.lua b/SSV2/includes/services/Translator.lua index 0e0e089..6cd38cc 100644 --- a/SSV2/includes/services/Translator.lua +++ b/SSV2/includes/services/Translator.lua @@ -124,3 +124,23 @@ end function _T(label) return Translator:Translate(label) end + +-- Translates text using GXTs if expected and available. +---@param label string +---@return string +function Translator:TranslateGXT(label) + local GXT = Game.GetGXTLabel(label) + if (string.isvalid(GXT) and GXT ~= "NULL") then + return GXT -- get label from the game. + else + return _T(label) -- no GXT; use our own translations + end +end + +---@param labels array +function Translator:TranslateGXTList(labels) + for i = 1, #labels do + local label = labels[i] + labels[i] = self:TranslateGXT(label) + end +end From cd3add0acadc4131ea39f341ec9be8b6e44a64c3 Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:32:50 -0500 Subject: [PATCH 4/6] feat(YHV1): Enable KW teleport to blip --- SSV2/includes/features/YimHeistsV1.lua | 14 ++++++++++++++ SSV2/includes/frontend/yhv1_ui.lua | 17 ++++++++++++++--- SSV2/includes/lib/translations/en-US.lua | 2 +- SSV2/includes/modules/LocalPlayer.lua | 4 ++++ 4 files changed, 33 insertions(+), 4 deletions(-) diff --git a/SSV2/includes/features/YimHeistsV1.lua b/SSV2/includes/features/YimHeistsV1.lua index f6a2c86..9002d01 100644 --- a/SSV2/includes/features/YimHeistsV1.lua +++ b/SSV2/includes/features/YimHeistsV1.lua @@ -164,6 +164,20 @@ function YimHeists:ReadPropertyData() end) end +---@return vec3 +function YimHeists:GetAviLocation() + local stat = stats.get_int("MPX_M25_AVI_MISSION_CURRENT") + local blip = HUD.GET_FIRST_BLIP_INFO_ID(76) + if (blip and stat ~= 4) then + local blip_coords = HUD.GET_BLIP_INFO_ID_COORD(blip) + local forward_angle = math.rad(HUD.GET_BLIP_ROTATION(blip) + 90) + local offset = vec3:new(math.cos(forward_angle), math.sin(forward_angle), 0) -- front of payphone + return blip_coords + offset + end + + return vec3:new(42.82, -1599.19, 29.60) -- final payphone +end + ---@return AgencyProperty? function YimHeists:GetAgencyProperty() return self.m_properties.agency diff --git a/SSV2/includes/frontend/yhv1_ui.lua b/SSV2/includes/frontend/yhv1_ui.lua index 8daaa0f..6b7599b 100644 --- a/SSV2/includes/frontend/yhv1_ui.lua +++ b/SSV2/includes/frontend/yhv1_ui.lua @@ -12,11 +12,17 @@ local SGSL = require("includes.services.SGSL") local secondary_targets = { "Cash", "Weed", "Coke", "Gold" } local cayo_secondary_target_i, cayo_secondary_target_c +-- https://github.com/root-cause/v-labels/blob/master/labels.json local heistNames = { "AWT_1026", -- The Cluckin' Bell Farm Raid - "AWT_1109", -- No Way KnoWay + "DLCC_AVIM", -- KnoWay Out "AWT_973", -- Don't Fuck With Dre "HACK24_MFM_STR", -- Oscar Guzman Flies Again + "HTITLE_TUT", -- The Fleeca Job + "HTITLE_PRISON", -- The Prison Break + "HTITLE_HUMANE", -- The Humane Labs Raid + "HTITLE_NARC", -- Series A Funding + "HTITLE_ORNATE", -- The Pacific Standard Job } local tabNames = { "YH_BASIC_TAB", -- Basic @@ -45,7 +51,7 @@ local HEIST_TYPES = { return heistNames[2] end, get_coords = function() - return vec3:new(42.82, -1599.19, 29.60) + return YHV1:GetAviLocation() end, stat = { name = "MPX_M25_AVI_MISSION_CURRENT", @@ -130,7 +136,6 @@ local function drawBasicTab() YRV3:SetCooldownStateDirty(key, true) end }) - ImGui.PopID() ImGui.Spacing() @@ -381,6 +386,12 @@ local function drawDDayTab() }) end +-- Maybe port https://github.com/YimMenu/YimMenuV2/blob/enhanced/src/game/features/recovery/Heist/ApartmentHeist.cpp ? +-- Apartment heists actually seem complicated in that (I assume) since they're old they use a different method of storing progress as there isn't just 1 stat to check like all the others +-- Or if there is, there only *was* because no stats I've found seem to do anything today, like the stat from that link right there. Doesn't do anything, am I missing something? +local function drawAptTab() +end + local tabCallbacks = { drawBasicTab, drawCayoTab, diff --git a/SSV2/includes/lib/translations/en-US.lua b/SSV2/includes/lib/translations/en-US.lua index 54ba8b6..678a452 100644 --- a/SSV2/includes/lib/translations/en-US.lua +++ b/SSV2/includes/lib/translations/en-US.lua @@ -738,7 +738,7 @@ return { ["YH_CAYO_RESET_ALL"] = "Reset ALL Progress", ["YH_FACILITY_NOT_OWNED"] = "Purchase a Facility to access The Doomsday Heist.", -- GOPS_BASE_HELP ["YH_TP_FACILITY"] = "Teleport to Facility", - ["YH_DDAY_FORCE"] = "FORCE ENABLE", + ["YH_DDAY_FORCE"] = "FORCE RESET", ["YH_DDAY_HELP1"] = "This method is necessary if you have never played Doomsday as a host. If you have already played and completed some heists as host, skip this step.", ["YH_DDAY_HELP2_FMT"] = diff --git a/SSV2/includes/modules/LocalPlayer.lua b/SSV2/includes/modules/LocalPlayer.lua index a75c57b..76ed708 100644 --- a/SSV2/includes/modules/LocalPlayer.lua +++ b/SSV2/includes/modules/LocalPlayer.lua @@ -489,6 +489,10 @@ function LocalPlayer:Reset() self:Destroy() end +function LocalPlayer.ForceCloudSave() + STATS.STAT_SAVE(0, 0, 3, 0) +end + Backend:RegisterEventCallbackAll(function() LocalPlayer:Reset() end) From 1ad4b0111a90d847f03a42a09cde82a9138f8bd9 Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Wed, 25 Feb 2026 01:35:31 -0500 Subject: [PATCH 5/6] docs(Features): Update YimHeists section --- docs/Features.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/Features.md b/docs/Features.md index c4aef96..2ade88c 100644 --- a/docs/Features.md +++ b/docs/Features.md @@ -361,6 +361,31 @@ An updated and slightly refactored version of [Casino Pacino](https://github.com A heist editor added by [@How-Bout-No](https://github.com/How-Bout-No) [WIP]. +Contains the following modules: + +- **Basic** + + Options for Teleport, Set Waypoint, Skip Preps, and Disable Cooldowns on: + - Cluckin Bell + - KnoWay + - Dr Dre Contract + - Oscar Guzman + +- **Cayo Perico** + + Options for Teleport, Set Waypoint, and Request Submarine. + + Ability to change Primary Target, all Secondary Targets on the island and inside the compound, Weapon Loadout, Hard Mode, Unlock All Heist Options *(Approach Vehicles, Disruptions, etc)*, Disable Cooldown + +- **Doomsday** + + Options for Teleport and Set Waypoint to Facility. + + Skip all Preps/Setups and Disable Cooldowns on all 3 Acts (your choice): + 1. The Data Breaches + 2. The Bogdan Problem + 3. The Doomsday Scenario + ## Extra ### YimActionsV3 From c02b2fd01041c07b8546466516f4c97675c9832f Mon Sep 17 00:00:00 2001 From: How-Bout-No <10456231+How-Bout-No@users.noreply.github.com> Date: Wed, 25 Feb 2026 10:38:36 -0500 Subject: [PATCH 6/6] fix: Small corrections --- SSV2/includes/data/yrv3_data.lua | 4 ++-- SSV2/includes/services/Translator.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/SSV2/includes/data/yrv3_data.lua b/SSV2/includes/data/yrv3_data.lua index 25977d0..3e09fb7 100644 --- a/SSV2/includes/data/yrv3_data.lua +++ b/SSV2/includes/data/yrv3_data.lua @@ -321,8 +321,8 @@ local RawBusinessData = { return GVars.features.yim_heists.dday_cd end, onEnable = function() - if (stats.get_int("MPX_GANGOPS_FLOW_MISSION_PROG") > 0) then - stats.set_int("MPX_GANGOPS_FLOW_MISSION_PROG", 0) + if (stats.get_int("MPX_GANGOPS_LAUNCH_TIME") > 0) then + stats.set_int("MPX_GANGOPS_LAUNCH_TIME", 0) end end }, diff --git a/SSV2/includes/services/Translator.lua b/SSV2/includes/services/Translator.lua index 6cd38cc..0c3ed79 100644 --- a/SSV2/includes/services/Translator.lua +++ b/SSV2/includes/services/Translator.lua @@ -133,7 +133,7 @@ function Translator:TranslateGXT(label) if (string.isvalid(GXT) and GXT ~= "NULL") then return GXT -- get label from the game. else - return _T(label) -- no GXT; use our own translations + return self:Translate(label) -- no GXT; use our own translations end end