From 24e56068d4054db18edd7050d3b95004e4413186 Mon Sep 17 00:00:00 2001 From: Space V <40030799+ahcenezdh@users.noreply.github.com> Date: Sat, 19 Oct 2024 13:50:54 +0200 Subject: [PATCH] feat(natives/vehicle): implement getter/setter for vehicle flags --- .../src/VehicleExtraNatives.cpp | 43 ++++++++++++ ext/native-decls/GetVehicleHasFlag.md | 67 +++++++++++++++++++ ext/native-decls/SetVehicleFlag.md | 32 +++++++++ 3 files changed, 142 insertions(+) create mode 100644 ext/native-decls/GetVehicleHasFlag.md create mode 100644 ext/native-decls/SetVehicleFlag.md diff --git a/code/components/extra-natives-five/src/VehicleExtraNatives.cpp b/code/components/extra-natives-five/src/VehicleExtraNatives.cpp index 9f4872d232..320edde24a 100644 --- a/code/components/extra-natives-five/src/VehicleExtraNatives.cpp +++ b/code/components/extra-natives-five/src/VehicleExtraNatives.cpp @@ -281,6 +281,7 @@ static int VisualHeightSetOffset = 0x07C; static int LightMultiplierGetOffset; static int VehiclePitchBiasOffset; static int VehicleRollBiasOffset; +static int VehicleFlagsOffset; static int VehicleDamageParentOffset; static int VehicleHandlingOffset; @@ -755,6 +756,11 @@ static HookFunction initFunction([]() VehicleRollBiasOffset = VehiclePitchBiasOffset - 4; } + { + auto location = hook::get_pattern("48 85 C0 74 3C 8B 80 ? ? ? ? C1 E8 0F"); + VehicleFlagsOffset = *(uint32_t*)(location + 7); + } + { auto location = hook::get_pattern("F3 0F 59 3D ? ? ? ? F3 0F 58 3D ? ? ? ? 48 85 C9", 4); PassengerMassPtr = hook::get_address(location); @@ -1380,6 +1386,43 @@ static HookFunction initFunction([]() } }); + fx::ScriptEngine::RegisterNativeHandler("GET_VEHICLE_HAS_FLAG", [](fx::ScriptContext& context) + { + int flagIndex = context.GetArgument(1); + + if (flagIndex < 0 || flagIndex >= 256) + { + return; + } + + if (fwEntity* vehicle = getAndCheckVehicle(context, "GET_VEHICLE_HAS_FLAG")) + { + auto addr = readValue(vehicle, ModelInfoPtrOffset); + auto flagBlocks = reinterpret_cast*>(addr + VehicleFlagsOffset); + + context.SetResult(flagBlocks->test(flagIndex)); + } + }); + + fx::ScriptEngine::RegisterNativeHandler("SET_VEHICLE_FLAG", [](fx::ScriptContext& context) + { + int flagIndex = context.GetArgument(1); + bool value = context.GetArgument(2); + + if (flagIndex < 0 || flagIndex >= 256) + { + return; + } + + if (fwEntity* vehicle = getAndCheckVehicle(context, "SET_VEHICLE_FLAG")) + { + auto addr = readValue(vehicle, ModelInfoPtrOffset); + auto flagBlocks = reinterpret_cast*>(addr + VehicleFlagsOffset); + + flagBlocks->set(flagIndex, value); + } + }); + fx::ScriptEngine::RegisterNativeHandler("IS_VEHICLE_WANTED", std::bind(readVehicleMemoryBit<&IsWantedOffset, 3>, _1, "IS_VEHICLE_WANTED")); fx::ScriptEngine::RegisterNativeHandler("IS_VEHICLE_PREVIOUSLY_OWNED_BY_PLAYER", std::bind(readVehicleMemoryBit<&PreviouslyOwnedByPlayerOffset, 1>, _1, "IS_VEHICLE_PREVIOUSLY_OWNED_BY_PLAYER")); diff --git a/ext/native-decls/GetVehicleHasFlag.md b/ext/native-decls/GetVehicleHasFlag.md new file mode 100644 index 0000000000..d4837cd9d5 --- /dev/null +++ b/ext/native-decls/GetVehicleHasFlag.md @@ -0,0 +1,67 @@ +--- +ns: CFX +apiset: client +--- +## GET_VEHICLE_HAS_FLAG + +```c +bool GET_VEHICLE_HAS_FLAG(Vehicle vehicle, int flagIndex); +``` + +**Note**: Flags are not the same based on your `gamebuild`. Please see [here](https://docs.fivem.net/docs/game-references/vehicle-references/vehicle-flags) to see a complete list of all vehicle flags. + +Get vehicle.meta flag by index. Useful examples include `FLAG_LAW_ENFORCEMENT` (31), `FLAG_RICH_CAR` (36), `FLAG_IS_ELECTRIC` (43), `FLAG_IS_OFFROAD_VEHICLE` (48). + +## Parameters +* **vehicle**: The vehicle to obtain flags for. +* **flagIndex**: Flag index. + +## Return value +A boolean for whether the flag is set. + +### Example +```lua +local vehicleFlags = { + FLAG_SMALL_WORKER = 0, + FLAG_BIG = 1, + FLAG_NO_BOOT = 2, + FLAG_ONLY_DURING_OFFICE_HOURS = 3 + -- This is just a example, see fivem-docs to see all flags. +} + +local function getAllVehicleFlags(vehicle) + local flags = {} + for i = 0, 256 do + if GetVehicleHasFlag(vehicle, i) then + flags[#flags+1] = i + end + end + return flags +end + +local flagsVehicle = GetVehiclePedIsIn(PlayerPedId(), false) +print(getAllVehicleFlags) +``` + +```javascript +const VEHICLE_FLAGS = { + FLAG_SMALL_WORKER: 0, + FLAG_BIG: 1, + FLAG_NO_BOOT: 2, + FLAG_ONLY_DURING_OFFICE_HOURS: 3 + // This is just a example, see fivem-docs to see all flags. +}; + +function getAllVehicleFlags(mVehicle = GetVehiclePedIsIn(PlayerPedId(), false)) { + const flags = []; + for (let i = 0; i < 204; i++) { + if (GetVehicleHasFlag(mVehicle, i)) { + flags.push(i); + } + } + return flags; +} + +let flagsVehicle = GetVehiclePedIsIn(PlayerPedId(), false); +console.log(getAllVehicleFlags); +``` \ No newline at end of file diff --git a/ext/native-decls/SetVehicleFlag.md b/ext/native-decls/SetVehicleFlag.md new file mode 100644 index 0000000000..f159d69636 --- /dev/null +++ b/ext/native-decls/SetVehicleFlag.md @@ -0,0 +1,32 @@ +--- +ns: CFX +apiset: client +--- +## SET_VEHICLE_FLAG + +```c +bool SET_VEHICLE_FLAG(Vehicle vehicle, int flagIndex, bool value); +``` + +This native is a setter for [`GET_VEHICLE_HAS_FLAG`](#_0xD85C9F57). + +## Parameters +* **vehicle**: The vehicle to set flag for. +* **flagIndex**: Flag index. +* **value**: `true` to enable the flag, `false` to disable it. + + +### Example +```lua +local vehicle = GetVehiclePedIsIn(PlayerPedId(), false) +if not vehicle then return end + +SetVehicleFlag(vehicle, 43, true) -- Set the vehicle as electric +``` + +```javascript +let vehicle = GetVehiclePedIsIn(PlayerPedId(), false); +if (!vehicle) return; + +SetVehicleFlag(vehicle, 43, true); // Set the vehicle as electric +``` \ No newline at end of file