diff --git a/.github/workflows/zip-release.yml b/.github/workflows/zip-release.yml index ee9c969..ba62471 100644 --- a/.github/workflows/zip-release.yml +++ b/.github/workflows/zip-release.yml @@ -123,10 +123,10 @@ jobs: changelog += `## PR #${pr.number}: ${pr.title}\n`; const body = pr.body if (body) { - const lines = body.split('\n').map(line => line.trim().replace(/^-\s*/, '')); + const lines = body.split('\n').map(line => line.trim()); for (const line of lines) { if (line) - changelog += `- ${line}\n`; + changelog += `${line}\n`; } changelog += "\n"; } diff --git a/README.md b/README.md index 0223bec..899c7f8 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,26 @@ +
+ Table of Contents +
    +
  1. About
  2. +
  3. + Getting Started + +
  4. +
  5. Contributing
  6. +
  7. Documentation
  8. +
  9. Features
  10. +
  11. FAQ
  12. +
  13. Contact
  14. +
  15. Acknowledgments
  16. +
+
+ # About ![ss](./docs/ss.png) @@ -72,6 +92,10 @@ This project was rewritten from scratch using [SmallBase](https://github.com/xes > Some parts of the API were refactored or extended but nothing has drastically changed. > All changes introduced in this project are documented in the source. +## Features + +A full list of available features and their usage [can be found here](docs/Features.md). + ## FAQ - **Q:** Does this support Enhanced? @@ -91,6 +115,14 @@ This project was rewritten from scratch using [SmallBase](https://github.com/xes - **Short Answer:** No. - **Long Answer:** Yes, a compatibility layer can be added to accomodate for all language and API differences but is it worth the trouble and code bloat? Absolutely not. We would be better off rewriting this for V2's API. +## Contact + +
+ + Discord + +
+ ## Acknowledgments | Name | Contribution | @@ -104,11 +136,3 @@ This project was rewritten from scratch using [SmallBase](https://github.com/xes | DurtyFree
Alexander Schmid
| [GTA V data dumps](https://github.com/DurtyFree/gta-v-data-dumps) | | Yimura
Andreas Maerten
| GTA V classes (archived/removed) | | UC
UnknownCheats
| A treasure trove of information | - -## Contact - -
- - Discord - -
diff --git a/SSV2/includes/classes/Mutex.lua b/SSV2/includes/classes/Mutex.lua new file mode 100644 index 0000000..f207a50 --- /dev/null +++ b/SSV2/includes/classes/Mutex.lua @@ -0,0 +1,49 @@ +-------------------------------------- +-- Class: Mutex +-------------------------------------- +-- Simple mutual exclusion. +---@class Mutex +---@field protected m_locked boolean +---@overload fun(): Mutex +local Mutex = {} +Mutex.__index = Mutex +---@diagnostic disable-next-line +setmetatable(Mutex, { + __call = function(_) + return Mutex.new() + end +}) + +---@return Mutex +function Mutex.new() + ---@diagnostic disable-next-line + return setmetatable({ m_locked = false }, Mutex) +end + +function Mutex:Acquire() + while (self.m_locked) do + yield() + end + + self.m_locked = true +end + +function Mutex:Release() + self.m_locked = false +end + +-- Scoped lock. +---@param func function +---@param ... any +---@return ... +function Mutex:WithLock(func, ...) + self:Acquire() + local ret = { xpcall(func, function(msg) + self:Release() + error(msg) + end, ...) } + self:Release() + return table.unpack(ret) +end + +return Mutex diff --git a/SSV2/includes/features/vehicle/stancer.lua b/SSV2/includes/features/vehicle/stancer.lua index df0de64..5c856bb 100644 --- a/SSV2/includes/features/vehicle/stancer.lua +++ b/SSV2/includes/features/vehicle/stancer.lua @@ -285,11 +285,11 @@ function Stancer:ForEach(array, fn) end function Stancer:IsVehicleModelSaved() - if (not self.m_cached_model) then + if (not self.m_entity or not self.m_entity:IsValid()) then return false end - return GVars.features.vehicle.stancer.saved_models[tostring(self.m_cached_model)] ~= nil + return GVars.features.vehicle.stancer.saved_models[tostring(self.m_entity:GetModelHash())] ~= nil end function Stancer:ReadWheelArray() @@ -413,7 +413,7 @@ function Stancer:AreSavedDeltasLoaded() return false end - local model = tostring(self.m_cached_model or self.m_entity:GetModelHash()) + local model = tostring(self.m_entity:GetModelHash()) local saved = GVars.features.vehicle.stancer.saved_models local front_obj = saved[model][tostring(self.eWheelSide.FRONT)] local rear_obj = saved[model][tostring(self.eWheelSide.BACK)] @@ -471,45 +471,36 @@ function Stancer:LoadSavedDeltas() return false end - local model = tostring(self.m_cached_model or self.m_entity:GetModelHash()) + local model = tostring(self.m_entity:GetModelHash()) local saved = GVars.features.vehicle.stancer.saved_models - local front_obj = saved[model][tostring(self.eWheelSide.FRONT)] - local rear_obj = saved[model][tostring(self.eWheelSide.BACK)] + local front_obj = saved[model][self.eWheelSide.FRONT] + local rear_obj = saved[model][self.eWheelSide.BACK] - if (not front_obj or not rear_obj or next(front_obj) == nil or next(rear_obj) == nil) then + if (not front_obj or not rear_obj) then return false end for k, v in pairs(front_obj) do - self.m_deltas[self.eWheelSide.FRONT][k] = v + if (k == "m_suspension_height") then + self.m_suspension_height.m_current = v + else + self.m_deltas[self.eWheelSide.FRONT][k] = v + end end for k, v in pairs(rear_obj) do self.m_deltas[self.eWheelSide.BACK][k] = v end - self.m_suspension_height.m_current = saved[model]["m_suspension_height"] or 0.0 - + PHYSICS.ACTIVATE_PHYSICS(self.m_entity:GetHandle()) return true end function Stancer:SaveCurrentVehicle() - local model = self.m_cached_model or self.m_entity:GetModelHash() - local __t = { - [self.eWheelSide.FRONT] = StanceObject.new(), - [self.eWheelSide.BACK] = StanceObject.new(), - m_suspension_height = self.m_suspension_height.m_current - } - - for k, v in pairs(self.m_deltas[self.eWheelSide.FRONT]) do - __t[self.eWheelSide.FRONT][k] = v - end - - for k, v in pairs(self.m_deltas[self.eWheelSide.BACK]) do - __t[self.eWheelSide.BACK][k] = v - end - - GVars.features.vehicle.stancer.saved_models[tostring(model)] = table.copy(__t) + local strModel = tostring(self.m_entity:GetModelHash()) + local saved = GVars.features.vehicle.stancer.saved_models + saved[strModel] = table.copy(self.m_deltas) + saved[strModel][self.eWheelSide.FRONT]["m_suspension_height"] = self.m_suspension_height.m_current end ---@return boolean diff --git a/SSV2/includes/frontend/settings/settings_ui.lua b/SSV2/includes/frontend/settings/settings_ui.lua index da8abfd..4057df2 100644 --- a/SSV2/includes/frontend/settings/settings_ui.lua +++ b/SSV2/includes/frontend/settings/settings_ui.lua @@ -7,13 +7,12 @@ local draw_cfg_reset_window = false ---@type Set local cfg_reset_exceptions = Set.new("backend.debug_mode") local cfg_exc_keys = { - { pair = Pair.new("YimActions Favorites", "features.yim_actions.favorites"), clicked = false, selected = false }, - { pair = Pair.new("YimResupplier", "features.yrv3"), clicked = false, selected = false }, - { pair = Pair.new("Casino Pacino", "features.dunk"), clicked = false, selected = false }, - { pair = Pair.new("Keyboard Keybinds", "keyboard_keybinds"), clicked = false, selected = false }, - { pair = Pair.new("Controller Keybinds", "gamepad_keybinds"), clicked = false, selected = false }, - { pair = Pair.new("EntityForge Favorites", "features.entity_forge.favorites"), clicked = false, selected = false }, - { pair = Pair.new("EntityForge Creations", "features.entity_forge.forged_entities"), clicked = false, selected = false }, + { pair = Pair.new("Casino Pacino", "features.dunk"), clicked = false, selected = false }, + { pair = Pair.new("EntityForge", "features.entity_forge"), clicked = false, selected = false }, + { pair = Pair.new("YimActions", "features.yim_actions"), clicked = false, selected = false }, + { pair = Pair.new("YimResupplier", "features.yrv3"), clicked = false, selected = false }, + { pair = Pair.new("Controller Keybinds", "gamepad_keybinds"), clicked = false, selected = false }, + { pair = Pair.new("Keyboard Keybinds", "keyboard_keybinds"), clicked = false, selected = false }, } local function OnConfigReset() diff --git a/SSV2/includes/frontend/vehicle/stancer_ui.lua b/SSV2/includes/frontend/vehicle/stancer_ui.lua index 511439d..18527da 100644 --- a/SSV2/includes/frontend/vehicle/stancer_ui.lua +++ b/SSV2/includes/frontend/vehicle/stancer_ui.lua @@ -273,21 +273,23 @@ return function() local saved_models = GVars.features.vehicle.stancer.saved_models if (next(saved_models) ~= nil) then + ImGui.SameLine() + if (GUI:Button(_T("VEH_STANCE_VIEW_SAVED"))) then + saved_vehs_window.should_draw = true + end + + ImGui.SameLine() GVars.features.vehicle.stancer.auto_apply_saved, auto_apply_clicked = GUI:Checkbox( _T("VEH_STANCE_AUTOAPPLY"), GVars.features.vehicle.stancer.auto_apply_saved, { tooltip = _T("VEH_STANCE_AUTOAPPLY_TT") } ) - if (GVars.features.vehicle.stancer.auto_apply_saved and auto_apply_clicked) then + if (auto_apply_clicked and GVars.features.vehicle.stancer.auto_apply_saved) then ThreadManager:Run(function() Stancer:LoadSavedDeltas() end) end - - if (GUI:Button(_T("VEH_STANCE_VIEW_SAVED"))) then - saved_vehs_window.should_draw = true - end end if (saved_vehs_window.should_draw) then @@ -323,9 +325,8 @@ return function() end if (GUI:ConfirmPopup("##confirm_remove_all")) then - Serializer:WithLock(function() - GVars.features.vehicle.stancer.saved_models = {} - end) + GVars.features.vehicle.stancer.saved_models = {} + saved_vehs_window.should_draw = false end end, function() saved_vehs_window.should_draw = false diff --git a/SSV2/includes/frontend/vehicle/vehicle_ui.lua b/SSV2/includes/frontend/vehicle/vehicle_ui.lua index 0d33c1e..a805592 100644 --- a/SSV2/includes/frontend/vehicle/vehicle_ui.lua +++ b/SSV2/includes/frontend/vehicle/vehicle_ui.lua @@ -113,7 +113,9 @@ local function driftOptions() } ) - ImGui.ColorEditVec3(_T("VEH_DRIFT_SMOKE_COL"), GVars.features.vehicle.drift.smoke_fx.color) + if (GVars.features.vehicle.drift.smoke_fx.enabled) then + ImGui.ColorEditVec3(_T("VEH_DRIFT_SMOKE_COL"), GVars.features.vehicle.drift.smoke_fx.color) + end end local function driftMinigameOptions() diff --git a/SSV2/includes/frontend/yav3_ui.lua b/SSV2/includes/frontend/yav3_ui.lua index 0494c1f..eb05289 100644 --- a/SSV2/includes/frontend/yav3_ui.lua +++ b/SSV2/includes/frontend/yav3_ui.lua @@ -28,7 +28,6 @@ local b_SearchBarUsed = false local b_PreviewPeds = false local b_SpawnInvincible = false local b_SpawnArmed = false -local b_AutoCloseSpawnWindow = false ---@type Action? local t_SelectedAction = nil @@ -243,32 +242,24 @@ local function DrawAnims() local has_command = GVars.features.yim_actions.action_commands[action.label] ~= nil local label = action.label - if is_favorite then - label = _F("%s [ * ]", action.label) - end - - if is_selected then - if is_favorite then - ImGui.PushStyleColor(ImGuiCol.Header, 1.0, 0.843, 0.0, 0.65) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 1.0, 0.875, 0.2, 0.85) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 1.0, 0.9, 0.3, 1.0) - else - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end + if (is_favorite) then + label = _F("* %s", action.label) + ImGui.PushStyleColor(ImGuiCol.Text, 0.8, 0.8, 0.4, 0.8) end if ImGui.Selectable(label, is_selected) then i_SelectedAnimIndex = i end + if (is_favorite) then + ImGui.PopStyleColor() + end + if (not hwnd_NewCommandWindow.should_draw) then GUI:Tooltip(_F("Right click for more options.")) end if (is_selected) then - ImGui.PopStyleColor(3) t_SelectedAction = Action.new( t_AnimList[i_SelectedAnimIndex], Enums.eActionType.ANIM @@ -333,32 +324,24 @@ local function DrawScenarios() local has_command = GVars.features.yim_actions.action_commands[action.label] ~= nil local label = action.label - if is_favorite then - label = _F("%s [ * ]", action.label) - end - - if is_selected then - if is_favorite then - ImGui.PushStyleColor(ImGuiCol.Header, 1.0, 0.843, 0.0, 0.65) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 1.0, 0.875, 0.2, 0.85) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 1.0, 0.9, 0.3, 1.0) - else - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end + if (is_favorite) then + label = _F("* %s", action.label) + ImGui.PushStyleColor(ImGuiCol.Text, 0.8, 0.8, 0.4, 0.8) end if ImGui.Selectable(label, is_selected) then i_SelectedScenarioIndex = i end + if (is_favorite) then + ImGui.PopStyleColor() + end + if (not hwnd_NewCommandWindow.should_draw) then GUI:Tooltip(_F("Right click for more options.")) end - if is_selected then - ImGui.PopStyleColor(3) + if (is_selected) then t_SelectedAction = Action.new( t_PedScenarios[i_SelectedScenarioIndex], Enums.eActionType.SCENARIO @@ -451,12 +434,6 @@ local function ListFavoritesByCategory(category) for label, data in pairs(GVars.features.yim_actions.favorites[category]) do local is_selected = (s_SelectedFavoriteName == label) - if is_selected then - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end - if ImGui.Selectable(data.label, is_selected) then s_SelectedFavoriteName = label end @@ -464,7 +441,6 @@ local function ListFavoritesByCategory(category) GUI:Tooltip("Right click to remove from favorites.") if is_selected then - ImGui.PopStyleColor(3) t_SelectedAction = Action.new( data, data.type @@ -825,32 +801,21 @@ local function DrawCustomMovementClipsets() local is_selected = (t_SelectedMovementClipset == t_MovementClipsets[i]) local is_favorite = YimActions:DoesFavoriteExist("clipsets", t_MovementClipsets[i].Name) - if is_favorite then - label = _F("%s [ * ]", t_MovementClipsets[i].Name) - end - - if is_selected then - if is_favorite then - ImGui.PushStyleColor(ImGuiCol.Header, 1.0, 0.843, 0.0, 0.65) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 1.0, 0.875, 0.2, 0.85) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 1.0, 0.9, 0.3, 1.0) - else - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end + if (is_favorite) then + label = _F("* %s", t_MovementClipsets[i].Name) + ImGui.PushStyleColor(ImGuiCol.Text, 0.8, 0.8, 0.4, 0.8) end if ImGui.Selectable(label, is_selected) then t_SelectedMovementClipset = t_MovementClipsets[i] end - GUI:Tooltip("Right click to add to favorites.") - - if is_selected then - ImGui.PopStyleColor(3) + if (is_favorite) then + ImGui.PopStyleColor() end + GUI:Tooltip(_F("Right click to %s favorites.", is_favorite and "remove from" or "add to")) + if GUI:IsItemClicked(1) then ImGui.OpenPopup("##custom_mvmt_" .. i) t_SelectedMovementClipset = t_MovementClipsets[i] @@ -931,32 +896,22 @@ local function DrawJsonMovementClipsets() local is_selected = (t_SelectedMovementClipset == t_MovementClipsetsJson[i]) local is_favorite = YimActions:DoesFavoriteExist("clipsets", t_MovementClipsetsJson[i].Name) - if (is_favorite) then - label = _F("%s [ * ]", t_MovementClipsetsJson[i].Name) - end - if (is_selected) then - if (is_favorite) then - ImGui.PushStyleColor(ImGuiCol.Header, 1.0, 0.843, 0.0, 0.65) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 1.0, 0.875, 0.2, 0.85) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 1.0, 0.9, 0.3, 1.0) - else - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end + if (is_favorite) then + label = _F("* %s", t_MovementClipsetsJson[i].Name) + ImGui.PushStyleColor(ImGuiCol.Text, 0.8, 0.8, 0.4, 0.8) end if ImGui.Selectable(label, is_selected) then t_SelectedMovementClipset = t_MovementClipsetsJson[i] end - GUI:Tooltip("Right click to add to favorites.") - - if is_selected then - ImGui.PopStyleColor(3) + if (is_favorite) then + ImGui.PopStyleColor() end + GUI:Tooltip(_F("Right click to %s favorites.", is_favorite and "remove from" or "add to")) + if GUI:IsItemClicked(1) then GUI:PlaySound("Click") ImGui.OpenPopup("##context_" .. i) @@ -1008,22 +963,12 @@ local function DrawFavoriteMovementClipsets() for label, data in pairs(favs) do local is_selected = (t_SelectedMovementClipset == data) - if is_selected then - ImGui.PushStyleColor(ImGuiCol.Header, 0.3, 0.3, 0.7, 0.6) - ImGui.PushStyleColor(ImGuiCol.HeaderHovered, 0.4, 0.4, 0.8, 0.8) - ImGui.PushStyleColor(ImGuiCol.HeaderActive, 0.5, 0.5, 0.9, 1.0) - end - if ImGui.Selectable(data.Name, is_selected) then t_SelectedMovementClipset = data end GUI:Tooltip("Right click to remove from favorites.") - if (is_selected) then - ImGui.PopStyleColor(3) - end - if GUI:IsItemClicked(1) then GUI:PlaySound("Click") ImGui.OpenPopup("##context_" .. label) @@ -1404,21 +1349,22 @@ local function DrawPedSpawnWindow() false ) - if b_AutoCloseSpawnWindow then + if (GVars.features.yim_actions.auto_close_ped_window) then hwnd_PedSpawnWindow.should_draw = false end end) end + ImGui.EndDisabled() ImGui.SameLine() ImGui.Spacing() ImGui.SameLine() + GVars.features.yim_actions.auto_close_ped_window, _ = GUI:Checkbox( "Auto-Close Window", GVars.features.yim_actions.auto_close_ped_window ) - ImGui.EndDisabled() ImGui.PopStyleVar() if (PreviewService.m_current and (not ImGui.IsAnyItemHovered() or not b_PreviewPeds)) then diff --git a/SSV2/includes/services/CommandExecutor.lua b/SSV2/includes/services/CommandExecutor.lua index b08206b..bd23e0d 100644 --- a/SSV2/includes/services/CommandExecutor.lua +++ b/SSV2/includes/services/CommandExecutor.lua @@ -449,7 +449,7 @@ function CommandExecutor:Draw() if (self:ShouldFocusInput()) then ImGui.SetKeyboardFocusHere() end - -- end + self.m_user_cmd, self.m_cmd_entered = ImGui.InputTextWithHint( "##cmd", self.m_hint_text, @@ -497,7 +497,7 @@ function CommandExecutor:Draw() ImGui.PopTextWrapPos() ImGui.SetWindowFontScale(1) - if self.m_window.popup.should_draw then + if (self.m_window.popup.should_draw) then ImGui.OpenPopup(self.m_window.popup.name) self.m_window.popup.should_draw = false end diff --git a/SSV2/includes/services/GUI.lua b/SSV2/includes/services/GUI.lua index 23bbda8..ec13b11 100644 --- a/SSV2/includes/services/GUI.lua +++ b/SSV2/includes/services/GUI.lua @@ -838,6 +838,7 @@ function GUI:ConfirmPopup(name) ImGui.SetCursorPosX(ImGui.GetCursorPosX() + firstCursorPos) if (self:Button(_T("GENERIC_CONFIRM"), { size = buttonSize })) then ImGui.CloseCurrentPopup() + ImGui.EndPopup() return true end @@ -846,6 +847,7 @@ function GUI:ConfirmPopup(name) if (self:Button(_T("GENERIC_CANCEL"), { size = buttonSize })) then ImGui.CloseCurrentPopup() + ImGui.EndPopup() return false end diff --git a/docs/Features.md b/docs/Features.md new file mode 100644 index 0000000..7d7eecf --- /dev/null +++ b/docs/Features.md @@ -0,0 +1,372 @@ + + +# Features + +SSV2 includes polished versions of your favorite features from previous versions before the rework plus some new additions. + +
+ Table of Contents +
    +
  1. Self
  2. +
  3. + Vehicle + +
  4. +
  5. World
  6. +
  7. + Online + +
  8. +
  9. + Extra + +
  10. +
+
+ +## Self + +_Player-centric features affecting movement, combat, and animations._ + +- **Auto-Heal** + + Constantly refills your health and armor. + +- **Enable Phone Animations** + + Restores mobile phone animations in Online mode. + +- **Enable MC Riding Style** + + Restores the alternate bike riding style in GTA Online for MCs. + + _Usage:_ Automatically applies when riding a motorcycle at low speed while registered as an MC. + +- **Disable Action Mode** + + Disables the player's forced stance when in combat or wanted by the police. + +- **Allow Head Props In Vehicles** + + Allows you to keep your headgear (hats, helmets, masks, etc.) inside vehicles. + +- **Stand On Vehicles** + + Prevents you from ragdolling when standing on top of a moving vehicle. + +- **No Carjacking** + + Prevents NPCs from carjacking you. Enemies will not try to open your vehicle's door and force you out. + +- **Crouch** + + Allows you to crouch. + + _Usage:_ Toggle by pressing **[Left Control]**. + +- **Hands Up** + + Allows you to put your hands up _(surrender)_. This replaces the **"Point At"** action in Online. + + _Usage:_ Toggle by pressing **[B]**. + +- **Sprint Inside Interiors** + + Allows you to sprint at full speed inside _most_ interiors. + +- **Lockpick Animation** + + Increases the chance of using a lock picking animation when stealing vehicles instead of smashing the window. + +- **Ragdoll On Demand** + + Allows you to ragdoll at any time. + + _Usage:_ Triggered via keybind _(default: **[X]**)_. + +- **Clumsy** + + Makes you stumble and fall whenever you bump into anything; including sidewalks. + +- **Magic Bullet** + + Shoots the last ped you aimed at in the head as soon as you fire your weapon. + +- **Laser Sights** + + Adds a visible laser beam to supported firearms. + + _Usage:_ Toggle via keybind while aiming, same as weapon flashlight _(default: **[L]**)_. + +- **Katana** + + Replaces a selected melee weapon with a katana for close-quarters combat. + + _Usage:_ Choose base weapon in settings, then equip normally. + +

[🔝]

+ +## Vehicle + +_Vehicle-centric features extending the capabilities of vanilla vehicles._ + +### General + +- **Speedometer** + + Draws a custom speedometer that switches modes between vehicles and aircraft. + +- **Brake Force Display** + + Flashes your brake lights when you apply the brakes from high speed. + +- **Fast Vehicles** + + Greatly increases the acceleration and top speed of any land vehicle you drive. + +- **NOS** + + Allows you to use a custom NOS boost. + + _Usage:_ Triggered via keybind while driving _(default: **[Left Shift]**)_. + +- **NOS Purge** + + Allows you to perform a NOS purge [à la 2 Fast 2 Furious](https://www.youtube.com/watch?v=aBRCDqabqTE) + + _Usage:_ Triggered via keybind while driving _(default: **[X]**)_. + +- **Pops & Bangs** + + Enables extremely loud exhaust pops that scare nearby NPCs. + + _Usage:_ Triggered automatically when you release the accelerator from high RPM. + +- **Drift Mode** + + Introduces new arcade-style drift mechanics. + + _Usage:_ Triggered via keybind while driving _(default: **[Left Shift]**)_. + +- **Big Subwoofer** + + Makes your vehicle's radio sound louder from the outside. + +- **High Beams On Horn** + + Flashes your high beams when you use the horn. + +- **Auto Brake Lights** + + Turns on your brake lights when you come to a complete stop. + +- **Unbreakable Windows** + + Prevents your vehicle's windows from breaking. + +- **Stronger Crashes** + + Makes car crashes more dangerous by increasing deformation, introducing engine damage, screen effects, and potential loss of life. + +- **RGB Headlights** + + Starts an RGB loop on your vehicle's headlights. + +- **Auto Lock** + + Automatically locks your vehicle when you walk away from it. + +- **Launch Control** + + Simulates launch control by making your vehicle accelerate faster from a standstill and decreasing wheel spin. + +- **IV-Style Exit** + + Re-introduces GTA IV's vehicle exit style. + + _Usage:_ Hold **[F]** to turn the engine off before exiting or press and release normally to keep it running. + +- **Keep Wheels Turned** + + Preserves the last angle your wheels were steered at before exiting. + +- **Vehicle Mines** + + Allows you to deploy all types of mines from any land vehicle. + + _Usage:_ Choose a type then press the assigned keybind _(default: **[Numpad 0]**)_. + +- **Drift Minigame** + + Score points by drifting around Los Santos. You can bank your points for cash in Single Player. + +### Aircraft + +- **Fast Planes** + + Increases the top speed of any plane you fly to ±560 km/h as long as the plane can reach 250 km/h on its own. + +- **Disable Engine Stalling** + + Prevents your plane engine(s) from stalling when you hold the brake button mid-air. + +- **Disable Air Turbulence _(Experimental)_** + + Disables air turbulence for some aircraft. + +- **Flare Countermeasures** + + Allows you to deploy flares from any aircraft. + + _Usage:_ Triggered via default countermeasures keybind. + +- **Cobra Maneuver** + + Allows you to perform a [cobra maneuver](https://www.youtube.com/shorts/H0X7D3Ga4mo). + + _Usage:_ Triggered via keybind while flying _(default: **[X]**)_. + +- **Machine Gun Triggerbot** + + Automatically fires your aircraft's machine gun. + + _Usage:_ Get in a weaponized aircraft and equip the machine gun. + +- **Machine Gun Manual Aim** + + Allows you to manually aim your aircraft's machine gun. + +- **Autopilot** + + Automatically flies your aircraft to the selected destination. + + _Usage:_ Sit in the pilot's seat and select a destination from the menu _(Objective, Waypoint, or Random)_. + +### Stancer + +_VStancer's Carthaginian cousin._ + +Allows advanced stance tuning, including: + +- **Per-axle _(affects handling)_** + + Camber, suspension height, track width. + +- **Global _(visual only)_** + + Wheel size, wheel width, ride height. + +Additional features: + +- Air suspension controls. +- Bounce mode _(SUVs only)_. + +### Engine Swap + +Changes your current vehicle's engine sound and power. + +### Handling Editor + +Extends the pre-existing handling editor in YimMenu with more options focused on handling flags. + +### Custom Paint Jobs + +Choose from a list of over 300 hand-picked real-life paint jobs and apply them to your current vehicle. + +### Flatbed Script + +A script that allows you to use the [MTL Flatbed](https://gta.fandom.com/wiki/Flatbed) truck to tow vehicles. You can either spawn a truck yourself or find one in the open world. + +_Usage:_ Sit in the driver's seat of a flatbed truck then approach any vehicle and press the assigned keybind _(default: **[X]**)_ to tow it. + +

[🔝]

+ +## World + +- **Disable Ocean Waves** + + Completely removes waves from the ocean. + +- **Extend World Boundaries** + + Allows you to travel further in any direction without dying. + +- **Disable Flight Music** + + Disables the ambient music that automatically plays when you're flying an aircraft. + +- **Disable Wanted Music** + + Disables the ambient music that automatically plays when you have a wanted level higher than 2 stars. + +- **Hide & Seek** + + Allows you to hide in several places (car trunks, trash bins, inside vehicles). Also makes it easier to lose a wanted level. + +- **Carpool** + + Allows you to get in any NPC vehicle as a passenger. Works for police vehicles too but they won't be happy. + +- **Public Enemy #1** + + All nearby NPCs attack you. + +- **Kill All Enemies** + + Kills all nearby enemies. + + _Usage:_ Triggered via a button in the UI or a keybind _(default: **[F7]**)_. + +- **Scare All Enemies** + + Forces all nearby enemies to flee _(except NOOSE)_. + + _Usage:_ Triggered via a button in the UI or a keybind _(default: **[F8]**)_. + +

[🔝]

+ +## Online + +### YimResupplierV3 + +A business manager that supports auto-fill and auto-sell for several businesses, controls some job cooldowns, and integrates with CommandExecutor. + +### CasinoPacino + +An updated and slightly refactored version of [Casino Pacino](https://github.com/YimMenu-Lua/Casino-Pacino). + +### SalvageYard + +A script focused on the Chop Shop business. Added by [szalikdev](https://github.com/szalikdev). + +## Extra + +### YimActionsV3 + +A greatly improved version of my all-in-one animations script. + +### EntityForge + +An experimental script that allows you to attach, merge, and create things using peds, objects and vehicles and share them with friends. + +### Billionaire Services + +Offers exclusive bodyguard, escort, jet, heli, and limousine services. + +

[🔝]