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

1
.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

@@ -27,13 +27,29 @@ All of the configuration for the Wraith ARS 2X is done inside the `config.lua` f
-- 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 =
@@ -84,7 +100,15 @@ CONFIG.menuDefaults =
-- 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,9 +118,9 @@ 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.

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
@@ -68,6 +68,10 @@ READER.vars =
} }
} }
--[[----------------------------------------------------------------------------------
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
@@ -82,64 +86,58 @@ function READER:ToggleDisplayState()
SendNUIMessage( { _type = "setReaderDisplayState", state = self:GetDisplayState() } ) SendNUIMessage( { _type = "setReaderDisplayState", state = self:GetDisplayState() } )
end end
-- Sets the display's hidden state to the given state -- Getter and setter for the display hidden state
function READER:SetDisplayHidden( state ) function READER:GetDisplayHidden() return self.vars.hidden end
self.vars.hidden = state function READER:SetDisplayHidden( state ) self.vars.hidden = state end
end
-- Returns if the display is hidden -- Getter and setter for the given camera's plate
function READER:GetDisplayHidden() function READER:GetPlate( cam ) return self.vars.cams[cam].plate end
return self.vars.hidden function READER:SetPlate( cam, plate ) self.vars.cams[cam].plate = plate end
end
-- Returns the stored plate for the given reader -- Getter and setter for the given camera's plate display index
function READER:GetPlate( cam ) function READER:GetIndex( cam ) return self.vars.cams[cam].index end
return self.vars.cams[cam].plate function READER:SetIndex( cam, index ) self.vars.cams[cam].index = index end
end
-- Sets the plate for the given reader to the given plate
function READER:SetPlate( cam, plate )
self.vars.cams[cam].plate = plate
end
-- Returns the stored plate index for the given reader
function READER:GetIndex( cam )
return self.vars.cams[cam].index
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()
if ( self.vars.boloPlate ~= nil ) then
return self.vars.boloPlate return self.vars.boloPlate
end
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
-- Clears the BOLO plate
function READER:ClearBoloPlate()
self.vars.boloPlate = nil
UTIL:Notify( "~b~BOLO plate cleared!" )
end 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
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = isBolo } )
-- Play a beep -- Play a beep
if ( self:GetCamLocked( cam ) ) then 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] )
self:ForceNUIUpdate( false )
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
@@ -151,6 +149,9 @@ function READER:LockCam( cam, playBeep, isBolo )
-- 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
-- Tell the NUI side to show/hide the lock icon
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = isBolo } )
end end
end end
@@ -168,25 +169,64 @@ function READER:GetCamFromNum( relPos )
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 )
--[[----------------------------------------------------------------------------------
Plate reader NUI callbacks
----------------------------------------------------------------------------------]]--
-- Runs when the "Toggle Display" button is pressed on the plate reder box -- 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
@@ -237,11 +277,15 @@ function READER:Main()
-- 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 )
SYNC:LockReaderCam( cam, READER:GetCameraDataPacket( cam ) )
end 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 } )
-- If we use Sonoran CAD, reduce the plate events to just player's vehicle, otherwise life as normal
if ( ( CONFIG.use_sonorancad and ( UTIL:IsPlayerInVeh( veh ) or IsVehiclePreviouslyOwnedByPlayer( veh ) ) and GetVehicleClass( veh ) ~= 18 ) or not CONFIG.use_sonorancad ) then
-- Trigger the event so developers can hook into the scanner every time a plate is scanned -- Trigger the event so developers can hook into the scanner every time a plate is scanned
TriggerServerEvent( "wk:onPlateScanned", cam, plate, index ) TriggerServerEvent( "wk:onPlateScanned", cam, plate, index )
end end
@@ -249,6 +293,7 @@ function READER:Main()
end end
end end
end end
end
end end
-- Main thread -- Main thread
@@ -269,7 +314,7 @@ 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

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 )

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
@@ -39,31 +39,89 @@ local tostring = tostring
local math = math local math = math
local pairs = pairs local pairs = pairs
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
Resource Rename Fix - for those muppets who rename the resource and Key bind registering
complain that the NUI aspect doesn't work!
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
Citizen.SetTimeout( 1000, function() local function RegisterKeyBinds()
-- Get the name of the resource, for example the default name is 'wk_wars2x' if ( UTIL:IsResourceNameValid() ) then
local name = string.lower( GetCurrentResourceName() ) UTIL:Log( "Registering radar commands and key binds." )
-- Print a little message in the client's console -- Opens the remote control
UTIL:Log( "Sending resource name (" .. name .. ") to JavaScript side." ) RegisterCommand( "radar_remote", function()
if ( not RADAR:GetKeyLockState() ) then
RADAR:OpenRemote()
end
end )
RegisterKeyMapping( "radar_remote", "Open Remote Control", "keyboard", CONFIG.keyDefaults.remote_control )
-- Send a message through the NUI system to the JavaScript file to give the name of the resource -- Locks speed from front antenna
SendNUIMessage( { _type = "updatePathName", pathName = name } ) RegisterCommand( "radar_fr_ant", function()
end ) if ( not RADAR:GetKeyLockState() and PLY:CanControlRadar() ) then
RADAR:LockAntennaSpeed( "front", nil )
SYNC:LockAntennaSpeed( "front", RADAR:GetAntennaDataPacket( "front" ) )
end
end )
RegisterKeyMapping( "radar_fr_ant", "Front Antenna Lock/Unlock", "keyboard", CONFIG.keyDefaults.front_lock )
-- Locks speed from rear antenna
RegisterCommand( "radar_bk_ant", function()
if ( not RADAR:GetKeyLockState() and PLY:CanControlRadar() ) then
RADAR:LockAntennaSpeed( "rear", nil )
SYNC:LockAntennaSpeed( "rear", RADAR:GetAntennaDataPacket( "rear" ) )
end
end )
RegisterKeyMapping( "radar_bk_ant", "Rear Antenna Lock/Unlock", "keyboard", CONFIG.keyDefaults.rear_lock )
-- Locks front plate reader
RegisterCommand( "radar_fr_cam", function()
if ( not RADAR:GetKeyLockState() and PLY:CanControlRadar() ) then
READER:LockCam( "front", true, false )
SYNC:LockReaderCam( "front", READER:GetCameraDataPacket( "front" ) )
end
end )
RegisterKeyMapping( "radar_fr_cam", "Front Plate Reader Lock/Unlock", "keyboard", CONFIG.keyDefaults.plate_front_lock )
-- Locks rear plate reader
RegisterCommand( "radar_bk_cam", function()
if ( not RADAR:GetKeyLockState() and PLY:CanControlRadar() ) then
READER:LockCam( "rear", true, false )
SYNC:LockReaderCam( "rear", READER:GetCameraDataPacket( "rear" ) )
end
end )
RegisterKeyMapping( "radar_bk_cam", "Rear Plate Reader Lock/Unlock", "keyboard", CONFIG.keyDefaults.plate_rear_lock )
-- Toggles the key lock state
RegisterCommand( "radar_key_lock", function()
RADAR:ToggleKeyLock()
end )
RegisterKeyMapping( "radar_key_lock", "Toggle Keybind Lock", "keyboard", CONFIG.keyDefaults.key_lock )
-- Deletes all of the KVPs
RegisterCommand( "reset_radar_data", function()
DeleteResourceKvp( "wk_wars2x_ui_data" )
DeleteResourceKvp( "wk_wars2x_om_data" )
DeleteResourceKvp( "wk_wars2x_new_user" )
UTIL:Notify( "Radar data deleted, please immediately restart your game without opening the radar's remote." )
end, false )
TriggerEvent( "chat:addSuggestion", "/reset_radar_data", "Resets the KVP data stored for the wk_wars2x resource." )
else
UTIL:Log( "ERROR: Resource name is not wk_wars2x. Key binds will not be registered for compatibility reasons. Contact the server owner and ask them to change the resource name back to wk_wars2x" )
end
end
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
UI loading trigger UI loading and key binds trigger
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
local spawned = false local spawned = false
-- Runs every time the player spawns, but the additional check means it only runs the first time local function LoadUISettings()
-- the player spawns
AddEventHandler( "playerSpawned", function()
if ( not spawned ) then
UTIL:Log( "Attempting to load saved UI settings data." ) UTIL:Log( "Attempting to load saved UI settings data." )
-- Try and get the saved UI data -- Try and get the saved UI data
@@ -80,39 +138,31 @@ AddEventHandler( "playerSpawned", function()
UTIL:Log( "Could not find any saved UI settings data." ) UTIL:Log( "Could not find any saved UI settings data." )
end end
end
-- Runs every time the player spawns, but the additional check means it only runs the first time
-- the player spawns
AddEventHandler( "playerSpawned", function()
if ( not spawned ) then
RegisterKeyBinds()
LoadUISettings()
spawned = true spawned = true
end end
end ) end )
-- Loads the UI settings when the resource gets restarted, this way active users don't have the
-- default settings applied
AddEventHandler( "onResourceStart", function( resourceName )
if ( GetCurrentResourceName() == resourceName ) then
Citizen.CreateThread( function()
Citizen.Wait( 1000 )
--[[---------------------------------------------------------------------------------- RegisterKeyBinds()
Player info variables LoadUISettings()
----------------------------------------------------------------------------------]]--
PLY =
{
ped = PlayerPedId(),
veh = nil,
inDriverSeat = false,
vehClassValid = false
}
-- Used to check if the player is in a position where the radar should be allowed operation DecorSetBool( PlayerPedId(), "wk_wars2x_sync_remoteOpen", false )
function PLY:VehicleStateValid() end )
return DoesEntityExist( self.veh ) and self.veh > 0 and self.inDriverSeat and self.vehClassValid
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.vehClassValid = GetVehicleClass( PLY.veh ) == 18
Citizen.Wait( 500 )
end end
end ) end )
@@ -157,7 +207,13 @@ RADAR.vars =
["plateAudio"] = CONFIG.menuDefaults["plateAudio"], ["plateAudio"] = CONFIG.menuDefaults["plateAudio"],
-- The speed unit used in conversions -- The speed unit used in conversions
["speedType"] = CONFIG.menuDefaults["speedType"] ["speedType"] = CONFIG.menuDefaults["speedType"],
-- The state of automatic speed locking
["fastLock"] = CONFIG.menuDefaults["fastLock"],
-- The speed limit for automatic speed locking
["fastLimit"] = CONFIG.menuDefaults["fastLimit"]
}, },
-- These 3 variables are for the in-radar menu that can be accessed through the remote control, the menuOptions table -- These 3 variables are for the in-radar menu that can be accessed through the remote control, the menuOptions table
@@ -218,10 +274,6 @@ RADAR.vars =
-- Table to store tables for hit entities of captured vehicles -- Table to store tables for hit entities of captured vehicles
capturedVehicles = {}, capturedVehicles = {},
-- Table for temp id storage to stop unnecessary trace checks
-- needs to be redone
-- tempVehicleIDs = {},
-- Table to store the valid vehicle models -- Table to store the valid vehicle models
validVehicles = {}, validVehicles = {},
@@ -286,18 +338,24 @@ function RADAR:SetPoweringUpState( state )
end end
-- Toggles the radar power -- Toggles the radar power
function RADAR:TogglePower() function RADAR:SetPowerState( state, instantOverride )
local currentState = self:IsPowerOn()
-- Only power up if the system is not already powering up
if ( not self:IsPoweringUp() and currentState ~= state ) then
-- Toggle the power variable -- Toggle the power variable
self.vars.power = not self.vars.power self.vars.power = state
-- Send the NUI message to toggle the power -- Send the NUI message to toggle the power
SendNUIMessage( { _type = "radarPower", state = self:IsPowerOn() } ) SendNUIMessage( { _type = "radarPower", state = state, override = instantOverride, fast = self:IsFastDisplayEnabled() } )
-- Power is now turned on -- Power is now turned on
if ( self:IsPowerOn() ) then if ( self:IsPowerOn() ) then
-- Also make sure the operator menu is inactive -- Also make sure the operator menu is inactive
self:SetMenuState( false ) self:SetMenuState( false )
-- Only do the power up simulation if allowed
if ( not instantOverride ) then
-- Tell the system the radar is 'powering up' -- Tell the system the radar is 'powering up'
self:SetPoweringUpState( true ) self:SetPoweringUpState( true )
@@ -307,13 +365,15 @@ function RADAR:TogglePower()
self:SetPoweringUpState( false ) self:SetPoweringUpState( false )
-- Let the UI side know the system has loaded -- Let the UI side know the system has loaded
SendNUIMessage( { _type = "poweredUp" } ) SendNUIMessage( { _type = "poweredUp", fast = self:IsFastDisplayEnabled() } )
end ) end )
end
else else
-- If the system is being turned off, then we reset the antennas -- If the system is being turned off, then we reset the antennas
self:ResetAntenna( "front" ) self:ResetAntenna( "front" )
self:ResetAntenna( "rear" ) self:ResetAntenna( "rear" )
end end
end
end end
-- Toggles the display state of the radar system -- Toggles the display state of the radar system
@@ -330,29 +390,9 @@ function RADAR:GetDisplayState()
return self.vars.displayed return self.vars.displayed
end end
-- Used to set individual settings within RADAR.vars.settings, as all of the settings use string keys, using this
-- function makes updating settings easier
function RADAR:SetSettingValue( setting, value )
-- Make sure that we're not trying to set a nil value for the setting
if ( value ~= nil ) then
-- Set the setting's value
self.vars.settings[setting] = value
-- If the setting that's being updated is same or opp, then we update the end coordinates for the ray tracer
if ( setting == "same" or setting == "opp" ) then
self:UpdateRayEndCoords()
end
end
end
-- Returns the value of the given setting
function RADAR:GetSettingValue( setting )
return self.vars.settings[setting]
end
-- Return the state of the fastDisplay setting, short hand direct way to check if the fast system is enabled -- Return the state of the fastDisplay setting, short hand direct way to check if the fast system is enabled
function RADAR:IsFastDisplayEnabled() function RADAR:IsFastDisplayEnabled()
return self.vars.settings["fastDisplay"] return self:GetSettingValue( "fastDisplay" )
end end
-- Returns if either of the antennas are transmitting -- Returns if either of the antennas are transmitting
@@ -385,32 +425,28 @@ function RADAR:CanPerformMainTask()
return self:IsPowerOn() and not self:IsPoweringUp() and not self:IsMenuOpen() return self:IsPowerOn() and not self:IsPoweringUp() and not self:IsMenuOpen()
end end
-- Returns what the dynamic thread wait time is -- Returns/sets what the dynamic thread wait time is
function RADAR:GetThreadWaitTime() function RADAR:GetThreadWaitTime() return self.vars.threadWaitTime end
return self.vars.threadWaitTime function RADAR:SetThreadWaitTime( time ) self.vars.threadWaitTime = time end
end
-- Sets the dynamic thread wait time to the given value -- Returns/sets the radr's display hidden state
function RADAR:SetThreadWaitTime( time ) function RADAR:GetDisplayHidden() return self.vars.hidden end
self.vars.threadWaitTime = time function RADAR:SetDisplayHidden( state ) self.vars.hidden = state end
end
-- Sets the display's hidden state to the given state -- Opens the remote only if the pause menu is not open and the player's vehicle state is valid, as the
function RADAR:SetDisplayHidden( state ) -- passenger can also open the remote, we check the config variable as well.
self.vars.hidden = state
end
-- Returns if the display is hidden
function RADAR:GetDisplayHidden()
return self.vars.hidden
end
-- Opens the remote only if the pause menu is not open and the player's vehicle state is valid
function RADAR:OpenRemote() function RADAR:OpenRemote()
if ( not IsPauseMenuActive() and PLY:VehicleStateValid() ) then if ( not IsPauseMenuActive() and PLY:CanViewRadar() ) then
-- Get the remote open state from the other player
local openByOtherPly = SYNC:IsRemoteAlreadyOpen( PLY:GetOtherPed() )
-- Check that the remote can be opened
if ( not openByOtherPly ) then
-- Tell the NUI side to open the remote -- Tell the NUI side to open the remote
SendNUIMessage( { _type = "openRemote" } ) SendNUIMessage( { _type = "openRemote" } )
SYNC:SetRemoteOpenState( true )
if ( CONFIG.allow_quick_start_video ) then if ( CONFIG.allow_quick_start_video ) then
-- Display the new user popup if we can -- Display the new user popup if we can
local show = GetResourceKvpInt( "wk_wars2x_new_user" ) local show = GetResourceKvpInt( "wk_wars2x_new_user" )
@@ -422,6 +458,9 @@ function RADAR:OpenRemote()
-- Bring focus to the NUI side -- Bring focus to the NUI side
SetNuiFocus( true, true ) SetNuiFocus( true, true )
else
UTIL:Notify( "Another player already has the remote open." )
end
end end
end end
@@ -431,6 +470,22 @@ AddEventHandler( "wk:openRemote", function()
RADAR:OpenRemote() RADAR:OpenRemote()
end ) end )
-- Returns if the passenger can view the radar too
function RADAR:IsPassengerViewAllowed()
return CONFIG.allow_passenger_view
end
-- Returns if the passenger can control the radar and plate reader, reliant on the passenger being
-- able to view the radar and plate reader too
function RADAR:IsPassengerControlAllowed()
return CONFIG.allow_passenger_view and CONFIG.allow_passenger_control
end
-- Returns if we only auto lock vehicle speeds if said vehicle is a player
function RADAR:OnlyLockFastPlayers()
return CONFIG.only_lock_players
end
-- Returns if the fast limit option should be available for the radar -- Returns if the fast limit option should be available for the radar
function RADAR:IsFastLimitAllowed() function RADAR:IsFastLimitAllowed()
return CONFIG.allow_fast_limit return CONFIG.allow_fast_limit
@@ -455,10 +510,6 @@ if ( RADAR:IsFastLimitAllowed() ) then
table.insert( fastOptions[2].options, i ) table.insert( fastOptions[2].options, i )
end end
-- Create the settings with the default options
self:SetSettingValue( "fastLock", false )
self:SetSettingValue( "fastLimit", 60 )
-- Add the fast options to the main menu options table -- Add the fast options to the main menu options table
table.insert( self.vars.menuOptions, fastOptions[1] ) table.insert( self.vars.menuOptions, fastOptions[1] )
table.insert( self.vars.menuOptions, fastOptions[2] ) table.insert( self.vars.menuOptions, fastOptions[2] )
@@ -466,19 +517,19 @@ if ( RADAR:IsFastLimitAllowed() ) then
-- Returns the numerical fast limit -- Returns the numerical fast limit
function RADAR:GetFastLimit() function RADAR:GetFastLimit()
return self.vars.settings["fastLimit"] return self:GetSettingValue( "fastLimit" )
end end
-- Returns if the fast lock menu option is on or off -- Returns if the fast lock menu option is on or off
function RADAR:IsFastLockEnabled() function RADAR:IsFastLockEnabled()
return self.vars.settings["fastLock"] return self:GetSettingValue( "fastLock" )
end end
end end
-- Toggles the internal key lock state, which stops any of the radar's key binds from working -- Toggles the internal key lock state, which stops any of the radar's key binds from working
function RADAR:ToggleKeyLock() function RADAR:ToggleKeyLock()
-- Check the player state is valid -- Check the player state is valid
if ( PLY:VehicleStateValid() ) then if ( PLY:CanViewRadar() ) then
-- Toggle the key lock variable -- Toggle the key lock variable
self.vars.keyLock = not self.vars.keyLock self.vars.keyLock = not self.vars.keyLock
@@ -510,6 +561,30 @@ function RADAR:SetMenuState( state )
end end
end end
-- Closes the operator menu
function RADAR:CloseMenu( playAudio )
-- Set the internal menu state to be closed (false)
RADAR:SetMenuState( false )
-- Send a setting update to the NUI side
RADAR:SendSettingUpdate()
-- Play a menu done beep
if ( playAudio or playAudio == nil ) then
SendNUIMessage( { _type = "audio", name = "done", vol = RADAR:GetSettingValue( "beep" ) } )
end
-- Save the operator menu values
local omData = json.encode( RADAR.vars.settings )
SetResourceKvp( "wk_wars2x_om_data", omData )
-- Send the operator menu to the passenger if allowed
if ( self:IsPassengerViewAllowed() ) then
local updatedOMData = self:GetOMTableData()
SYNC:SendUpdatedOMData( updatedOMData )
end
end
-- Returns if the operator menu is open -- Returns if the operator menu is open
function RADAR:IsMenuOpen() function RADAR:IsMenuOpen()
return self.vars.menuActive return self.vars.menuActive
@@ -600,6 +675,26 @@ function RADAR:SendMenuUpdate()
SendNUIMessage( { _type = "menu", text = self:GetMenuOptionDisplayText(), option = self:GetMenuOptionText() } ) SendNUIMessage( { _type = "menu", text = self:GetMenuOptionDisplayText(), option = self:GetMenuOptionText() } )
end end
-- Used to set individual settings within RADAR.vars.settings, as all of the settings use string keys, using this
-- function makes updating settings easier
function RADAR:SetSettingValue( setting, value )
-- Make sure that we're not trying to set a nil value for the setting
if ( value ~= nil ) then
-- Set the setting's value
self.vars.settings[setting] = value
-- If the setting that's being updated is same or opp, then we update the end coordinates for the ray tracer
if ( setting == "same" or setting == "opp" ) then
self:UpdateRayEndCoords()
end
end
end
-- Returns the value of the given setting
function RADAR:GetSettingValue( setting )
return self.vars.settings[setting]
end
-- Attempts to load the saved operator menu data -- Attempts to load the saved operator menu data
function RADAR:LoadOMData() function RADAR:LoadOMData()
UTIL:Log( "Attempting to load saved operator menu data." ) UTIL:Log( "Attempting to load saved operator menu data." )
@@ -620,8 +715,10 @@ end
-- Updates the operator menu option indexes, as the default menu values can be changed in the config, we -- Updates the operator menu option indexes, as the default menu values can be changed in the config, we
-- need to update the indexes otherwise the menu will display the wrong values -- need to update the indexes otherwise the menu will display the wrong values
function RADAR:UpdateOptionIndexes() function RADAR:UpdateOptionIndexes( loadSaved )
if ( loadSaved ) then
self:LoadOMData() self:LoadOMData()
end
-- Iterate through each of the internal settings -- Iterate through each of the internal settings
for k, v in pairs( self.vars.settings ) do for k, v in pairs( self.vars.settings ) do
@@ -647,29 +744,19 @@ end
Radar basics functions Radar basics functions
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
-- Returns the patrol speed value stored -- Returns the patrol speed value stored
function RADAR:GetPatrolSpeed() function RADAR:GetPatrolSpeed() return self.vars.patrolSpeed end
return self.vars.patrolSpeed
end
-- Returns the current vehicle pool -- Returns the current vehicle pool
function RADAR:GetVehiclePool() function RADAR:GetVehiclePool() return self.vars.vehiclePool end
return self.vars.vehiclePool
end
-- Returns the maximum distance a ray trace can go -- Returns the maximum distance a ray trace can go
function RADAR:GetMaxCheckDist() function RADAR:GetMaxCheckDist() return self.vars.maxCheckDist end
return self.vars.maxCheckDist
end
-- Returns the table sorting function 'strongest' -- Returns the table sorting function 'strongest'
function RADAR:GetStrongestSortFunc() function RADAR:GetStrongestSortFunc() return self.sorting.strongest end
return self.sorting.strongest
end
-- Returns the table sorting function 'fastest' -- Returns the table sorting function 'fastest'
function RADAR:GetFastestSortFunc() function RADAR:GetFastestSortFunc() return self.sorting.fastest end
return self.sorting.fastest
end
-- Sets the patrol speed to a formatted version of the given number -- Sets the patrol speed to a formatted version of the given number
function RADAR:SetPatrolSpeed( speed ) function RADAR:SetPatrolSpeed( speed )
@@ -690,29 +777,19 @@ end
Radar ray trace functions Radar ray trace functions
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
-- Returns what the current ray trace state is -- Returns what the current ray trace state is
function RADAR:GetRayTraceState() function RADAR:GetRayTraceState() return self.vars.rayTraceState end
return self.vars.rayTraceState
end
-- Caches the number of ray traces in RADAR.rayTraces -- Caches the number of ray traces in RADAR.rayTraces
function RADAR:CacheNumRays() function RADAR:CacheNumRays() self.vars.numberOfRays = #self.rayTraces end
self.vars.numberOfRays = #self.rayTraces
end
-- Returns the number of ray traces the system has -- Returns the number of ray traces the system has
function RADAR:GetNumOfRays() function RADAR:GetNumOfRays() return self.vars.numberOfRays end
return self.vars.numberOfRays
end
-- Increases the system's ray trace state ny 1 -- Increases the system's ray trace state ny 1
function RADAR:IncreaseRayTraceState() function RADAR:IncreaseRayTraceState() self.vars.rayTraceState = self.vars.rayTraceState + 1 end
self.vars.rayTraceState = self.vars.rayTraceState + 1
end
-- Resets the ray trace state to 0 -- Resets the ray trace state to 0
function RADAR:ResetRayTraceState() function RADAR:ResetRayTraceState() self.vars.rayTraceState = 0 end
self.vars.rayTraceState = 0
end
-- This function is used to determine if a sphere intersect is in front or behind the player's vehicle, the -- This function is used to determine if a sphere intersect is in front or behind the player's vehicle, the
-- sphere intersect calculation has a 'tProj' value that is a line from the centre of the sphere that goes onto -- sphere intersect calculation has a 'tProj' value that is a line from the centre of the sphere that goes onto
@@ -913,21 +990,22 @@ end
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
-- Toggles the state of the given antenna between hold and transmitting, only works if the radar's power is -- Toggles the state of the given antenna between hold and transmitting, only works if the radar's power is
-- on. Also runs a callback function when present. -- on. Also runs a callback function when present.
function RADAR:ToggleAntenna( ant, cb ) function RADAR:ToggleAntenna( ant )
-- Check power is on -- Check power is on
if ( self:IsPowerOn() ) then if ( self:IsPowerOn() ) then
-- Toggle the given antennas state -- Toggle the given antennas state
self.vars.antennas[ant].xmit = not self.vars.antennas[ant].xmit self.vars.antennas[ant].xmit = not self.vars.antennas[ant].xmit
-- Run the callback function if there is one -- Update the interface with the new antenna transmit state
if ( cb ) then cb() end SendNUIMessage( { _type = "antennaXmit", ant = ant, on = self:IsAntennaTransmitting( ant ) } )
-- Play some audio specific to the transmit state
SendNUIMessage( { _type = "audio", name = self:IsAntennaTransmitting( ant ) and "xmit_on" or "xmit_off", vol = self:GetSettingValue( "beep" ) } )
end end
end end
-- Returns if the given antenna is transmitting -- Returns if the given antenna is transmitting
function RADAR:IsAntennaTransmitting( ant ) function RADAR:IsAntennaTransmitting( ant ) return self.vars.antennas[ant].xmit end
return self.vars.antennas[ant].xmit
end
-- Returns if the given relative position value is for the front or rear antenna -- Returns if the given relative position value is for the front or rear antenna
function RADAR:GetAntennaTextFromNum( relPos ) function RADAR:GetAntennaTextFromNum( relPos )
@@ -939,13 +1017,11 @@ function RADAR:GetAntennaTextFromNum( relPos )
end end
-- Returns the mode of the given antenna -- Returns the mode of the given antenna
function RADAR:GetAntennaMode( ant ) function RADAR:GetAntennaMode( ant ) return self.vars.antennas[ant].mode end
return self.vars.antennas[ant].mode
end
-- Sets the mode of the given antenna if the mode is valid and the power is on. Also runs a callback function -- Sets the mode of the given antenna if the mode is valid and the power is on. Also runs a callback function
-- when present. -- when present.
function RADAR:SetAntennaMode( ant, mode, cb ) function RADAR:SetAntennaMode( ant, mode )
-- Check the mode is actually a number, this is needed as the radar system relies on the mode to be -- Check the mode is actually a number, this is needed as the radar system relies on the mode to be
-- a number to work -- a number to work
if ( type( mode ) == "number" ) then if ( type( mode ) == "number" ) then
@@ -954,57 +1030,36 @@ function RADAR:SetAntennaMode( ant, mode, cb )
-- Update the mode for the antenna -- Update the mode for the antenna
self.vars.antennas[ant].mode = mode self.vars.antennas[ant].mode = mode
-- Run the callback function if there is one -- Update the interface with the new mode
if ( cb ) then cb() end SendNUIMessage( { _type = "antennaMode", ant = ant, mode = mode } )
-- Play a beep
SendNUIMessage( { _type = "audio", name = "beep", vol = self:GetSettingValue( "beep" ) } )
end end
end end
end end
-- Returns the speed stored for the given antenna -- Returns/sets the speed for the given antenna
function RADAR:GetAntennaSpeed( ant ) function RADAR:GetAntennaSpeed( ant ) return self.vars.antennas[ant].speed end
return self.vars.antennas[ant].speed function RADAR:SetAntennaSpeed( ant, speed ) self.vars.antennas[ant].speed = speed end
end
-- Sets the speed of the given antenna to the given speed -- Returns/sets the direction for the given antenna
function RADAR:SetAntennaSpeed( ant, speed ) function RADAR:GetAntennaDir( ant ) return self.vars.antennas[ant].dir end
self.vars.antennas[ant].speed = speed function RADAR:SetAntennaDir( ant, dir ) self.vars.antennas[ant].dir = dir end
end
-- Returns the direction value stored for the given antenna -- Sets the speed and direction in one go
function RADAR:GetAntennaDir( ant )
return self.vars.antennas[ant].dir
end
-- Sets the direction value of the given antenna to the given direction
function RADAR:SetAntennaDir( ant, dir )
self.vars.antennas[ant].dir = dir
end
-- Sets the fast speed and direction in one go
function RADAR:SetAntennaData( ant, speed, dir ) function RADAR:SetAntennaData( ant, speed, dir )
self:SetAntennaSpeed( ant, speed ) self:SetAntennaSpeed( ant, speed )
self:SetAntennaDir( ant, dir ) self:SetAntennaDir( ant, dir )
end end
-- Returns the fast speed stored for the given antenna -- Returns/sets the fast speed for the given antenna
function RADAR:GetAntennaFastSpeed( ant ) function RADAR:GetAntennaFastSpeed( ant ) return self.vars.antennas[ant].fastSpeed end
return self.vars.antennas[ant].fastSpeed function RADAR:SetAntennaFastSpeed( ant, speed ) self.vars.antennas[ant].fastSpeed = speed end
end
-- Sets the fast speed of the given antenna to the given speed -- Returns/sets the fast direction for the given antenna
function RADAR:SetAntennaFastSpeed( ant, speed ) function RADAR:GetAntennaFastDir( ant ) return self.vars.antennas[ant].fastDir end
self.vars.antennas[ant].fastSpeed = speed function RADAR:SetAntennaFastDir( ant, dir ) self.vars.antennas[ant].fastDir = dir end
end
-- Returns the direction value for the fast box stored for the given antenna
function RADAR:GetAntennaFastDir( ant )
return self.vars.antennas[ant].fastDir
end
-- Sets the direction value of the given antenna's fast box to the given direction
function RADAR:SetAntennaFastDir( ant, dir )
self.vars.antennas[ant].fastDir = dir
end
-- Sets the fast speed and direction in one go -- Sets the fast speed and direction in one go
function RADAR:SetAntennaFastData( ant, speed, dir ) function RADAR:SetAntennaFastData( ant, speed, dir )
@@ -1042,7 +1097,7 @@ function RADAR:SetAntennaSpeedIsLocked( ant, state )
end end
-- Sets a speed and direction to be locked in for the given antenna -- Sets a speed and direction to be locked in for the given antenna
function RADAR:SetAntennaSpeedLock( ant, speed, dir, lockType ) function RADAR:SetAntennaSpeedLock( ant, speed, dir, lockType, playAudio )
-- Check that the passed speed and direction are actually valid -- Check that the passed speed and direction are actually valid
if ( speed ~= nil and dir ~= nil and lockType ~= nil ) then if ( speed ~= nil and dir ~= nil and lockType ~= nil ) then
-- Set the locked speed and direction to the passed values -- Set the locked speed and direction to the passed values
@@ -1053,11 +1108,13 @@ function RADAR:SetAntennaSpeedLock( ant, speed, dir, lockType )
-- Tell the system that a speed has been locked for the given antenna -- Tell the system that a speed has been locked for the given antenna
self:SetAntennaSpeedIsLocked( ant, true ) self:SetAntennaSpeedIsLocked( ant, true )
if ( playAudio ) then
-- Send a message to the NUI side to play the beep sound with the current volume setting -- Send a message to the NUI side to play the beep sound with the current volume setting
SendNUIMessage( { _type = "audio", name = "beep", vol = self:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = self:GetSettingValue( "beep" ) } )
-- Send a message to the NUI side to play the lock audio with the current voice volume setting -- Send a message to the NUI side to play the lock audio with the current voice volume setting
SendNUIMessage( { _type = "lockAudio", ant = ant, dir = dir, vol = self:GetSettingValue( "voice" ) } ) SendNUIMessage( { _type = "lockAudio", ant = ant, dir = dir, vol = self:GetSettingValue( "voice" ) } )
end
-- Great Scott! -- Great Scott!
if ( speed == "¦88" and self:GetSettingValue( "speedType" ) == "mph" ) then if ( speed == "¦88" and self:GetSettingValue( "speedType" ) == "mph" ) then
@@ -1101,12 +1158,28 @@ end
-- When the user presses the speed lock key for either antenna, this function is called to get the -- When the user presses the speed lock key for either antenna, this function is called to get the
-- necessary information from the antenna, and then lock it into the display -- necessary information from the antenna, and then lock it into the display
function RADAR:LockAntennaSpeed( ant ) function RADAR:LockAntennaSpeed( ant, override, lockRegardless )
-- Only lock a speed if the antenna is on and the UI is displayed -- Only lock a speed if the antenna is on and the UI is displayed
if ( self:IsPowerOn() and self:GetDisplayState() and not self:GetDisplayHidden() and self:IsAntennaTransmitting( ant ) ) then if ( self:IsPowerOn() and ( ( self:GetDisplayState() and not self:GetDisplayHidden() ) or lockRegardless ) and self:IsAntennaTransmitting( ant ) ) then
-- Used to determine whether or not to play the audio and update the display. This is mainly for the passenger
-- control system, as in theory one player could be in the operator menu, and the other player could lock a speed.
local isMenuOpen = self:IsMenuOpen()
-- Check if the antenna doesn't have a locked speed, if it doesn't then we lock in the speed, otherwise we -- Check if the antenna doesn't have a locked speed, if it doesn't then we lock in the speed, otherwise we
-- reset the lock -- reset the lock
if ( not self:IsAntennaSpeedLocked( ant ) ) then if ( not self:IsAntennaSpeedLocked( ant ) ) then
-- Here we check if the override parameter is valid, if so then we set the radar's speed data to the
-- speed data provided in the override table.
if ( override ~= nil ) then
self:SetAntennaData( ant, override[1], override[2] )
self:SetAntennaFastData( ant, override[3], override[4] )
end
-- This override parameter is used for the passenger control system, as the speeds displayed on the
-- recipients display can't be trusted. When the player who locks the speed triggers the sync, their
-- speed data is collected and sent to the other player so that their speed data is overriden to be the same.
override = override or { nil, nil, nil, nil }
-- Set up a temporary table with 3 nil values, this way if the system isn't able to get a speed or -- Set up a temporary table with 3 nil values, this way if the system isn't able to get a speed or
-- direction, the speed lock function won't work -- direction, the speed lock function won't work
local data = { nil, nil, nil } local data = { nil, nil, nil }
@@ -1124,15 +1197,17 @@ function RADAR:LockAntennaSpeed( ant )
end end
-- Lock in the speed data for the antenna -- Lock in the speed data for the antenna
self:SetAntennaSpeedLock( ant, data[1], data[2], data[3] ) self:SetAntennaSpeedLock( ant, data[1], data[2], data[3], not isMenuOpen )
else else
self:ResetAntennaSpeedLock( ant ) self:ResetAntennaSpeedLock( ant )
end end
if ( not isMenuOpen ) then
-- Send an NUI message to change the lock label, otherwise we'd have to wait until the next main loop -- Send an NUI message to change the lock label, otherwise we'd have to wait until the next main loop
SendNUIMessage( { _type = "antennaLock", ant = ant, state = self:IsAntennaSpeedLocked( ant ) } ) SendNUIMessage( { _type = "antennaLock", ant = ant, state = self:IsAntennaSpeedLocked( ant ) } )
SendNUIMessage( { _type = "antennaFast", ant = ant, state = self:ShouldFastBeDisplayed( ant ) } ) SendNUIMessage( { _type = "antennaFast", ant = ant, state = self:ShouldFastBeDisplayed( ant ) } )
end end
end
end end
-- Resets an antenna, used when the system is turned off -- Resets an antenna, used when the system is turned off
@@ -1146,6 +1221,16 @@ function RADAR:ResetAntenna( ant )
self:ResetAntennaSpeedLock( ant ) self:ResetAntennaSpeedLock( ant )
end end
-- Returns a table with the given antenna's speed data and directions
function RADAR:GetAntennaDataPacket( ant )
return {
self:GetAntennaSpeed( ant ),
self:GetAntennaDir( ant ),
self:GetAntennaFastSpeed( ant ),
self:GetAntennaFastDir( ant )
}
end
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
Radar captured vehicle functions Radar captured vehicle functions
@@ -1267,15 +1352,9 @@ function RADAR:GetVehSpeedConverted( speed )
return UTIL:Round( speed * self.speedConversions[unit], 0 ) return UTIL:Round( speed * self.speedConversions[unit], 0 )
end end
-- Returns the validity of the given vehicle model -- Returns/sets the validity of the given vehicle model
function RADAR:GetVehicleValidity( key ) function RADAR:GetVehicleValidity( key ) return self.vars.validVehicles[key] end
return self.vars.validVehicles[key] function RADAR:SetVehicleValidity( key, validity ) self.vars.validVehicles[key] = validity end
end
-- Sets the validity for the given vehicle model
function RADAR:SetVehicleValidity( key, validity )
self.vars.validVehicles[key] = validity
end
-- Returns if vehicle validity data exists for the given vehicle model -- Returns if vehicle validity data exists for the given vehicle model
function RADAR:DoesVehicleValidityExist( key ) function RADAR:DoesVehicleValidityExist( key )
@@ -1422,57 +1501,61 @@ end
RegisterNUICallback( "toggleRadarDisplay", function( data, cb ) RegisterNUICallback( "toggleRadarDisplay", function( data, cb )
-- Toggle the display state -- Toggle the display state
RADAR:ToggleDisplayState() RADAR:ToggleDisplayState()
cb('ok') cb( "ok" )
end ) end )
-- Runs when the user presses the power button on the radar ui -- Runs when the user presses the power button on the radar ui
RegisterNUICallback( "togglePower", function( data, cb ) RegisterNUICallback( "togglePower", function( data, cb )
if ( PLY:CanControlRadar() ) then
if ( not RADAR:IsPoweringUp() ) then
-- Toggle the radar's power -- Toggle the radar's power
RADAR:TogglePower() RADAR:SetPowerState( not RADAR:IsPowerOn(), false )
cb('ok')
SYNC:SendPowerState( RADAR:IsPowerOn() )
end
end
cb( "ok" )
end ) end )
-- Runs when the user presses the ESC or RMB when the remote is open -- Runs when the user presses the ESC or RMB when the remote is open
RegisterNUICallback( "closeRemote", function( data, cb ) RegisterNUICallback( "closeRemote", function( data, cb )
-- Remove focus to the NUI side -- Remove focus to the NUI side
SetNuiFocus( false, false ) SetNuiFocus( false, false )
cb('ok')
if ( RADAR:IsMenuOpen() ) then
RADAR:CloseMenu( false )
end
SYNC:SetRemoteOpenState( false )
cb( "ok" )
end ) end )
-- Runs when the user presses any of the antenna mode buttons on the remote -- Runs when the user presses any of the antenna mode buttons on the remote
RegisterNUICallback( "setAntennaMode", function( data, cb ) RegisterNUICallback( "setAntennaMode", function( data, cb )
if ( PLY:CanControlRadar() ) then
-- Only run the codw if the radar has power and is not powering up -- Only run the codw if the radar has power and is not powering up
if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then
-- As the mode buttons are used to exit the menu, we check for that -- As the mode buttons are used to exit the menu, we check for that
if ( RADAR:IsMenuOpen() ) then if ( RADAR:IsMenuOpen() ) then
-- Set the internal menu state to be closed (false) RADAR:CloseMenu()
RADAR:SetMenuState( false )
-- Send a setting update to the NUI side
RADAR:SendSettingUpdate()
-- Play a menu done beep
SendNUIMessage( { _type = "audio", name = "done", vol = RADAR:GetSettingValue( "beep" ) } )
-- Save the operator menu values
local omData = json.encode( RADAR.vars.settings )
SetResourceKvp( "wk_wars2x_om_data", omData )
else else
-- Change the mode for the designated antenna, pass along a callback which contains data from this NUI callback -- Change the mode for the designated antenna, pass along a callback which contains data from this NUI callback
RADAR:SetAntennaMode( data.value, tonumber( data.mode ), function() RADAR:SetAntennaMode( data.value, tonumber( data.mode ) )
-- Update the interface with the new mode
SendNUIMessage( { _type = "antennaMode", ant = data.value, mode = tonumber( data.mode ) } )
-- Play a beep -- Sync
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } ) SYNC:SendAntennaMode( data.value, tonumber( data.mode ) )
end )
end end
end end
cb('ok') end
cb( "ok" )
end ) end )
-- Runs when the user presses either of the XMIT/HOLD buttons on the remote -- Runs when the user presses either of the XMIT/HOLD buttons on the remote
RegisterNUICallback( "toggleAntenna", function( data, cb ) RegisterNUICallback( "toggleAntenna", function( data, cb )
if ( PLY:CanControlRadar() ) then
-- Only run the codw if the radar has power and is not powering up -- Only run the codw if the radar has power and is not powering up
if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then
-- As the xmit/hold buttons are used to change settings in the menu, we check for that -- As the xmit/hold buttons are used to change settings in the menu, we check for that
@@ -1484,20 +1567,20 @@ RegisterNUICallback( "toggleAntenna", function( data, cb )
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } )
else else
-- Toggle the transmit state for the designated antenna, pass along a callback which contains data from this NUI callback -- Toggle the transmit state for the designated antenna, pass along a callback which contains data from this NUI callback
RADAR:ToggleAntenna( data.value, function() RADAR:ToggleAntenna( data.value )
-- Update the interface with the new antenna transmit state
SendNUIMessage( { _type = "antennaXmit", ant = data.value, on = RADAR:IsAntennaTransmitting( data.value ) } )
-- Play some audio specific to the transmit state -- Sync
SendNUIMessage( { _type = "audio", name = RADAR:IsAntennaTransmitting( data.value ) and "xmit_on" or "xmit_off", vol = RADAR:GetSettingValue( "beep" ) } ) SYNC:SendAntennaPowerState( RADAR:IsAntennaTransmitting( data.value ), data.value )
end )
end end
end end
cb('ok') end
cb( "ok" )
end ) end )
-- Runs when the user presses the menu button on the remote control -- Runs when the user presses the menu button on the remote control
RegisterNUICallback( "menu", function( data, cb ) RegisterNUICallback( "menu", function( data, cb )
if ( PLY:CanControlRadar() ) then
-- Only run the codw if the radar has power and is not powering up -- Only run the codw if the radar has power and is not powering up
if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then if ( RADAR:IsPowerOn() and not RADAR:IsPoweringUp() ) then
-- As the menu button is a multipurpose button, we first check to see if the menu is already open -- As the menu button is a multipurpose button, we first check to see if the menu is already open
@@ -1515,20 +1598,22 @@ RegisterNUICallback( "menu", function( data, cb )
-- Play the standard audio beep -- Play the standard audio beep
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } )
end end
cb('ok') end
cb( "ok" )
end ) end )
-- Runs when the JavaScript side sends the UI data for saving -- Runs when the JavaScript side sends the UI data for saving
RegisterNUICallback( "saveUiData", function( data, cb ) RegisterNUICallback( "saveUiData", function( data, cb )
UTIL:Log( "Saving updated UI settings data." ) UTIL:Log( "Saving updated UI settings data." )
SetResourceKvp( "wk_wars2x_ui_data", json.encode( data ) ) SetResourceKvp( "wk_wars2x_ui_data", json.encode( data ) )
cb('ok') cb( "ok" )
end ) end )
-- Runs when the JavaScript side sends the quick start video has been watched -- Runs when the JavaScript side sends the quick start video has been watched
RegisterNUICallback( "qsvWatched", function( data, cb ) RegisterNUICallback( "qsvWatched", function( data, cb )
SetResourceKvpInt( "wk_wars2x_new_user", 1 ) SetResourceKvpInt( "wk_wars2x_new_user", 1 )
cb('ok') cb( "ok" )
end ) end )
@@ -1573,7 +1658,7 @@ end )
function RADAR:RunThreads() function RADAR:RunThreads()
-- For the system to even run, the player needs to be sat in the driver's seat of a class 18 vehicle, the -- For the system to even run, the player needs to be sat in the driver's seat of a class 18 vehicle, the
-- radar has to be visible and the power must be on, and either one of the antennas must be enabled. -- radar has to be visible and the power must be on, and either one of the antennas must be enabled.
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() and self:IsEitherAntennaOn() ) then if ( PLY:CanViewRadar() and self:CanPerformMainTask() and self:IsEitherAntennaOn() ) then
-- Before we create any of the custom ray trace threads, we need to make sure that the ray trace state -- Before we create any of the custom ray trace threads, we need to make sure that the ray trace state
-- is at zero, if it is not at zero, then it means the system is still currently tracing -- is at zero, if it is not at zero, then it means the system is still currently tracing
if ( self:GetRayTraceState() == 0 ) then if ( self:GetRayTraceState() == 0 ) then
@@ -1615,7 +1700,7 @@ end )
function RADAR:Main() function RADAR:Main()
-- Only run any of the main code if all of the states are met, player in the driver's seat of a class 18 vehicle, and -- Only run any of the main code if all of the states are met, player in the driver's seat of a class 18 vehicle, and
-- the system has to be able to perform main tasks -- the system has to be able to perform main tasks
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then if ( PLY:CanViewRadar() and self:CanPerformMainTask() ) then
-- Create a table that will be used to store all of the data to be sent to the NUI side -- Create a table that will be used to store all of the data to be sent to the NUI side
local data = {} local data = {}
@@ -1687,7 +1772,12 @@ function RADAR:Main()
if ( self:IsFastLimitAllowed() ) then if ( self:IsFastLimitAllowed() ) then
-- Make sure the speed is larger than the limit, and that there isn't already a locked speed -- Make sure the speed is larger than the limit, and that there isn't already a locked speed
if ( self:IsFastLockEnabled() and convertedSpeed > self:GetFastLimit() and not self:IsAntennaSpeedLocked( ant ) ) then if ( self:IsFastLockEnabled() and convertedSpeed > self:GetFastLimit() and not self:IsAntennaSpeedLocked( ant ) ) then
self:LockAntennaSpeed( ant ) if ( ( self:OnlyLockFastPlayers() and UTIL:IsPlayerInVeh( av[ant][i].veh ) ) or not self:OnlyLockFastPlayers() ) then
if ( PLY:IsDriver() ) then
self:LockAntennaSpeed( ant, nil, false )
SYNC:LockAntennaSpeed( ant, RADAR:GetAntennaDataPacket( ant ) )
end
end
end end
end end
else else
@@ -1719,14 +1809,14 @@ Citizen.CreateThread( function()
-- Update the end coordinates for the ray traces based on the config, again, reduced hard coding -- Update the end coordinates for the ray traces based on the config, again, reduced hard coding
RADAR:UpdateRayEndCoords() RADAR:UpdateRayEndCoords()
-- Update the operator menu positions
RADAR:UpdateOptionIndexes()
-- If the fast limit feature is allowed, create the config in the radar variables -- If the fast limit feature is allowed, create the config in the radar variables
if ( RADAR:IsFastLimitAllowed() ) then if ( RADAR:IsFastLimitAllowed() ) then
RADAR:CreateFastLimitConfig() RADAR:CreateFastLimitConfig()
end end
-- Update the operator menu positions
RADAR:UpdateOptionIndexes( true )
-- Run the main radar function -- Run the main radar function
while ( true ) do while ( true ) do
RADAR:Main() RADAR:Main()
@@ -1742,7 +1832,7 @@ function RADAR: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 = "setRadarDisplayState", state = false } ) SendNUIMessage( { _type = "setRadarDisplayState", 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 = "setRadarDisplayState", state = true } ) SendNUIMessage( { _type = "setRadarDisplayState", state = true } )
end end
@@ -1764,7 +1854,7 @@ end )
-- Update the vehicle pool every 3 seconds -- Update the vehicle pool every 3 seconds
function RADAR:UpdateVehiclePool() function RADAR:UpdateVehiclePool()
-- Only update the vehicle pool if we need to -- Only update the vehicle pool if we need to
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() and self:IsEitherAntennaOn() ) then if ( PLY:CanViewRadar() and self:CanPerformMainTask() and self:IsEitherAntennaOn() ) then
-- Get the active vehicle set -- Get the active vehicle set
local vehs = self:GetAllVehicles() local vehs = self:GetAllVehicles()
@@ -1783,60 +1873,3 @@ Citizen.CreateThread( function()
Citizen.Wait( 3000 ) Citizen.Wait( 3000 )
end end
end ) end )
Citizen.CreateThread( function()
Citizen.Wait( 3000 )
-- Opens the remote control
RegisterCommand( "radar_remote", function()
if ( not RADAR:GetKeyLockState() ) then
RADAR:OpenRemote()
end
end )
RegisterKeyMapping( "radar_remote", "Open Remote Control", "keyboard", CONFIG.keyDefaults.remote_control )
-- Locks speed from front antenna
RegisterCommand( "radar_fr_ant", function()
if ( not RADAR:GetKeyLockState() ) then
RADAR:LockAntennaSpeed( "front" )
end
end )
RegisterKeyMapping( "radar_fr_ant", "Front Antenna Lock/Unlock", "keyboard", CONFIG.keyDefaults.front_lock )
-- Locks speed from rear antenna
RegisterCommand( "radar_bk_ant", function()
if ( not RADAR:GetKeyLockState() ) then
RADAR:LockAntennaSpeed( "rear" )
end
end )
RegisterKeyMapping( "radar_bk_ant", "Rear Antenna Lock/Unlock", "keyboard", CONFIG.keyDefaults.rear_lock )
-- Locks front plate reader
RegisterCommand( "radar_fr_cam", function()
if ( not RADAR:GetKeyLockState() ) then
READER:LockCam( "front", true, false )
end
end )
RegisterKeyMapping( "radar_fr_cam", "Front Plate Reader Lock/Unlock", "keyboard", CONFIG.keyDefaults.plate_front_lock )
-- Locks rear plate reader
RegisterCommand( "radar_bk_cam", function()
if ( not RADAR:GetKeyLockState() ) then
READER:LockCam( "rear", true, false )
end
end )
RegisterKeyMapping( "radar_bk_cam", "Rear Plate Reader Lock/Unlock", "keyboard", CONFIG.keyDefaults.plate_rear_lock )
-- Toggles the key lock state
RegisterCommand( "radar_key_lock", function()
RADAR:ToggleKeyLock()
end )
RegisterKeyMapping( "radar_key_lock", "Toggle Keybind Lock", "keyboard", CONFIG.keyDefaults.key_lock )
-- Deletes all of the KVPs
RegisterCommand( "reset_radar_data", function()
DeleteResourceKvp( "wk_wars2x_ui_data" )
DeleteResourceKvp( "wk_wars2x_om_data" )
DeleteResourceKvp( "wk_wars2x_new_user" )
end, false )
end )

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

@@ -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
@@ -110,6 +110,19 @@ function UTIL:GetEntityRelativeDirection( myAng, tarAng )
return 0 return 0
end end
-- 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 -- Your everyday GTA notification function
function UTIL:Notify( text ) function UTIL:Notify( text )
SetNotificationTextEntry( "STRING" ) SetNotificationTextEntry( "STRING" )
@@ -117,10 +130,12 @@ function UTIL:Notify( 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

@@ -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
@@ -36,13 +36,29 @@ 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 =
@@ -93,7 +109,15 @@ CONFIG.menuDefaults =
-- 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,9 +127,9 @@ 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.

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
@@ -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

@@ -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
@@ -34,12 +34,10 @@
local label = local label =
[[ [[
// //
|| __ __ _ _ _ _____ _____ ___ __ __ || __ __ _ _ _ _ ___ ___ _____ __
|| \ \ / / (_) | | | /\ | __ \ / ____| |__ \\ \ / / || \ \ / / _ __ _(_) |_| |_ /_\ | _ \/ __| |_ ) \/ /
|| \ \ /\ / / __ __ _ _| |_| |__ / \ | |__) | (___ ) |\ V / || \ \/\/ / '_/ _` | | _| ' \ / _ \| /\__ \ / / > <
|| \ \/ \/ / '__/ _` | | __| '_ \ / /\ \ | _ / \___ \ / / > < || \_/\_/|_| \__,_|_|\__|_||_| /_/ \_\_|_\|___/ /___/_/\_\
|| \ /\ /| | | (_| | | |_| | | | / ____ \| | \ \ ____) | / /_ / . \
|| \/ \/ |_| \__,_|_|\__|_| |_| /_/ \_\_| \_\_____/ |____/_/ \_\
|| ||
|| Created by WolfKnight || Created by WolfKnight
||]] ||]]
@@ -60,9 +58,10 @@ PerformHttpRequest( "https://wolfknight98.github.io/wk_wars2x_web/version.txt",
-- Get the current resource version -- Get the current resource version
local curVer = GetCurrentVersion() local curVer = GetCurrentVersion()
if ( text ~= nil ) then
-- Print out the current and latest version
print( " || Current version: " .. curVer ) 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
@@ -73,6 +72,11 @@ PerformHttpRequest( "https://wolfknight98.github.io/wk_wars2x_web/version.txt",
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
-- 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 ) end )