Merge pull request #16 from WolfKnight98/passenger-control

1.3.0 - Passenger control update
This commit is contained in:
Dan
2021-03-21 21:25:24 +00:00
committed by GitHub
16 changed files with 1979 additions and 1155 deletions

3
.gitignore vendored
View File

@@ -1 +1,2 @@
saves/*.json saves/*.json
.vscode/settings.json

View File

@@ -1,6 +1,6 @@
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

View File

@@ -25,23 +25,39 @@ Although these can be viewed ingame through the operator manual, the default key
All of the configuration for the Wraith ARS 2X is done inside the `config.lua` file, below is a copy of the configuration file. All of the options have comments to describe what they do, along with the available options you can set. You have the ability to change the key binds for the large and small key set, the default operator menu options, and the default UI element scale and safezone. All of the configuration for the Wraith ARS 2X is done inside the `config.lua` file, below is a copy of the configuration file. All of the options have comments to describe what they do, along with the available options you can set. You have the ability to change the key binds for the large and small key set, the default operator menu options, and the default UI element scale and safezone.
```lua ```lua
-- Radar fast limit locking -- Radar fast limit locking
-- When enabled, the player will be able to define a fast limit within the radar's menu, when a vehicle -- When enabled, the player will be able to define a fast limit within the radar's menu, when a vehicle
-- exceeds the fast limit, it will be locked into the fast box. Default setting is disabled to maintain realism -- exceeds the fast limit, it will be locked into the fast box. Default setting is disabled to maintain realism
CONFIG.allow_fast_limit = false CONFIG.allow_fast_limit = true
-- Radar only lock players with auto fast locking
-- When enabled, the radar will only automatically lock a speed if the caught vehicle has a real player in it.
CONFIG.only_lock_players = false
-- In-game first time quick start video -- In-game first time quick start video
-- When enabled, the player will be asked if they'd like to view the quick start video the first time they -- When enabled, the player will be asked if they'd like to view the quick start video the first time they
-- open the remote. -- open the remote.
CONFIG.allow_quick_start_video = true CONFIG.allow_quick_start_video = true
-- Allow passenger view
-- When enabled, the front seat passenger will be able to view the radar and plate reader from their end.
CONFIG.allow_passenger_view = true
-- Allow passenger control
-- Dependent on CONFIG.allow_passenger_view. When enabled, the front seat passenger will be able to open the
-- radar remote and control the radar and plate reader for themself and the driver.
CONFIG.allow_passenger_control = true
-- Set this to true if you use Sonoran CAD with the WraithV2 plugin
CONFIG.use_sonorancad = false
-- Sets the defaults of all keybinds -- Sets the defaults of all keybinds
-- These keybinds can be changed by each person in their GTA Settings->Keybinds->FiveM -- These keybinds can be changed by each person in their GTA Settings->Keybinds->FiveM
CONFIG.keyDefaults = CONFIG.keyDefaults =
{ {
-- Remote control key -- Remote control key
remote_control = "f5", remote_control = "f5",
-- Radar key lock key -- Radar key lock key
key_lock = "l", key_lock = "l",
-- Radar front antenna lock/unlock Key -- Radar front antenna lock/unlock Key
@@ -58,33 +74,41 @@ CONFIG.keyDefaults =
} }
-- Here you can change the default values for the operator menu, do note, if any of these values are not -- Here you can change the default values for the operator menu, do note, if any of these values are not
-- one of the options listed, the script will not work. -- one of the options listed, the script will not work.
CONFIG.menuDefaults = CONFIG.menuDefaults =
{ {
-- Should the system calculate and display faster targets -- Should the system calculate and display faster targets
-- Options: true or false -- Options: true or false
["fastDisplay"] = true, ["fastDisplay"] = true,
-- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles -- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles
-- Options: 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.2, 0.4, 0.6, 0.8, 1.0
["same"] = 0.6, ["same"] = 0.6,
["opp"] = 0.6, ["opp"] = 0.6,
-- The volume of the audible beep -- The volume of the audible beep
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["beep"] = 0.6, ["beep"] = 0.6,
-- The volume of the verbal lock confirmation -- The volume of the verbal lock confirmation
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["voice"] = 0.6, ["voice"] = 0.6,
-- The volume of the plate reader audio -- The volume of the plate reader audio
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["plateAudio"] = 0.6, ["plateAudio"] = 0.6,
-- The speed unit used in conversions -- The speed unit used in conversions
-- Options: mph or kmh -- Options: mph or kmh
["speedType"] = "mph" ["speedType"] = "mph",
-- The state for automatic speed locking. This requires CONFIG.allow_fast_limit to be true.
-- Options: true or false
["fastLock"] = false,
-- The speed limit required for automatic speed locking. This requires CONFIG.allow_fast_limit to be true.
-- Options: 0 to 200
["fastLimit"] = 60
} }
-- Here you can change the default scale of the UI elements, as well as the safezone size -- Here you can change the default scale of the UI elements, as well as the safezone size
@@ -94,14 +118,14 @@ CONFIG.uiDefaults =
-- Options: 0.25 - 2.5 -- Options: 0.25 - 2.5
scale = scale =
{ {
radar = 1.0, radar = 0.75,
remote = 1.0, remote = 0.75,
plateReader = 1.0 plateReader = 0.75
}, },
-- The safezone size, must be a multiple of 5. -- The safezone size, must be a multiple of 5.
-- Options: 0 - 100 -- Options: 0 - 100
safezone = 20 safezone = 20
} }
``` ```
@@ -109,4 +133,4 @@ CONFIG.uiDefaults =
If there is an improvement that you think should be made, open a pull request with your modified code, I will then review your request and either accept/deny it. Code in a pull request should be well formatted and commented, it will make it much easier for others to read and understand. In the event that you want to suggest something, but don't know how to code, open an issue with the enhancement tag and then fully describe your suggestion. If there is an improvement that you think should be made, open a pull request with your modified code, I will then review your request and either accept/deny it. Code in a pull request should be well formatted and commented, it will make it much easier for others to read and understand. In the event that you want to suggest something, but don't know how to code, open an issue with the enhancement tag and then fully describe your suggestion.
## Reporting issues/bugs ## Reporting issues/bugs
Open an issue if you encounter any problems with the resource, if applicable, try to include detailed information on the issue and how to reproduce it. This will make it much easier to find and fix. Open an issue if you encounter any problems with the resource, if applicable, try to include detailed information on the issue and how to reproduce it. This will make it much easier to find and fix.

View File

@@ -2,13 +2,13 @@
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD my Discord: https://discord.gg/fD4e6WD
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -36,163 +36,203 @@ READER = {}
Plate reader variables Plate reader variables
NOTE - This is not a config, do not touch anything unless you know what NOTE - This is not a config, do not touch anything unless you know what
you are actually doing. you are actually doing.
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
READER.vars = READER.vars =
{ {
-- Whether or not the plate reader's UI is visible -- Whether or not the plate reader's UI is visible
displayed = false, displayed = false,
-- Whether or not the plate reader should be hidden, e.g. the display is active but the player then steps -- Whether or not the plate reader should be hidden, e.g. the display is active but the player then steps
-- out of their vehicle -- out of their vehicle
hidden = false, hidden = false,
-- The BOLO plate -- The BOLO plate
boloPlate = "", boloPlate = "",
-- Cameras, this table contains all of the data needed for operation of the front and rear plate reader -- Cameras, this table contains all of the data needed for operation of the front and rear plate reader
cams = { cams = {
-- Variables for the front camera -- Variables for the front camera
["front"] = { ["front"] = {
plate = "", -- The current plate caught by the reader plate = "", -- The current plate caught by the reader
index = "", -- The index of the current plate index = "", -- The index of the current plate
locked = false -- If the reader is locked locked = false -- If the reader is locked
}, },
-- Variables for the rear camera -- Variables for the rear camera
["rear"] = { ["rear"] = {
plate = "", -- The current plate caught by the reader plate = "", -- The current plate caught by the reader
index = "", -- The index of the current plate index = "", -- The index of the current plate
locked = false -- If the reader is locked locked = false -- If the reader is locked
} }
} }
} }
--[[----------------------------------------------------------------------------------
Plate reader functions
----------------------------------------------------------------------------------]]--
-- Gets the display state -- Gets the display state
function READER:GetDisplayState() function READER:GetDisplayState()
return self.vars.displayed return self.vars.displayed
end end
-- Toggles the display state of the plate reader system -- Toggles the display state of the plate reader system
function READER:ToggleDisplayState() function READER:ToggleDisplayState()
-- Toggle the display variable -- Toggle the display variable
self.vars.displayed = not self.vars.displayed self.vars.displayed = not self.vars.displayed
-- Send the toggle message to the NUI side -- Send the toggle message to the NUI side
SendNUIMessage( { _type = "setReaderDisplayState", state = self:GetDisplayState() } ) SendNUIMessage( { _type = "setReaderDisplayState", state = self:GetDisplayState() } )
end
-- Sets the display's hidden state to the given state
function READER:SetDisplayHidden( state )
self.vars.hidden = state
end
-- Returns if the display is hidden
function READER:GetDisplayHidden()
return self.vars.hidden
end end
-- Returns the stored plate for the given reader -- Getter and setter for the display hidden state
function READER:GetPlate( cam ) function READER:GetDisplayHidden() return self.vars.hidden end
return self.vars.cams[cam].plate function READER:SetDisplayHidden( state ) self.vars.hidden = state end
end
-- Sets the plate for the given reader to the given plate -- Getter and setter for the given camera's plate
function READER:SetPlate( cam, plate ) function READER:GetPlate( cam ) return self.vars.cams[cam].plate end
self.vars.cams[cam].plate = plate function READER:SetPlate( cam, plate ) self.vars.cams[cam].plate = plate end
end
-- Returns the stored plate index for the given reader -- Getter and setter for the given camera's plate display index
function READER:GetIndex( cam ) function READER:GetIndex( cam ) return self.vars.cams[cam].index end
return self.vars.cams[cam].index function READER:SetIndex( cam, index ) self.vars.cams[cam].index = index end
end
-- Sets the plate index for the given reader to the given index
function READER:SetIndex( cam, index )
self.vars.cams[cam].index = index
end
-- Returns the bolo plate -- Returns the bolo plate
function READER:GetBoloPlate() function READER:GetBoloPlate()
return self.vars.boloPlate if ( self.vars.boloPlate ~= nil ) then
end return self.vars.boloPlate
end
end
-- Sets the bolo plate to the given plate -- Sets the bolo plate to the given plate
function READER:SetBoloPlate( plate ) function READER:SetBoloPlate( plate )
self.vars.boloPlate = plate self.vars.boloPlate = plate
UTIL:Notify( "BOLO plate set to: " .. plate ) UTIL:Notify( "BOLO plate set to: ~b~" .. plate )
end end
-- Clears the BOLO plate
function READER:ClearBoloPlate()
self.vars.boloPlate = nil
UTIL:Notify( "~b~BOLO plate cleared!" )
end
-- Returns if the given reader is locked -- Returns if the given reader is locked
function READER:GetCamLocked( cam ) function READER:GetCamLocked( cam ) return self.vars.cams[cam].locked end
return self.vars.cams[cam].locked
end
-- Locks the given reader -- Locks the given reader
function READER:LockCam( cam, playBeep, isBolo ) function READER:LockCam( cam, playBeep, isBolo, override )
-- Check that plate readers can actually be locked -- Check that plate readers can actually be locked
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then if ( PLY:VehicleStateValid() and self:CanPerformMainTask() and self:GetPlate( cam ) ~= "" ) then
-- Toggle the lock state -- Toggle the lock state
self.vars.cams[cam].locked = not self.vars.cams[cam].locked self.vars.cams[cam].locked = not self.vars.cams[cam].locked
-- Tell the NUI side to show/hide the lock icon -- Play a beep
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = isBolo } ) if ( self:GetCamLocked( cam ) ) then
-- Here we check if the override parameter is valid, if so then we set the reader's plate data to the
-- plate data provided in the override table.
if ( override ~= nil ) then
self:SetPlate( cam, override[1] )
self:SetIndex( cam, override[2] )
-- Play a beep self:ForceNUIUpdate( false )
if ( self:GetCamLocked( cam ) ) then end
if ( playBeep ) then
if ( playBeep ) then
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "plateAudio" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "plateAudio" ) } )
end end
if ( isBolo ) then if ( isBolo ) then
SendNUIMessage( { _type = "audio", name = "plate_hit", vol = RADAR:GetSettingValue( "plateAudio" ) } ) SendNUIMessage( { _type = "audio", name = "plate_hit", vol = RADAR:GetSettingValue( "plateAudio" ) } )
end end
-- Trigger an event so developers can hook into the scanner every time a plate is locked -- Trigger an event so developers can hook into the scanner every time a plate is locked
TriggerServerEvent( "wk:onPlateLocked", cam, self:GetPlate( cam ), self:GetIndex( cam ) ) TriggerServerEvent( "wk:onPlateLocked", cam, self:GetPlate( cam ), self:GetIndex( cam ) )
end end
end
end -- Tell the NUI side to show/hide the lock icon
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = isBolo } )
end
end
-- Returns if the plate reader system can perform tasks -- Returns if the plate reader system can perform tasks
function READER:CanPerformMainTask() function READER:CanPerformMainTask()
return self.vars.displayed and not self.vars.hidden return self.vars.displayed and not self.vars.hidden
end end
-- Returns if the given relative position value is for front or rear -- Returns if the given relative position value is for front or rear
function READER:GetCamFromNum( relPos ) function READER:GetCamFromNum( relPos )
if ( relPos == 1 ) then if ( relPos == 1 ) then
return "front" return "front"
elseif ( relPos == -1 ) then elseif ( relPos == -1 ) then
return "rear" return "rear"
end end
end end
-- Forces an NUI update, used by the passenger control system
function READER:ForceNUIUpdate( lock )
for cam in UTIL:Values( { "front", "rear" } ) do
local plate = self:GetPlate( cam )
local index = self:GetIndex( cam )
if ( plate ~= "" and index ~= "" ) then
SendNUIMessage( { _type = "changePlate", cam = cam, plate = plate, index = index } )
if ( lock ) then
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = false } )
end
end
end
end
-- Returns a table with both antenna's speed data and directions
function READER:GetCameraDataPacket( cam )
return {
self:GetPlate( cam ),
self:GetIndex( cam )
}
end
RegisterNetEvent( "wk:togglePlateLock" ) RegisterNetEvent( "wk:togglePlateLock" )
AddEventHandler( "wk:togglePlateLock", function( cam, beep, bolo ) AddEventHandler( "wk:togglePlateLock", function( cam, beep, bolo )
READER:LockCam( cam, beep, bolo ) READER:LockCam( cam, beep, bolo )
end ) end )
-- Runs when the "Toggle Display" button is pressed on the plate reder box
--[[----------------------------------------------------------------------------------
Plate reader NUI callbacks
----------------------------------------------------------------------------------]]--
-- Runs when the "Toggle Display" button is pressed on the plate reder box
RegisterNUICallback( "togglePlateReaderDisplay", function( data, cb ) RegisterNUICallback( "togglePlateReaderDisplay", function( data, cb )
-- Toggle the display state -- Toggle the display state
READER:ToggleDisplayState() READER:ToggleDisplayState()
cb('ok') cb( "ok" )
end ) end )
-- Runs when the "Set BOLO Plate" button is pressed on the plate reader box -- Runs when the "Set BOLO Plate" button is pressed on the plate reader box
RegisterNUICallback( "setBoloPlate", function( plate, cb ) RegisterNUICallback( "setBoloPlate", function( plate, cb )
-- Set the BOLO plate -- Set the BOLO plate
READER:SetBoloPlate( plate ) READER:SetBoloPlate( plate )
cb('ok') cb( "ok" )
end ) end )
-- Runs when the "Clear BOLO Plate" button is pressed on the plate reader box
RegisterNUICallback( "clearBoloPlate", function( plate, cb )
-- Clear the BOLO plate
READER:ClearBoloPlate()
cb( "ok" )
end )
--[[----------------------------------------------------------------------------------
Plate reader threads
----------------------------------------------------------------------------------]]--
-- This is the main function that runs and scans all vehicles in front and behind the patrol vehicle -- This is the main function that runs and scans all vehicles in front and behind the patrol vehicle
function READER:Main() function READER:Main()
-- Check that the system can actually run -- Check that the system can actually run
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then
-- Loop through front (1) and rear (-1) -- Loop through front (1) and rear (-1)
for i = 1, -1, -2 do for i = 1, -1, -2 do
-- Get the world position of the player's vehicle -- Get the world position of the player's vehicle
local pos = GetEntityCoords( PLY.veh ) local pos = GetEntityCoords( PLY.veh )
@@ -202,14 +242,14 @@ function READER:Main()
-- Get the end position 50m in front/behind the player's vehicle -- Get the end position 50m in front/behind the player's vehicle
local offset = GetOffsetFromEntityInWorldCoords( PLY.veh, -2.5, ( 50.0 * i ), 0.0 ) local offset = GetOffsetFromEntityInWorldCoords( PLY.veh, -2.5, ( 50.0 * i ), 0.0 )
-- Run the ray trace to get a vehicle -- Run the ray trace to get a vehicle
local veh = UTIL:GetVehicleInDirection( PLY.veh, start, offset ) local veh = UTIL:GetVehicleInDirection( PLY.veh, start, offset )
-- Get the plate reader text for front/rear -- Get the plate reader text for front/rear
local cam = self:GetCamFromNum( i ) local cam = self:GetCamFromNum( i )
-- Only proceed to read a plate if the hit entity is a valid vehicle and the current camera isn't locked -- Only proceed to read a plate if the hit entity is a valid vehicle and the current camera isn't locked
if ( DoesEntityExist( veh ) and IsEntityAVehicle( veh ) and not self:GetCamLocked( cam ) ) then if ( DoesEntityExist( veh ) and IsEntityAVehicle( veh ) and not self:GetCamLocked( cam ) ) then
-- Get the heading of the player's vehicle and the hit vehicle -- Get the heading of the player's vehicle and the hit vehicle
local ownH = UTIL:Round( GetEntityHeading( PLY.veh ), 0 ) local ownH = UTIL:Round( GetEntityHeading( PLY.veh ), 0 )
local tarH = UTIL:Round( GetEntityHeading( veh ), 0 ) local tarH = UTIL:Round( GetEntityHeading( veh ), 0 )
@@ -218,16 +258,16 @@ function READER:Main()
local dir = UTIL:GetEntityRelativeDirection( ownH, tarH ) local dir = UTIL:GetEntityRelativeDirection( ownH, tarH )
-- Only run the rest of the plate check code if we can see the front or rear of the vehicle -- Only run the rest of the plate check code if we can see the front or rear of the vehicle
if ( dir > 0 ) then if ( dir > 0 ) then
-- Get the licence plate text from the vehicle -- Get the licence plate text from the vehicle
local plate = GetVehicleNumberPlateText( veh ) local plate = GetVehicleNumberPlateText( veh )
-- Get the licence plate index from the vehicle -- Get the licence plate index from the vehicle
local index = GetVehicleNumberPlateTextIndex( veh ) local index = GetVehicleNumberPlateTextIndex( veh )
-- Only update the stored plate if it's different, otherwise we'd keep sending a NUI message to update the displayed -- Only update the stored plate if it's different, otherwise we'd keep sending a NUI message to update the displayed
-- plate and image even though they're the same -- plate and image even though they're the same
if ( self:GetPlate( cam ) ~= plate ) then if ( self:GetPlate( cam ) ~= plate ) then
-- Set the plate for the current reader -- Set the plate for the current reader
self:SetPlate( cam, plate ) self:SetPlate( cam, plate )
@@ -235,21 +275,26 @@ function READER:Main()
self:SetIndex( cam, index ) self:SetIndex( cam, index )
-- Automatically lock the plate if the scanned plate matches the BOLO -- Automatically lock the plate if the scanned plate matches the BOLO
if ( plate == self:GetBoloPlate() ) then if ( plate == self:GetBoloPlate() ) then
self:LockCam( cam, false, true ) self:LockCam( cam, false, true )
end
SYNC:LockReaderCam( cam, READER:GetCameraDataPacket( cam ) )
end
-- Send the plate information to the NUI side to update the UI -- Send the plate information to the NUI side to update the UI
SendNUIMessage( { _type = "changePlate", cam = cam, plate = plate, index = index } ) SendNUIMessage( { _type = "changePlate", cam = cam, plate = plate, index = index } )
-- Trigger the event so developers can hook into the scanner every time a plate is scanned -- If we use Sonoran CAD, reduce the plate events to just player's vehicle, otherwise life as normal
TriggerServerEvent( "wk:onPlateScanned", cam, plate, index ) if ( ( CONFIG.use_sonorancad and ( UTIL:IsPlayerInVeh( veh ) or IsVehiclePreviouslyOwnedByPlayer( veh ) ) and GetVehicleClass( veh ) ~= 18 ) or not CONFIG.use_sonorancad ) then
end -- Trigger the event so developers can hook into the scanner every time a plate is scanned
end TriggerServerEvent( "wk:onPlateScanned", cam, plate, index )
end end
end end
end end
end end
end
end
end
-- Main thread -- Main thread
Citizen.CreateThread( function() Citizen.CreateThread( function()
@@ -259,31 +304,31 @@ Citizen.CreateThread( function()
-- Wait half a second -- Wait half a second
Citizen.Wait( 500 ) Citizen.Wait( 500 )
end end
end ) end )
-- This function is pretty much straight from WraithRS, it does the job so I didn't see the point in not -- This function is pretty much straight from WraithRS, it does the job so I didn't see the point in not
-- using it. Hides the radar UI when certain criteria is met, e.g. in pause menu or stepped out ot the -- using it. Hides the radar UI when certain criteria is met, e.g. in pause menu or stepped out ot the
-- patrol vehicle -- patrol vehicle
function READER:RunDisplayValidationCheck() function READER:RunDisplayValidationCheck()
if ( ( ( PLY.veh == 0 or ( PLY.veh > 0 and not PLY.vehClassValid ) ) and self:GetDisplayState() and not self:GetDisplayHidden() ) or IsPauseMenuActive() and self:GetDisplayState() ) then if ( ( ( PLY.veh == 0 or ( PLY.veh > 0 and not PLY.vehClassValid ) ) and self:GetDisplayState() and not self:GetDisplayHidden() ) or IsPauseMenuActive() and self:GetDisplayState() ) then
self:SetDisplayHidden( true ) self:SetDisplayHidden( true )
SendNUIMessage( { _type = "setReaderDisplayState", state = false } ) SendNUIMessage( { _type = "setReaderDisplayState", state = false } )
elseif ( PLY.veh > 0 and PLY.vehClassValid and PLY.inDriverSeat and self:GetDisplayState() and self:GetDisplayHidden() ) then elseif ( PLY:CanViewRadar() and self:GetDisplayState() and self:GetDisplayHidden() ) then
self:SetDisplayHidden( false ) self:SetDisplayHidden( false )
SendNUIMessage( { _type = "setReaderDisplayState", state = true } ) SendNUIMessage( { _type = "setReaderDisplayState", state = true } )
end end
end end
-- Runs the display validation check for the radar -- Runs the display validation check for the radar
Citizen.CreateThread( function() Citizen.CreateThread( function()
Citizen.Wait( 100 ) Citizen.Wait( 100 )
while ( true ) do while ( true ) do
-- Run the check -- Run the check
READER:RunDisplayValidationCheck() READER:RunDisplayValidationCheck()
-- Wait half a second -- Wait half a second
Citizen.Wait( 500 ) Citizen.Wait( 500 )
end end
end ) end )

136
cl_player.lua Normal file
View File

@@ -0,0 +1,136 @@
--[[---------------------------------------------------------------------------------------
Wraith ARS 2X
Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------------------]]--
--[[----------------------------------------------------------------------------------
Player info variables
----------------------------------------------------------------------------------]]--
PLY =
{
ped = PlayerPedId(),
veh = nil,
inDriverSeat = false,
inPassengerSeat = false,
vehClassValid = false
}
-- Returns if the current vehicle fits the validity requirements for the radar to work
function PLY:VehicleStateValid()
return DoesEntityExist( self.veh ) and self.veh > 0 and self.vehClassValid
end
-- Used to check if the player is in a position where the radar should be allowed operation
function PLY:IsDriver()
return self:VehicleStateValid() and self.inDriverSeat
end
-- Returns if the player is in the front passenger seat of an emergency vehicle
function PLY:IsPassenger()
return self:VehicleStateValid() and self.inPassengerSeat
end
-- Returns if the player can view the radar, ensures their vehicle state is valid and that they are a driver or
-- a passenger (where valid)
function PLY:CanViewRadar()
return self:IsDriver() or ( self:IsPassenger() and RADAR:IsPassengerViewAllowed() )
end
-- Returns if the player is allowed to control the radar from the passenger seat
function PLY:CanControlRadar()
return self:IsDriver() or ( self:IsPassenger() and RADAR:IsPassengerControlAllowed() )
end
-- Returns the ped in the opposite seat to the player, e.g. if we're the passenger, then return the driver
function PLY:GetOtherPed()
if ( self:IsDriver() ) then
return GetPedInVehicleSeat( PLY.veh, 0 )
elseif ( self:IsPassenger() ) then
return GetPedInVehicleSeat( PLY.veh, -1 )
end
return nil
end
-- Returns the server ID of the player in the opposite seat (driver/passenger)
function PLY:GetOtherPedServerId()
local otherPed = self:GetOtherPed()
if ( otherPed ~= nil and otherPed ~= 0 and IsPedAPlayer( otherPed ) ) then
local otherPly = GetPlayerServerId( NetworkGetPlayerIndexFromPed( otherPed ) )
return otherPly
end
return nil
end
-- The main purpose of this thread is to update the information about the local player, including their
-- ped id, the vehicle id (if they're in one), whether they're in a driver seat, and if the vehicle's class
-- is valid or not
Citizen.CreateThread( function()
while ( true ) do
PLY.ped = PlayerPedId()
PLY.veh = GetVehiclePedIsIn( PLY.ped, false )
PLY.inDriverSeat = GetPedInVehicleSeat( PLY.veh, -1 ) == PLY.ped
PLY.inPassengerSeat = GetPedInVehicleSeat( PLY.veh, 0 ) == PLY.ped
PLY.vehClassValid = GetVehicleClass( PLY.veh ) == 18
Citizen.Wait( 500 )
end
end )
-- This thread is used to check when the player is entering a vehicle and then triggers the sync system
Citizen.CreateThread( function()
while ( true ) do
-- The sync trigger should only start when the player is getting into a vehicle
if ( IsPedGettingIntoAVehicle( PLY.ped ) and RADAR:IsPassengerViewAllowed() ) then
-- Get the vehicle the player is entering
local vehEntering = GetVehiclePedIsEntering( PLY.ped )
-- Only proceed if the vehicle the player is entering is an emergency vehicle
if ( GetVehicleClass( vehEntering ) == 18 ) then
-- Wait two seconds, this gives enough time for the player to get sat in the seat
Citizen.Wait( 2000 )
-- Get the vehicle the player is now in
local veh = GetVehiclePedIsIn( PLY.ped, false )
-- Trigger the main sync data function if the vehicle the player is now in is the same as the one they
-- began entering
if ( veh == vehEntering ) then
SYNC:SyncDataOnEnter()
end
end
end
Citizen.Wait( 500 )
end
end )

File diff suppressed because it is too large Load Diff

437
cl_sync.lua Normal file
View File

@@ -0,0 +1,437 @@
--[[---------------------------------------------------------------------------------------
Wraith ARS 2X
Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------------------]]--
-- Register the decorator used to tell if the other player has the remote open
DecorRegister( "wk_wars2x_sync_remoteOpen", 2 )
-- Takes the given backup functions and restores the data
local function RestoreData( obj, getFunc, setFunc, setBackupFunc, key )
if ( key ~= nil ) then
local data = getFunc( obj, key )
if ( data ~= nil ) then
setFunc( obj, key, data )
setBackupFunc( obj, key, nil )
end
else
local data = getFunc( obj )
if ( data ~= nil ) then
setFunc( obj, data )
setBackupFunc( obj, nil )
end
end
end
--[[----------------------------------------------------------------------------------
Plate reader sync variables and functions
----------------------------------------------------------------------------------]]--
-- Declares a table that is used to backup the player's plate reader data
READER.backupData =
{
cams = {
["front"] = nil,
["rear"] = nil
}
}
-- Returns a table with the front and rear plate reader data
function READER:GetReaderDataForSync()
return {
["front"] = self.vars.cams["front"],
["rear"] = self.vars.cams["rear"]
}
end
-- Sets the internal plate reader data for the given camera
function READER:SetReaderCamData( cam, data )
if ( type( data ) == "table" ) then
self.vars.cams[cam] = data
end
end
-- Getter and setter for the backup plate reader data
function READER:GetBackupReaderData( cam ) return self.backupData.cams[cam] end
function READER:SetBackupReaderData( cam, data ) self.backupData.cams[cam] = data end
-- Returns if there is any backup data for the plate reader
function READER:IsThereBackupData()
return self:GetBackupReaderData( "front" ) ~= nil or self:GetBackupReaderData( "rear" ) ~= nil
end
-- Backs up the player's plate reader data
function READER:BackupData()
-- Get the player's data
local data = self:GetReaderDataForSync()
-- Iterate through the front and rear camera
for cam in UTIL:Values( { "front", "rear" } ) do
-- Check that there isn't already backup data, then if not, back up the player's data
if ( self:GetBackupReaderData( cam ) == nil ) then
self:SetBackupReaderData( cam, data[cam] )
end
end
end
-- Replaces the internal plate reader data with the data provided
function READER:LoadDataFromDriver( data )
-- Backup the local data first
self:BackupData()
-- As a precaution, give the system 50ms before it replaces the local data with the data from the driver
Citizen.SetTimeout( 50, function()
-- Set the camera data
for cam in UTIL:Values( { "front", "rear" } ) do
self:SetReaderCamData( cam, data[cam] )
end
-- Force the NUI side to update the plate reader display with the new data
self:ForceNUIUpdate( true )
end )
end
-- Restores the backed up plate reader data
function READER:RestoreFromBackup()
-- Iterate through the cameras and restore their backups
for cam in UTIL:Values( { "front", "rear" } ) do
RestoreData( READER, READER.GetBackupReaderData, READER.SetReaderCamData, READER.SetBackupReaderData, cam )
end
-- Force the NUI side to update the plate reader display with the restored data
self:ForceNUIUpdate( true )
end
--[[----------------------------------------------------------------------------------
Radar sync variables and functions
----------------------------------------------------------------------------------]]--
-- Declares a table that is used to backup the player's radar data
RADAR.backupData = {
power = nil,
om = nil,
antennas = {
["front"] = nil,
["rear"] = nil
}
}
-- Returns a table with the power state, operator meny, front and rear radar data
function RADAR:GetRadarDataForSync()
return {
power = self.vars.power,
om = self.vars.settings,
["front"] = self.vars.antennas["front"],
["rear"] = self.vars.antennas["rear"]
}
end
-- Returns the radar's internal operator menu settings table
function RADAR:GetOMTableData() return self.vars.settings end
-- Sets the operator menu settings table within the radar's main variables table
function RADAR:SetOMTableData( data )
if ( type( data ) == "table" ) then
self.vars.settings = data
self:UpdateOptionIndexes( false )
end
end
-- Sets the antenna settings table for the given antenna within the radar's main variables table
function RADAR:SetAntennaTableData( ant, data )
if ( type( data ) == "table" ) then
self.vars.antennas[ant] = data
end
end
-- Getter and setter for the backup radar power state
function RADAR:GetBackupPowerState() return self.backupData.power end
function RADAR:SetBackupPowerState( state ) self.backupData.power = state end
-- Getter and setter for the backup radar operator menu data
function RADAR:GetBackupOMData() return self.backupData.om end
function RADAR:SetBackupOMData( data ) self.backupData.om = data end
-- Getter and setter for the backup radar antennas data
function RADAR:GetBackupAntennaData( ant ) return self.backupData.antennas[ant] end
function RADAR:SetBackupAntennaData( ant, data ) self.backupData.antennas[ant] = data end
-- Retuns if there is any backup radar data
function RADAR:IsThereBackupData()
return self:GetBackupOMData() ~= nil or self:GetBackupAntennaData( "front" ) ~= nil or self:GetBackupAntennaData( "rear" ) ~= nil
end
-- Used when the player becomes a passenger in another vehicle. The local data is backed up to make way for the data
-- provided by the driver. When the player becomes the driver again, the local data is restored.
function RADAR:BackupData()
local data = self:GetRadarDataForSync()
-- Backup the power state
if ( self:GetBackupPowerState() == nil ) then
self:SetBackupPowerState( data.power )
end
-- Backup operator menu data
if ( self:GetBackupOMData() == nil ) then
self:SetBackupOMData( data.om )
end
-- Only backup the radar data if the player has the power on. There's no point backing up the data as it'll just
-- get reset when they turn the power on anyway
if ( data.power ) then
-- Backup front and rear antenna data
for ant in UTIL:Values( { "front", "rear" } ) do
if ( self:GetBackupAntennaData( ant ) == nil ) then
self:SetBackupAntennaData( ant, data[ant] )
end
end
end
end
-- Backs up the local radar data and then replaces it with the data provided by the driver
function RADAR:LoadDataFromDriver( data )
-- Backup the local data first
self:BackupData()
-- As a precaution, give the system 50ms before it replaces the local data with the data from the driver
Citizen.SetTimeout( 50, function()
-- Set the operator menu settings
self:SetOMTableData( data.om )
-- Set the antenna data
for ant in UTIL:Values( { "front", "rear" } ) do
self:SetAntennaTableData( ant, data[ant] )
end
-- Set the power state
self:SetPowerState( data.power, true )
-- Update the display
if ( data.power ) then
self:SendSettingUpdate()
end
end )
end
-- Restores the local player's operator menu and antenna data
function RADAR:RestoreFromBackup()
-- Restore the operator menu data
RestoreData( RADAR, RADAR.GetBackupOMData, RADAR.SetOMTableData, RADAR.SetBackupOMData )
-- Iterate through the antennas and restore their backups
for ant in UTIL:Values( { "front", "rear" } ) do
RestoreData( RADAR, RADAR.GetBackupAntennaData, RADAR.SetAntennaTableData, RADAR.SetBackupAntennaData, ant )
end
-- Get the power state
local pwrState = self:GetBackupPowerState()
-- Restore the power state
if ( pwrState ~= nil ) then
self:SetPowerState( pwrState, true )
self:SetBackupPowerState( nil )
end
-- Update the display
if ( pwrState ) then
Citizen.SetTimeout( 50, function()
self:SendSettingUpdate()
end )
end
end
--[[----------------------------------------------------------------------------------
Sync variables
----------------------------------------------------------------------------------]]--
SYNC = {}
--[[----------------------------------------------------------------------------------
Sync functions
----------------------------------------------------------------------------------]]--
-- Returns if the given player has the remote open
function SYNC:IsRemoteAlreadyOpen( ply )
if ( not RADAR:IsPassengerViewAllowed() ) then
return false
else
return DecorGetBool( ply, "wk_wars2x_sync_remoteOpen" )
end
end
-- Sets the remote open decor for the local player to the given state
function SYNC:SetRemoteOpenState( state )
if ( RADAR:IsPassengerViewAllowed() ) then
DecorSetBool( PLY.ped, "wk_wars2x_sync_remoteOpen", state )
end
end
-- Used to get the other ped (driver/passenger) in a vehicle and calls the given callback. This function will only work
-- if the player can control the radar, it also ensures that the other ped (if found) exists and is a player. The other
-- player's server ID is passed to the given callback as an argument.
function SYNC:SyncData( cb )
if ( PLY:CanControlRadar() ) then
local otherPly = PLY:GetOtherPedServerId()
if ( otherPly ~= nil ) then
cb( otherPly )
end
end
end
-- Sends the radar's power state to the other player (driver/passenger)
function SYNC:SendPowerState( state )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendPowerState", ply, state )
end )
end
-- Sends the power state for the given antenna to the other player (driver/passenger)
function SYNC:SendAntennaPowerState( state, ant )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendAntennaPowerState", ply, state, ant )
end )
end
-- Sends the mode for the given antenna to the other player (driver/passenger)
function SYNC:SendAntennaMode( ant, mode )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendAntennaMode", ply, ant, mode )
end )
end
-- Sends a lock/unlock state, as well as the current player's displayed data to the other player (driver/passenger)
function SYNC:LockAntennaSpeed( ant, data )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendLockAntennaSpeed", ply, ant, data )
end )
end
-- Sends the given operator menu table data to the other player
function SYNC:SendUpdatedOMData( data )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendUpdatedOMData", ply, data )
end )
end
-- Sends the plate reader lock event with the data from the reader that was locked
function SYNC:LockReaderCam( cam, data )
self:SyncData( function( ply )
TriggerServerEvent( "wk_wars2x_sync:sendLockCameraPlate", ply, cam, data )
end )
end
-- Requests radar data from the driver if the player has just entered a valid vehicle as a front seat passenger
function SYNC:SyncDataOnEnter()
-- Make sure passenger view is allowed, also, using PLY:IsPassenger() already checks that the player's
-- vehicle meets the requirements of what the radar requires. This way we don't have to do additional
-- checks manually.
if ( PLY:IsPassenger() ) then
local driver = PLY:GetOtherPedServerId()
-- Only trigger the event if there is actually a driver
if ( driver ~= nil ) then
TriggerServerEvent( "wk_wars2x_sync:requestRadarData", driver )
end
elseif ( PLY:IsDriver() ) then
if ( RADAR:IsThereBackupData() ) then
-- Restore the local data
RADAR:RestoreFromBackup()
READER:RestoreFromBackup()
end
end
end
--[[----------------------------------------------------------------------------------
Sync client events
----------------------------------------------------------------------------------]]--
-- Event for receiving the radar powet state
RegisterNetEvent( "wk_wars2x_sync:receivePowerState" )
AddEventHandler( "wk_wars2x_sync:receivePowerState", function( state )
-- Set the radar's power
RADAR:SetPowerState( state, false )
end )
-- Event for receiving a power state for the given antenna
RegisterNetEvent( "wk_wars2x_sync:receiveAntennaPowerState" )
AddEventHandler( "wk_wars2x_sync:receiveAntennaPowerState", function( state, antenna )
-- Get the current local antenna power state
local power = RADAR:IsAntennaTransmitting( antenna )
-- If the local power state is not the same as the given state, toggle the antenna's power
if ( power ~= state ) then
RADAR:ToggleAntenna( antenna )
end
end )
-- Event for receiving a mode for the given antenna
RegisterNetEvent( "wk_wars2x_sync:receiveAntennaMode" )
AddEventHandler( "wk_wars2x_sync:receiveAntennaMode", function( antenna, mode )
RADAR:SetAntennaMode( antenna, mode )
end )
-- Event for receiving a lock state and speed data for the given antenna
RegisterNetEvent( "wk_wars2x_sync:receiveLockAntennaSpeed" )
AddEventHandler( "wk_wars2x_sync:receiveLockAntennaSpeed", function( antenna, data )
RADAR:LockAntennaSpeed( antenna, data, true )
end )
RegisterNetEvent( "wk_wars2x_sync:receiveLockCameraPlate" )
AddEventHandler( "wk_wars2x_sync:receiveLockCameraPlate", function( camera, data )
READER:LockCam( camera, true, false, data )
end )
-- Event for gathering the radar data and sending it to another player
RegisterNetEvent( "wk_wars2x_sync:getRadarDataFromDriver" )
AddEventHandler( "wk_wars2x_sync:getRadarDataFromDriver", function( playerFor )
local radarData = RADAR:GetRadarDataForSync()
local readerData = READER:GetReaderDataForSync()
TriggerServerEvent( "wk_wars2x_sync:sendRadarDataForPassenger", playerFor, { radarData, readerData } )
end )
-- Event for receiving radar data from another player
RegisterNetEvent( "wk_wars2x_sync:receiveRadarData" )
AddEventHandler( "wk_wars2x_sync:receiveRadarData", function( data )
RADAR:LoadDataFromDriver( data[1] )
READER:LoadDataFromDriver( data[2] )
end )
-- Event for receiving updated operator menu data from another player
RegisterNetEvent( "wk_wars2x_sync:receiveUpdatedOMData" )
AddEventHandler( "wk_wars2x_sync:receiveUpdatedOMData", function( data )
if ( PLY:IsDriver() or ( PLY:IsPassenger() and RADAR:IsThereBackupData() ) ) then
RADAR:SetOMTableData( data )
RADAR:SendSettingUpdate()
end
end )

View File

@@ -2,13 +2,13 @@
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD my Discord: https://discord.gg/fD4e6WD
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -35,49 +35,49 @@ UTIL = {}
-- Returns a number to a set number of decimal places -- Returns a number to a set number of decimal places
function UTIL:Round( num, numDecimalPlaces ) function UTIL:Round( num, numDecimalPlaces )
return tonumber( string.format( "%." .. ( numDecimalPlaces or 0 ) .. "f", num ) ) return tonumber( string.format( "%." .. ( numDecimalPlaces or 0 ) .. "f", num ) )
end end
-- The custom font used for the digital displays have the ¦ symbol as an empty character, this function -- The custom font used for the digital displays have the ¦ symbol as an empty character, this function
-- takes a speed and returns a formatted speed that can be displayed on the radar -- takes a speed and returns a formatted speed that can be displayed on the radar
function UTIL:FormatSpeed( speed ) function UTIL:FormatSpeed( speed )
-- Return "Err" (Error) if the given speed is outside the 0-999 range -- Return "Err" (Error) if the given speed is outside the 0-999 range
if ( speed < 0 or speed > 999 ) then return "Err" end if ( speed < 0 or speed > 999 ) then return "Err" end
-- Convert the speed to a string -- Convert the speed to a string
local text = tostring( speed ) local text = tostring( speed )
local pipes = "" local pipes = ""
-- Create a string of pipes (¦) for the number of spaces -- Create a string of pipes (¦) for the number of spaces
for i = 1, 3 - string.len( text ) do for i = 1, 3 - string.len( text ) do
pipes = pipes .. "¦" pipes = pipes .. "¦"
end end
-- Return the formatted speed -- Return the formatted speed
return pipes .. text return pipes .. text
end end
-- Returns a clamped numerical value based on the given parameters -- Returns a clamped numerical value based on the given parameters
function UTIL:Clamp( val, min, max ) function UTIL:Clamp( val, min, max )
-- Return the min value if the given value is less than the min -- Return the min value if the given value is less than the min
if ( val < min ) then if ( val < min ) then
return min return min
-- Return the max value if the given value is larger than the max -- Return the max value if the given value is larger than the max
elseif ( val > max ) then elseif ( val > max ) then
return max return max
end end
-- Return the given value if it's between the min and max -- Return the given value if it's between the min and max
return val return val
end end
-- Returns if the given table is empty, includes numerical and non-numerical key values -- Returns if the given table is empty, includes numerical and non-numerical key values
function UTIL:IsTableEmpty( t ) function UTIL:IsTableEmpty( t )
local c = 0 local c = 0
for _ in pairs( t ) do c = c + 1 end for _ in pairs( t ) do c = c + 1 end
return c == 0 return c == 0
end end
-- Credit to Deltanic for this function -- Credit to Deltanic for this function
function UTIL:Values( xs ) function UTIL:Values( xs )
@@ -96,31 +96,46 @@ function UTIL:GetVehicleInDirection( entFrom, coordFrom, coordTo )
return vehicle return vehicle
end end
-- Returns if a target vehicle is coming towards or going away from the patrol vehicle, it has a range -- Returns if a target vehicle is coming towards or going away from the patrol vehicle, it has a range
-- so if a vehicle is sideways compared to the patrol vehicle, the directional arrows won't light up -- so if a vehicle is sideways compared to the patrol vehicle, the directional arrows won't light up
function UTIL:GetEntityRelativeDirection( myAng, tarAng ) function UTIL:GetEntityRelativeDirection( myAng, tarAng )
local angleDiff = math.abs( ( myAng - tarAng + 180 ) % 360 - 180 ) local angleDiff = math.abs( ( myAng - tarAng + 180 ) % 360 - 180 )
if ( angleDiff < 45 ) then if ( angleDiff < 45 ) then
return 1 return 1
elseif ( angleDiff > 135 ) then elseif ( angleDiff > 135 ) then
return 2 return 2
end end
return 0 return 0
end end
-- Your everyday GTA notification function -- Returns if there is a player in the given vehicle
function UTIL:IsPlayerInVeh( veh )
for i = -1, GetVehicleMaxNumberOfPassengers( veh ) + 1, 1 do
local ped = GetPedInVehicleSeat( veh, i )
if ( DoesEntityExist( ped ) ) then
if ( IsPedAPlayer( ped ) ) then return true end
end
end
return false
end
-- Your everyday GTA notification function
function UTIL:Notify( text ) function UTIL:Notify( text )
SetNotificationTextEntry( "STRING" ) SetNotificationTextEntry( "STRING" )
AddTextComponentSubstringPlayerName( text ) AddTextComponentSubstringPlayerName( text )
DrawNotification( false, true ) DrawNotification( false, true )
end end
-- Prints the given message to the client console
function UTIL:Log( msg ) function UTIL:Log( msg )
print( "[Wraith ARS 2X]: " .. msg ) print( "[Wraith ARS 2X]: " .. msg )
end end
-- Used to draw text to the screen, helpful for debugging issues
function UTIL:DrawDebugText( x, y, scale, centre, text ) function UTIL:DrawDebugText( x, y, scale, centre, text )
SetTextFont( 4 ) SetTextFont( 4 )
SetTextProportional( 0 ) SetTextProportional( 0 )
@@ -136,6 +151,11 @@ function UTIL:DrawDebugText( x, y, scale, centre, text )
DrawText( x, y ) DrawText( x, y )
end end
-- Returns if the current resource name is valid
function UTIL:IsResourceNameValid()
return GetCurrentResourceName() == "wk_wars2x"
end
--[[The MIT License (MIT) --[[The MIT License (MIT)
Copyright (c) 2017 IllidanS4 Copyright (c) 2017 IllidanS4

View File

@@ -2,13 +2,13 @@
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD my Discord: https://discord.gg/fD4e6WD
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -34,23 +34,39 @@
CONFIG = {} CONFIG = {}
-- Radar fast limit locking -- Radar fast limit locking
-- When enabled, the player will be able to define a fast limit within the radar's menu, when a vehicle -- When enabled, the player will be able to define a fast limit within the radar's menu, when a vehicle
-- exceeds the fast limit, it will be locked into the fast box. Default setting is disabled to maintain realism -- exceeds the fast limit, it will be locked into the fast box. Default setting is disabled to maintain realism
CONFIG.allow_fast_limit = false CONFIG.allow_fast_limit = true
-- Radar only lock players with auto fast locking
-- When enabled, the radar will only automatically lock a speed if the caught vehicle has a real player in it.
CONFIG.only_lock_players = false
-- In-game first time quick start video -- In-game first time quick start video
-- When enabled, the player will be asked if they'd like to view the quick start video the first time they -- When enabled, the player will be asked if they'd like to view the quick start video the first time they
-- open the remote. -- open the remote.
CONFIG.allow_quick_start_video = true CONFIG.allow_quick_start_video = true
-- Allow passenger view
-- When enabled, the front seat passenger will be able to view the radar and plate reader from their end.
CONFIG.allow_passenger_view = false
-- Allow passenger control
-- Dependent on CONFIG.allow_passenger_view. When enabled, the front seat passenger will be able to open the
-- radar remote and control the radar and plate reader for themself and the driver.
CONFIG.allow_passenger_control = false
-- Set this to true if you use Sonoran CAD with the WraithV2 plugin
CONFIG.use_sonorancad = false
-- Sets the defaults of all keybinds -- Sets the defaults of all keybinds
-- These keybinds can be changed by each person in their GTA Settings->Keybinds->FiveM -- These keybinds can be changed by each person in their GTA Settings->Keybinds->FiveM
CONFIG.keyDefaults = CONFIG.keyDefaults =
{ {
-- Remote control key -- Remote control key
remote_control = "f5", remote_control = "f5",
-- Radar key lock key -- Radar key lock key
key_lock = "l", key_lock = "l",
-- Radar front antenna lock/unlock Key -- Radar front antenna lock/unlock Key
@@ -67,33 +83,41 @@ CONFIG.keyDefaults =
} }
-- Here you can change the default values for the operator menu, do note, if any of these values are not -- Here you can change the default values for the operator menu, do note, if any of these values are not
-- one of the options listed, the script will not work. -- one of the options listed, the script will not work.
CONFIG.menuDefaults = CONFIG.menuDefaults =
{ {
-- Should the system calculate and display faster targets -- Should the system calculate and display faster targets
-- Options: true or false -- Options: true or false
["fastDisplay"] = true, ["fastDisplay"] = true,
-- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles -- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles
-- Options: 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.2, 0.4, 0.6, 0.8, 1.0
["same"] = 0.6, ["same"] = 0.6,
["opp"] = 0.6, ["opp"] = 0.6,
-- The volume of the audible beep -- The volume of the audible beep
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["beep"] = 0.6, ["beep"] = 0.6,
-- The volume of the verbal lock confirmation -- The volume of the verbal lock confirmation
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["voice"] = 0.6, ["voice"] = 0.6,
-- The volume of the plate reader audio -- The volume of the plate reader audio
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["plateAudio"] = 0.6, ["plateAudio"] = 0.6,
-- The speed unit used in conversions -- The speed unit used in conversions
-- Options: mph or kmh -- Options: mph or kmh
["speedType"] = "mph" ["speedType"] = "mph",
-- The state for automatic speed locking. This requires CONFIG.allow_fast_limit to be true.
-- Options: true or false
["fastLock"] = false,
-- The speed limit required for automatic speed locking. This requires CONFIG.allow_fast_limit to be true.
-- Options: 0 to 200
["fastLimit"] = 60
} }
-- Here you can change the default scale of the UI elements, as well as the safezone size -- Here you can change the default scale of the UI elements, as well as the safezone size
@@ -103,12 +127,12 @@ CONFIG.uiDefaults =
-- Options: 0.25 - 2.5 -- Options: 0.25 - 2.5
scale = scale =
{ {
radar = 1.0, radar = 0.75,
remote = 1.0, remote = 0.75,
plateReader = 1.0 plateReader = 0.75
}, },
-- The safezone size, must be a multiple of 5. -- The safezone size, must be a multiple of 5.
-- Options: 0 - 100 -- Options: 0 - 100
safezone = 20 safezone = 20
} }

View File

@@ -2,13 +2,13 @@
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD my Discord: https://discord.gg/fD4e6WD
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -31,20 +31,19 @@
---------------------------------------------------------------------------------------]]-- ---------------------------------------------------------------------------------------]]--
-- Define the FX Server version and game type -- Define the FX Server version and game type
fx_version "bodacious" fx_version "cerulean"
game "gta5" game "gta5"
-- Define the resource metadata -- Define the resource metadata
name "Wraith ARS 2X" name "Wraith ARS 2X"
description "Police radar and plate reader system for FiveM" description "Police radar and plate reader system for FiveM"
author "WolfKnight" author "WolfKnight"
version "1.2.4" version "1.3.0"
-- Include the files -- Include the files
files { files {
"nui/radar.html", "nui/radar.html",
"nui/radar.css", "nui/radar.css",
"nui/jquery-3.4.1.min.js",
"nui/radar.js", "nui/radar.js",
"nui/images/*.png", "nui/images/*.png",
"nui/images/plates/*.png", "nui/images/plates/*.png",
@@ -59,10 +58,13 @@ ui_page "nui/radar.html"
-- Run the server scripts -- Run the server scripts
server_script "sv_version_check.lua" server_script "sv_version_check.lua"
server_script "sv_exports.lua" server_script "sv_exports.lua"
server_script "sv_sync.lua"
server_export "TogglePlateLock" server_export "TogglePlateLock"
-- Run the client scripts -- Run the client scripts
client_script "config.lua" client_script "config.lua"
client_script "cl_utils.lua" client_script "cl_utils.lua"
client_script "cl_player.lua"
client_script "cl_radar.lua" client_script "cl_radar.lua"
client_script "cl_plate_reader.lua" client_script "cl_plate_reader.lua"
client_script "cl_sync.lua"

File diff suppressed because one or more lines are too long

View File

@@ -8,7 +8,7 @@
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -159,6 +159,14 @@ button:focus { outline: none; }
color: rgb(255, 255, 0); color: rgb(255, 255, 0);
} }
.green {
color: rgb( 0, 255, 0 );
}
.red {
color: rgb( 255, 0, 0 );
}
.arrow { .arrow {
width: 11px; width: 11px;
height: 15.4px; height: 15.4px;
@@ -770,7 +778,7 @@ button:focus { outline: none; }
#plateReaderBox { #plateReaderBox {
width: 225px; width: 225px;
height: 300px; height: 330px;
position: absolute; position: absolute;
margin: auto; margin: auto;

View File

@@ -8,7 +8,7 @@
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -245,6 +245,8 @@
<input id="boloText" type="text" maxlength="8" placeholder="12ABC345" onkeypress="checkPlateInput(event)" class="plate_input"/> <input id="boloText" type="text" maxlength="8" placeholder="12ABC345" onkeypress="checkPlateInput(event)" class="plate_input"/>
<button id="setBoloPlate" class="btn">Set BOLO Plate</button> <button id="setBoloPlate" class="btn">Set BOLO Plate</button>
<button id="clearBoloPlate" class="btn">Clear BOLO Plate</button>
</div> </div>
<button id="closePlateReaderSettings" class="close">CLOSE</button> <button id="closePlateReaderSettings" class="close">CLOSE</button>
@@ -298,7 +300,7 @@
<button id="closeUiSettings" class="close">CLOSE</button> <button id="closeUiSettings" class="close">CLOSE</button>
</div> </div>
<p id="keyLockLabel">Radar key lock <span id="keyLockStateLabel"></span></p> <p id="keyLockLabel">Radar key binds <span id="keyLockStateLabel"></span></p>
<div id="helpWindow"> <div id="helpWindow">
<iframe id="helpWeb" src="about:blank"></iframe> <iframe id="helpWeb" src="about:blank"></iframe>
@@ -317,7 +319,7 @@
</div> </div>
<!-- Load JavaScript files --> <!-- Load JavaScript files -->
<script src="jquery-3.4.1.min.js"></script> <script src="nui://game/ui/jquery.js" type="text/javascript"></script>
<script src="radar.js"></script> <script src="radar.js"></script>
</body> </body>
</html> </html>

View File

@@ -8,7 +8,7 @@
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -33,7 +33,6 @@
/*------------------------------------------------------------------------------------ /*------------------------------------------------------------------------------------
Variables Variables
------------------------------------------------------------------------------------*/ ------------------------------------------------------------------------------------*/
var resourceName;
var uiEdited = false; var uiEdited = false;
// All of the audio file names // All of the audio file names
@@ -90,6 +89,7 @@ const elements =
plateReaderBox: $( "#plateReaderBox" ), plateReaderBox: $( "#plateReaderBox" ),
boloText: $( "#boloText" ), boloText: $( "#boloText" ),
setBoloBtn: $( "#setBoloPlate" ), setBoloBtn: $( "#setBoloPlate" ),
clearBoloBtn: $( "#clearBoloPlate" ),
closePrBtn: $( "#closePlateReaderSettings" ), closePrBtn: $( "#closePlateReaderSettings" ),
openHelp: $( "#helpBtn" ), openHelp: $( "#helpBtn" ),
@@ -494,7 +494,7 @@ function poweringUp()
} }
// Simulates the 'fully powered' state of the radar unit // Simulates the 'fully powered' state of the radar unit
function poweredUp() function poweredUp( fastDisplay )
{ {
// Completely clear everything // Completely clear everything
clearEverything(); clearEverything();
@@ -505,14 +505,14 @@ function poweredUp()
// Even though the clearEverything() function is called above, we run this so the fast window // Even though the clearEverything() function is called above, we run this so the fast window
// displays 'HLd' // displays 'HLd'
setAntennaXmit( ant, false ); setAntennaXmit( ant, false );
setAntennaFastMode( ant, true ); setAntennaFastMode( ant, fastDisplay );
} }
} }
// Runs the startup process or clears everything, the Lua side calls for the full powered up state // Runs the startup process or clears everything, the Lua side calls for the full powered up state
function radarPower( state ) function radarPower( state, override, fastDisplay )
{ {
state ? poweringUp() : clearEverything(); state ? ( override ? poweredUp( fastDisplay ) : poweringUp() ) : clearEverything();
} }
@@ -605,17 +605,27 @@ function menu( optionText, option )
elements.patrolSpeed.html( option ); elements.patrolSpeed.html( option );
} }
var keyLockTimeout;
// Makes the key lock label fade in then fade out after 2 seconds // Makes the key lock label fade in then fade out after 2 seconds
function displayKeyLock( state ) function displayKeyLock( state )
{ {
let sl = elements.keyLock.stateLabel;
// Set the state label text to enabled or disabled // Set the state label text to enabled or disabled
elements.keyLock.stateLabel.html( state ? "enabled" : "disabled" ); sl.html( state ? "blocked" : "enabled" );
// Change the colour of the altered text
state ? sl.addClass( "red" ).removeClass( "green" ) : sl.addClass( "green" ).removeClass( "red" );
// Fade in the label // Fade in the label
elements.keyLock.label.fadeIn(); elements.keyLock.label.fadeIn();
// Clear the timeout if it already exists
clearTimeout( keyLockTimeout );
// Make the label fade out after 2 seconds // Make the label fade out after 2 seconds
setTimeout( function() { keyLockTimeout = setTimeout( function() {
elements.keyLock.label.fadeOut(); elements.keyLock.label.fadeOut();
}, 2000 ); }, 2000 );
} }
@@ -629,7 +639,7 @@ $.ajaxSetup({
// This function is used to send data back through to the LUA side // This function is used to send data back through to the LUA side
function sendData( name, data ) { function sendData( name, data ) {
$.post( "https://" + resourceName + "/" + name, JSON.stringify( data ), function( datab ) { $.post( "https://wk_wars2x/" + name, JSON.stringify( data ), function( datab ) {
if ( datab != "ok" ) { if ( datab != "ok" ) {
console.log( datab ); console.log( datab );
} }
@@ -767,6 +777,11 @@ elements.setBoloBtn.click( function() {
} }
} ) } )
// Sets the on click function for the clear BOLO button
elements.clearBoloBtn.click( function() {
sendData( "clearBoloPlate", null );
} )
// Checks what the user is typing into the plate box // Checks what the user is typing into the plate box
function checkPlateInput( event ) function checkPlateInput( event )
{ {
@@ -1077,9 +1092,6 @@ window.addEventListener( "message", function( event ) {
switch ( type ) { switch ( type ) {
// System events // System events
case "updatePathName":
resourceName = item.pathName
break;
case "loadUiSettings": case "loadUiSettings":
loadUiSettings( item.data, true ); loadUiSettings( item.data, true );
break; break;
@@ -1102,10 +1114,10 @@ window.addEventListener( "message", function( event ) {
setEleVisible( elements.radar, item.state ); setEleVisible( elements.radar, item.state );
break; break;
case "radarPower": case "radarPower":
radarPower( item.state ); radarPower( item.state, item.override, item.fast );
break; break;
case "poweredUp": case "poweredUp":
poweredUp(); poweredUp( item.fast );
break; break;
case "update": case "update":
updateDisplays( item.speed, item.antennas ); updateDisplays( item.speed, item.antennas );

78
sv_sync.lua Normal file
View File

@@ -0,0 +1,78 @@
--[[---------------------------------------------------------------------------------------
Wraith ARS 2X
Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
---------------------------------------------------------------------------------------]]--
--[[----------------------------------------------------------------------------------
Sync server events
----------------------------------------------------------------------------------]]--
RegisterNetEvent( "wk_wars2x_sync:sendPowerState" )
AddEventHandler( "wk_wars2x_sync:sendPowerState", function( target, state )
TriggerClientEvent( "wk_wars2x_sync:receivePowerState", target, state )
end )
RegisterNetEvent( "wk_wars2x_sync:sendAntennaPowerState" )
AddEventHandler( "wk_wars2x_sync:sendAntennaPowerState", function( target, state, ant )
TriggerClientEvent( "wk_wars2x_sync:receiveAntennaPowerState", target, state, ant )
end )
RegisterNetEvent( "wk_wars2x_sync:sendAntennaMode" )
AddEventHandler( "wk_wars2x_sync:sendAntennaMode", function( target, ant, mode )
TriggerClientEvent( "wk_wars2x_sync:receiveAntennaMode", target, ant, mode )
end )
RegisterNetEvent( "wk_wars2x_sync:sendLockAntennaSpeed" )
AddEventHandler( "wk_wars2x_sync:sendLockAntennaSpeed", function( target, ant, data )
TriggerClientEvent( "wk_wars2x_sync:receiveLockAntennaSpeed", target, ant, data )
end )
RegisterNetEvent( "wk_wars2x_sync:sendLockCameraPlate" )
AddEventHandler( "wk_wars2x_sync:sendLockCameraPlate", function( target, cam, data )
TriggerClientEvent( "wk_wars2x_sync:receiveLockCameraPlate", target, cam, data )
end )
--[[----------------------------------------------------------------------------------
Radar data sync server events
----------------------------------------------------------------------------------]]--
RegisterNetEvent( "wk_wars2x_sync:requestRadarData" )
AddEventHandler( "wk_wars2x_sync:requestRadarData", function( target )
TriggerClientEvent( "wk_wars2x_sync:getRadarDataFromDriver", target, source )
end )
RegisterNetEvent( "wk_wars2x_sync:sendRadarDataForPassenger" )
AddEventHandler( "wk_wars2x_sync:sendRadarDataForPassenger", function( playerFor, data )
TriggerClientEvent( "wk_wars2x_sync:receiveRadarData", playerFor, data )
end )
RegisterNetEvent( "wk_wars2x_sync:sendUpdatedOMData" )
AddEventHandler( "wk_wars2x_sync:sendUpdatedOMData", function( playerFor, data )
TriggerClientEvent( "wk_wars2x_sync:receiveUpdatedOMData", playerFor, data )
end )

View File

@@ -2,13 +2,13 @@
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD my Discord: https://discord.gg/fD4e6WD
MIT License MIT License
Copyright (c) 2020 WolfKnight Copyright (c) 2020-2021 WolfKnight
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
@@ -31,48 +31,52 @@
---------------------------------------------------------------------------------------]]-- ---------------------------------------------------------------------------------------]]--
-- Branding! -- Branding!
local label = local label =
[[ [[
// //
|| __ __ _ _ _ _____ _____ ___ __ __ || __ __ _ _ _ _ ___ ___ _____ __
|| \ \ / / (_) | | | /\ | __ \ / ____| |__ \\ \ / / || \ \ / / _ __ _(_) |_| |_ /_\ | _ \/ __| |_ ) \/ /
|| \ \ /\ / / __ __ _ _| |_| |__ / \ | |__) | (___ ) |\ V / || \ \/\/ / '_/ _` | | _| ' \ / _ \| /\__ \ / / > <
|| \ \/ \/ / '__/ _` | | __| '_ \ / /\ \ | _ / \___ \ / / > < || \_/\_/|_| \__,_|_|\__|_||_| /_/ \_\_|_\|___/ /___/_/\_\
|| \ /\ /| | | (_| | | |_| | | | / ____ \| | \ \ ____) | / /_ / . \ ||
|| \/ \/ |_| \__,_|_|\__|_| |_| /_/ \_\_| \_\_____/ |____/_/ \_\ || Created by WolfKnight
||
|| Created by WolfKnight
||]] ||]]
-- Returns the current version set in fxmanifest.lua -- Returns the current version set in fxmanifest.lua
function GetCurrentVersion() function GetCurrentVersion()
return GetResourceMetadata( GetCurrentResourceName(), "version" ) return GetResourceMetadata( GetCurrentResourceName(), "version" )
end end
-- Grabs the latest version number from the web GitHub -- Grabs the latest version number from the web GitHub
PerformHttpRequest( "https://wolfknight98.github.io/wk_wars2x_web/version.txt", function( err, text, headers ) PerformHttpRequest( "https://wolfknight98.github.io/wk_wars2x_web/version.txt", function( err, text, headers )
-- Wait to reduce spam -- Wait to reduce spam
Citizen.Wait( 2000 ) Citizen.Wait( 2000 )
-- Print the branding! -- Print the branding!
print( label ) print( label )
-- Get the current resource version -- Get the current resource version
local curVer = GetCurrentVersion() local curVer = GetCurrentVersion()
if ( text ~= nil ) then print( " || Current version: " .. curVer )
-- Print out the current and latest version
print( " || Current version: " .. curVer ) if ( text ~= nil ) then
-- Print latest version
print( " || Latest recommended version: " .. text .."\n ||" ) print( " || Latest recommended version: " .. text .."\n ||" )
-- If the versions are different, print it out -- If the versions are different, print it out
if ( text ~= curVer ) then if ( text ~= curVer ) then
print( " || ^1Your Wraith ARS 2X version is outdated, visit the FiveM forum post to get the latest version.\n^0 \\\\\n" ) print( " || ^1Your Wraith ARS 2X version is outdated, visit the FiveM forum post to get the latest version.\n^0 \\\\\n" )
else else
print( " || ^2Wraith ARS 2X is up to date!\n^0 ||\n \\\\\n" ) print( " || ^2Wraith ARS 2X is up to date!\n^0 ||\n \\\\\n" )
end end
else else
-- In case the version can not be requested, print out an error message -- In case the version can not be requested, print out an error message
print( " || ^1There was an error getting the latest version information, if the issue persists contact WolfKnight#8586 on Discord.\n^0 ||\n \\\\\n" ) print( " || ^1There was an error getting the latest version information.\n^0 ||\n \\\\\n" )
end end
-- Warn the console if the resource has been renamed, as this will cause issues with the resource's functionality.
if ( GetCurrentResourceName() ~= "wk_wars2x" ) then
print( "^1ERROR: Resource name is not wk_wars2x, expect there to be issues with the resource. To ensure there are no issues, please leave the resource name as wk_wars2x^0\n\n" )
end
end ) end )