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
+
+ - About
+ -
+ Getting Started
+
+
+ - Contributing
+ - Documentation
+ - Features
+ - FAQ
+ - Contact
+ - Acknowledgments
+
+
+
# About

@@ -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
+
+
+
## Acknowledgments
| Name | Contribution |
@@ -104,11 +136,3 @@ This project was rewritten from scratch using [SmallBase](https://github.com/xes
| 
Alexander Schmid | [GTA V data dumps](https://github.com/DurtyFree/gta-v-data-dumps) |
| 
Andreas Maerten | GTA V classes (archived/removed) |
| 
UnknownCheats | A treasure trove of information |
-
-## Contact
-
-
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
+
+ - Self
+ -
+ Vehicle
+
+
+ - World
+ -
+ Online
+
+
+ -
+ Extra
+
+
+
+
+
+## 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.
+
+[🔝]