- Added a server export to toggle plate lock on a client
- Removed old and redundant code
- Added the licence to the top of every file
- Added a small section at the bottom of config.lua to set the default UI element scale, as well as the safezone
- Changed the height of the UI settings box to stop the slider and close button from overlapping
- Added the ability to disable server console messages
- Formatted all code to tab size 4!
This commit is contained in:
Dan
2020-03-05 19:40:37 +00:00
parent d028d35c58
commit d491dc50e4
11 changed files with 1569 additions and 1203 deletions

View File

@@ -1,9 +1,34 @@
--[[----------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
-----------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
READER = {} READER = {}
@@ -15,32 +40,32 @@ READER = {}
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
READER.vars = READER.vars =
{ {
-- Whether or not the plate reader's UI is visible -- Whether or not the plate reader's UI is visible
displayed = false, displayed = false,
-- Whether or not the plate reader should be hidden, e.g. the display is active but the player then steps -- Whether or not the plate reader should be hidden, e.g. the display is active but the player then steps
-- out of their vehicle -- out of their vehicle
hidden = false, hidden = false,
-- The BOLO plate -- The BOLO plate
boloPlate = "", boloPlate = "",
-- Cameras, this table contains all of the data needed for operation of the front and rear plate reader -- Cameras, this table contains all of the data needed for operation of the front and rear plate reader
cams = { cams = {
-- Variables for the front camera -- Variables for the front camera
["front"] = { ["front"] = {
plate = "", -- The current plate caught by the reader plate = "", -- The current plate caught by the reader
index = "", -- The index of the current plate index = "", -- The index of the current plate
locked = false -- If the reader is locked locked = false -- If the reader is locked
}, },
-- Variables for the rear camera -- Variables for the rear camera
["rear"] = { ["rear"] = {
plate = "", -- The current plate caught by the reader plate = "", -- The current plate caught by the reader
index = "", -- The index of the current plate index = "", -- The index of the current plate
locked = false -- If the reader is locked locked = false -- If the reader is locked
} }
} }
} }
-- Gets the display state -- Gets the display state
@@ -69,75 +94,85 @@ end
-- Returns the stored plate for the given reader -- Returns the stored plate for the given reader
function READER:GetPlate( cam ) function READER:GetPlate( cam )
return self.vars.cams[cam].plate return self.vars.cams[cam].plate
end end
-- Sets the plate for the given reader to the given plate -- Sets the plate for the given reader to the given plate
function READER:SetPlate( cam, plate ) function READER:SetPlate( cam, plate )
self.vars.cams[cam].plate = plate self.vars.cams[cam].plate = plate
end end
-- Returns the stored plate index for the given reader -- Returns the stored plate index for the given reader
function READER:GetIndex( cam ) function READER:GetIndex( cam )
return self.vars.cams[cam].index return self.vars.cams[cam].index
end end
-- Sets the plate index for the given reader to the given index -- Sets the plate index for the given reader to the given index
function READER:SetIndex( cam, index ) function READER:SetIndex( cam, index )
self.vars.cams[cam].index = index self.vars.cams[cam].index = index
end end
-- Returns the bolo plate -- Returns the bolo plate
function READER:GetBoloPlate() function READER:GetBoloPlate()
return self.vars.boloPlate return self.vars.boloPlate
end end
-- Sets the bolo plate to the given plate -- Sets the bolo plate to the given plate
function READER:SetBoloPlate( plate ) function READER:SetBoloPlate( plate )
self.vars.boloPlate = plate self.vars.boloPlate = plate
UTIL:Notify( "BOLO plate set to: " .. plate ) UTIL:Notify( "BOLO plate set to: " .. plate )
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 return self.vars.cams[cam].locked
end end
-- Locks the given reader -- Locks the given reader
function READER:LockCam( cam, playAudio, isBolo ) function READER:LockCam( cam, playBeep, isBolo )
-- 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() ) 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 -- Tell the NUI side to show/hide the lock icon
SendNUIMessage( { _type = "lockPlate", cam = cam, state = self:GetCamLocked( cam ), isBolo = isBolo } ) 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
if ( playAudio ) then if ( playBeep ) then
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "plateAudio" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "plateAudio" ) } )
end end
TriggerEvent( "wk:onPlateLocked", cam, self:GetPlate( cam ), self:GetIndex( cam ) ) if ( isBolo ) then
SendNUIMessage( { _type = "audio", name = "plate_hit", vol = RADAR:GetSettingValue( "plateAudio" ) } )
end
-- 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 ) )
end end
end end
end end
-- Returns if the plate reader system can perform tasks -- Returns if the plate reader system can perform tasks
function READER:CanPerformMainTask() function READER:CanPerformMainTask()
return self.vars.displayed and not self.vars.hidden return self.vars.displayed and not self.vars.hidden
end end
-- Returns if the given relative position value is for front or rear -- Returns if the given relative position value is for front or rear
function READER:GetCamFromNum( relPos ) function READER:GetCamFromNum( relPos )
if ( relPos == 1 ) then if ( relPos == 1 ) then
return "front" return "front"
elseif ( relPos == -1 ) then elseif ( relPos == -1 ) then
return "rear" return "rear"
end end
end end
RegisterNetEvent( "wk:togglePlateLock" )
AddEventHandler( "wk:togglePlateLock", function( cam, beep, bolo )
READER:LockCam( cam, beep, bolo )
end )
-- 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() RegisterNUICallback( "togglePlateReaderDisplay", function()
-- Toggle the display state -- Toggle the display state
@@ -146,85 +181,85 @@ 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 )
end ) end )
-- This is the main function that runs and scans all vehicles in front and behind the patrol vehicle -- This is the main function that runs and scans all vehicles in front and behind the patrol vehicle
function READER:Main() function READER:Main()
-- Check that the system can actually run -- Check that the system can actually run
if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then if ( PLY:VehicleStateValid() and self:CanPerformMainTask() ) then
-- Loop through front (1) and rear (-1) -- Loop through front (1) and rear (-1)
for i = 1, -1, -2 do for i = 1, -1, -2 do
-- Get the world position of the player's vehicle -- Get the world position of the player's vehicle
local pos = GetEntityCoords( PLY.veh ) local pos = GetEntityCoords( PLY.veh )
-- Get a start position 5m in front/behind the player's vehicle -- Get a start position 5m in front/behind the player's vehicle
local start = GetOffsetFromEntityInWorldCoords( PLY.veh, 0.0, ( 5.0 * i ), 0.0 ) local start = GetOffsetFromEntityInWorldCoords( PLY.veh, 0.0, ( 5.0 * i ), 0.0 )
-- Get the end position 40m in front/behind the player's vehicle -- Get the end position 50m in front/behind the player's vehicle
local offset = GetOffsetFromEntityInWorldCoords( PLY.veh, -2.5, ( 50.0 * i ), 0.0 ) local offset = GetOffsetFromEntityInWorldCoords( PLY.veh, -2.5, ( 50.0 * i ), 0.0 )
-- Run the ray trace to get a vehicle -- Run the ray trace to get a vehicle
local veh = UTIL:GetVehicleInDirection( PLY.veh, start, offset ) local veh = UTIL:GetVehicleInDirection( PLY.veh, start, offset )
-- Get the plate reader text for front/rear -- Get the plate reader text for front/rear
local cam = self:GetCamFromNum( i ) local cam = self:GetCamFromNum( i )
-- Only proceed to read a plate if the hit entity is a valid vehicle and the current camera isn't locked -- Only proceed to read a plate if the hit entity is a valid vehicle and the current camera isn't locked
if ( DoesEntityExist( veh ) and IsEntityAVehicle( veh ) and not self:GetCamLocked( cam ) ) then if ( DoesEntityExist( veh ) and IsEntityAVehicle( veh ) and not self:GetCamLocked( cam ) ) then
-- Get the heading of the player's vehicle and the hit vehicle -- Get the heading of the player's vehicle and the hit vehicle
local ownH = UTIL:Round( GetEntityHeading( PLY.veh ), 0 ) local ownH = UTIL:Round( GetEntityHeading( PLY.veh ), 0 )
local tarH = UTIL:Round( GetEntityHeading( veh ), 0 ) local tarH = UTIL:Round( GetEntityHeading( veh ), 0 )
-- Get the relative direction between the player's vehicle and the hit vehicle -- Get the relative direction between the player's vehicle and the hit vehicle
local dir = UTIL:GetEntityRelativeDirection( ownH, tarH ) local dir = UTIL:GetEntityRelativeDirection( ownH, tarH )
-- Only run the rest of the plate check code if we can see the front or rear of the vehicle -- Only run the rest of the plate check code if we can see the front or rear of the vehicle
if ( dir > 0 ) then if ( dir > 0 ) then
-- Get the licence plate text from the vehicle -- Get the licence plate text from the vehicle
local plate = GetVehicleNumberPlateText( veh ) local plate = GetVehicleNumberPlateText( veh )
-- Get the licence plate index from the vehicle -- Get the licence plate index from the vehicle
local index = GetVehicleNumberPlateTextIndex( veh ) local index = GetVehicleNumberPlateTextIndex( veh )
-- Only update the stored plate if it's different, otherwise we'd keep sending a NUI message to update the displayed -- Only update the stored plate if it's different, otherwise we'd keep sending a NUI message to update the displayed
-- plate and image even though they're the same -- plate and image even though they're the same
if ( self:GetPlate( cam ) ~= plate ) then if ( self:GetPlate( cam ) ~= plate ) then
-- Set the plate for the current reader -- Set the plate for the current reader
self:SetPlate( cam, plate ) self:SetPlate( cam, plate )
-- Set the plate index for the current reader -- Set the plate index for the current reader
self:SetIndex( cam, index ) self:SetIndex( cam, index )
-- Automatically lock the plate if the scanned plate matches the BOLO -- Automatically lock the plate if the scanned plate matches the BOLO
if ( plate == self:GetBoloPlate() ) then if ( plate == self:GetBoloPlate() ) then
self:LockCam( cam, false, true ) self:LockCam( cam, false, true )
SendNUIMessage( { _type = "audio", name = "plate_hit", vol = RADAR:GetSettingValue( "plateAudio" ) } ) -- SendNUIMessage( { _type = "audio", name = "plate_hit", vol = RADAR:GetSettingValue( "plateAudio" ) } )
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 } )
-- Trigger the event so developers can hook into the scanner -- Trigger the event so developers can hook into the scanner every time a plate is scanned
TriggerEvent( "wk:onPlateScanned", cam, plate, index ) TriggerServerEvent( "wk:onPlateScanned", cam, plate, index )
end end
end end
end end
end end
end end
end end
-- Main thread -- Main thread
Citizen.CreateThread( function() Citizen.CreateThread( function()
while ( true ) do while ( true ) do
-- Run the main plate reader function -- Run the main plate reader function
READER:Main() READER:Main()
-- Wait half a second -- Wait half a second
Citizen.Wait( 500 ) Citizen.Wait( 500 )
end end
end ) end )
-- This function is pretty much straight from WraithRS, it does the job so I didn't see the point in not -- This function is pretty much straight from WraithRS, it does the job so I didn't see the point in not
@@ -244,11 +279,11 @@ end
Citizen.CreateThread( function() Citizen.CreateThread( function()
Citizen.Wait( 100 ) Citizen.Wait( 100 )
while ( true ) do while ( true ) do
-- Run the check -- Run the check
READER:RunDisplayValidationCheck() READER:RunDisplayValidationCheck()
-- Wait half a second -- Wait half a second
Citizen.Wait( 500 ) Citizen.Wait( 500 )
end end
end ) end )

View File

@@ -1,9 +1,34 @@
--[[---------------------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
----------------------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
-- Cache some of the main Lua functions and libraries -- Cache some of the main Lua functions and libraries
local next = next local next = next
@@ -23,7 +48,7 @@ Citizen.SetTimeout( 1000, function()
local name = GetCurrentResourceName() local name = GetCurrentResourceName()
-- Print a little message in the client's console -- Print a little message in the client's console
print( "WK_WARS2X: Sending resource name (" .. name .. ") to JavaScript side." ) print( "[wk_wars2x]: Sending resource name (" .. name .. ") to JavaScript side." )
-- Send a message through the NUI system to the JavaScript file to give the name of the resource -- Send a message through the NUI system to the JavaScript file to give the name of the resource
SendNUIMessage( { _type = "updatePathName", pathName = name } ) SendNUIMessage( { _type = "updatePathName", pathName = name } )
@@ -51,6 +76,12 @@ AddEventHandler( "wk:loadUiData", function( data )
SendNUIMessage( { _type = "loadUiSettings", data = data } ) SendNUIMessage( { _type = "loadUiSettings", data = data } )
end ) end )
RegisterNetEvent( "wk:setUiDefaults" )
AddEventHandler( "wk:setUiDefaults", function()
SendNUIMessage( { _type = "setUiDefaults", data = CONFIG.uiDefaults } )
end )
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
Player info variables Player info variables
----------------------------------------------------------------------------------]]-- ----------------------------------------------------------------------------------]]--
@@ -116,10 +147,10 @@ RADAR.vars =
["beep"] = CONFIG.menuDefaults["beep"], ["beep"] = CONFIG.menuDefaults["beep"],
-- The volume of the verbal lock confirmation -- The volume of the verbal lock confirmation
["voice"] = CONFIG.menuDefaults["voice"], ["voice"] = CONFIG.menuDefaults["voice"],
-- The volume of the plate reader audio -- The volume of the plate reader audio
["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"]
@@ -134,8 +165,8 @@ RADAR.vars =
{ displayText = { "¦SL", "SEn" }, optionsText = { "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "same" }, { displayText = { "¦SL", "SEn" }, optionsText = { "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "same" },
{ displayText = { "¦OP", "SEn" }, optionsText = { "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "opp" }, { displayText = { "¦OP", "SEn" }, optionsText = { "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "opp" },
{ displayText = { "bEE", "P¦¦" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "beep" }, { displayText = { "bEE", "P¦¦" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "beep" },
{ displayText = { "VOI", "CE¦" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "voice" }, { displayText = { "VOI", "CE¦" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "voice" },
{ displayText = { "PLt", "AUd" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "plateAudio" }, { displayText = { "PLt", "AUd" }, optionsText = { "Off", "¦1¦", "¦2¦", "¦3¦", "¦4¦", "¦5¦" }, options = { 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 }, optionIndex = -1, settingText = "plateAudio" },
{ displayText = { "Uni", "tS¦" }, optionsText = { "USA", "INT" }, options = { "mph", "kmh" }, optionIndex = -1, settingText = "speedType" } { displayText = { "Uni", "tS¦" }, optionsText = { "USA", "INT" }, options = { "mph", "kmh" }, optionIndex = -1, settingText = "speedType" }
}, },
@@ -158,6 +189,7 @@ RADAR.vars =
lockedType = nil -- The locked type, 1 = strongest, 2 = fastest lockedType = nil -- The locked type, 1 = strongest, 2 = fastest
}, },
-- Variables for the rear antenna
[ "rear" ] = { [ "rear" ] = {
xmit = false, -- Whether the antenna is transmitting or in hold xmit = false, -- Whether the antenna is transmitting or in hold
mode = 0, -- Current antenna mode, 0 = none, 1 = same, 2 = opp, 3 = same and opp mode = 0, -- Current antenna mode, 0 = none, 1 = same, 2 = opp, 3 = same and opp
@@ -204,11 +236,11 @@ RADAR.vars =
threadWaitTime = 500, threadWaitTime = 500,
-- Key lock, when true, prevents any of the radar's key events from working, like the ELS key lock -- Key lock, when true, prevents any of the radar's key events from working, like the ELS key lock
keyLock = false, keyLock = false,
-- Full keyboard, when true, the keybinds for the radar will be set to the keys on the numpad, when false, the -- Full keyboard, when true, the keybinds for the radar will be set to the keys on the numpad, when false, the
-- keybinds for the radar will be set to the number keys above WASD -- keybinds for the radar will be set to the number keys above WASD
fullKeyboard = true fullKeyboard = true
} }
-- Speed conversion values -- Speed conversion values
@@ -377,28 +409,6 @@ function RADAR:OpenRemote()
end end
end end
-- 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
function RADAR:UpdateOptionIndexes()
-- Iterate through each of the internal settings
for k, v in pairs( self.vars.settings ) do
-- Iterate through all of the menu options
for i, t in pairs( self.vars.menuOptions ) do
-- If the current menu option is the same as the current setting
if ( t.settingText == k ) then
-- Iterate through the option values of the current menu option
for oi, ov in pairs( t.options ) do
-- If the value of the current option set in the config matches the current value of
-- the option value, then we update the option index variable
if ( v == ov ) then
t.optionIndex = oi
end
end
end
end
end
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
@@ -462,28 +472,28 @@ end
-- Toggles between the full and small keybinds -- Toggles between the full and small keybinds
function RADAR:ToggleFullKeyboard() function RADAR:ToggleFullKeyboard()
-- Check the player state is valid -- Check the player state is valid
if ( PLY:VehicleStateValid() ) then if ( PLY:VehicleStateValid() ) then
-- Toggle the full keyboard state -- Toggle the full keyboard state
self.vars.fullKeyboard = not self.vars.fullKeyboard self.vars.fullKeyboard = not self.vars.fullKeyboard
-- Tell the NUI side to display the keybind message -- Tell the NUI side to display the keybind message
SendNUIMessage( { _type = "displayKeybindChange", state = self:GetFullKeyboardState() } ) SendNUIMessage( { _type = "displayKeybindChange", state = self:GetFullKeyboardState() } )
end end
end end
-- Returns the full keyboard state -- Returns the full keyboard state
function RADAR:GetFullKeyboardState() function RADAR:GetFullKeyboardState()
return self.vars.fullKeyboard return self.vars.fullKeyboard
end end
-- Returns which keybind set to use -- Returns which keybind set to use
function RADAR:GetKeybindType() function RADAR:GetKeybindType()
if ( self:GetFullKeyboardState() ) then if ( self:GetFullKeyboardState() ) then
return "full" return "full"
else else
return "small" return "small"
end end
end end
@@ -594,6 +604,28 @@ function RADAR:SendMenuUpdate()
SendNUIMessage( { _type = "menu", text = self:GetMenuOptionDisplayText(), option = self:GetMenuOptionText() } ) SendNUIMessage( { _type = "menu", text = self:GetMenuOptionDisplayText(), option = self:GetMenuOptionText() } )
end end
-- 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
function RADAR:UpdateOptionIndexes()
-- Iterate through each of the internal settings
for k, v in pairs( self.vars.settings ) do
-- Iterate through all of the menu options
for i, t in pairs( self.vars.menuOptions ) do
-- If the current menu option is the same as the current setting
if ( t.settingText == k ) then
-- Iterate through the option values of the current menu option
for oi, ov in pairs( t.options ) do
-- If the value of the current option set in the config matches the current value of
-- the option value, then we update the option index variable
if ( v == ov ) then
t.optionIndex = oi
end
end
end
end
end
end
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
Radar basics functions Radar basics functions
@@ -991,19 +1023,19 @@ function RADAR:SetAntennaSpeedLock( ant, speed, dir, lockType )
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" ) } )
-- Great Scott! -- Great Scott!
if ( speed == "¦88" and self:GetSettingValue( "speedType" ) == "mph" ) then if ( speed == "¦88" and self:GetSettingValue( "speedType" ) == "mph" ) then
math.randomseed( GetGameTimer() ) math.randomseed( GetGameTimer() )
local chance = math.random() local chance = math.random()
-- 15% chance -- 15% chance
if ( chance <= 0.15 ) then if ( chance <= 0.15 ) then
SendNUIMessage( { _type = "audio", name = "speed_alert", vol = self:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "speed_alert", vol = self:GetSettingValue( "beep" ) } )
end end
end end
end end
end end
@@ -1110,28 +1142,6 @@ function RADAR:InsertCapturedVehicleData( t, rt )
end end
end end
--[[
These need to be changed so a ray type can be set too, otherwise in its current state, messes up vehicle
detection.
-- Sets the given value to true in the temp vehicles table, it is a test system used to reduce ray traces
-- on vehicles that have already been hit by another trace. Currently not implemented fully, as it doesn't
-- check for ray traces of different types, e.g. same or opp.
function RADAR:HasVehicleAlreadyBeenHit( key )
return self.vars.tempVehicleIDs[key]
end
-- Returns if a vehicle has already been hit by a ray trace
function RADAR:SetVehicleHasBeenHit( key )
self.vars.tempVehicleIDs[key] = true
end
-- Resets the temporary vehicle ids table
function RADAR:ResetTempVehicleIDs()
self.vars.tempVehicleIDs = {}
end
]]
--[[---------------------------------------------------------------------------------- --[[----------------------------------------------------------------------------------
Radar dynamic sphere radius functions Radar dynamic sphere radius functions
@@ -1351,74 +1361,74 @@ 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 ) RegisterNUICallback( "setAntennaMode", function( data )
-- 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) -- Set the internal menu state to be closed (false)
RADAR:SetMenuState( false ) RADAR:SetMenuState( false )
-- Send a setting update to the NUI side -- Send a setting update to the NUI side
RADAR:SendSettingUpdate() RADAR:SendSettingUpdate()
-- Play a menu done beep -- Play a menu done beep
SendNUIMessage( { _type = "audio", name = "done", vol = RADAR:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "done", vol = RADAR:GetSettingValue( "beep" ) } )
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 ), function()
-- Update the interface with the new mode -- Update the interface with the new mode
SendNUIMessage( { _type = "antennaMode", ant = data.value, mode = tonumber( data.mode ) } ) SendNUIMessage( { _type = "antennaMode", ant = data.value, mode = tonumber( data.mode ) } )
-- Play a beep -- Play a beep
SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = "beep", vol = RADAR:GetSettingValue( "beep" ) } )
end ) end )
end end
end end
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 ) RegisterNUICallback( "toggleAntenna", function( data )
-- 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
if ( RADAR:IsMenuOpen() ) then if ( RADAR:IsMenuOpen() ) then
-- Change the menu option based on which button is pressed -- Change the menu option based on which button is pressed
RADAR:ChangeMenuOption( data.value ) RADAR:ChangeMenuOption( data.value )
-- Play a beep noise -- Play a beep noise
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, function()
-- Update the interface with the new antenna transmit state -- Update the interface with the new antenna transmit state
SendNUIMessage( { _type = "antennaXmit", ant = data.value, on = RADAR:IsAntennaTransmitting( data.value ) } ) SendNUIMessage( { _type = "antennaXmit", ant = data.value, on = RADAR:IsAntennaTransmitting( data.value ) } )
-- Play some audio specific to the transmit state -- Play some audio specific to the transmit state
SendNUIMessage( { _type = "audio", name = RADAR:IsAntennaTransmitting( data.value ) and "xmit_on" or "xmit_off", vol = RADAR:GetSettingValue( "beep" ) } ) SendNUIMessage( { _type = "audio", name = RADAR:IsAntennaTransmitting( data.value ) and "xmit_on" or "xmit_off", vol = RADAR:GetSettingValue( "beep" ) } )
end ) end )
end end
end end
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() RegisterNUICallback( "menu", function()
-- 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
if ( RADAR:IsMenuOpen() ) then if ( RADAR:IsMenuOpen() ) then
-- As the menu is already open, we then iterate to the next option in the settings list -- As the menu is already open, we then iterate to the next option in the settings list
RADAR:ChangeMenuIndex() RADAR:ChangeMenuIndex()
else else
-- Set the menu state to open, which will prevent anything else within the radar from working -- Set the menu state to open, which will prevent anything else within the radar from working
RADAR:SetMenuState( true ) RADAR:SetMenuState( true )
-- Send an update to the NUI side -- Send an update to the NUI side
RADAR:SendMenuUpdate() RADAR:SendMenuUpdate()
end end
-- 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
end ) end )
-- Runs when the JavaScript side sends the UI data for saving -- Runs when the JavaScript side sends the UI data for saving
@@ -1600,8 +1610,6 @@ function RADAR:Main()
-- Send the update to the NUI side -- Send the update to the NUI side
SendNUIMessage( { _type = "update", speed = data.patrolSpeed, antennas = data.antennas } ) SendNUIMessage( { _type = "update", speed = data.patrolSpeed, antennas = data.antennas } )
-- self:ResetTempVehicleIDs()
end end
end end
@@ -1614,10 +1622,10 @@ Citizen.CreateThread( function()
RADAR:CacheNumRays() RADAR:CacheNumRays()
-- 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 -- Update the operator menu positions
RADAR:UpdateOptionIndexes() 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
@@ -1684,8 +1692,8 @@ end )
function RunControlManager() function RunControlManager()
-- Make sure only the keyboard works -- Make sure only the keyboard works
if ( IsInputDisabled( 0 ) ) then if ( IsInputDisabled( 0 ) ) then
if ( not RADAR:GetKeyLockState() ) then if ( not RADAR:GetKeyLockState() ) then
local keyType = RADAR:GetKeybindType() local keyType = RADAR:GetKeybindType()
-- Opens the remote control -- Opens the remote control
if ( IsDisabledControlJustPressed( 1, CONFIG.keys.remote_control ) ) then if ( IsDisabledControlJustPressed( 1, CONFIG.keys.remote_control ) ) then
@@ -1716,18 +1724,13 @@ function RunControlManager()
-- Toggles the key lock state -- Toggles the key lock state
if ( IsDisabledControlJustPressed( 1, CONFIG.keys.key_lock ) ) then if ( IsDisabledControlJustPressed( 1, CONFIG.keys.key_lock ) ) then
RADAR:ToggleKeyLock() RADAR:ToggleKeyLock()
end end
-- Toggles between the keybind types -- Toggles between the keybind types
if ( IsDisabledControlJustPressed( 1, CONFIG.keys.switch_keys ) ) then if ( IsDisabledControlJustPressed( 1, CONFIG.keys.switch_keys ) ) then
RADAR:ToggleFullKeyboard() RADAR:ToggleFullKeyboard()
end end
end end
-- Shortcut to restart the resource
--[[ if ( IsDisabledControlJustPressed( 1, 167 ) ) then
ExecuteCommand( "restart wk_wars2x" )
end ]]
end end
-- Control manager -- Control manager

View File

@@ -1,9 +1,34 @@
--[[----------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
-----------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
UTIL = {} UTIL = {}

View File

@@ -1,9 +1,34 @@
--[[------------------------------------------------------------------------ --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
------------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
-- Do not touch this -- Do not touch this
CONFIG = {} CONFIG = {}
@@ -16,83 +41,100 @@ CONFIG.allow_fast_limit = true
-- Sets all of the controls -- Sets all of the controls
CONFIG.keys = CONFIG.keys =
{ {
-- Remote control key -- Remote control key
-- The default key to open the remote control is 166 (F5 - INPUT_SELECT_CHARACTER_MICHAEL) -- The default key to open the remote control is 166 (F5 - INPUT_SELECT_CHARACTER_MICHAEL)
remote_control = 166, remote_control = 166,
-- Radar key lock key -- Radar key lock key
-- The default key to enable/disable the radar key lock is 182 (L - INPUT_CELLPHONE_CAMERA_FOCUS_LOCK) -- The default key to enable/disable the radar key lock is 182 (L - INPUT_CELLPHONE_CAMERA_FOCUS_LOCK)
key_lock = 182, key_lock = 182,
-- Radar keybinds switch -- Radar keybinds switch
-- The default to key to switch the bind set is (K - INPUT_REPLAY_SHOWHOTKEY) -- The default to key to switch the bind set is (K - INPUT_REPLAY_SHOWHOTKEY)
switch_keys = 311, switch_keys = 311,
-- Keys for a full size keyboard -- Keys for a full size keyboard
[ "full" ] = { [ "full" ] = {
-- Radar front antenna lock/unlock Key -- Radar front antenna lock/unlock Key
-- The default full keyboard key to lock/unlock the front antenna is 111 (Numpad 8 - INPUT_VEH_FLY_PITCH_UP_ONLY) -- The default full keyboard key to lock/unlock the front antenna is 111 (Numpad 8 - INPUT_VEH_FLY_PITCH_UP_ONLY)
front_lock = 111, front_lock = 111,
-- Radar rear antenna lock/unlock Key -- Radar rear antenna lock/unlock Key
-- The default full keyboard key to lock/unlock the rear antenna is 112 (Numpad 5 - INPUT_VEH_FLY_PITCH_DOWN_ONLY) -- The default full keyboard key to lock/unlock the rear antenna is 112 (Numpad 5 - INPUT_VEH_FLY_PITCH_DOWN_ONLY)
rear_lock = 112, rear_lock = 112,
-- Plate reader front lock/unlock Key -- Plate reader front lock/unlock Key
-- The default full keyboard key to lock/unlock the front plate reader is 118 (Numpad 9 - INPUT_VEH_FLY_SELECT_TARGET_RIGHT) -- The default full keyboard key to lock/unlock the front plate reader is 118 (Numpad 9 - INPUT_VEH_FLY_SELECT_TARGET_RIGHT)
plate_front_lock = 118, plate_front_lock = 118,
-- Plate reader rear lock/unlock Key -- Plate reader rear lock/unlock Key
-- The default full keyboard key to lock/unlock the rear plate reader is 109 (Numpad 6 - INPUT_VEH_FLY_ROLL_RIGHT_ONLY) -- The default full keyboard key to lock/unlock the rear plate reader is 109 (Numpad 6 - INPUT_VEH_FLY_ROLL_RIGHT_ONLY)
plate_rear_lock = 109 plate_rear_lock = 109
}, },
-- Keys for smaller keyboards -- Keys for smaller keyboards
[ "small" ] = { [ "small" ] = {
-- Radar front antenna lock/unlock Key -- Radar front antenna lock/unlock Key
-- The default small keyboard key to lock/unlock the front antenna is 157 (1 - INPUT_SELECT_WEAPON_UNARMED) -- The default small keyboard key to lock/unlock the front antenna is 157 (1 - INPUT_SELECT_WEAPON_UNARMED)
front_lock = 157, front_lock = 157,
-- Radar rear antenna lock/unlock Key -- Radar rear antenna lock/unlock Key
-- The default small keyboard key to lock/unlock the rear antenna is 158 (2 - INPUT_SELECT_WEAPON_MELEE) -- The default small keyboard key to lock/unlock the rear antenna is 158 (2 - INPUT_SELECT_WEAPON_MELEE)
rear_lock = 158, rear_lock = 158,
-- Plate reader front lock/unlock Key -- Plate reader front lock/unlock Key
-- The default small keyboard key to lock/unlock the front plate reader is 160 (3 - INPUT_SELECT_WEAPON_SHOTGUN) -- The default small keyboard key to lock/unlock the front plate reader is 160 (3 - INPUT_SELECT_WEAPON_SHOTGUN)
plate_front_lock = 160, plate_front_lock = 160,
-- Plate reader rear lock/unlock Key -- Plate reader rear lock/unlock Key
-- The default small keyboard key to lock/unlock the rear plate reader is 164 (4 - INPUT_SELECT_WEAPON_HEAVY) -- The default small keyboard key to lock/unlock the rear plate reader is 164 (4 - INPUT_SELECT_WEAPON_HEAVY)
plate_rear_lock = 164 plate_rear_lock = 164
} }
} }
-- Here you can change the default values for the operator menu, do note, if any of these values are not -- Here you can change the default values for the operator menu, do note, if any of these values are not
-- one of the options listed, the script will not work. -- one of the options listed, the script will not work.
CONFIG.menuDefaults = CONFIG.menuDefaults =
{ {
-- Should the system calculate and display faster targets -- Should the system calculate and display faster targets
-- Options: true or false -- Options: true or false
["fastDisplay"] = true, ["fastDisplay"] = true,
-- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles -- Sensitivity for each radar mode, this changes how far the antennas will detect vehicles
-- Options: 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.2, 0.4, 0.6, 0.8, 1.0
["same"] = 0.6, ["same"] = 0.6,
["opp"] = 0.6, ["opp"] = 0.6,
-- The volume of the audible beep -- The volume of the audible beep
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["beep"] = 0.6, ["beep"] = 0.6,
-- The volume of the verbal lock confirmation -- The volume of the verbal lock confirmation
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["voice"] = 0.6, ["voice"] = 0.6,
-- The volume of the plate reader audio -- The volume of the plate reader audio
-- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0 -- Options: 0.0, 0.2, 0.4, 0.6, 0.8, 1.0
["plateAudio"] = 0.6, ["plateAudio"] = 0.6,
-- The speed unit used in conversions -- The speed unit used in conversions
-- Options: mph or kmh -- Options: mph or kmh
["speedType"] = "mph" ["speedType"] = "mph"
}
-- Here you can change the default scale of the UI elements, as well as the safezone size
CONFIG.uiDefaults =
{
-- The default scale of the UI elements.
-- Options: 0.25 - 2.5
scale =
{
radar = 1.5,
remote = 1.5,
plateReader = 1.5
},
-- The safezone size, must be a multiple of 5.
-- Options: 0 - 100
safezone = 20
} }

View File

@@ -1,9 +1,34 @@
--[[----------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
-----------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
-- Define the FX Server version and game type -- Define the FX Server version and game type
fx_version "adamant" fx_version "adamant"
@@ -13,19 +38,19 @@ game "gta5"
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 "pre-release" version "1.0.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/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",
"nui/fonts/*.ttf", "nui/fonts/*.ttf",
"nui/fonts/Segment7Standard.otf", "nui/fonts/Segment7Standard.otf",
"nui/sounds/*.ogg" "nui/sounds/*.ogg"
} }
-- Set the NUI page -- Set the NUI page
@@ -34,6 +59,8 @@ 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_saving.lua" server_script "sv_saving.lua"
server_script "sv_exports.lua"
server_export "TogglePlateLock"
-- Run the client scripts -- Run the client scripts
client_script "config.lua" client_script "config.lua"

View File

@@ -1,3 +1,35 @@
/*-----------------------------------------------------------------------------------------
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 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.
-----------------------------------------------------------------------------------------*/
@font-face { @font-face {
font-family: "Seg-7"; font-family: "Seg-7";
src: url( "fonts/Segment7Standard.otf" ); src: url( "fonts/Segment7Standard.otf" );
@@ -14,30 +46,30 @@
} }
@font-face { @font-face {
font-family: "Plate-Font"; font-family: "Plate-Font";
src: url( "fonts/plate-font.ttf" ); src: url( "fonts/plate-font.ttf" );
} }
@font-face { @font-face {
font-family: "Plate-Font-Hilite"; font-family: "Plate-Font-Hilite";
src: url( "fonts/plate-font-hilite.ttf" ); src: url( "fonts/plate-font-hilite.ttf" );
} }
@font-face { @font-face {
font-family: "Plate-Font-Lolite"; font-family: "Plate-Font-Lolite";
src: url( "fonts/plate-font-lolite.ttf" ); src: url( "fonts/plate-font-lolite.ttf" );
} }
@font-face { @font-face {
font-family: "Plate-Font-Shadow"; font-family: "Plate-Font-Shadow";
src: url( "fonts/plate-font-Shadow.ttf" ); src: url( "fonts/plate-font-Shadow.ttf" );
} }
* { * {
font-family: 'Heebo', Verdana, Geneva, Tahoma, sans-serif; font-family: 'Heebo', Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px; font-size: 13px;
box-sizing: border-box; box-sizing: border-box;
user-select: none; user-select: none;
} }
body { body {
@@ -52,18 +84,18 @@ button:focus { outline: none; }
height: 230px; height: 230px;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: calc( ( 100% - 10px ) - 230px ); top: calc( ( 100% - 10px ) - 230px );
left: calc( ( 100% - 10px ) - 715px ); left: calc( ( 100% - 10px ) - 715px );
background-image: url( "images/frame.png" ); background-image: url( "images/frame.png" );
/* Settings for scaling */ /* Settings for scaling */
transform: scale( 1.0 ); transform: scale( 1.0 );
transform-origin: 0 0; transform-origin: 0 0;
transition: transform 0.5s; transition: transform 0.5s;
z-index: 2; z-index: 2;
} }
@@ -117,14 +149,14 @@ button:focus { outline: none; }
transform: translateX( -1px ); transform: translateX( -1px );
background-image: url( "images/bg_right.png" ); background-image: url( "images/bg_right.png" );
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.plate_blue { .plate_blue {
color: rgb(0, 0, 163); color: rgb(0, 0, 163);
} }
.plate_yellow { .plate_yellow {
color: rgb(255, 255, 0); color: rgb(255, 255, 0);
} }
.arrow { .arrow {
@@ -247,7 +279,10 @@ button:focus { outline: none; }
border: 2px solid rgb( 0, 0, 0 ); border: 2px solid rgb( 0, 0, 0 );
margin: auto 0; margin: auto 0;
/* If you would like your strong target window to be solid rather than have a gradient, swap the comment for the 2 lines below */
background-color: rgb( 61, 18, 0 ); background-color: rgb( 61, 18, 0 );
/* background: linear-gradient( to bottom, rgb( 52, 13, 1 ), rgb( 57, 16, 0 ) 40%, rgb( 65, 25, 4 ) 85% ); */
} }
#radar .speeds_container .display p { #radar .speeds_container .display p {
grid-row-start: 1; grid-row-start: 1;
@@ -266,7 +301,10 @@ button:focus { outline: none; }
#radar .speeds_container .fast { #radar .speeds_container .fast {
height: 60px; height: 60px;
/* If you would like your fast target window to be solid rather than have a gradient, swap the comment for the 2 lines below */
background-color: rgb( 50, 0, 0 ); background-color: rgb( 50, 0, 0 );
/* background: linear-gradient( to bottom, rgb( 40, 0, 0 ), rgb( 45, 0, 0 ) 40%, rgb( 50, 0, 0 ) 85% ); */
} }
#radar .speeds_container .fast p { #radar .speeds_container .fast p {
font-size: 60px; font-size: 60px;
@@ -326,6 +364,7 @@ button:focus { outline: none; }
} }
#radar .patrol_and_logo_container .display { #radar .patrol_and_logo_container .display {
/* If you would like your patrol speed window to be solid rather than have a gradient, swap the comment for the 2 lines below */
background-color: rgb( 0, 57, 35 ); background-color: rgb( 0, 57, 35 );
/* background: linear-gradient( to bottom, rgb( 0, 40, 29 ), rgb( 0, 46, 32 ) 40%, rgb( 1, 64, 27 ) 85% ); */ /* background: linear-gradient( to bottom, rgb( 0, 40, 29 ), rgb( 0, 46, 32 ) 40%, rgb( 1, 64, 27 ) 85% ); */
} }
@@ -372,8 +411,8 @@ button:focus { outline: none; }
height: 800px; height: 800px;
position: absolute; position: absolute;
top: calc( 50% - ( 800px / 2 ) ); top: calc( 50% - ( 800px / 2 ) );
left: calc( 50% - ( 315px / 2 ) ); left: calc( 50% - ( 315px / 2 ) );
margin: auto; margin: auto;
padding: 65px 30px 50px 30px; padding: 65px 30px 50px 30px;
@@ -383,15 +422,15 @@ button:focus { outline: none; }
align-items: center; align-items: center;
color: white; color: white;
background-image: url( "images/rc_bg.png" ); background-image: url( "images/rc_bg.png" );
transition: transform 0.5s; transition: transform 0.5s;
/* Settings for scaling */ /* Settings for scaling */
transform: scale( 1.0 ); transform: scale( 1.0 );
transform-origin: 0 0; transform-origin: 0 0;
z-index: 3; z-index: 3;
} }
/* Button template classes */ /* Button template classes */
#rc button { #rc button {
@@ -567,8 +606,8 @@ button:focus { outline: none; }
} }
#rc .plate_reader_and_help_container .help { #rc .plate_reader_and_help_container .help {
padding: 0 10px; padding: 0 10px;
font-size: 15px; font-size: 15px;
} }
#rc .light { #rc .light {
@@ -587,250 +626,250 @@ button:focus { outline: none; }
#rc .blue { #rc .blue {
background-color: rgb( 84, 210, 255 ); background-color: rgb( 84, 210, 255 );
} }
#plateReaderFrame { #plateReaderFrame {
width: 500px; width: 500px;
height: 200px; height: 200px;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: calc( 50% - ( 200px / 2 ) ); top: calc( 50% - ( 200px / 2 ) );
left: calc( 50% - ( 500px / 2 ) ); left: calc( 50% - ( 500px / 2 ) );
background-image: url( "images/pr_frame.png" ); background-image: url( "images/pr_frame.png" );
transition: transform 0.5s; transition: transform 0.5s;
/* Settings for scaling */ /* Settings for scaling */
transform: scale( 1.0 ); transform: scale( 1.0 );
transform-origin: 0 0; transform-origin: 0 0;
z-index: 1; z-index: 1;
} }
#plateReaderFrame .frame_border { #plateReaderFrame .frame_border {
width: 465px; width: 465px;
height: 175px; height: 175px;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
background-color: rgb( 20, 22, 18 ); background-color: rgb( 20, 22, 18 );
border-radius: 5px; border-radius: 5px;
} }
#plateReader { #plateReader {
width: 460px; width: 460px;
height: 170px; height: 170px;
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-image: url( "images/pr_bg.png" );
box-shadow: inset 0px 20px 20px -15px rgba( 0, 0, 0, 0.4 );
display: grid;
grid-template-rows: 30px 1fr 30px;
align-content: center;
}
#plateReader .labels {
display: grid;
grid-template-columns: 1fr 1fr;
align-content: center;
}
#plateReader .labels .title {
color: rgb( 255, 255, 255 );
}
#plateReader .labels p {
margin: 0;
text-align: center;
font-size: 18px;
}
#plateReader .plates {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
align-content: center;
justify-items: center;
}
#plateReader .plates .plate_container {
width: 90%;
height: 100%;
display: grid;
grid-template-columns: 1fr;
justify-content: center;
}
#plateReader .plates .plate_container .plate {
display: block;
max-width: 100%;
height: auto;
grid-column: 1;
grid-row: 1;
}
#plateReader .plates .plate_container .text_container {
grid-column: 1;
grid-row: 1;
display: grid;
grid-template-columns: 1fr;
justify-content: center;
}
#plateReader .plates .plate_container .text_container p {
display: block;
font-family: "Plate-Font";
font-size: 58px;
text-align: center;
letter-spacing: -3px;
padding-top: 5px;
margin: 0;
grid-column: 1;
grid-row: 1;
}
#plateReader .plates .plate_container .text_container .hilite {
font-family: "Plate-Font-Hilite";
color: rgb( 93, 65, 255 );
}
#plateReader .plates .plate_container .text_container .lolite {
font-family: "Plate-Font-Lolite";
color: rgb( 255, 255, 255 );
}
#plateReader .plates .plate_container .text_container .shadow {
font-family: "Plate-Font-Shadow";
color: rgb( 100, 100, 100 );
}
.plate_hit {
animation: plate_flash linear 0.6s infinite;
}
@keyframes plate_flash {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
#plateReaderBox {
width: 225px;
height: 300px;
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient( to bottom, rgb( 70, 70, 70 ), rgb( 45, 45, 45 ) );
border: 3px solid rgb( 0, 0, 0 );
z-index: 4;
}
#plateReaderBox .title {
text-align: center;
font-size: 20px;
padding: 5px 0;
margin: 0 auto;
color: rgb( 255, 255, 255 );
background-color: rgb( 20, 22, 18 );
}
#plateReaderBox .header {
width: 100%;
}
#plateReaderBox .container {
width: 100%;
height: 200px;
display: grid;
grid-template-rows: 60px 70px 60px;
align-items: center;
justify-items: center;
}
#plateReaderBox .container .btn {
width: 140px;
height: 35px;
border-radius: 10px;
font-size: 16px;
border: none;
}
#plateReaderBox .container .btn:hover {
background-color: rgb( 255, 255, 255 );
}
#plateReaderBox .container .btn:active {
background-color: rgb( 190, 190, 190 );
padding: 0;
}
#plateReaderBox .container .plate_input {
width: 75%;
height: 50px;
font-family: "Plate-Font";
text-align: center;
font-size: 38px;
text-transform: uppercase;
padding: 0;
padding-bottom: 15px;
margin-bottom: -15px;
}
#plateReaderBox .close {
width: 80px;
height: 20px;
position: absolute;
left: 0;
right: 0;
bottom: 10px;
margin: auto;
border-radius: 10px;
border: none;
background-color: rgb( 225, 225, 225 );
}
#plateReaderBox .close:hover {
background-color: rgb( 255, 255, 255 );
}
#plateReaderBox .close:active {
background-color: rgb( 190, 190, 190 );
padding: 0;
}
#uiSettingsBox {
width: 250px;
height: 375px;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
background: linear-gradient( to bottom, rgb( 70, 70, 70 ), rgb( 45, 45, 45 ) ); background-image: url( "images/pr_bg.png" );
border: 3px solid rgb( 0, 0, 0 );
box-shadow: inset 0px 20px 20px -15px rgba( 0, 0, 0, 0.4 );
display: grid;
grid-template-rows: 30px 1fr 30px;
align-content: center;
}
#plateReader .labels {
display: grid;
grid-template-columns: 1fr 1fr;
align-content: center;
}
#plateReader .labels .title {
color: rgb( 255, 255, 255 );
}
#plateReader .labels p {
margin: 0;
text-align: center;
font-size: 18px;
}
#plateReader .plates {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: 1fr 1fr;
align-content: center;
justify-items: center;
}
#plateReader .plates .plate_container {
width: 90%;
height: 100%;
display: grid;
grid-template-columns: 1fr;
justify-content: center;
}
#plateReader .plates .plate_container .plate {
display: block;
max-width: 100%;
height: auto;
grid-column: 1;
grid-row: 1;
}
#plateReader .plates .plate_container .text_container {
grid-column: 1;
grid-row: 1;
display: grid;
grid-template-columns: 1fr;
justify-content: center;
}
#plateReader .plates .plate_container .text_container p {
display: block;
font-family: "Plate-Font";
font-size: 58px;
text-align: center;
letter-spacing: -3px;
padding-top: 5px;
margin: 0;
grid-column: 1;
grid-row: 1;
}
#plateReader .plates .plate_container .text_container .hilite {
font-family: "Plate-Font-Hilite";
color: rgb( 93, 65, 255 );
}
#plateReader .plates .plate_container .text_container .lolite {
font-family: "Plate-Font-Lolite";
color: rgb( 255, 255, 255 );
}
#plateReader .plates .plate_container .text_container .shadow {
font-family: "Plate-Font-Shadow";
color: rgb( 100, 100, 100 );
}
.plate_hit {
animation: plate_flash linear 0.6s infinite;
}
@keyframes plate_flash {
0% { opacity: 1.0; }
50% { opacity: 0.0; }
100% { opacity: 1.0; }
}
#plateReaderBox {
width: 225px;
height: 300px;
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient( to bottom, rgb( 70, 70, 70 ), rgb( 45, 45, 45 ) );
border: 3px solid rgb( 0, 0, 0 );
z-index: 4;
}
#plateReaderBox .title {
text-align: center;
font-size: 20px;
padding: 5px 0;
margin: 0 auto;
color: rgb( 255, 255, 255 );
background-color: rgb( 20, 22, 18 );
}
#plateReaderBox .header {
width: 100%;
}
#plateReaderBox .container {
width: 100%;
height: 200px;
display: grid;
grid-template-rows: 60px 70px 60px;
align-items: center;
justify-items: center;
}
#plateReaderBox .container .btn {
width: 140px;
height: 35px;
border-radius: 10px;
font-size: 16px;
border: none;
}
#plateReaderBox .container .btn:hover {
background-color: rgb( 255, 255, 255 );
}
#plateReaderBox .container .btn:active {
background-color: rgb( 190, 190, 190 );
padding: 0;
}
#plateReaderBox .container .plate_input {
width: 75%;
height: 50px;
font-family: "Plate-Font";
text-align: center;
font-size: 38px;
text-transform: uppercase;
padding: 0;
padding-bottom: 15px;
margin-bottom: -15px;
}
#plateReaderBox .close {
width: 80px;
height: 20px;
position: absolute;
left: 0;
right: 0;
bottom: 10px;
margin: auto;
border-radius: 10px;
border: none;
background-color: rgb( 225, 225, 225 );
}
#plateReaderBox .close:hover {
background-color: rgb( 255, 255, 255 );
}
#plateReaderBox .close:active {
background-color: rgb( 190, 190, 190 );
padding: 0;
}
#uiSettingsBox {
width: 250px;
height: 400px;
position: absolute;
margin: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
background: linear-gradient( to bottom, rgb( 70, 70, 70 ), rgb( 45, 45, 45 ) );
border: 3px solid rgb( 0, 0, 0 );
z-index: 3; z-index: 3;
} }
@@ -845,20 +884,20 @@ button:focus { outline: none; }
#uiSettingsBox .header { #uiSettingsBox .header {
width: 100%; width: 100%;
} }
#uiSettingsBox .scaling_container { #uiSettingsBox .scaling_container {
height: 225px; height: 225px;
display: grid; display: grid;
grid-template-rows: 1fr 1fr 1fr; grid-template-rows: 1fr 1fr 1fr;
} }
#uiSettingsBox .scaling { #uiSettingsBox .scaling {
height: 70px; height: 70px;
display: grid; display: grid;
grid-template-columns: 1fr 2fr 1fr; grid-template-columns: 1fr 2fr 1fr;
place-items: center center; place-items: center center;
} }
#uiSettingsBox .scaling p { #uiSettingsBox .scaling p {
font-size: 18px; font-size: 18px;
@@ -890,60 +929,60 @@ button:focus { outline: none; }
#uiSettingsBox .scaling .plus { #uiSettingsBox .scaling .plus {
clip-path: polygon( 0 35%, 35% 35%, 35% 0, 65% 0, 65% 35%, 100% 35%, 100% 65%, 65% 65%, 65% 100%, 35% 100%, 35% 65%, 0 65% ); clip-path: polygon( 0 35%, 35% 35%, 35% 0, 65% 0, 65% 35%, 100% 35%, 100% 65%, 65% 65%, 65% 100%, 35% 100%, 35% 65%, 0 65% );
} }
#uiSettingsBox .safezone_container { #uiSettingsBox .safezone_container {
width: 85%; width: 85%;
margin: 0 auto; margin: 0 auto;
} }
#uiSettingsBox .safezone_container p, #uiSettingsBox .safezone_container p,
#uiSettingsBox .safezone_container span { #uiSettingsBox .safezone_container span {
font-size: 18px; font-size: 18px;
margin: 0 auto; margin: 0 auto;
text-align: center; text-align: center;
color: rgb( 255, 255, 255 ); color: rgb( 255, 255, 255 );
} }
#uiSettingsBox .safezone_container .slider { #uiSettingsBox .safezone_container .slider {
width: 100%; width: 100%;
height: 10px; height: 10px;
margin: 10px 0; margin: 10px 0;
border-radius: 5px; border-radius: 5px;
-webkit-appearance: none; -webkit-appearance: none;
background-color: rgb( 180, 180, 180 ); background-color: rgb( 180, 180, 180 );
} }
#uiSettingsBox .safezone_container .slider:focus { #uiSettingsBox .safezone_container .slider:focus {
outline: none; outline: none;
} }
#uiSettingsBox .safezone_container .slider::-webkit-slider-thumb { #uiSettingsBox .safezone_container .slider::-webkit-slider-thumb {
-webkit-appearance: none; -webkit-appearance: none;
appearance: none; appearance: none;
width: 15px; width: 15px;
height: 25px; height: 25px;
background: rgb( 84, 210, 255 ); background: rgb( 84, 210, 255 );
cursor: pointer; cursor: pointer;
} }
#uiSettingsBox .safezone_container .slider::-moz-range-thumb { #uiSettingsBox .safezone_container .slider::-moz-range-thumb {
width: 15px; width: 15px;
height: 25px; height: 25px;
background: rgb( 84, 210, 255 ); background: rgb( 84, 210, 255 );
cursor: pointer; cursor: pointer;
} }
#uiSettingsBox .close { #uiSettingsBox .close {
width: 80px; width: 80px;
height: 20px; height: 20px;
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 30px; bottom: 30px;
margin: auto; margin: auto;
border-radius: 10px; border-radius: 10px;
border: none; border: none;
@@ -956,61 +995,61 @@ button:focus { outline: none; }
#uiSettingsBox .close:active { #uiSettingsBox .close:active {
background-color: rgb( 190, 190, 190 ); background-color: rgb( 190, 190, 190 );
padding: 0; padding: 0;
} }
#keyLockLabel, #keyBindsLabel { #keyLockLabel, #keyBindsLabel {
position: absolute; position: absolute;
left: 0; left: 0;
right: 0; right: 0;
bottom: 350px; bottom: 350px;
text-align: center; text-align: center;
font-size: 30px; font-size: 30px;
color: rgb(255, 255, 255); color: rgb(255, 255, 255);
text-shadow: 3px 2px 5px rgb( 0, 0, 0 ); text-shadow: 3px 2px 5px rgb( 0, 0, 0 );
z-index: 5; z-index: 5;
} }
#keyBindsLabel { #keyBindsLabel {
bottom: 300px; bottom: 300px;
} }
#keyLockLabel span, #keyBindsLabel span { #keyLockLabel span, #keyBindsLabel span {
font-size: 30px; font-size: 30px;
} }
#helpWindow { #helpWindow {
width: 75%; width: 75%;
height: 90%; height: 90%;
position: absolute; position: absolute;
margin: auto; margin: auto;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
display: grid; display: grid;
grid-template-rows: 90% 10%; grid-template-rows: 90% 10%;
justify-items: center; justify-items: center;
z-index: 6; z-index: 6;
} }
#helpWindow iframe { #helpWindow iframe {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
} }
#helpWindow .close { #helpWindow .close {
width: 150px; width: 150px;
height: 50px; height: 50px;
margin: auto; margin: auto;
font-size: 18px; font-size: 18px;
border-radius: 10px; border-radius: 10px;
border: none; border: none;
@@ -1023,10 +1062,10 @@ button:focus { outline: none; }
#helpWindow .close:active { #helpWindow .close:active {
background-color: rgb( 190, 190, 190 ); background-color: rgb( 190, 190, 190 );
padding: 0; padding: 0;
} }
@media ( max-width: 1024px ) { @media ( max-width: 1024px ) {
#helpWindow { #helpWindow {
width: 80%; width: 80%;
} }
} }

View File

@@ -1,3 +1,35 @@
<!-----------------------------------------------------------------------------------------
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 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.
------------------------------------------------------------------------------------------>
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
@@ -6,7 +38,7 @@
</head> </head>
<body> <body>
<div id="radarFrame"> <div id="radarFrame">
<div class="frame_border"></div> <div class="frame_border"></div>
<div class="radar_container"> <div class="radar_container">
@@ -160,63 +192,63 @@
<button id="uiSettings" class="rounded_btn light blue">UI SETTINGS</button> <button id="uiSettings" class="rounded_btn light blue">UI SETTINGS</button>
<p class="logo"><span class="large">Wraith</span> ARS 2X</p> <p class="logo"><span class="large">Wraith</span> ARS 2X</p>
</div> </div>
<div id="plateReaderFrame"> <div id="plateReaderFrame">
<div class="frame_border"></div> <div class="frame_border"></div>
<div id="plateReader"> <div id="plateReader">
<div class="labels"> <div class="labels">
<p class="title">FRONT</p> <p class="title">FRONT</p>
<p class="title">REAR</p> <p class="title">REAR</p>
</div> </div>
<div class="plates"> <div class="plates">
<div id="frontPlate" class="plate_container"> <div id="frontPlate" class="plate_container">
<img id="frontPlateImg" class="plate" src="images/plates/0.png"> <img id="frontPlateImg" class="plate" src="images/plates/0.png">
<div id="frontPlateText" class="text_container"> <div id="frontPlateText" class="text_container">
<p id="frontPlateTextFill" class="plate_blue"></p> <p id="frontPlateTextFill" class="plate_blue"></p>
<p class="hilite"></p> <p class="hilite"></p>
<p id="frontPlateTextLolite" class="lolite"></p> <p id="frontPlateTextLolite" class="lolite"></p>
<p class="shadow"></p> <p class="shadow"></p>
</div> </div>
</div> </div>
<div id="rearPlate" class="plate_container"> <div id="rearPlate" class="plate_container">
<img id="rearPlateImg" class="plate" src="images/plates/0.png"> <img id="rearPlateImg" class="plate" src="images/plates/0.png">
<div id="rearPlateText" class="text_container"> <div id="rearPlateText" class="text_container">
<p id="rearPlateTextFill" class="plate_blue"></p> <p id="rearPlateTextFill" class="plate_blue"></p>
<p class="hilite"></p> <p class="hilite"></p>
<p id="rearPlateTextLolite" class="lolite"></p> <p id="rearPlateTextLolite" class="lolite"></p>
<p class="shadow"></p> <p class="shadow"></p>
</div> </div>
</div> </div>
</div> </div>
<div class="labels"> <div class="labels">
<p id="frontPlateLock">LOCKED</p> <p id="frontPlateLock">LOCKED</p>
<p id="rearPlateLock">LOCKED</p> <p id="rearPlateLock">LOCKED</p>
</div> </div>
</div> </div>
</div> </div>
<div id="plateReaderBox"> <div id="plateReaderBox">
<div class="header"> <div class="header">
<p class="title">Plate Reader</p> <p class="title">Plate Reader</p>
</div> </div>
<div class="container"> <div class="container">
<button id="togglePlateReader" data-nuitype="togglePlateReaderDisplay" class="btn">Toggle Display</button> <button id="togglePlateReader" data-nuitype="togglePlateReaderDisplay" class="btn">Toggle Display</button>
<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>
</div> </div>
<button id="closePlateReaderSettings" class="close">CLOSE</button> <button id="closePlateReaderSettings" class="close">CLOSE</button>
</div> </div>
<div id="uiSettingsBox"> <div id="uiSettingsBox">
<div class="header"> <div class="header">
@@ -224,59 +256,58 @@
</div> </div>
<div class="scaling_container"> <div class="scaling_container">
<div class="scaling"> <div class="scaling">
<div id="radarDecreaseScale" class="symbol minus"></div> <div id="radarDecreaseScale" class="symbol minus"></div>
<div class="info"> <div class="info">
<p>Radar Scale</p> <p>Radar Scale</p>
<p id="radarScaleDisplay" class="multiplier">1.00x</p> <p id="radarScaleDisplay" class="multiplier">1.00x</p>
</div> </div>
<div id="radarIncreaseScale" class="symbol plus"></div> <div id="radarIncreaseScale" class="symbol plus"></div>
</div> </div>
<div class="scaling"> <div class="scaling">
<div id="remoteDecreaseScale" class="symbol minus"></div> <div id="remoteDecreaseScale" class="symbol minus"></div>
<div class="info"> <div class="info">
<p>Remote Scale</p> <p>Remote Scale</p>
<p id="remoteScaleDisplay" class="multiplier">1.00x</p> <p id="remoteScaleDisplay" class="multiplier">1.00x</p>
</div> </div>
<div id="remoteIncreaseScale" class="symbol plus"></div> <div id="remoteIncreaseScale" class="symbol plus"></div>
</div> </div>
<div class="scaling"> <div class="scaling">
<div id="readerDecreaseScale" class="symbol minus"></div> <div id="readerDecreaseScale" class="symbol minus"></div>
<div class="info"> <div class="info">
<p>Reader Scale</p> <p>Reader Scale</p>
<p id="readerScaleDisplay" class="multiplier">1.00x</p> <p id="readerScaleDisplay" class="multiplier">1.00x</p>
</div> </div>
<div id="readerIncreaseScale" class="symbol plus"></div> <div id="readerIncreaseScale" class="symbol plus"></div>
</div> </div>
</div> </div>
<div class="safezone_container"> <div class="safezone_container">
<p>Safezone: <span id="safezoneDisplay">0px</span></p> <p>Safezone: <span id="safezoneDisplay">0px</span></p>
<input type="range" min="0" max="100" value="0" step="5" class="slider" id="safezone"> <input type="range" min="0" max="100" value="0" step="5" class="slider" id="safezone">
</div> </div>
<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 lock <span id="keyLockStateLabel"></span></p>
<p id="keyBindsLabel">Radar keybinds set for a <span id="keyBindsStateLabel"></span></p> <p id="keyBindsLabel">Radar keybinds set for a <span id="keyBindsStateLabel"></span></p>
<div id="helpWindow"> <div id="helpWindow">
<iframe id="helpWeb" src="about:blank"></iframe> <iframe id="helpWeb" src="about:blank"></iframe>
<button id="closeHelp" class="close">CLOSE HELP</button> <button id="closeHelp" class="close">CLOSE HELP</button>
</div> </div>
<!-- Load JavaScript files --> <!-- Load JavaScript files -->
<!-- <script src="nui://game/ui/jquery.js"></script> --> <script src="jquery-3.4.1.min.js"></script>
<script src="jquery-3.4.1.min.js"></script>
<script src="radar.js"></script> <script src="radar.js"></script>
</body> </body>
</html> </html>

File diff suppressed because it is too large Load Diff

50
sv_exports.lua Normal file
View File

@@ -0,0 +1,50 @@
--[[---------------------------------------------------------------------------------------
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 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.
---------------------------------------------------------------------------------------]]--
-- Although there is only one export at the moment, more may be added down the line.
--[[---------------------------------------------------------------------------------------
Locks the designated plate reader camera for the given client.
Parameters:
clientId:
The id of the client
cam:
The camera to lock, either "front" or "rear"
beepAudio:
Play an audible beep, either true or false
boloAudio:
Play the bolo lock sound, either true or false
---------------------------------------------------------------------------------------]]--
function TogglePlateLock( clientId, cam, beepAudio, boloAudio )
TriggerClientEvent( "wk:togglePlateLock", clientId, cam, beepAudio, boloAudio )
end

View File

@@ -1,9 +1,34 @@
--[[----------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
-----------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
local DATASAVE = {} local DATASAVE = {}
DATASAVE.dir = "saves" DATASAVE.dir = "saves"
@@ -19,6 +44,9 @@ DATASAVE.dir = "saves"
-- - ip -- - ip
DATASAVE.idType = "license" DATASAVE.idType = "license"
-- Whether or not to print messages
DATASAVE.printMessages = true
-- Saves the data for the given player into the saves folder within the resource -- Saves the data for the given player into the saves folder within the resource
function DATASAVE:SavePlayerData( src, data ) function DATASAVE:SavePlayerData( src, data )
-- Get the player's identifier -- Get the player's identifier
@@ -115,7 +143,9 @@ end
-- Prints the given message with the resource name attached -- Prints the given message with the resource name attached
function DATASAVE:Print( msg ) function DATASAVE:Print( msg )
print( "^3[wk_wars2x] ^0" .. msg .. "^0" ) if ( self.printMessages ) then
print( "^3[wk_wars2x] ^0" .. msg .. "^0" )
end
end end
-- Serverside event for saving a player's UI data -- Serverside event for saving a player's UI data
@@ -146,5 +176,8 @@ AddEventHandler( "wk:getUiData", function()
else else
-- When player's first use the radar, they won't have saved UI data -- When player's first use the radar, they won't have saved UI data
DATASAVE:Print( "Player " .. GetPlayerName( source ) .. " (ID: " .. source .. ") doesn't have a UI settings file." ) DATASAVE:Print( "Player " .. GetPlayerName( source ) .. " (ID: " .. source .. ") doesn't have a UI settings file." )
-- Tell the system to load the UI defaults for the client
TriggerClientEvent( "wk:setUiDefaults", source )
end end
end ) end )

View File

@@ -1,9 +1,34 @@
--[[----------------------------------------------------------------------- --[[---------------------------------------------------------------------------------------
Wraith ARS 2X Wraith ARS 2X
Created by WolfKnight Created by WolfKnight
For discussions, information on future updates, and more, join
my Discord: https://discord.gg/fD4e6WD
MIT License
-----------------------------------------------------------------------]]-- Copyright (c) 2020 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.
---------------------------------------------------------------------------------------]]--
-- Branding! -- Branding!
local label = local label =
@@ -15,6 +40,8 @@ local label =
|| \ \/ \/ / '__/ _` | | __| '_ \ / /\ \ | _ / \___ \ / / > < || \ \/ \/ / '__/ _` | | __| '_ \ / /\ \ | _ / \___ \ / / > <
|| \ /\ /| | | (_| | | |_| | | | / ____ \| | \ \ ____) | / /_ / . \ || \ /\ /| | | (_| | | |_| | | | / ____ \| | \ \ ____) | / /_ / . \
|| \/ \/ |_| \__,_|_|\__|_| |_| /_/ \_\_| \_\_____/ |____/_/ \_\ || \/ \/ |_| \__,_|_|\__|_| |_| /_/ \_\_| \_\_____/ |____/_/ \_\
||
|| Created by WolfKnight
||]] ||]]
-- Returns the current version set in fxmanifest.lua -- Returns the current version set in fxmanifest.lua