structura foldere
mutat kq- folders in un singur folder [kq]
This commit is contained in:
BIN
resources/[framework]/[addons]/[kq]/kq_animsuggest/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_animsuggest/.fxap
Normal file
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
# KQ_ANIMSUGGEST INSTALLATION GUIDE
|
||||
|
||||
This guide will provide step-by-step instructions on how to install and set up the KQ_ANIMSUGGEST script for FiveM.
|
||||
|
||||
## Step 1:
|
||||
After downloading the script, unzip the folder and place it in the `resources` directory on your FiveM server.
|
||||
|
||||
## Step 2:
|
||||
Add the script to your `server.cfg` file.
|
||||
|
||||
## Step 3:
|
||||
Configure the script to your likings. Add your own animations, or customize the keybind tooltip look
|
||||
|
||||
## Done
|
||||
Enjoy the script
|
||||
|
||||
|
||||
https://kuzquality.com/
|
||||
https://discord.gg/fZsyam7Rvz
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,85 @@
|
||||
local BLOCKED = false
|
||||
|
||||
RegisterNetEvent('kq_animsuggest:client:toggleSuggestions')
|
||||
AddEventHandler('kq_animsuggest:client:toggleSuggestions', function(allow)
|
||||
BLOCKED = not allow
|
||||
end)
|
||||
|
||||
function CanUseSuggestions()
|
||||
return (not BLOCKED and not IsPlayerUnreachable())
|
||||
end
|
||||
|
||||
--- Keybind Hint
|
||||
function ShowKeybindHint(keybind, label)
|
||||
SendNUIMessage({
|
||||
event = 'show',
|
||||
keybind = keybind,
|
||||
prefix = L('Press'),
|
||||
suffix = L('to {action}'):gsub('{action}', label)
|
||||
})
|
||||
end
|
||||
|
||||
function HideKeybindHint()
|
||||
SendNUIMessage({
|
||||
event = 'hide',
|
||||
})
|
||||
end
|
||||
|
||||
--- Main animation triggering functions
|
||||
function PlayAnim(ped, dict, anim, flag, duration)
|
||||
Citizen.CreateThread(function()
|
||||
RequestAnimDict(dict)
|
||||
local timeout = 0
|
||||
while not HasAnimDictLoaded(dict) do
|
||||
Citizen.Wait(50)
|
||||
timeout = timeout + 1
|
||||
if timeout > 100 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
TaskPlayAnim(ped or PlayerPedId(), dict, anim, 1.5, 1.0, duration or -1, flag or 1, 0, false, false, false)
|
||||
RemoveAnimDict(dict)
|
||||
end)
|
||||
end
|
||||
|
||||
function PlayAnimAdvanced(ped, dict, anim, flag, coords, rotation)
|
||||
Citizen.CreateThread(function()
|
||||
RequestAnimDict(dict)
|
||||
local timeout = 0
|
||||
while not HasAnimDictLoaded(dict) do
|
||||
Citizen.Wait(50)
|
||||
timeout = timeout + 1
|
||||
if timeout > 100 then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
TaskPlayAnimAdvanced(ped or PlayerPedId(), dict, anim,
|
||||
coords.x, coords.y, coords.z,
|
||||
rotation.x, rotation.y, rotation.z,
|
||||
1.5, 1.0, -1, flag or 1, 0.0, false, false)
|
||||
|
||||
RemoveAnimDict(dict)
|
||||
end)
|
||||
end
|
||||
---
|
||||
|
||||
function IsPlayerUnreachable()
|
||||
local playerPed = PlayerPedId()
|
||||
return IsPedInAnyVehicle(playerPed) or IsPedRagdoll(playerPed) or IsEntityDead(playerPed)
|
||||
end
|
||||
|
||||
|
||||
function CreateProp(toolData)
|
||||
local playerPed = PlayerPedId()
|
||||
local toolModel = toolData.model
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
local boneIndex = GetPedBoneIndex(playerPed, toolData.bone or 28422)
|
||||
|
||||
DoRequestModel(toolModel)
|
||||
local object = CreateObject(toolModel, coords, true, true, true)
|
||||
AttachEntityToEntity(object, playerPed, boneIndex, toolData.pos.x, toolData.pos.y, toolData.pos.z, toolData.rot.x, toolData.rot.y, toolData.rot.z, true, true, false, true, 1, true)
|
||||
|
||||
return object
|
||||
end
|
||||
Binary file not shown.
Binary file not shown.
579
resources/[framework]/[addons]/[kq]/kq_animsuggest/config.lua
Normal file
579
resources/[framework]/[addons]/[kq]/kq_animsuggest/config.lua
Normal file
@@ -0,0 +1,579 @@
|
||||
Config = {}
|
||||
|
||||
--- Debug mode
|
||||
---
|
||||
--- This feature will enable additional debug views as well as some debug prints
|
||||
--- Should only be used in a development-environment
|
||||
Config.debug = false
|
||||
|
||||
|
||||
--- Default keybinds & tooltip look
|
||||
Config.keybinds = {
|
||||
play = {
|
||||
key = 'minus', -- Default keybind - After loading the script once. This keybind will be assigned to your game settings
|
||||
},
|
||||
style = {
|
||||
-- Whether to show the suggested animation tooltip
|
||||
show = true,
|
||||
|
||||
-- Positioning of the keybind tooltip (offsets)
|
||||
top = 'auto',
|
||||
left = 'auto',
|
||||
bottom = '16px',
|
||||
right = '16px',
|
||||
|
||||
-- Size of the tooltip text
|
||||
fontSize = 1.4,
|
||||
|
||||
-- RGBA value of the tooltip background
|
||||
bgColor = { 194, 207, 204, 0.6 },
|
||||
|
||||
-- RGBA value of the tooltip text
|
||||
textColor = { 20, 20, 20, 1 },
|
||||
|
||||
-- RGBA value of the keybind background
|
||||
keybindBgColor = { 40, 40, 40, 0.6 },
|
||||
|
||||
-- RGBA value of the keybind text
|
||||
keybindTextColor = { 255, 255, 255, 1 },
|
||||
|
||||
-- Strength of corner rounding
|
||||
borderRadius = 0.1,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
--- Animation play cooldown in ms
|
||||
Config.cooldown = 1000
|
||||
|
||||
|
||||
--- Controls which will cancel the animation when pressed
|
||||
-- https://docs.fivem.net/docs/game-references/controls/
|
||||
Config.cancelControls = {
|
||||
22, 23, 25, 263, 264,
|
||||
}
|
||||
|
||||
|
||||
--- Animation lists
|
||||
---
|
||||
--- Here you can create your own lists of animations which you may want to reuse
|
||||
---
|
||||
--- Mind that not all pre-configured events use lists. You can also simply input the animations directly into the
|
||||
--- specific events.
|
||||
---
|
||||
--- Animations can also contain tools, noted under a "tool" attribute.
|
||||
--- these should be a table containing the following values:
|
||||
--- pos = vector3 of the tool offset position
|
||||
--- rot = vector3 of the tool offset rotation
|
||||
--- model = the model name of the tool
|
||||
--- bone = the numerical bone of attachment
|
||||
---
|
||||
--- e.g.
|
||||
-- tool = {
|
||||
-- pos = vector3(0.08, -0.1, -0.03),
|
||||
-- rot = vector3(-75.0, 0.0, 10.0),
|
||||
-- model = 'prop_tool_pickaxe',
|
||||
-- bone = 28422,
|
||||
-- },
|
||||
---
|
||||
--- The animations are able to trigger events as well. Noted under an "event" attribute
|
||||
--- these should contain the following values:
|
||||
--- event = name of the event
|
||||
--- type = "client" or "server"
|
||||
---
|
||||
---e.g.
|
||||
-- event = {
|
||||
-- event = "kq_yourscript:random-event",
|
||||
-- type = "client"
|
||||
-- }
|
||||
---
|
||||
--- You can see the barbeque prop for an example of the "tool" and "event" usage
|
||||
Config.animLists = {
|
||||
['sitting'] = {
|
||||
{
|
||||
dict = 'timetable@ron@ig_5_p3',
|
||||
anim = 'ig_5_p3_base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.55, 0.52),
|
||||
},
|
||||
{
|
||||
dict = 'timetable@reunited@ig_10',
|
||||
anim = 'base_amanda',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.55, 0.52),
|
||||
},
|
||||
{
|
||||
dict = 'timetable@ron@ig_3_couch',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.65, 0.52),
|
||||
},
|
||||
{
|
||||
dict = 'timetable@maid@couch@',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.45, 0.65),
|
||||
},
|
||||
},
|
||||
['dance'] = {
|
||||
{
|
||||
dict = 'anim@amb@nightclub@dancers@solomun_entourage@',
|
||||
anim = 'mi_dance_facedj_17_v1_female^1',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@mini@dance@dance_solo@female@var_a@',
|
||||
anim = 'high_center',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@mini@dance@dance_solo@female@var_b@',
|
||||
anim = 'high_center',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@mini@dance@dance_solo@male@var_b@',
|
||||
anim = 'high_center_down',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@dancers@podium_dancers@',
|
||||
anim = 'hi_dance_facedj_17_v2_male^5',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@dancers@crowddance_facedj@hi_intensity',
|
||||
anim = 'hi_dance_facedj_09_v2_female^1',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@mini@dance@dance_solo@female@var_a@',
|
||||
anim = 'high_center_up',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
--- Animation suggestions for specific props
|
||||
---
|
||||
--- Define specific props along with their co-responding animations
|
||||
--- Feel free to add or remove these
|
||||
---
|
||||
--- label: text displayed in the keybind tooltip
|
||||
--- align: whether or not to align the player with the prop (make sure to specify the offset when true)
|
||||
--- offset: offset of the animation from the prop
|
||||
--- models: models of the props on which this action will be possible
|
||||
--- animations: an inline table of animations or an `Config.animList` table of animations
|
||||
Config.propSpecific = {
|
||||
{
|
||||
label = 'aseaza-te',
|
||||
align = true,
|
||||
offset = vector3(0.0, -1.3, 0.45),
|
||||
models = {
|
||||
'prop_bench_01a',
|
||||
'prop_bench_01c',
|
||||
'prop_bench_02',
|
||||
'prop_bench_03',
|
||||
'prop_bench_04',
|
||||
'prop_bench_05',
|
||||
'prop_bench_06',
|
||||
'prop_bench_07',
|
||||
'prop_bench_08',
|
||||
'prop_bench_09',
|
||||
'prop_bench_10',
|
||||
'prop_bench_11',
|
||||
},
|
||||
animations = Config.animLists['sitting'],
|
||||
},
|
||||
{
|
||||
label = 'cauta in cos',
|
||||
align = false,
|
||||
models = {
|
||||
'prop_bin_01a',
|
||||
'prop_bin_03a',
|
||||
'prop_bin_05a',
|
||||
},
|
||||
animations = {
|
||||
{
|
||||
dict = 'mini@repair',
|
||||
anim = 'fixing_a_ped',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
},
|
||||
},
|
||||
{ -- Complete example with all the options
|
||||
label = 'gratar',
|
||||
align = false,
|
||||
models = {
|
||||
'prop_bbq_5',
|
||||
},
|
||||
animations = {
|
||||
{
|
||||
dict = 'amb@prop_human_bbq@male@idle_a',
|
||||
anim = 'idle_b',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
event = {
|
||||
event = 'your-event:name',
|
||||
type = 'client', -- client or server
|
||||
params = 'bbq-start', -- this could be a table as well. It will be sent as the first attribute of the event
|
||||
},
|
||||
tool = {
|
||||
pos = vector3(0.0, 0.0, 0.0),
|
||||
rot = vector3(0.0, 0.0, 0.0),
|
||||
model = 'prop_fish_slice_01',
|
||||
bone = 28422,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
--- Animation suggestions for specific areas
|
||||
---
|
||||
--- Define specific areas along with their co-responding animations
|
||||
--- Feel free to add or remove these
|
||||
---
|
||||
--- label: text displayed in the keybind tooltip
|
||||
--- coords: coordinates of the area
|
||||
--- radius: radius of the animation area
|
||||
--- animations: an inline table of animations or an `Config.animList` table of animations
|
||||
Config.areaSpecific = {
|
||||
{ -- vanilla unicorn
|
||||
label = 'danseaza',
|
||||
coords = vector3(115.6, -1289.0, 28.2),
|
||||
radius = 13.0,
|
||||
animations = Config.animLists['dance'],
|
||||
},
|
||||
{ -- tequilalala
|
||||
label = 'danseaza',
|
||||
coords = vector3(-557.65, 285.32, 82.2),
|
||||
radius = 10.0,
|
||||
animations = Config.animLists['dance'],
|
||||
},
|
||||
{ -- bahamas mammas
|
||||
label = 'danseaza',
|
||||
coords = vector3(-1386.73, -619.17, 30.8),
|
||||
radius = 10.0,
|
||||
animations = Config.animLists['dance'],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
--- Main animation suggestion configuration
|
||||
---
|
||||
--- Available events:
|
||||
--- - lean - Leaning when something is directly behind the player
|
||||
--- - leanBar - Leaning forward when something is directly in front the player but not higher up than their chest (bar etc.)
|
||||
--- - sit - Sitting down when something is located behind the player below their waist (walls, stairs, chairs etc.)
|
||||
--- - idle - May be used anywhere. Active after the player has been stationary for 4 or more seconds
|
||||
--- - intimidate - General intimidation gestures. Active for few seconds after player has been in melee combat
|
||||
--- - showPain - Shows that the player is hurt. Active when player has below 60% of their health
|
||||
--- - inspectCar - Inspects cars engine/trunk. Active when player is looking at an engine bay or trunk which is open
|
||||
--- - cheerBurnout - Cheering/clapping. Active when player is looking at a car performing a burnout or drifting
|
||||
--- - greet - Waving hello. Active when a player is looking at another player whom he hasn't greeted before in the last 15 minutes
|
||||
--- - conversation - Hand motion imitating player talking with others. Active when player is looking at a nearby player
|
||||
---
|
||||
--- enabled: whether the specific action type should be enabled
|
||||
--- label: text displayed in the keybind tooltip
|
||||
--- animations: an inline table of animations or an `Config.animList` table of animations
|
||||
Config.animations = {
|
||||
lean = {
|
||||
enabled = true,
|
||||
label = 'sprijina-te',
|
||||
animations = {
|
||||
{
|
||||
dict = 'anim@scripted@freemode_npc@fix_agy_ig4_lamar@',
|
||||
anim = 'lean_wall_idle_01_lamar',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.35, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'amb@world_human_leaning@male@wall@back@foot_up@idle_a',
|
||||
anim = 'idle_a',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.35, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@scripted@freemode_npc@fix_agy_ig4_lamar@',
|
||||
anim = 'lean_wall_idle_01_lamar',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.35, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'amb@world_human_leaning@female@wall@back@holding_elbow@idle_a',
|
||||
anim = 'idle_a',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.35, 0.0),
|
||||
}
|
||||
},
|
||||
},
|
||||
leanBar = {
|
||||
enabled = true,
|
||||
label = 'apleca-te',
|
||||
animations = {
|
||||
{
|
||||
dict = 'anim@amb@nightclub@lazlow@ig1_vip@',
|
||||
anim = 'clubvip_base_laz',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, -0.55, 0.02),
|
||||
},
|
||||
{
|
||||
dict = 'amb@prop_human_bum_shopping_cart@male@idle_a',
|
||||
anim = 'idle_c',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, -0.55, 0.02),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@lazlow@ig1_vip@',
|
||||
anim = 'clubvip_dlg_jimmyboston_laz',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, -0.45, 0.085),
|
||||
},
|
||||
},
|
||||
},
|
||||
sit = {
|
||||
enabled = true,
|
||||
label = 'aseaza-te',
|
||||
animations = Config.animLists['sitting'],
|
||||
},
|
||||
idle = {
|
||||
enabled = true,
|
||||
label = 'relaxeaza-te',
|
||||
minimumTime = 4, -- Minimum time in seconds it'll take before the suggestion appears
|
||||
animations = {
|
||||
{
|
||||
dict = 'rcmjosh1',
|
||||
anim = 'idle',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'rcmnigel1a',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'missbigscore2aig_3',
|
||||
anim = 'wait_for_van_c',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'amb@world_human_hang_out_street@female_arms_crossed@idle_a',
|
||||
anim = 'idle_a',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@heists@heist_corona@single_team',
|
||||
anim = 'single_team_loop_boss',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
}
|
||||
},
|
||||
intimidate = {
|
||||
enabled = true,
|
||||
label = 'intimideaza',
|
||||
animations = {
|
||||
{
|
||||
dict = 'anim@mp_player_intselfiethe_bird',
|
||||
anim = 'idle_a',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@mp_player_intupperfinger',
|
||||
anim = 'idle_a_fp',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'mini@triathlon',
|
||||
anim = 'want_some_of_this',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@mp_player_intcelebrationfemale@knuckle_crunch',
|
||||
anim = 'knuckle_crunch',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'mp_player_int_uppergrab_crotch',
|
||||
anim = 'mp_player_int_grab_crotch',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'misscommon@response',
|
||||
anim = 'bring_it_on',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'misscommon@response',
|
||||
anim = 'screw_you',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
}
|
||||
},
|
||||
showPain = {
|
||||
enabled = true,
|
||||
label = 'arata durere',
|
||||
animations = {
|
||||
{
|
||||
dict = 'anim@amb@casino@valet_scenario@pose_d@',
|
||||
anim = 'scratch_face_a_m_y_vinewood_01',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@machinery@lathe@',
|
||||
anim = 'scratch_amy_skater_01',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'timetable@gardener@smoking_joint',
|
||||
anim = 'idle_cough',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
}
|
||||
},
|
||||
inspectCar = {
|
||||
enabled = true,
|
||||
label = 'inspectare vehicul',
|
||||
animations = {
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_a@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_b@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_c@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_d@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_f@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_g@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@carmeet@checkout_engine@male_h@base',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
},
|
||||
},
|
||||
cheerBurnout = {
|
||||
enabled = true,
|
||||
label = 'aplauze',
|
||||
animations = {
|
||||
{
|
||||
dict = 'amb@world_human_cheering@male_a',
|
||||
anim = 'base',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'anim@amb@nightclub@peds@',
|
||||
anim = 'amb_world_human_cheering_female_c',
|
||||
flag = 33,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
},
|
||||
},
|
||||
greet = {
|
||||
enabled = true,
|
||||
label = 'saluta',
|
||||
animations = {
|
||||
{
|
||||
dict = 'friends@frj@ig_1',
|
||||
anim = 'wave_e',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'gestures@m@standing@casual',
|
||||
anim = 'gesture_hello',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
},
|
||||
},
|
||||
conversation = {
|
||||
enabled = true,
|
||||
label = 'vorbeste',
|
||||
animations = {
|
||||
{
|
||||
dict = 'misscarsteal4@vendor',
|
||||
anim = 'idle_a_customer1',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'missfbi3_party_d',
|
||||
anim = 'stand_talk_loop_a_male1',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'missfbi3_party_d',
|
||||
anim = 'stand_talk_loop_a_male2',
|
||||
flag = 48,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'missfbi3_party_d',
|
||||
anim = 'stand_talk_loop_b_male2',
|
||||
flag = 49,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
{
|
||||
dict = 'missfbi3_party_d',
|
||||
anim = 'stand_talk_loop_b_male3',
|
||||
flag = 49,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Animation suggestions by KuzQuality'
|
||||
version '1.2.2'
|
||||
|
||||
|
||||
ui_page 'nui/index.html'
|
||||
|
||||
files {
|
||||
'nui/*.html',
|
||||
'nui/js/*.js',
|
||||
}
|
||||
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'config.lua',
|
||||
'locale.lua',
|
||||
'client/constants.lua',
|
||||
'client/settings.lua',
|
||||
'client/functions.lua',
|
||||
'client/cache.lua',
|
||||
'client/client.lua',
|
||||
'client/editable/client.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'locale.lua',
|
||||
'client/editable/*.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
@@ -0,0 +1,7 @@
|
||||
--- Only modify the value on the right side. Do not change the original text located between the square brackets!
|
||||
|
||||
Locale = {
|
||||
['Press'] = 'Apasa',
|
||||
['to {action}'] = 'pentru a {action}',
|
||||
['Play suggested animation'] = 'Reda animatia sugerata',
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="js/jquery.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="keybind-hint">
|
||||
<label id="text-prefix">Press</label>
|
||||
<div class="keybind-block">
|
||||
<label id="text-keybind">-</label>
|
||||
</div>
|
||||
<label id="text-suffix">to idle</label>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$keybindHint = $('.keybind-hint');
|
||||
$keybindHint.hide();
|
||||
|
||||
window.addEventListener('message', ({data}) => {
|
||||
if (data.event === 'setStyle') {
|
||||
$keybindHint.css('top', data.top);
|
||||
$keybindHint.css('bottom', data.bottom);
|
||||
$keybindHint.css('left', data.left);
|
||||
$keybindHint.css('right', data.right);
|
||||
$keybindHint.show();
|
||||
|
||||
const $body = $('body').get(0).style;
|
||||
|
||||
$body.setProperty('--fontSize', data.fontSize + 'vh');
|
||||
$body.setProperty('--bgColor', data.bgColor);
|
||||
$body.setProperty('--textColor', data.textColor);
|
||||
$body.setProperty('--keybindBgColor', data.keybindBgColor);
|
||||
$body.setProperty('--keybindTextColor', data.keybindTextColor);
|
||||
$body.setProperty('--borderRadius', data.borderRadius + 'vh');
|
||||
}
|
||||
if (data.event === 'hide') {
|
||||
$('body').fadeOut(300);
|
||||
}
|
||||
if (data.event === 'show') {
|
||||
$('body').fadeIn(300);
|
||||
|
||||
$('#text-prefix').html(data.prefix);
|
||||
$('#text-keybind').html(data.keybind);
|
||||
$('#text-suffix').html(data.suffix);
|
||||
}
|
||||
});
|
||||
|
||||
fetch(`https://${GetParentResourceName()}/UILoaded`, {
|
||||
method: 'POST',
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=Roboto+Condensed:wght@300;400&display=swap');
|
||||
|
||||
body {
|
||||
display: none;
|
||||
|
||||
--fontSize: 0.9vh;
|
||||
|
||||
--bgColor: rgba(194, 207, 204, 0.6);
|
||||
--textColor: rgba(20, 20, 20, 1);
|
||||
|
||||
--keybindBgColor: rgba(40, 40, 40, 0.6);
|
||||
--keybindTextColor: rgba(255, 255, 255, 1);
|
||||
|
||||
--borderRadius: 0px;
|
||||
}
|
||||
|
||||
.keybind-hint {
|
||||
position: fixed;
|
||||
|
||||
top: auto;
|
||||
left: auto;
|
||||
right: 16px;
|
||||
bottom: 16px;
|
||||
|
||||
background-color: var(--bgColor);
|
||||
border-radius: var(--borderRadius);
|
||||
height: auto;
|
||||
width: auto;
|
||||
padding: 2px 5px;
|
||||
|
||||
|
||||
text-transform: uppercase;
|
||||
|
||||
color: var(--textColor);
|
||||
font-size: var(--fontSize);
|
||||
font-weight: lighter;
|
||||
font-family: 'Roboto Condensed', sans-serif;
|
||||
}
|
||||
|
||||
.keybind-block {
|
||||
padding: 2px;
|
||||
height: var(--fontSize);
|
||||
width: var(--fontSize);
|
||||
background-color: var(--keybindBgColor);
|
||||
color: var(--keybindTextColor);
|
||||
border-radius: var(--borderRadius);
|
||||
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
#text-keybind {
|
||||
width: var(--fontSize);
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
2
resources/[framework]/[addons]/[kq]/kq_animsuggest/nui/js/jquery.js
vendored
Normal file
2
resources/[framework]/[addons]/[kq]/kq_animsuggest/nui/js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/.fxap
Normal file
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
# KQ_BIKEJUMP INSTALLATION GUIDE
|
||||
|
||||
This guide will provide step-by-step instructions on how to install and set up the KQ_BIKEJUMP script for FiveM.
|
||||
|
||||
## Step 1:
|
||||
After downloading the script, unzip the folder and place it in the `resources` directory on your FiveM server.
|
||||
|
||||
## Step 2:
|
||||
Add the script to your `server.cfg` file.
|
||||
|
||||
## Step 3:
|
||||
Configure the script to your likings via the `config.lua` file
|
||||
|
||||
## Done
|
||||
Enjoy the script
|
||||
|
||||
|
||||
# Usage
|
||||
(Using default config)
|
||||
|
||||
While on a moving bike, press `G`. This will enable the "Jump mode".
|
||||
|
||||
When the jump mode is enabled you can hold `Left mouse button` or `Right mouse button` to prepare for a jump.
|
||||
After letting go of the mouse button, you will perform the jump to that direction.
|
||||
|
||||
Auto-jump: When in the "Jump mode", look at a vehicle that's travelling at a similar speed and direction.
|
||||
If the vehicle is within your jump range, you will see a keybind hint allowing you to press `E` to perform a jump onto the vehicle.
|
||||
This doesn't guarantee the jump to be successful at all times, it simply makes it easier. But the player still needs to think
|
||||
when to jump. This "Auto-jump" feature can be disabled via the `config.lua` file.
|
||||
|
||||
|
||||
https://kuzquality.com/
|
||||
https://discord.gg/fZsyam7Rvz
|
||||
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/cache.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/cache.lua
Normal file
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,96 @@
|
||||
|
||||
-- Decides whether the player is able to perform a jump from a vehicle
|
||||
function CanJumpFromVehicle(vehicle)
|
||||
local class = GetVehicleClass(vehicle)
|
||||
local speed = GetEntitySpeed(vehicle) * 3.6
|
||||
|
||||
local whitelist = Config.jumpableVehicles
|
||||
|
||||
-- Check whether the vehicle class or model is whitelisted
|
||||
if not Contains(whitelist.classes, class) and not ContainsHashed(whitelist.models, GetEntityModel(vehicle)) then
|
||||
return false
|
||||
end
|
||||
|
||||
return speed >= (Config.minBikeSpeed or 5.0)
|
||||
end
|
||||
|
||||
function ShouldFallOffVehicle(vehicle, holding)
|
||||
if IsEntityUpsidedown(vehicle) then
|
||||
return true
|
||||
end
|
||||
|
||||
local difference = GetSpeedDifference(vehicle)
|
||||
local falloffForces = Config.roofHolding.falloffForces or 15.0
|
||||
if holding then
|
||||
falloffForces = falloffForces * Config.roofHolding.holdingForceMultiplier
|
||||
end
|
||||
|
||||
return difference > falloffForces
|
||||
end
|
||||
|
||||
|
||||
local LAST_VEHICLE = nil
|
||||
local LAST_SPEED = nil
|
||||
function GetSpeedDifference(vehicle)
|
||||
return UseCache('GetSpeedDifference_' .. vehicle, function()
|
||||
local speed = GetEntitySpeed(vehicle) * 3.6
|
||||
|
||||
local difference = 0
|
||||
if LAST_VEHICLE == vehicle then
|
||||
difference = math.abs(speed - LAST_SPEED)
|
||||
end
|
||||
|
||||
LAST_SPEED = speed
|
||||
LAST_VEHICLE = vehicle
|
||||
return difference
|
||||
end, 100)
|
||||
end
|
||||
|
||||
function KeybindTip(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, 200)
|
||||
end
|
||||
|
||||
-- This function is responsible for all the tooltips displayed on top right of the screen, you could
|
||||
-- replace it with a custom notification etc.
|
||||
function Notify(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, -1)
|
||||
end
|
||||
|
||||
-- Floating keybind help
|
||||
function FloatingText(coords, message, arrowSide)
|
||||
local tag = 'KqBikeJumpHelpNotification'
|
||||
AddTextEntry(tag, message)
|
||||
SetFloatingHelpTextWorldPosition(1, coords)
|
||||
SetFloatingHelpTextStyle(1, 2, 2, 90, arrowSide or 0, 2)
|
||||
BeginTextCommandDisplayHelp(tag)
|
||||
EndTextCommandDisplayHelp(2, false, false, -1)
|
||||
end
|
||||
|
||||
|
||||
--This function is responsible for drawing all the 3d texts
|
||||
function Draw3DText(coords, textInput, scaleX)
|
||||
scaleX = scaleX * (Config.textScale or 1.0)
|
||||
local px, py, pz = table.unpack(GetGameplayCamCoords())
|
||||
local dist = GetDistanceBetweenCoords(px, py, pz, coords, true)
|
||||
local scale = (1 / dist) * 20
|
||||
local fov = (1 / GetGameplayCamFov()) * 100
|
||||
scale = scale * fov
|
||||
|
||||
SetTextScale(scaleX * scale, scaleX * scale)
|
||||
SetTextFont(Config.textFont or 4)
|
||||
SetTextProportional(1)
|
||||
SetTextDropshadow(1, 1, 1, 1, 255)
|
||||
SetTextEdge(2, 0, 0, 0, 150)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextEntry("STRING")
|
||||
SetTextCentre(1)
|
||||
AddTextComponentString(textInput)
|
||||
SetDrawOrigin(coords, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/jump.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/jump.lua
Normal file
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/roof.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_bikejump/client/roof.lua
Normal file
Binary file not shown.
89
resources/[framework]/[addons]/[kq]/kq_bikejump/config.lua
Normal file
89
resources/[framework]/[addons]/[kq]/kq_bikejump/config.lua
Normal file
@@ -0,0 +1,89 @@
|
||||
Config = {}
|
||||
|
||||
Config.debug = false
|
||||
|
||||
-- Vehicles from which players can jump
|
||||
Config.jumpableVehicles = {
|
||||
classes = { 8, 13 },
|
||||
models = {
|
||||
'blazer',
|
||||
'blazer2',
|
||||
'blazer3',
|
||||
'blazer4',
|
||||
'seashark',
|
||||
},
|
||||
}
|
||||
|
||||
-- Type of the input hints. '3d-text' or 'floating'
|
||||
Config.inputType = 'floating'
|
||||
-- Size of the 3d text. (Only applicable for the 3d-text option)
|
||||
Config.textScale = 1.0
|
||||
|
||||
-- Minimum bike speed in km/h
|
||||
Config.minBikeSpeed = 10.0
|
||||
|
||||
-- Force of a normal jump. (side, front, up)
|
||||
Config.jumpForce = vector3(8.0, 0.7, 5.0)
|
||||
|
||||
-- Settings related to landing and holding onto roofs of cars
|
||||
Config.roofHolding = {
|
||||
enabled = true,
|
||||
|
||||
-- Minimum force to fall off a roof
|
||||
falloffForces = 8.0,
|
||||
|
||||
-- Multiplier of the minimum force required to fall off when holding onto the roof
|
||||
holdingForceMultiplier = 2.5,
|
||||
|
||||
-- Whether to allow players to enter vehicles from the roof
|
||||
allowVehicleEntering = true,
|
||||
}
|
||||
|
||||
-- Settings related to "focus" jumping. (Jumping onto specific vehicles, sort of an aimbot for jumping)
|
||||
Config.focusJump = {
|
||||
enabled = true,
|
||||
|
||||
-- Maximum difference of velocity for focused jump
|
||||
maxVelocityDifference = 5.0
|
||||
}
|
||||
|
||||
-- Controls which will be disabled when jumping/preparing a jump
|
||||
Config.jumping = {
|
||||
disableControls = {
|
||||
24, 69, 92, 106, 122, 135, 223, 257,
|
||||
25, 68, 70, 91, 114, 330,
|
||||
38, 86,
|
||||
140, 141, 142, 143
|
||||
}
|
||||
}
|
||||
|
||||
-- Keybinds
|
||||
-- https://docs.fivem.net/docs/game-references/controls/
|
||||
Config.keybinds = {
|
||||
-- Hardcoded keybinds
|
||||
jumpRight = {
|
||||
name = 'INPUT_VEH_AIM',
|
||||
label = 'RMB',
|
||||
input = 68,
|
||||
},
|
||||
jumpLeft = {
|
||||
name = 'INPUT_VEH_ATTACK',
|
||||
label = 'LMB',
|
||||
input = 69,
|
||||
},
|
||||
jumpFocus = {
|
||||
name = 'INPUT_VEH_HORN',
|
||||
label = 'E',
|
||||
input = 86,
|
||||
},
|
||||
enterVehicleSeat = {
|
||||
name = 'INPUT_VEH_HORN',
|
||||
label = 'E',
|
||||
input = 86,
|
||||
},
|
||||
|
||||
-- FiveM Keybinds. Editable through the in-game keybinds settings
|
||||
jumpPrepare = {
|
||||
key = 'G',
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Bike jump by KuzQuality'
|
||||
version '1.0.0'
|
||||
|
||||
client_scripts {
|
||||
'locale.lua',
|
||||
'config.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/cache.lua',
|
||||
'client/functions.lua',
|
||||
'client/client.lua',
|
||||
'client/jump.lua',
|
||||
'client/roof.lua',
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
'config.lua',
|
||||
'locale.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'locale.lua',
|
||||
'client/editable/*.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
11
resources/[framework]/[addons]/[kq]/kq_bikejump/locale.lua
Normal file
11
resources/[framework]/[addons]/[kq]/kq_bikejump/locale.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
Locale = {
|
||||
['~g~Jump mode engaged'] = '~g~Modul de saritura activat',
|
||||
['~r~Jump cancelled'] = '~r~Saritura anulata',
|
||||
['~r~Jump mode disabled'] = '~r~Modul de saritura dezactivat',
|
||||
|
||||
['~r~[~w~{INPUT}~r~]~w~ Jump'] = '~r~[~w~{INPUT}~r~]~w~ Sari',
|
||||
['~{INPUT}~ Jump'] = '~{INPUT}~ Sari',
|
||||
|
||||
['~r~[~w~{INPUT}~r~]~w~ Enter'] = '~r~[~w~{INPUT}~r~]~w~ Intra',
|
||||
['~{INPUT}~ Enter'] = '~{INPUT}~ Intra',
|
||||
}
|
||||
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_brakeoverheat/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_brakeoverheat/.fxap
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,57 @@
|
||||
function GetVehicleClassHeatupMultiplier(vehicle)
|
||||
local class = GetVehicleClass(vehicle)
|
||||
return Config.heatUp.classes[class] or 1.0
|
||||
end
|
||||
|
||||
function GetVehicleClassCooldownMultiplier(vehicle)
|
||||
local class = GetVehicleClass(vehicle)
|
||||
return Config.cooldown.classes[class] or 1.0
|
||||
end
|
||||
|
||||
function GetVehicleUpgradeHeatupMultiplier(vehicle)
|
||||
local brakeUpgrade = GetVehicleMod(vehicle, 12)
|
||||
return Config.heatUp.brakeUpgrade[brakeUpgrade] or 1.0
|
||||
end
|
||||
|
||||
function GetVehicleUpgradeCooldownMultiplier(vehicle)
|
||||
local brakeUpgrade = GetVehicleMod(vehicle, 12)
|
||||
return Config.cooldown.brakeUpgrade[brakeUpgrade] or 1.0
|
||||
end
|
||||
|
||||
--This function is responsible for drawing all the 3d texts
|
||||
function Draw3DText(coords, textInput, scaleX)
|
||||
scaleX = scaleX * (Config.textScale or 1.0)
|
||||
local px, py, pz = table.unpack(GetGameplayCamCoords())
|
||||
local dist = GetDistanceBetweenCoords(px, py, pz, coords, true)
|
||||
local scale = (1 / dist) * 20
|
||||
local fov = (1 / GetGameplayCamFov()) * 100
|
||||
scale = scale * fov
|
||||
|
||||
SetTextScale(scaleX * scale, scaleX * scale)
|
||||
SetTextFont(Config.textFont or 4)
|
||||
SetTextProportional(1)
|
||||
SetTextDropshadow(1, 1, 1, 1, 255)
|
||||
SetTextEdge(2, 0, 0, 0, 150)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextEntry("STRING")
|
||||
SetTextCentre(1)
|
||||
AddTextComponentString(textInput)
|
||||
SetDrawOrigin(coords, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
|
||||
function KeybindTip(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, 200)
|
||||
end
|
||||
|
||||
-- This function is responsible for all the tooltips displayed on top right of the screen, you could
|
||||
-- replace it with a custom notification etc.
|
||||
function Notify(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, -1)
|
||||
end
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,85 @@
|
||||
Config = {}
|
||||
|
||||
Config.debug = false
|
||||
|
||||
-- Multiplier | How fast the brakes should heat up and overheat
|
||||
Config.heatIntensity = 1.0
|
||||
|
||||
-- Multiplier | How fast the brakes should cool down
|
||||
Config.cooldownSpeed = 1.0
|
||||
|
||||
-- Multiplier | Amount of the brake loss when brakes are hot
|
||||
Config.brakeFadeStrength = 1.0
|
||||
|
||||
Config.visual = {
|
||||
-- (This is an additional glow, not the primary brake coloring/heat effect)
|
||||
-- Makes the visual effect look quite a bit nicer
|
||||
-- But is quite resource intensive. Adds about 0.06ms when the brakes are glowing
|
||||
glow = {
|
||||
enabled = true,
|
||||
strength = 1.0,
|
||||
},
|
||||
|
||||
-- Adds sparks when braking with hot brakes.
|
||||
-- Not very resource intensive
|
||||
sparks = {
|
||||
enabled = true,
|
||||
size = 0.6,
|
||||
},
|
||||
}
|
||||
|
||||
-- Multipliers for the brake heat up speed
|
||||
Config.heatUp = {
|
||||
classes = {
|
||||
[CLASS_COMPACT] = 0.9,
|
||||
[CLASS_SUV] = 1.1,
|
||||
[CLASS_COUPES] = 1.0,
|
||||
[CLASS_MUSCLE] = 1.0,
|
||||
[CLASS_SPORTS_CLASSICS] = 0.9,
|
||||
[CLASS_SPORTS] = 0.85,
|
||||
[CLASS_SUPER] = 0.8,
|
||||
[CLASS_BIKE] = 0.5,
|
||||
[CLASS_OFFROAD] = 0.9,
|
||||
[CLASS_INDUSTRIAL] = 0.7,
|
||||
[CLASS_UTILITY] = 0.7,
|
||||
[CLASS_VANS] = 1.0,
|
||||
[CLASS_SERVICE] = 1.0,
|
||||
[CLASS_EMERGENCY] = 0.7,
|
||||
[CLASS_MILITARY] = 0.7,
|
||||
[CLASS_COMMERCIAL] = 1.0,
|
||||
},
|
||||
brakeUpgrade = {
|
||||
[-1] = 1.0, -- Stock brakes
|
||||
[0] = 0.8, -- Brake upgrade level 1
|
||||
[1] = 0.65, -- Brake upgrade level 2
|
||||
[2] = 0.6, -- Brake upgrade level 3
|
||||
},
|
||||
}
|
||||
|
||||
-- Multipliers for the brake cooldown speed
|
||||
Config.cooldown = {
|
||||
classes = {
|
||||
[CLASS_COMPACT] = 1.0,
|
||||
[CLASS_SUV] = 1.0,
|
||||
[CLASS_COUPES] = 1.0,
|
||||
[CLASS_MUSCLE] = 1.1,
|
||||
[CLASS_SPORTS_CLASSICS] = 1.1,
|
||||
[CLASS_SPORTS] = 1.15,
|
||||
[CLASS_SUPER] = 1.25,
|
||||
[CLASS_BIKE] = 1.5,
|
||||
[CLASS_OFFROAD] = 1.0,
|
||||
[CLASS_INDUSTRIAL] = 1.0,
|
||||
[CLASS_UTILITY] = 1.0,
|
||||
[CLASS_VANS] = 1.0,
|
||||
[CLASS_SERVICE] = 1.0,
|
||||
[CLASS_EMERGENCY] = 1.15,
|
||||
[CLASS_MILITARY] = 1.15,
|
||||
[CLASS_COMMERCIAL] = 1.0,
|
||||
},
|
||||
brakeUpgrade = {
|
||||
[-1] = 1.0, -- Stock brakes
|
||||
[0] = 1.1, -- Brake upgrade level 1
|
||||
[1] = 1.25, -- Brake upgrade level 2
|
||||
[2] = 1.5, -- Brake upgrade level 3
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
CLASS_COMPACT = 0
|
||||
CLASS_SEDAN = 1
|
||||
CLASS_SUV = 2
|
||||
CLASS_COUPES = 3
|
||||
CLASS_MUSCLE = 4
|
||||
CLASS_SPORTS_CLASSICS = 5
|
||||
CLASS_SPORTS = 6
|
||||
CLASS_SUPER = 7
|
||||
CLASS_BIKE = 8
|
||||
CLASS_OFFROAD = 9
|
||||
CLASS_INDUSTRIAL = 10
|
||||
CLASS_UTILITY = 11
|
||||
CLASS_VANS = 12
|
||||
CLASS_CYCLES = 13
|
||||
CLASS_BOATS = 14
|
||||
CLASS_HELICOPTER = 15
|
||||
CLASS_PLANE = 16
|
||||
CLASS_SERVICE = 17
|
||||
CLASS_EMERGENCY = 18
|
||||
CLASS_MILITARY = 19
|
||||
CLASS_COMMERCIAL = 20
|
||||
CLASS_TRAIN = 21
|
||||
CLASS_OPEN_WHEEL = 22
|
||||
@@ -0,0 +1,31 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Brake overheating by KuzQuality'
|
||||
version '1.0.5'
|
||||
|
||||
client_scripts {
|
||||
'constants.lua',
|
||||
'config.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/cache.lua',
|
||||
'client/functions.lua',
|
||||
'client/client.lua',
|
||||
'client/visual.lua',
|
||||
}
|
||||
|
||||
server_scripts {
|
||||
'constants.lua',
|
||||
'config.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'constants.lua',
|
||||
'client/editable/*.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_carheist/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_carheist/.fxap
Normal file
Binary file not shown.
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
@@ -0,0 +1 @@
|
||||
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('kq_angle_grinder', 'Angle grinder', 3, 0, 1);
|
||||
@@ -0,0 +1 @@
|
||||
["kq_angle_grinder"] = {["name"] = "kq_angle_grinder", ["label"] = "Angle Grinder", ["weight"] = 1000, ["type"] = "item", ["image"] = "kq_angle_grinder.png", ["unique"] = false, ["useable"] = false, ["shouldClose"] = false, ["combinable"] = nil, ["description"] = "Used to cut metals"},
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 64 KiB |
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,130 @@
|
||||
-- Gang and police check variables
|
||||
local heistAllowed = true
|
||||
local gangCheckDone = false
|
||||
|
||||
-- Check if the player meets requirements to participate in the heist
|
||||
function CheckHeistRequirements()
|
||||
if Config.requireGang then
|
||||
if not IsInGang() then
|
||||
ShowTooltip(L('~r~You must be in a gang to participate in this heist'))
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function AfterTruckCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterTrailerCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterTrailerVehicleCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterDriverCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function AfterPassengerCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function AfterSupportVehicleCreated(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function AfterSupportPedCreated(ped)
|
||||
|
||||
end
|
||||
|
||||
function OnStartOpeningTrailer()
|
||||
if not CheckHeistRequirements() then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function OnTrailerOpened()
|
||||
|
||||
end
|
||||
|
||||
function OnVehicleDetach(vehicle)
|
||||
|
||||
end
|
||||
|
||||
function DrawCustomMarker(dropCoords)
|
||||
DrawMarker(36, dropCoords.x, dropCoords.y, dropCoords.z + 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 3.0, 3.0, 3.0, 210, 232, 7, 50, 0, 1, 0, 0)
|
||||
end
|
||||
|
||||
RegisterNetEvent('kq_carheist:dropOffCompleted')
|
||||
AddEventHandler('kq_carheist:dropOffCompleted', function(reward, losses, vehName)
|
||||
if losses > 0 then
|
||||
Alert(L('{vehicle} dropped off'):gsub('{vehicle}', vehName), (L('You made ~g~${reward}\n~r~${losses} deducted due to vehicle damage')):gsub('{reward}', reward):gsub('{losses}', losses), 5000)
|
||||
else
|
||||
Alert(L('{vehicle} dropped off'):gsub('{vehicle}', vehName), (L('You made ~g~${reward}')):gsub('{reward}', reward), 5000)
|
||||
end
|
||||
PlaySoundFrontend(-1, 'PROPERTY_PURCHASE', 'HUD_AWARDS', false)
|
||||
end)
|
||||
|
||||
|
||||
function SendAnnouncementMessage(message, subtitle, coords)
|
||||
BeginTextCommandThefeedPost("STRING")
|
||||
AddTextComponentSubstringPlayerName(message)
|
||||
|
||||
-- Set the notification icon, title and subtitle.
|
||||
local title = L('Martin')
|
||||
local iconType = 0
|
||||
local flash = false -- Flash doesn't seem to work no matter what.
|
||||
EndTextCommandThefeedPostMessagetext("CHAR_MARTIN", "CHAR_MARTIN", flash, iconType, title, subtitle)
|
||||
|
||||
-- Draw the notification
|
||||
local showInBrief = true
|
||||
local blink = false -- blink doesn't work when using icon notifications.
|
||||
EndTextCommandThefeedPostTicker(blink, showInBrief)
|
||||
|
||||
local blipConf = Config.announcementBlip.primary
|
||||
CreateTemporaryBlip(coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport'), blipConf.shortRange, true)
|
||||
|
||||
blipConf = Config.announcementBlip.secondary
|
||||
CreateTemporaryBlip(coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport'), blipConf.shortRange)
|
||||
end
|
||||
|
||||
-- This function is responsible for creating the text shown on the bottom of the screen
|
||||
function DrawMissionText(text, time)
|
||||
SetTextEntry_2("STRING")
|
||||
AddTextComponentString(text)
|
||||
DrawSubtitleTimed(time or 30000, 1)
|
||||
end
|
||||
|
||||
-- This function is responsible for all the tooltips displayed on top right of the screen, you could
|
||||
-- replace it with a custom notification etc.
|
||||
function ShowTooltip(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, -1)
|
||||
end
|
||||
|
||||
-- This function is responsible for drawing all the 3d texts ('Press [E] to prepare for an engine swap' e.g)
|
||||
function Draw3DText(x, y, z, textInput, fontId, scaleX, scaleY)
|
||||
local px, py, pz = table.unpack(GetGameplayCamCoords())
|
||||
local dist = GetDistanceBetweenCoords(px, py, pz, x, y, z, true)
|
||||
local scale = (1 / dist) * 20
|
||||
local fov = (1 / GetGameplayCamFov()) * 100
|
||||
local scale = scale * fov
|
||||
SetTextScale(scaleX * scale, scaleY * scale)
|
||||
SetTextFont(fontId)
|
||||
SetTextProportional(1)
|
||||
SetTextDropshadow(1, 1, 1, 1, 255)
|
||||
SetTextEdge(2, 0, 0, 0, 150)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextEntry("STRING")
|
||||
SetTextCentre(1)
|
||||
AddTextComponentString(textInput)
|
||||
SetDrawOrigin(x, y, z, 0)
|
||||
DrawText(0.0, 0.0)
|
||||
ClearDrawOrigin()
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
if Config.esxSettings.enabled then
|
||||
ESX = nil
|
||||
|
||||
|
||||
if Config.esxSettings.useNewESXExport then
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
else
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil do
|
||||
TriggerEvent('esx:getSharedObject', function(obj)
|
||||
ESX = obj
|
||||
end)
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil or ESX.GetPlayerData().job == nil do
|
||||
Citizen.Wait(10)
|
||||
end
|
||||
|
||||
ESX.PlayerData = ESX.GetPlayerData()
|
||||
TriggerServerEvent('kq_carheist:playerLoaded')
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob')
|
||||
AddEventHandler('esx:setJob', function(job)
|
||||
ESX.PlayerData.job = job
|
||||
ClearPoliceBlips()
|
||||
end)
|
||||
|
||||
function IsPolice()
|
||||
if not ESX.PlayerData.job then
|
||||
return false
|
||||
end
|
||||
return Contains(Config.policeJobNames, ESX.PlayerData.job.name)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,135 @@
|
||||
----------------------
|
||||
-- BLIPS
|
||||
----------------------
|
||||
local policeBlips = {}
|
||||
|
||||
RegisterNetEvent('kq_carheist:refreshPoliceAlarm')
|
||||
AddEventHandler('kq_carheist:refreshPoliceAlarm', function(trailerCoords, vehiclesCoords)
|
||||
ClearPoliceBlips()
|
||||
|
||||
if trailerCoords then
|
||||
RefreshPoliceTrailerAlarm(trailerCoords)
|
||||
end
|
||||
RefreshPoliceVehiclesAlarm(vehiclesCoords, trailerCoords)
|
||||
end)
|
||||
|
||||
function RefreshPoliceTrailerAlarm(trailerCoords)
|
||||
if trailerBlip ~= nil then
|
||||
RemoveBlip(trailerBlip)
|
||||
end
|
||||
|
||||
local blipConf = Config.policeBlip.truck.primary
|
||||
local primBlip = CreatePoliceBlip(trailerCoords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport robbery'), blipConf.shortRange)
|
||||
SetBlipDisplay(primBlip, 8)
|
||||
table.insert(policeBlips, primBlip)
|
||||
|
||||
blipConf = Config.policeBlip.truck.secondary
|
||||
local secBlip = CreatePoliceBlip(trailerCoords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Car transport robbery'), blipConf.shortRange)
|
||||
table.insert(policeBlips, secBlip)
|
||||
|
||||
end
|
||||
|
||||
|
||||
function RefreshPoliceVehiclesAlarm(vehiclesCoords, trailerCoords)
|
||||
for k, veh in pairs(vehiclesCoords) do
|
||||
if not trailerCoords or GetDistanceBetweenCoords(trailerCoords, veh.coords, false) > 25.0 then
|
||||
|
||||
local blipConf = Config.policeBlip.vehicles.primary
|
||||
|
||||
|
||||
local distance = GetDistanceBetweenCoords(GetEntityCoords(PlayerPedId()), veh.coords, true)
|
||||
|
||||
local _, z = GetGroundZFor_3dCoord(veh.coords.x, veh.coords.y, 900.0, true)
|
||||
if z == 0.0 then
|
||||
z = GetHeightmapTopZForPosition(veh.coords.x, veh.coords.y)
|
||||
end
|
||||
|
||||
z = z - 6.0
|
||||
|
||||
if Config.policeBlip.makeTunnelsLowerSignal and distance > 10.0 and (IsInsideATunnel(veh.coords) or (Config.policeBlip.unknownTunnelChecking and z > veh.coords.z)) then
|
||||
math.randomseed(math.floor((veh.coords.x / 10) + (veh.coords.y / 10)))
|
||||
local newCoords = vector3(veh.coords.x + math.random(-130, 130), veh.coords.y + math.random(-130, 130), veh.coords.z)
|
||||
veh.coords = newCoords
|
||||
math.randomseed(GetGameTimer())
|
||||
|
||||
local tunnelBlip = CreateTunnelPoliceBlip(veh.coords, blipConf.color, blipConf.alpha)
|
||||
table.insert(policeBlips, tunnelBlip)
|
||||
else
|
||||
local primBlip = CreatePoliceBlip(veh.coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle: ') .. veh.name, blipConf.shortRange)
|
||||
SetBlipDisplay(primBlip, 8)
|
||||
table.insert(policeBlips, primBlip)
|
||||
end
|
||||
|
||||
blipConf = Config.policeBlip.vehicles.secondary
|
||||
local secBlip = CreatePoliceBlip(veh.coords, blipConf.sprite, blipConf.color, blipConf.alpha, blipConf.scale, L('Stolen vehicle: ') .. veh.name, blipConf.shortRange)
|
||||
table.insert(policeBlips, secBlip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ClearPoliceBlips()
|
||||
for k, blip in pairs(policeBlips) do
|
||||
RemoveBlip(blip)
|
||||
end
|
||||
policeBlips = {}
|
||||
end
|
||||
|
||||
function RemovePoliceTrailerBlip()
|
||||
if trailerBlip then
|
||||
RemoveBlip(trailerBlip)
|
||||
end
|
||||
end
|
||||
|
||||
function CreatePoliceBlip(coords, sprite, color, alpha, scale, message, shortRange)
|
||||
local blip = AddBlipForCoord(coords)
|
||||
|
||||
SetBlipSprite(blip, sprite)
|
||||
SetBlipHighDetail(blip, true)
|
||||
SetBlipColour(blip, color)
|
||||
SetBlipAlpha(blip, alpha)
|
||||
SetBlipScale(blip, scale)
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandSetBlipName(blip)
|
||||
SetBlipAsShortRange(blip, shortRange)
|
||||
return blip
|
||||
end
|
||||
|
||||
|
||||
function CreateTunnelPoliceBlip(coords, color, alpha)
|
||||
local blip = AddBlipForRadius(coords, 300.0)
|
||||
|
||||
SetBlipHighDetail(blip, true)
|
||||
SetBlipColour(blip, color)
|
||||
SetBlipAlpha(blip, alpha)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
return blip
|
||||
end
|
||||
|
||||
|
||||
----------------------
|
||||
-- DISPATCH MESSAGES
|
||||
----------------------
|
||||
|
||||
function EndPoliceAlarm()
|
||||
if trailerBlip ~= nil then
|
||||
RemovePoliceTrailerBlip()
|
||||
SendDispatchMessage(L('Our truck has arrived to its destination. Thank you for your assistance'), L('Truck arrived'))
|
||||
end
|
||||
end
|
||||
|
||||
function SendDispatchMessage(message, subtitle)
|
||||
BeginTextCommandThefeedPost("STRING")
|
||||
AddTextComponentSubstringPlayerName(message)
|
||||
|
||||
-- Set the notification icon, title and subtitle.
|
||||
local title = L('Car Transports Inc.')
|
||||
local iconType = 0
|
||||
local flash = false -- Flash doesn't seem to work no matter what.
|
||||
EndTextCommandThefeedPostMessagetext("CHAR_CARSITE", "CHAR_CARSITE", flash, iconType, title, subtitle)
|
||||
|
||||
-- Draw the notification
|
||||
local showInBrief = true
|
||||
local blink = false -- blink doesn't work when using icon notifications.
|
||||
EndTextCommandThefeedPostTicker(blink, showInBrief)
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
if Config.qbSettings.enabled then
|
||||
if Config.qbSettings.useNewQBExport then
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
end
|
||||
|
||||
job = QBCore.Functions.GetPlayerData().job
|
||||
gang = QBCore.Functions.GetPlayerData().gang
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
|
||||
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
|
||||
job = QBCore.Functions.GetPlayerData().job
|
||||
gang = QBCore.Functions.GetPlayerData().gang
|
||||
TriggerServerEvent('kq_carheist:playerLoaded')
|
||||
end)
|
||||
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate')
|
||||
AddEventHandler('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||
job = JobInfo
|
||||
end)
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnGangUpdate')
|
||||
AddEventHandler('QBCore:Client:OnGangUpdate', function(GangInfo)
|
||||
gang = GangInfo
|
||||
end)
|
||||
|
||||
function IsPolice()
|
||||
if not job then
|
||||
return false
|
||||
end
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function IsInGang()
|
||||
if not gang then
|
||||
return false
|
||||
end
|
||||
return gang.name ~= nil and gang.name ~= 'none' and gang.name ~= ''
|
||||
end
|
||||
end
|
||||
1052
resources/[framework]/[addons]/[kq]/kq_carheist/client/functions.lua
Normal file
1052
resources/[framework]/[addons]/[kq]/kq_carheist/client/functions.lua
Normal file
File diff suppressed because it is too large
Load Diff
687
resources/[framework]/[addons]/[kq]/kq_carheist/config.lua
Normal file
687
resources/[framework]/[addons]/[kq]/kq_carheist/config.lua
Normal file
@@ -0,0 +1,687 @@
|
||||
Config = {}
|
||||
|
||||
-- Enables debug statements which will print in consoles
|
||||
-- Also enabled a command /cheist which will forcefully spawn a new heist even if one is already happening
|
||||
-- Do not enable this unless asked to by a KuzQuality staff member or you know what you're doing
|
||||
Config.debug = false
|
||||
|
||||
-- Experimental method of syncing the trucks between players
|
||||
Config.experimentalSync = false
|
||||
|
||||
--------------------------------------------------------
|
||||
--------------------------------------------------------
|
||||
--- MAKE SURE THAT THE CORRECT FRAMEWORK IS ENABLED ! --
|
||||
--------------------------------------------------------
|
||||
--------------------------------------------------------
|
||||
|
||||
--- SETTINGS FOR ESX
|
||||
Config.esxSettings = {
|
||||
enabled = false,
|
||||
-- Whether or not to use the new ESX export method
|
||||
useNewESXExport = true,
|
||||
-- Account on which players will receive their money after successfully dropping off their vehicle
|
||||
moneyAccount = 'black_money',
|
||||
}
|
||||
|
||||
--- SETTINGS FOR QBCORE
|
||||
Config.qbSettings = {
|
||||
enabled = true,
|
||||
-- If you're using an old QBCore version set this to 'false' and uncomment the old export in fxmanifest.lua
|
||||
useNewQBExport = true,
|
||||
-- Account on which players will receive their money after successfully dropping off their vehicle
|
||||
-- Using 'crypto' for dirty money feel; change to 'cash' or 'bank' as needed
|
||||
moneyAccount = 'cash'
|
||||
}
|
||||
|
||||
-- Minimum police officers that have to be online to allow spawning of the heist truck
|
||||
Config.minimumOfficers = 3
|
||||
|
||||
-- Whether the player must be in a gang to interact with the heist
|
||||
Config.requireGang = true
|
||||
|
||||
|
||||
-- How often the truck should be spawned (In minutes)
|
||||
-- If any players are still near the old truck new one won't be spawned
|
||||
-- Set to 45 minutes for RP pacing - prevents heist spam
|
||||
Config.heistSpawnTime = 45
|
||||
|
||||
-- Whether or not to announce the truck spawning to all players (Besides police officers)
|
||||
Config.announceTruckDepartureToPlayers = true
|
||||
|
||||
-- Announcement blip
|
||||
Config.announcementBlip = {
|
||||
-- How long the blip will stay on the map
|
||||
duration = 15000,
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 47,
|
||||
scale = 2.0,
|
||||
alpha = 150,
|
||||
shortRange = true,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 477,
|
||||
color = 47,
|
||||
scale = 1.3,
|
||||
alpha = 255,
|
||||
shortRange = true,
|
||||
},
|
||||
}
|
||||
|
||||
-- Whether or not to use audible vehicle alarms
|
||||
Config.useVehicleAlarm = true
|
||||
|
||||
-- Bike jump config
|
||||
Config.bikeJump = {
|
||||
enabled = true,
|
||||
keybind = 'X'
|
||||
}
|
||||
|
||||
|
||||
-- Whether or not to require a item to open the trailer
|
||||
Config.requireTool = true
|
||||
-- item names that will allow players to open the ramp of the trailer
|
||||
Config.cuttingTools = {
|
||||
'kq_angle_grinder'
|
||||
}
|
||||
-- Amount of key presses required to open the latch/ramp (Set it higher to make it take longer)
|
||||
Config.latchCuttingDuration = 15
|
||||
-- Keys used for the angle grinder / cutting the latches
|
||||
Config.grinderKeys = { 'W', 'A', 'S', 'D', 'G' }
|
||||
|
||||
Config.tracker = {
|
||||
-- How long it will take to search one spot on the vehicle (in ms)
|
||||
searchDuration = 15000,
|
||||
-- How many times the player has to press the keys to unscrew the tracker
|
||||
removalLength = 50,
|
||||
-- Time that players will need to wait when they misclick "drop the screwdriver" (in ms)
|
||||
removalMessedUpDuration = 6000,
|
||||
-- Keys used to unscrew the tracker
|
||||
removalKeybinds = {
|
||||
'A',
|
||||
'W',
|
||||
'D',
|
||||
'S'
|
||||
},
|
||||
-- For how long the GPS location is going to be visible for police after tracker gets removed (in ms)
|
||||
stayOnMapAfterRemovalTime = 90000,
|
||||
}
|
||||
|
||||
-- Name of the job(s) which will receive the alerts
|
||||
Config.policeJobNames = {
|
||||
'police'
|
||||
}
|
||||
|
||||
Config.policeBlip = {
|
||||
-- How often the trackers locations should be updated (Don't recommend putting it too low) (in ms)
|
||||
refreshTime = 5000,
|
||||
-- Whether or not to allow tunnels and underground areas to lower the accuracy of the tracker
|
||||
makeTunnelsLowerSignal = true,
|
||||
-- Check which works better for detection of tunnels but makes all trackers which are far away
|
||||
-- from the officer display as if the tracker is in a tunnel (Still recommended)
|
||||
unknownTunnelChecking = true,
|
||||
truck = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 47,
|
||||
scale = 2.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 477,
|
||||
color = 47,
|
||||
scale = 1.3,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
},
|
||||
vehicles = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 49,
|
||||
scale = 1.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 595,
|
||||
color = 49,
|
||||
scale = 1.0,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
-- ADVANCED! If you don't know what this does. Do not change it.
|
||||
Config.truckDriveStyle = 1074528293
|
||||
|
||||
-- Speed the truck will drive at (I don't recommend putting it above 30.0)
|
||||
Config.truckDriveSpeed = 20.0
|
||||
-- Color of the heist truck
|
||||
Config.truckColor = { r = 255, g = 60, b = 10 }
|
||||
|
||||
|
||||
-- All possible routes that the truck can spawn on and take
|
||||
-- (Be careful when adding new ones. Make sure that the NPC knows how to drive the route (test it))
|
||||
Config.startLocations = {
|
||||
{
|
||||
truck = { x = 1541.56, y = 854.07, z = 77.5, h = 329.0 },
|
||||
support = { x = 1524.74, y = 822.16, z = 77.5, h = 328.0 },
|
||||
finish = { x = 138.46, y = 6414.1, z = 26.13, h = 261.80 },
|
||||
},
|
||||
{
|
||||
truck = { x = -2875.27, y = 2188.37, z = 35.23, h = 129.0 },
|
||||
support = { x = -2841.30, y = 2207.92, z = 31.11, h = 121.19 },
|
||||
finish = { x = 2506.23, y = -280.09, z = 93.05, h = 91.77 },
|
||||
},
|
||||
{
|
||||
truck = { x = -1947.37, y = -337.79, z = 46.23, h = 280.77 },
|
||||
support = { x = -1980.10, y = -311.63, z = 43.65, h = 231.09 },
|
||||
finish = { x = -680.03, y = 5761.55, z = 16.88, h = 304.37 },
|
||||
},
|
||||
{
|
||||
truck = { x = 1156.20, y = -1695.16, z = 35.65, h = 164.31 },
|
||||
support = { x = 1165.83, y = -1669.85, z = 36.45, h = 150.35 },
|
||||
finish = { x = 138.46, y = 6414.1, z = 26.13, h = 261.80 },
|
||||
},
|
||||
{
|
||||
truck = { x = 2666.48, y = 3454.13, z = 55.73, h = 247.0 },
|
||||
support = { x = 2636.36, y = 3462.57, z = 55.37, h = 244.77 },
|
||||
finish = { x = 1379.78, y = -2068.52, z = 51.99, h = 156.80 },
|
||||
},
|
||||
}
|
||||
|
||||
-- Whether or not to reduce the drop off reward based on how damaged the vehicle is
|
||||
Config.reduceRewardByVehicleDamage = true
|
||||
-- How much percentage to remove off the vehicle price based on damage (0% nothing, 100% cars which have 0 health will pay $0)
|
||||
-- Set to 80% - forces careful driving for RP; damaged cars are worth much less
|
||||
Config.reduceByDamagePercentage = 80
|
||||
Config.dropOff = {
|
||||
-- Minimum amount of available drop off locations per heist
|
||||
minLocations = 2,
|
||||
-- Maximum amount of available drop off locations per heist
|
||||
maxLocations = 3,
|
||||
-- Whether or not to (almost) instantly delete the vehicle when dropping it off
|
||||
instantlyDeleteVehicle = false,
|
||||
blips = {
|
||||
primary = {
|
||||
sprite = 161,
|
||||
color = 46,
|
||||
scale = 1.0,
|
||||
alpha = 150,
|
||||
shortRange = false,
|
||||
},
|
||||
secondary = {
|
||||
sprite = 524,
|
||||
color = 46,
|
||||
scale = 1.0,
|
||||
alpha = 255,
|
||||
shortRange = false,
|
||||
}
|
||||
},
|
||||
-- All available drop off locations
|
||||
locations = {
|
||||
{ x = 1274.95, y = -3239.77, z = 5.88 },
|
||||
{ x = -302.86, y = -2723.41, z = 6.01 },
|
||||
{ x = -371.68, y = -2273.67, z = 7.60 },
|
||||
{ x = 452.45, y = -2755.19, z = 6.05 },
|
||||
{ x = -450.44, y = -2442.52, z = 6.00 },
|
||||
{ x = 489.70, y = -2227.92, z = 5.91 },
|
||||
{ x = -161.13, y = 928.02, z = 235.65 },
|
||||
{ x = 2469.17, y = 1589.04, z = 32.72 },
|
||||
{ x = 363.70, y = 3411.08, z = 36.40 },
|
||||
{ x = 3803.85, y = 4451.05, z = 4.25 },
|
||||
{ x = 2150.34, y = 4797.62, z = 41.13 },
|
||||
{ x = 1905.25, y = 4924.22, z = 48.87 },
|
||||
{ x = -197.12, y = 6536.59, z = 11.09 },
|
||||
{ x = -1585.75, y = 5157.74, z = 19.57 },
|
||||
{ x = 143.53, y = -2445.9, z = 5.99 },
|
||||
{ x = -38.46, y = -2547.16, z = 6.00 },
|
||||
{ x = -224.98, y = -2657.44, z = 6.00 },
|
||||
{ x = -566.59, y = -2341.45, z = 13.83 },
|
||||
{ x = -853.87, y = -1257.78, z = 4.99 },
|
||||
{ x = -81.51, y = 361.99, z = 112.46 },
|
||||
{ x = -1558.67, y = -247,35, z = 48.28 },
|
||||
},
|
||||
}
|
||||
|
||||
-- Color of the support vehicle
|
||||
Config.supportColor = { r = 0, g = 0, b = 0 }
|
||||
|
||||
-- Possible vehicle models for the support vehicle
|
||||
Config.supportVehicles = {
|
||||
'baller2',
|
||||
'kuruma',
|
||||
'buffalo2',
|
||||
'dubsta2',
|
||||
'stanier',
|
||||
'tailgater',
|
||||
}
|
||||
|
||||
-- Ped models that the support can have
|
||||
Config.supportPeds = {
|
||||
's_m_m_chemsec_01'
|
||||
}
|
||||
|
||||
|
||||
-- How much health all the npcs will have (normal npc's have 100)
|
||||
-- Increased for RP difficulty - guards are trained professionals
|
||||
Config.npcHealth = 250
|
||||
|
||||
-- Whether or not all the npcs suffer from critical hits (aka headshots)
|
||||
-- Enabled for realism - headshots should matter in RP
|
||||
Config.npcSuffersCriticalHits = true
|
||||
|
||||
-- Integer between 0 and 100
|
||||
-- Below 20 they barely hit, above 80 incredible aim
|
||||
-- Set to 55 for challenging but fair RP encounters
|
||||
Config.npcShootingAccuracy = 55
|
||||
|
||||
-- Chance of NPC's having a weapon (100% - armed transport convoy)
|
||||
Config.weaponChance = 100
|
||||
|
||||
Config.weapons = {
|
||||
'weapon_minismg',
|
||||
'weapon_snspistol',
|
||||
'weapon_combatpistol'
|
||||
}
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------
|
||||
-- chance = the chance of the event spawning
|
||||
-- trucks = list of all truck models that can be used
|
||||
-- npcs = list of all npc models that can be used (driver and passenger)
|
||||
-- passengerChance = the chance of the truck having a passenger
|
||||
-- bulletproofTiresChance = the chance of all heist vehicles having bullet proof tires
|
||||
-- vehicleSlotChance = the chance of a vehicle spawning in a trailer slot (there always is at least 1 vehicle)
|
||||
-- supportChance = the chance of the support vehicle spawning
|
||||
-- minimumVehicles = the minimum amount of the vehicles on the trailer (max 3)
|
||||
-- vehicles = {
|
||||
-- name = Vehicle name
|
||||
-- model = Vehicle model
|
||||
-- price = The max amount of money the players will get for dropping off the vehicle
|
||||
-- }
|
||||
---------------------------------------------------------------------------
|
||||
--- Chances of all events must add up to 100 !
|
||||
Config.events = {
|
||||
{
|
||||
chance = 20,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 70,
|
||||
supportChance = 100,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Adder',
|
||||
model = 'adder',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Entity XF',
|
||||
model = 'entityxf',
|
||||
price = 35000,
|
||||
},
|
||||
{
|
||||
name = 'Furia',
|
||||
model = 'furia',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'Nero Custom',
|
||||
model = 'nero2',
|
||||
price = 52000,
|
||||
},
|
||||
{
|
||||
name = 'Nero',
|
||||
model = 'nero',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'Cyclone',
|
||||
model = 'cyclone',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'T20',
|
||||
model = 't20',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Vacca',
|
||||
model = 'vacca',
|
||||
price = 29000,
|
||||
},
|
||||
{
|
||||
name = 'Bullet',
|
||||
model = 'bullet',
|
||||
price = 28000,
|
||||
},
|
||||
{
|
||||
name = 'Itali GTB',
|
||||
model = 'italigtb',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Itali GTB Custom',
|
||||
model = 'italigtb2',
|
||||
price = 38000,
|
||||
},
|
||||
{
|
||||
name = 'Visione',
|
||||
model = 'visione',
|
||||
price = 49000,
|
||||
},
|
||||
{
|
||||
name = 'SC1',
|
||||
model = 'SC1',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Taipan',
|
||||
model = 'taipan',
|
||||
price = 47000,
|
||||
},
|
||||
{
|
||||
name = 'Thrax',
|
||||
model = 'thrax',
|
||||
price = 55000,
|
||||
},
|
||||
{
|
||||
name = 'Emerus',
|
||||
model = 'emerus',
|
||||
price = 51000,
|
||||
},
|
||||
{
|
||||
name = 'Entity XXR',
|
||||
model = 'entity2',
|
||||
price = 54000,
|
||||
},
|
||||
{
|
||||
name = 'Reaper',
|
||||
model = 'reaper',
|
||||
price = 41000,
|
||||
},
|
||||
{
|
||||
name = 'Voltic',
|
||||
model = 'voltic',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = '811',
|
||||
model = 'pfister811',
|
||||
price = 39000,
|
||||
},
|
||||
{
|
||||
name = 'Lynx',
|
||||
model = 'lynx',
|
||||
price = 32000,
|
||||
},
|
||||
{
|
||||
name = 'Autarch',
|
||||
model = 'autarch',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'XA-21',
|
||||
model = 'xa21',
|
||||
price = 40000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 35,
|
||||
trucks = {
|
||||
'phantom3',
|
||||
'phantom',
|
||||
'hauler',
|
||||
'packer',
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 80,
|
||||
bulletproofTiresChance = 40,
|
||||
vehicleSlotChance = 70,
|
||||
supportChance = 40,
|
||||
minimumVehicles = 2,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Sultan RS',
|
||||
model = 'sultanrs',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Schlagen',
|
||||
model = 'schlagen',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Jester Classic',
|
||||
model = 'jester3',
|
||||
price = 28000,
|
||||
},
|
||||
{
|
||||
name = 'Comet',
|
||||
model = 'comet2',
|
||||
price = 22000,
|
||||
},
|
||||
{
|
||||
name = 'Comet Retro',
|
||||
model = 'comet3',
|
||||
price = 27000,
|
||||
},
|
||||
{
|
||||
name = 'Verlierer',
|
||||
model = 'verlierer2',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Omnis',
|
||||
model = 'omnis',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Kuruma',
|
||||
model = 'kuruma',
|
||||
price = 24000,
|
||||
},
|
||||
{
|
||||
name = 'Space Monkey Blista',
|
||||
model = 'blista3',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Coquette',
|
||||
model = 'coquette',
|
||||
price = 25000,
|
||||
},
|
||||
{
|
||||
name = 'Banshee',
|
||||
model = 'banshee',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = '9F',
|
||||
model = 'ninef',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Massacro',
|
||||
model = 'massacro',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Massacro Race car',
|
||||
model = 'massacro2',
|
||||
price = 33000,
|
||||
},
|
||||
{
|
||||
name = 'Dominator GTX',
|
||||
model = 'dominator3',
|
||||
price = 29000,
|
||||
},
|
||||
{
|
||||
name = 'Brioso R/A',
|
||||
model = 'brioso',
|
||||
price = 22000,
|
||||
},
|
||||
{
|
||||
name = 'F620',
|
||||
model = 'f620',
|
||||
price = 23000,
|
||||
},
|
||||
{
|
||||
name = 'Elegy Classic',
|
||||
model = 'elegy',
|
||||
price = 30000,
|
||||
},
|
||||
{
|
||||
name = 'Ruston',
|
||||
model = 'ruston',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Flash GT',
|
||||
model = 'flashgt',
|
||||
price = 27000,
|
||||
},
|
||||
{
|
||||
name = 'Elegy RH8',
|
||||
model = 'elegy2',
|
||||
price = 32000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 25,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 40,
|
||||
supportChance = 100,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Turismo Classic',
|
||||
model = 'turismo2',
|
||||
price = 60000,
|
||||
},
|
||||
{
|
||||
name = 'JB700W',
|
||||
model = 'jb7002',
|
||||
price = 53000,
|
||||
},
|
||||
{
|
||||
name = 'Torero',
|
||||
model = 'torero',
|
||||
price = 54000,
|
||||
},
|
||||
{
|
||||
name = 'Cheburek',
|
||||
model = 'cheburek',
|
||||
price = 15000,
|
||||
},
|
||||
{
|
||||
name = 'Dynasty',
|
||||
model = 'dynasty',
|
||||
price = 42000,
|
||||
},
|
||||
{
|
||||
name = 'Monroe',
|
||||
model = 'monroe',
|
||||
price = 40000,
|
||||
},
|
||||
{
|
||||
name = 'Swinger',
|
||||
model = 'swinger',
|
||||
price = 44000,
|
||||
},
|
||||
{
|
||||
name = 'Cheetah Classic',
|
||||
model = 'cheetah2',
|
||||
price = 62000,
|
||||
},
|
||||
{
|
||||
name = 'Infernus Classic',
|
||||
model = 'infernus2',
|
||||
price = 61000,
|
||||
},
|
||||
{
|
||||
name = 'Rapid GT Classic',
|
||||
model = 'rapidgt3',
|
||||
price = 26000,
|
||||
},
|
||||
{
|
||||
name = 'Savestra',
|
||||
model = 'savestra',
|
||||
price = 27000,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
chance = 20,
|
||||
trucks = {
|
||||
'phantom3'
|
||||
},
|
||||
npcs = {
|
||||
's_m_m_chemsec_01'
|
||||
},
|
||||
passengerChance = 100,
|
||||
bulletproofTiresChance = 100,
|
||||
vehicleSlotChance = 45,
|
||||
supportChance = 80,
|
||||
minimumVehicles = 1,
|
||||
vehicles = {
|
||||
{
|
||||
name = 'Comet Safari',
|
||||
model = 'comet4',
|
||||
price = 45000,
|
||||
},
|
||||
{
|
||||
name = 'Drag Tornado',
|
||||
model = 'tornado6',
|
||||
price = 47000,
|
||||
},
|
||||
{
|
||||
name = 'Apocalypse Issi',
|
||||
model = 'issi4',
|
||||
price = 37000,
|
||||
},
|
||||
{
|
||||
name = 'Drift Yosemite',
|
||||
model = 'yosemite2',
|
||||
price = 51000,
|
||||
},
|
||||
{
|
||||
name = 'Lowrider Primo',
|
||||
model = 'primo2',
|
||||
price = 42000,
|
||||
},
|
||||
{
|
||||
name = 'JB700',
|
||||
model = 'jb700',
|
||||
price = 58000,
|
||||
},
|
||||
{
|
||||
name = 'Raptor',
|
||||
model = 'raptor',
|
||||
price = 35000,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Car Heist by KuzQuality'
|
||||
version '1.0.14'
|
||||
|
||||
|
||||
-- UNCOMMENT IF YOU'RE USING OLD QB CORE EXPORT
|
||||
--shared_script '@qb-core/import.lua'
|
||||
|
||||
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
'locale/locale.lua',
|
||||
'config.lua',
|
||||
'shared/settings.lua',
|
||||
'server/editable/esx.lua',
|
||||
'server/editable/qb.lua',
|
||||
'server/server.lua',
|
||||
'server/functions.lua',
|
||||
'server/editable/editable.lua',
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'locale/locale.lua',
|
||||
'config.lua',
|
||||
'shared/settings.lua',
|
||||
'client/editable/esx.lua',
|
||||
'client/editable/qb.lua',
|
||||
'client/functions.lua',
|
||||
'client/client.lua',
|
||||
'client/bikeJump.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/editable/policeAlert.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'locale/locale.lua',
|
||||
'client/editable/editable.lua',
|
||||
'client/editable/policeAlert.lua',
|
||||
'client/editable/qb.lua',
|
||||
'client/editable/esx.lua',
|
||||
'client/functions.lua',
|
||||
'server/editable/editable.lua',
|
||||
'server/editable/esx.lua',
|
||||
'server/editable/qb.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
@@ -0,0 +1,41 @@
|
||||
-- To edit the messages edit the ones on the right side, not the ones inside the square brackets.
|
||||
-- ~r~ e.g. are colors. ~r~ being red, ~b~ being blue, ~y~ yellow etc.
|
||||
|
||||
|
||||
Locale = {
|
||||
['Car transport truck is currently departing.\nI\'ll pay top dollar if you can get them'] = 'Un transport de masini tocmai a plecat.\nPlatesc bine daca reusesti sa le aduci',
|
||||
['Martin'] = 'Martin',
|
||||
['Car collector'] = 'Colectionar de masini',
|
||||
['Car transport'] = 'Transport de masini',
|
||||
['Press ~w~[{keybinds}~w~] to unscrew'] = 'Apasa ~w~[{keybinds}~w~] pentru a desuruba',
|
||||
['~r~You dropped the screwdriver'] = '~r~Ai scapat surubelnita',
|
||||
['~w~Press [~r~E~w~] to force the ramp down'] = '~w~Apasa [~r~E~w~] pentru a forta rampa',
|
||||
['~w~Press [~r~E~w~] to cancel'] = '~w~Apasa [~r~E~w~] pentru a anula',
|
||||
['Cutting the latches...'] = 'Se taie incuietorile...',
|
||||
['~w~Press [~r~{keybinds}~w~] to continue cutting'] = '~w~Apasa [~r~{keybinds}~w~] pentru a continua taierea',
|
||||
['~w~Press [~r~E~w~] to climb up'] = '~w~Apasa [~r~E~w~] pentru a urca',
|
||||
['~w~Press [~r~{keybind}~w~] to attempt a jump'] = '~w~Apasa [~r~{keybind}~w~] pentru a incerca o saritura',
|
||||
['~y~! DANGEROUS !'] = '~y~! PERICULOS !',
|
||||
['Car transport robbery'] = 'Jaf transport de masini',
|
||||
['~r~You don\'t have anything that could be used to open this'] = '~r~Nu ai nimic cu care sa deschizi asta',
|
||||
['Our car transport is under attack! Coordinates have been shared!'] = 'Transportul nostru de masini este atacat! Coordonatele au fost distribuite!',
|
||||
['Car Transports Inc.'] = 'Car Transports Inc.',
|
||||
['Robbery in progress'] = 'Jaf in desfasurare',
|
||||
['Truck arrived'] = 'Camionul a ajuns',
|
||||
['Our truck has arrived to its destination. Thank you for your assistance'] = 'Camionul nostru a ajuns la destinatie. Va multumim pentru asistenta',
|
||||
['You need to remove the vehicle ~r~tracker ~w~before you sell it'] = 'Trebuie sa scoti ~r~trackerul ~w~de pe vehicul inainte sa il vinzi',
|
||||
['Stolen vehicle: '] = 'Vehicul furat: ',
|
||||
['~w~Press [~r~E~w~] to check for a tracker'] = '~w~Apasa [~r~E~w~] pentru a cauta un tracker',
|
||||
['~w~Searching for a tracking device'] = '~w~Se cauta un dispozitiv de urmarire',
|
||||
['~g~Tracking device found!'] = '~g~Dispozitiv de urmarire gasit!',
|
||||
['Deliver the ~g~{vehicle}~w~ to one of the drop off points'] = 'Livreaza ~g~{vehicle}~w~ la unul dintre punctele de predare',
|
||||
['Stolen vehicle drop off point'] = 'Punct de predare vehicul furat',
|
||||
['Vehicle dropped off'] = 'Vehicul predat',
|
||||
['You made ~g~${reward}'] = 'Ai castigat ~g~${reward}',
|
||||
['You made ~g~${reward}\n~r~${losses} deducted due to vehicle damage'] = 'Ai castigat ~g~${reward}\n~r~${losses} deduse din cauza daunelor vehiculului',
|
||||
['~w~Press [~r~E~w~] to drop off the vehicle'] = '~w~Apasa [~r~E~w~] pentru a preda vehiculul',
|
||||
|
||||
-- Gang & police requirement messages
|
||||
['~r~You must be in a gang to participate in this heist'] = '~r~Trebuie sa faci parte dintr-un gang pentru a participa la acest jaf',
|
||||
['~r~Not enough police officers online (minimum: {count})'] = '~r~Nu sunt suficienti politisti online (minim: {count})',
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
function OnHeistCreated()
|
||||
|
||||
end
|
||||
|
||||
function OnVehicleStartDroppingOff(source, vehEntity)
|
||||
-- Server-side gang check: prevent non-gang members from dropping off stolen vehicles
|
||||
if Config.requireGang and not IsInGang(source) then
|
||||
TriggerClientEvent('kq_carheist:gangCheckFailed', source)
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function OnVehicleDroppedOff(source, vehicle, reward)
|
||||
|
||||
end
|
||||
|
||||
function OnTrackerRemoved(source, coords)
|
||||
|
||||
end
|
||||
|
||||
|
||||
----------------------
|
||||
-- TRACKERS
|
||||
----------------------
|
||||
RegisterServerEvent('kq_carheist:removeTracker')
|
||||
AddEventHandler('kq_carheist:removeTracker', function(vehKey, coords)
|
||||
sellableVehicles[vehKey].tracker = false
|
||||
sellableVehicles[vehKey].trackerCoords = coords
|
||||
TriggerClientEvent('kq_carheist:syncSellableVehicles', -1, sellableVehicles)
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(Config.tracker.stayOnMapAfterRemovalTime)
|
||||
if sellableVehicles[vehKey] then
|
||||
sellableVehicles[vehKey].trackerCoords = nil
|
||||
end
|
||||
end)
|
||||
|
||||
OnTrackerRemoved(source, coords)
|
||||
end)
|
||||
@@ -0,0 +1,45 @@
|
||||
if Config.esxSettings.enabled then
|
||||
ESX = nil
|
||||
|
||||
if Config.esxSettings.useNewESXExport then
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
else
|
||||
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
|
||||
end
|
||||
|
||||
function HasItem(player, item)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
|
||||
return xPlayer.getInventoryItem(item).count >= 1
|
||||
end
|
||||
|
||||
function IsPolice(player)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
local job = xPlayer.getJob()
|
||||
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function GetPoliceCount()
|
||||
local currentOfficers = 0
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
if IsPolice(playerId) then
|
||||
currentOfficers = currentOfficers + 1
|
||||
end
|
||||
end
|
||||
return currentOfficers
|
||||
end
|
||||
|
||||
function AddMoney(player, amount)
|
||||
local xPlayer = ESX.GetPlayerFromId(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
xPlayer.addAccountMoney(Config.esxSettings.moneyAccount, amount)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,57 @@
|
||||
if Config.qbSettings.enabled then
|
||||
if Config.qbSettings.useNewQBExport then
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
end
|
||||
|
||||
function HasItem(player, item)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
|
||||
return xPlayer.Functions.GetItemByName(item)
|
||||
end
|
||||
|
||||
function IsPolice(player)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
local job = xPlayer.PlayerData.job
|
||||
|
||||
return Contains(Config.policeJobNames, job.name)
|
||||
end
|
||||
|
||||
function IsInGang(player)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
local gang = xPlayer.PlayerData.gang
|
||||
if not gang then
|
||||
return false
|
||||
end
|
||||
|
||||
return gang.name ~= nil and gang.name ~= 'none' and gang.name ~= ''
|
||||
end
|
||||
|
||||
function GetPoliceCount()
|
||||
local currentOfficers = 0
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
if IsPolice(playerId) then
|
||||
currentOfficers = currentOfficers + 1
|
||||
end
|
||||
end
|
||||
return currentOfficers
|
||||
end
|
||||
|
||||
function AddMoney(player, amount)
|
||||
local xPlayer = QBCore.Functions.GetPlayer(player)
|
||||
|
||||
if not xPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
xPlayer.Functions.AddMoney(Config.qbSettings.moneyAccount, amount)
|
||||
end
|
||||
end
|
||||
Binary file not shown.
@@ -0,0 +1,252 @@
|
||||
if Config.esxSettings.enabled and Config.qbSettings.enabled then
|
||||
print('^1BOTH FRAMEWORKS ENABLED!! MAKE SURE TO ONLY ENABLE ONE FRAMEWORK IN THE CONFIG FILE!')
|
||||
end
|
||||
if not Config.esxSettings.enabled and not Config.qbSettings.enabled then
|
||||
print('^1NO FRAMEWORK ENABLED!! MAKE SURE TO ENABLE ONE FRAMEWORK IN THE CONFIG FILE!')
|
||||
end
|
||||
|
||||
-- Do not remove this!
|
||||
sellableVehicles = {}
|
||||
|
||||
newHeist = {
|
||||
player = nil,
|
||||
truck = nil,
|
||||
trailer = nil,
|
||||
npc = nil,
|
||||
passenger = nil,
|
||||
support = nil,
|
||||
supportEnabled = nil,
|
||||
weaponsEnabled = nil,
|
||||
passengerEnabled = nil,
|
||||
bulletproofTiresEnabled = nil,
|
||||
touches = 0,
|
||||
vehicles = {}
|
||||
}
|
||||
|
||||
heist = {}
|
||||
|
||||
function AttemptCreateHeist()
|
||||
EndHeist()
|
||||
|
||||
heist = json.decode(json.encode(newHeist))
|
||||
|
||||
heist.hash = math.random(1, 99999)
|
||||
|
||||
heist.startLocation = Config.startLocations[math.random(1, #Config.startLocations)]
|
||||
heist.endLocation = heist.startLocation.finish
|
||||
|
||||
local closestPlayer = nil
|
||||
local closestDistance = 99999.9
|
||||
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
local playerCoords = GetEntityCoords(GetPlayerPed(playerId))
|
||||
|
||||
local distance = GetDistanceBetweenCoords(playerCoords.x, playerCoords.y, playerCoords.z, heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z)
|
||||
|
||||
if distance < 120 then
|
||||
return false
|
||||
end
|
||||
|
||||
if closestDistance > distance then
|
||||
closestPlayer = playerId
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
|
||||
if not closestPlayer then
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
heist.weaponsEnabled = true
|
||||
if math.random(0, 100) > Config.weaponChance then
|
||||
heist.weaponsEnabled = false
|
||||
end
|
||||
|
||||
local odds = 0
|
||||
local eventKey = nil
|
||||
local hit = math.random(0, 100)
|
||||
for k, event in pairs(Config.events) do
|
||||
if event.chance + odds > hit and not eventKey then
|
||||
eventKey = k
|
||||
else
|
||||
odds = odds + event.chance
|
||||
end
|
||||
end
|
||||
if not eventKey then
|
||||
eventKey = math.random(1, #Config.events)
|
||||
end
|
||||
|
||||
heist.event = eventKey
|
||||
local event = Config.events[eventKey]
|
||||
|
||||
local empty = 0
|
||||
for k, slot in pairs(Settings.trailerSlots) do
|
||||
if math.random(0, 100) <= event.vehicleSlotChance or (empty + event.minimumVehicles == #Settings.trailerSlots) then
|
||||
local vehicle = event.vehicles[math.random(1, #event.vehicles)]
|
||||
heist.vehicles[k] = { data = vehicle, vehicle = nil }
|
||||
else
|
||||
empty = empty + 1
|
||||
end
|
||||
end
|
||||
|
||||
heist.passengerEnabled = true
|
||||
if math.random(0, 100) > event.passengerChance then
|
||||
heist.passengerEnabled = false
|
||||
end
|
||||
|
||||
heist.bulletproofTiresEnabled = true
|
||||
if math.random(0, 100) > event.bulletproofTiresChance then
|
||||
heist.bulletproofTiresEnabled = false
|
||||
end
|
||||
|
||||
heist.supportEnabled = true
|
||||
if math.random(0, 100) > event.supportChance then
|
||||
heist.supportEnabled = false
|
||||
end
|
||||
|
||||
heist.player = closestPlayer
|
||||
Debug('starting heist, initiator: ' .. closestPlayer)
|
||||
TriggerClientEvent('kq_carheist:createHeist', closestPlayer, heist)
|
||||
|
||||
OnHeistCreated()
|
||||
return true
|
||||
end
|
||||
|
||||
function EndHeist()
|
||||
DeleteIfExists(heist.truck)
|
||||
DeleteIfExists(heist.trailer)
|
||||
DeleteIfExists(heist.npc)
|
||||
DeleteIfExists(heist.passenger)
|
||||
|
||||
if heist.supportEnabled and heist.support then
|
||||
DeleteIfExists(heist.support.vehicle)
|
||||
for k, ped in pairs(heist.support.peds) do
|
||||
DeleteIfExists(ped)
|
||||
end
|
||||
end
|
||||
|
||||
TriggerClientEvent('kq_carheist:endHeist', -1)
|
||||
|
||||
heist = json.decode(json.encode(newHeist))
|
||||
end
|
||||
|
||||
RegisterServerEvent('kq_carheist:heistCreated')
|
||||
AddEventHandler('kq_carheist:heistCreated', function(syncedHeist)
|
||||
if source ~= heist.player then
|
||||
return
|
||||
end
|
||||
|
||||
heist = syncedHeist
|
||||
|
||||
TriggerClientEvent('kq_carheist:startDriver', -1)
|
||||
TriggerClientEvent('kq_carheist:syncHeist', -1, heist)
|
||||
|
||||
if Config.announceTruckDepartureToPlayers then
|
||||
TriggerClientEvent('kq_carheist:announceHeist', -1, vector3(heist.startLocation.truck.x, heist.startLocation.truck.y, heist.startLocation.truck.z))
|
||||
end
|
||||
end)
|
||||
|
||||
if Config.debug then
|
||||
RegisterCommand('cheist', function(source, args)
|
||||
AttemptCreateHeist()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
local sleep = 20000
|
||||
if heist.player and heist.truck then
|
||||
sleep = 4000
|
||||
|
||||
local truckCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.truck))
|
||||
local trailerCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.trailer))
|
||||
local ended = false
|
||||
|
||||
Debug('Truck Owner: ' .. NetworkGetEntityOwner(NetworkGetEntityFromNetworkId(heist.truck)))
|
||||
Debug(truckCoords)
|
||||
|
||||
Debug('Trailer Owner: ' .. NetworkGetEntityOwner(NetworkGetEntityFromNetworkId(heist.trailer)))
|
||||
Debug(trailerCoords)
|
||||
|
||||
if not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.truck)) or not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.trailer)) or not DoesEntityExist(NetworkGetEntityFromNetworkId(heist.npc)) then
|
||||
Debug('Ending heist')
|
||||
EndHeist()
|
||||
ended = true
|
||||
end
|
||||
|
||||
if not ended then
|
||||
Debug('Remaining distance: ' .. GetDistanceBetweenCoords(truckCoords.x, truckCoords.y, truckCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z))
|
||||
|
||||
if GetDistanceBetweenCoords(truckCoords.x, truckCoords.y, truckCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z) < 18.0 and GetDistanceBetweenCoords(trailerCoords.x, trailerCoords.y, trailerCoords.z, heist.endLocation.x, heist.endLocation.y, heist.endLocation.z) < 25.0 then
|
||||
Debug('Truck arrived to its destination. Ending heist')
|
||||
TriggerClientEvent('kq_carheist:truckArrived', -1)
|
||||
EndHeist()
|
||||
end
|
||||
end
|
||||
end
|
||||
Citizen.Wait(sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
Citizen.Wait(30000)
|
||||
while true do
|
||||
if Config.minimumOfficers > 0 then
|
||||
local enough = false
|
||||
while not enough do
|
||||
local currentOfficers = GetPoliceCount()
|
||||
|
||||
if currentOfficers >= Config.minimumOfficers then
|
||||
enough = true
|
||||
else
|
||||
Debug('Couldn\'t start a new heist. Not enough police online')
|
||||
Citizen.Wait(120000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if heist.player ~= nil and heist.trailer and DoesEntityExist(NetworkGetEntityFromNetworkId(heist.trailer)) and not Config.ignoreDistances then
|
||||
Citizen.Wait(20000)
|
||||
|
||||
local tooClose = true
|
||||
while tooClose do
|
||||
local closestDistance = 99999.9
|
||||
|
||||
for _, playerId in ipairs(GetPlayers()) do
|
||||
playerId = tonumber(playerId)
|
||||
local playerCoords = GetEntityCoords(GetPlayerPed(playerId))
|
||||
|
||||
local trailerCoords = GetEntityCoords(NetworkGetEntityFromNetworkId(heist.trailer))
|
||||
|
||||
local distance = GetDistanceBetweenCoords(playerCoords.x, playerCoords.y, playerCoords.z, trailerCoords.x, trailerCoords.y, trailerCoords.z)
|
||||
|
||||
Debug('Distance: ' .. distance)
|
||||
if closestDistance > distance then
|
||||
closestDistance = distance
|
||||
end
|
||||
end
|
||||
|
||||
if closestDistance > 100.0 then
|
||||
tooClose = false
|
||||
else
|
||||
Debug('Couldn\'t start a new heist. Someone is too near the old trailer')
|
||||
Citizen.Wait(60000)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local success = false
|
||||
while not success do
|
||||
success = AttemptCreateHeist()
|
||||
if not success then
|
||||
Debug('Couldn\'t start a new heist. Someone is too close the spawn location')
|
||||
Citizen.Wait(60000)
|
||||
end
|
||||
end
|
||||
Citizen.Wait(Config.heistSpawnTime * 60000)
|
||||
end
|
||||
end)
|
||||
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_driftsmoke/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_driftsmoke/.fxap
Normal file
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,19 @@
|
||||
function IsWhitelisted(vehicle)
|
||||
for index, value in ipairs(Config.whitelist.vehicles) do
|
||||
if GetHashKey(value) == GetEntityModel(vehicle) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
if Config.toggleCommands then
|
||||
RegisterCommand('stopsmoke', function(source, args)
|
||||
smokeActive = false
|
||||
end)
|
||||
|
||||
RegisterCommand('startsmoke', function(source, args)
|
||||
smokeActive = true
|
||||
end)
|
||||
end
|
||||
71
resources/[framework]/[addons]/[kq]/kq_driftsmoke/config.lua
Normal file
71
resources/[framework]/[addons]/[kq]/kq_driftsmoke/config.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
Config = {}
|
||||
|
||||
Config.debug = false
|
||||
|
||||
|
||||
----------------------
|
||||
-- Smoke Settings --
|
||||
----------------------
|
||||
|
||||
-- The threshold of loss of traction at which the smoke will start appearing (6.0 is a good value)
|
||||
Config.driftThreshold = 6.0
|
||||
|
||||
-- Scale multiplier of the smoke, to make all smoke larger increase this value
|
||||
Config.scaleMultiplier = 1.5
|
||||
|
||||
-- Whether or not to use colored smoke, when false cars with custom tire smoke will still produce white smoke
|
||||
Config.allowColoredSmoke = true
|
||||
|
||||
-- Value between 0 and 100 | Defines the density of the smoke
|
||||
Config.smokeDensity = 90
|
||||
|
||||
-- Opacity of the smoke
|
||||
Config.smokeOpacity = 0.5
|
||||
|
||||
|
||||
----------------------
|
||||
-- Burnouts --
|
||||
----------------------
|
||||
|
||||
-- Whether or not to enlarge the smoke during a burnout
|
||||
Config.bigBurnoutSmoke = true
|
||||
|
||||
-- Whether or not to keep making the smoke larger as the burnout continues
|
||||
Config.growBurnoutSmoke = true
|
||||
|
||||
-- Maximum size of the burnout
|
||||
Config.maxBurnoutSmokeMultiplier = 1.6
|
||||
|
||||
|
||||
|
||||
----------------------
|
||||
-- Other --
|
||||
----------------------
|
||||
|
||||
-- Whether or not to enable /startsmoke and /stopsmoke commands
|
||||
Config.toggleCommands = false
|
||||
|
||||
-- Whether or not you want smoke to be produced on offroad surfaces like dirt
|
||||
Config.smokeOffroad = false
|
||||
|
||||
-- Surfaces where smoke will always be produced
|
||||
-- To check the surface you're on you can do /surface with debug mode enabled
|
||||
Config.roadSurfaces = {
|
||||
1, 3, 4, 12
|
||||
}
|
||||
|
||||
-- Whether or not only allow certain vehicles to produce the smoke
|
||||
Config.whitelist = {
|
||||
useWhitelist = false,
|
||||
vehicles = {
|
||||
'silvia',
|
||||
'brz13',
|
||||
'zion3',
|
||||
'tampa2',
|
||||
'futo',
|
||||
'yosemite2',
|
||||
}
|
||||
}
|
||||
|
||||
-- Whether or not to only enable drift smoke for vehicles that have drift tires (KuzQuality.com/(COMING SOON))
|
||||
Config.onlyWithDriftTires = false
|
||||
@@ -0,0 +1,34 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Drift Smoke by KuzQuality'
|
||||
version '1.2.0'
|
||||
|
||||
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
'config.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'config.lua',
|
||||
'client/client.lua',
|
||||
'client/editable.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'client/editable.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/.fxap
Normal file
Binary file not shown.
27
resources/[framework]/[addons]/[kq]/kq_dyno/_INSTALLATION.md
Normal file
27
resources/[framework]/[addons]/[kq]/kq_dyno/_INSTALLATION.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# KQ_DYNO INSTALLATION GUIDE
|
||||
|
||||
This guide will provide step-by-step instructions on how to install and set up the KQ_DYNO script for FiveM.
|
||||
|
||||
## Step 1:
|
||||
After downloading the script, unzip the folder and place it in the `resources` directory on your FiveM server.
|
||||
|
||||
## Step 2:
|
||||
Open the `config.lua` file in the script folder and make sure that the correct framework is enabled.
|
||||
|
||||
## Step 3:
|
||||
After the config file has been set up, add the script to your `server.cfg` file. Make sure that it's added **after** your framework of choice, so that it loads and starts properly.
|
||||
|
||||
## Step 4:
|
||||
Configure your dyno locations in the `config.lua` file
|
||||
|
||||
## Done
|
||||
Enjoy the script
|
||||
|
||||
|
||||
## Extra info
|
||||
To restart the script. Use our custom `/kq_dyno_restart` command. Simply restarting or ensuring it will cause you to crash
|
||||
due to the custom props being unloaded from the memory.
|
||||
|
||||
https://kuzquality.com/
|
||||
|
||||
https://discord.gg/fZsyam7Rvz
|
||||
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/cache.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/cache.lua
Normal file
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/client.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/client.lua
Normal file
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/display.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/display.lua
Normal file
Binary file not shown.
@@ -0,0 +1,9 @@
|
||||
-- Triggered when player starts a dyno run
|
||||
function OnDynoStart(dynoKey)
|
||||
|
||||
end
|
||||
|
||||
-- Triggered when the dyno run is fully finished
|
||||
function OnDynoFinish(dynoKey)
|
||||
|
||||
end
|
||||
@@ -0,0 +1,448 @@
|
||||
|
||||
function GetVehicleStats(veh)
|
||||
if not Config.dynoFormula then
|
||||
return GetVehicleStatsVanilla(veh)
|
||||
end
|
||||
|
||||
if Config.dynoFormula == 'highperformance1' then
|
||||
return GetVehicleStatsAlternative(veh)
|
||||
end
|
||||
|
||||
if Config.dynoFormula == 'highperformance2' then
|
||||
return GetVehicleStatsAlternative2(veh)
|
||||
end
|
||||
|
||||
if Config.dynoFormula == 'highperformance3' then
|
||||
return GetVehicleStatsAlternative3(veh)
|
||||
end
|
||||
|
||||
return GetVehicleStatsVanilla(veh)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function GetVehicleStatsVanilla(veh)
|
||||
return UseCache('vehStats' .. veh, function()
|
||||
local fInitialDriveForce = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveForce')
|
||||
local fDriveInertia = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveInertia')
|
||||
local fInitialDriveMaxFlatVel = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveMaxFlatVel')
|
||||
local fMass = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fMass')
|
||||
local nInitialDriveGears = GetVehicleHandlingFloat(veh, 'CHandlingData', 'nInitialDriveGears')
|
||||
|
||||
local fDriveBiasFront = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveBiasFront')
|
||||
|
||||
|
||||
local drivetrainLoss = 0.1 -- awd
|
||||
if fDriveBiasFront >= 0.85 then
|
||||
drivetrainLoss = 0.13 -- fwd
|
||||
end
|
||||
if fDriveBiasFront <= 0.15 then
|
||||
drivetrainLoss = 0.2 -- rwd
|
||||
end
|
||||
|
||||
local wheelPower = GetWheelPower(veh)
|
||||
|
||||
if IsVehicleFwd(veh) then
|
||||
wheelPower = wheelPower * fDriveBiasFront
|
||||
else
|
||||
wheelPower = wheelPower * (1 - fDriveBiasFront)
|
||||
end
|
||||
|
||||
local rpm = GetVehicleCurrentRpm(veh)
|
||||
|
||||
local maxRpm = ((math.min(161.0, fInitialDriveMaxFlatVel) / nInitialDriveGears / 30) * 8500) * 0.95
|
||||
local realRpm = math.floor(rpm * maxRpm)
|
||||
|
||||
local torque = math.floor((fInitialDriveForce * fMass) * (realRpm / maxRpm)
|
||||
+ (wheelPower * 40)
|
||||
* (math.min(4.0, math.max(0.7, (fMass / 1700) ^ 3)))
|
||||
)
|
||||
|
||||
local hpMultiplier = 0.95
|
||||
if fInitialDriveMaxFlatVel >= 150 then
|
||||
hpMultiplier = 1.0
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159 then
|
||||
hpMultiplier = 1.1
|
||||
torque = math.floor(torque * 1.05)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159.5 then
|
||||
hpMultiplier = 1.15
|
||||
torque = math.floor(torque * 1.15)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 164.0 then
|
||||
hpMultiplier = 1.05
|
||||
torque = math.floor(torque * 1.1)
|
||||
end
|
||||
|
||||
local hp = math.abs(math.floor(DiminishingReturns(
|
||||
((torque / 1.356) * (rpm * maxRpm) / 5252)
|
||||
* fDriveInertia
|
||||
* (math.min(160.0, fInitialDriveMaxFlatVel) / 150)
|
||||
* wheelPower
|
||||
* (1 - drivetrainLoss)
|
||||
* hpMultiplier
|
||||
* (math.min(2.0, math.max(0.95, fMass / 1400)))
|
||||
)))
|
||||
|
||||
local torqueInUnits = torque
|
||||
|
||||
if UsingFtLbs() then
|
||||
torqueInUnits = torque / 1.356
|
||||
end
|
||||
|
||||
return hp, torqueInUnits, realRpm, rpm
|
||||
end, 50)
|
||||
end
|
||||
|
||||
|
||||
function GetVehicleStatsAlternative(veh)
|
||||
return UseCache('vehStats' .. veh, function()
|
||||
local fInitialDriveForce = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveForce')
|
||||
local fDriveInertia = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveInertia')
|
||||
local fInitialDriveMaxFlatVel = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveMaxFlatVel')
|
||||
local fMass = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fMass')
|
||||
local nInitialDriveGears = GetVehicleHandlingFloat(veh, 'CHandlingData', 'nInitialDriveGears')
|
||||
|
||||
local fDriveBiasFront = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveBiasFront')
|
||||
|
||||
|
||||
local drivetrainLoss = 0.1 -- awd
|
||||
if fDriveBiasFront >= 0.85 then
|
||||
drivetrainLoss = 0.13 -- fwd
|
||||
end
|
||||
if fDriveBiasFront <= 0.15 then
|
||||
drivetrainLoss = 0.2 -- rwd
|
||||
end
|
||||
|
||||
local wheelPower = GetWheelPower(veh)
|
||||
|
||||
if IsVehicleFwd(veh) then
|
||||
wheelPower = wheelPower * fDriveBiasFront
|
||||
else
|
||||
wheelPower = wheelPower * (1 - fDriveBiasFront)
|
||||
end
|
||||
|
||||
local rpm = GetVehicleCurrentRpm(veh)
|
||||
|
||||
local maxRpm = ((math.min(161.0, fInitialDriveMaxFlatVel) / nInitialDriveGears / 30) * 8500) * 0.95
|
||||
local realRpm = math.floor(rpm * maxRpm)
|
||||
|
||||
local torque = math.floor((fInitialDriveForce * fMass) * (realRpm / maxRpm)
|
||||
+ (wheelPower * 40)
|
||||
* (math.min(4.0, math.max(0.7, (fMass / 1700) ^ 3)))
|
||||
)
|
||||
|
||||
local hpMultiplier = 0.95
|
||||
if fInitialDriveMaxFlatVel >= 150 then
|
||||
hpMultiplier = 1.0
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159 then
|
||||
hpMultiplier = 1.1
|
||||
torque = math.floor(torque * 1.05)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159.5 then
|
||||
hpMultiplier = 1.15
|
||||
torque = math.floor(torque * 1.15)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 164.0 then
|
||||
hpMultiplier = 1.05
|
||||
torque = math.floor(torque * 1.1)
|
||||
end
|
||||
|
||||
local hp = math.abs(math.floor(DiminishingReturns(
|
||||
((torque / 1.356) * (rpm * maxRpm) / 5252)
|
||||
* fDriveInertia
|
||||
* math.min(1.1, wheelPower)
|
||||
* (1 - drivetrainLoss)
|
||||
* hpMultiplier
|
||||
* (math.min(2.0, math.max(0.95, fMass / 1400)))
|
||||
)))
|
||||
|
||||
local torqueInUnits = torque
|
||||
|
||||
if UsingFtLbs() then
|
||||
torqueInUnits = torque / 1.356
|
||||
end
|
||||
|
||||
return hp, torqueInUnits, realRpm, rpm
|
||||
end, 50)
|
||||
end
|
||||
|
||||
function GetVehicleStatsAlternative2(veh)
|
||||
return UseCache('vehStats' .. veh, function()
|
||||
local fInitialDriveForce = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveForce')
|
||||
local fDriveInertia = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveInertia')
|
||||
local fInitialDriveMaxFlatVel = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveMaxFlatVel')
|
||||
local fMass = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fMass')
|
||||
local nInitialDriveGears = GetVehicleHandlingFloat(veh, 'CHandlingData', 'nInitialDriveGears')
|
||||
|
||||
local fDriveBiasFront = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveBiasFront')
|
||||
|
||||
|
||||
local drivetrainLoss = 0.1 -- awd
|
||||
if fDriveBiasFront >= 0.85 then
|
||||
drivetrainLoss = 0.13 -- fwd
|
||||
end
|
||||
if fDriveBiasFront <= 0.15 then
|
||||
drivetrainLoss = 0.2 -- rwd
|
||||
end
|
||||
|
||||
local wheelPower = GetWheelPower(veh)
|
||||
|
||||
if IsVehicleFwd(veh) then
|
||||
wheelPower = wheelPower * fDriveBiasFront
|
||||
else
|
||||
wheelPower = wheelPower * (1 - fDriveBiasFront)
|
||||
end
|
||||
|
||||
local rpm = GetVehicleCurrentRpm(veh)
|
||||
|
||||
local maxRpm = ((math.min(161.0, fInitialDriveMaxFlatVel) / nInitialDriveGears / 30) * 8500) * 0.95
|
||||
local realRpm = math.floor(rpm * maxRpm)
|
||||
|
||||
local torque = math.floor(((fInitialDriveForce * 0.5) * fMass) * (realRpm / maxRpm)
|
||||
+ (math.min(3.0, wheelPower))
|
||||
* (math.min(4.0, math.max(0.7, (fMass / 1700) ^ 3)))
|
||||
)
|
||||
|
||||
local hpMultiplier = 0.95
|
||||
if fInitialDriveMaxFlatVel >= 150 then
|
||||
hpMultiplier = 1.0
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159 then
|
||||
hpMultiplier = 1.1
|
||||
torque = math.floor(torque * 1.05)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159.5 then
|
||||
hpMultiplier = 1.15
|
||||
torque = math.floor(torque * 1.15)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 164.0 then
|
||||
hpMultiplier = 1.05
|
||||
torque = math.floor(torque * 1.1)
|
||||
end
|
||||
|
||||
local hp = math.abs(math.floor(DiminishingReturns(
|
||||
((torque / 1.356) * (rpm * maxRpm) / 5252)
|
||||
* fDriveInertia
|
||||
* (math.min(160.0, fInitialDriveMaxFlatVel) / 250)
|
||||
* math.min(2.0, wheelPower)
|
||||
* (1 - drivetrainLoss)
|
||||
* hpMultiplier
|
||||
* (math.min(2.0, math.max(0.95, fMass / 1400)))
|
||||
)))
|
||||
|
||||
local torqueInUnits = torque
|
||||
|
||||
if UsingFtLbs() then
|
||||
torqueInUnits = torque / 1.356
|
||||
end
|
||||
|
||||
return hp, torqueInUnits, realRpm, rpm
|
||||
end, 50)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function GetVehicleStatsAlternative3(veh)
|
||||
return UseCache('vehStats' .. veh, function()
|
||||
local fInitialDriveForce = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveForce')
|
||||
local fDriveInertia = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveInertia')
|
||||
local fInitialDriveMaxFlatVel = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fInitialDriveMaxFlatVel')
|
||||
local fMass = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fMass')
|
||||
local nInitialDriveGears = GetVehicleHandlingFloat(veh, 'CHandlingData', 'nInitialDriveGears')
|
||||
|
||||
local fDriveBiasFront = GetVehicleHandlingFloat(veh, 'CHandlingData', 'fDriveBiasFront')
|
||||
|
||||
|
||||
local drivetrainLoss = 0.1 -- awd
|
||||
if fDriveBiasFront >= 0.85 then
|
||||
drivetrainLoss = 0.13 -- fwd
|
||||
end
|
||||
if fDriveBiasFront <= 0.15 then
|
||||
drivetrainLoss = 0.2 -- rwd
|
||||
end
|
||||
|
||||
local wheelPower = GetWheelPower(veh)
|
||||
|
||||
if IsVehicleFwd(veh) then
|
||||
wheelPower = wheelPower * fDriveBiasFront
|
||||
else
|
||||
wheelPower = wheelPower * (1 - fDriveBiasFront)
|
||||
end
|
||||
|
||||
local rpm = GetVehicleCurrentRpm(veh)
|
||||
|
||||
local maxRpm = ((math.min(161.0, fInitialDriveMaxFlatVel) / nInitialDriveGears / 35) * 8500) * 0.95
|
||||
local realRpm = math.floor(rpm * maxRpm)
|
||||
|
||||
local torque = math.floor(((fInitialDriveForce * 0.4) * fMass) * (realRpm / maxRpm)
|
||||
+ (math.min(2.0, wheelPower / 2))
|
||||
* (math.min(4.0, math.max(0.7, (fMass / 1700) ^ 3)))
|
||||
)
|
||||
|
||||
local hpMultiplier = 0.95
|
||||
if fInitialDriveMaxFlatVel >= 150 then
|
||||
hpMultiplier = 1.0
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159 then
|
||||
hpMultiplier = 1.1
|
||||
torque = math.floor(torque * 1.05)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 159.5 then
|
||||
hpMultiplier = 1.15
|
||||
torque = math.floor(torque * 1.15)
|
||||
end
|
||||
if fInitialDriveMaxFlatVel >= 164.0 then
|
||||
hpMultiplier = 1.05
|
||||
torque = math.floor(torque * 1.1)
|
||||
end
|
||||
|
||||
local hp = math.abs(math.floor(DiminishingReturns(
|
||||
((torque / 1.356) * (rpm * maxRpm) / 5252)
|
||||
* fDriveInertia
|
||||
* math.min(2.0, wheelPower / 2)
|
||||
* (1 - drivetrainLoss)
|
||||
* hpMultiplier
|
||||
* (math.min(2.0, math.max(0.95, fMass / 1400)))
|
||||
)))
|
||||
|
||||
local torqueInUnits = torque
|
||||
|
||||
if UsingFtLbs() then
|
||||
torqueInUnits = torque / 1.356
|
||||
end
|
||||
|
||||
return hp, torqueInUnits, realRpm, rpm
|
||||
end, 50)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function GetWheelPower(veh)
|
||||
local power = 0
|
||||
for i = 0 , GetVehicleNumberOfWheels(veh) - 1 do
|
||||
power = power + GetVehicleWheelPower(veh, i) * (GetVehicleWheelTireColliderSize(veh, i) * 2 + 0.15)
|
||||
end
|
||||
return power
|
||||
end
|
||||
|
||||
function DiminishingReturns(x)
|
||||
return x * (1 - (math.min(0.3, (x + 100) / 2400) - 0.05))
|
||||
end
|
||||
|
||||
|
||||
function UsingFtLbs()
|
||||
return Config.torqueUnits == 'lb-ft' or Config.torqueUnits == 'lbs' or Config.torqueUnits == 'ft-lb'
|
||||
end
|
||||
|
||||
function GetTorqueUnit()
|
||||
if UsingFtLbs() then
|
||||
return L('lb-ft')
|
||||
end
|
||||
return L('nm')
|
||||
end
|
||||
|
||||
function IsPlayerUnreachable()
|
||||
local playerPed = PlayerPedId()
|
||||
return IsPedRagdoll(playerPed) or IsEntityDead(playerPed)
|
||||
end
|
||||
|
||||
|
||||
function KeybindTip(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, 200)
|
||||
end
|
||||
|
||||
-- This function is responsible for all the tooltips displayed on top right of the screen, you could
|
||||
-- replace it with a custom notification etc.
|
||||
function Notify(message)
|
||||
SetTextComponentFormat("STRING")
|
||||
AddTextComponentString(message)
|
||||
EndTextCommandDisplayHelp(0, 0, 0, -1)
|
||||
end
|
||||
|
||||
RegisterNetEvent('kq_dyno:client:notify')
|
||||
AddEventHandler('kq_dyno:client:notify', function(message)
|
||||
Notify(message)
|
||||
end)
|
||||
|
||||
function PlayAnim(dict, anim, flag, duration)
|
||||
Citizen.CreateThread(function()
|
||||
RequestAnimDict(dict)
|
||||
local timeout = 0
|
||||
while not HasAnimDictLoaded(dict) do
|
||||
Citizen.Wait(50)
|
||||
timeout = timeout + 1
|
||||
if timeout > 100 then
|
||||
return
|
||||
end
|
||||
end
|
||||
TaskPlayAnim(PlayerPedId(), dict, anim, 1.5, 1.0, duration or -1, flag or 1, 0, false, false, false)
|
||||
RemoveAnimDict(dict)
|
||||
end)
|
||||
end
|
||||
|
||||
function DrawDynoMarker(dyno)
|
||||
DrawMarker(43, dyno.coords + vector3(0.0, 0.0, -1.0), 0.0, 0.0, 0.0, 0.0, 0.0, dyno.heading, 2.5, 1.0, 0.5, 40, 110, 250, 30, 0, 0, 0, 0)
|
||||
end
|
||||
|
||||
function CanPerformDynoTests(dynoKey)
|
||||
return UseCache('CanPerformDynoTests' .. dynoKey, function()
|
||||
local dyno = Config.dynos[dynoKey]
|
||||
|
||||
return (not Config.jobWhitelist.enabled or (not PLAYER_JOB or not dyno.jobs or Contains(dyno.jobs, PLAYER_JOB)))
|
||||
end, 5000)
|
||||
end
|
||||
|
||||
-- Keybinds display
|
||||
buttons = nil
|
||||
keybinds = {}
|
||||
|
||||
function AddKeybindDisplay(key, label)
|
||||
buttons = nil
|
||||
|
||||
table.insert(keybinds, {
|
||||
key = '~' .. key .. '~',
|
||||
label = label,
|
||||
})
|
||||
|
||||
buttons = RequestScaleformMovie("INSTRUCTIONAL_BUTTONS")
|
||||
while not HasScaleformMovieLoaded(buttons) do
|
||||
Wait(0)
|
||||
end
|
||||
|
||||
BeginScaleformMovieMethod(buttons, "CLEAR_ALL")
|
||||
EndScaleformMovieMethod()
|
||||
|
||||
for k, keybind in pairs(keybinds) do
|
||||
BeginScaleformMovieMethod(buttons, "SET_DATA_SLOT")
|
||||
ScaleformMovieMethodAddParamInt(k - 1)
|
||||
ScaleformMovieMethodAddParamPlayerNameString(keybind.key)
|
||||
PushScaleformMovieMethodParameterString(keybind.label)
|
||||
EndScaleformMovieMethod()
|
||||
end
|
||||
|
||||
BeginScaleformMovieMethod(buttons, "DRAW_INSTRUCTIONAL_BUTTONS")
|
||||
EndScaleformMovieMethod()
|
||||
end
|
||||
|
||||
function ClearKeybinds()
|
||||
buttons = nil
|
||||
keybinds = {}
|
||||
end
|
||||
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while true do
|
||||
local sleep = 500
|
||||
|
||||
if buttons ~= nil then
|
||||
sleep = 1
|
||||
DrawScaleformMovieFullscreen(buttons, 255, 255, 255, 255, 0)
|
||||
end
|
||||
Citizen.Wait(sleep)
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,31 @@
|
||||
if Config.esxSettings.enabled then
|
||||
ESX = nil
|
||||
|
||||
if Config.esxSettings.useNewESXExport then
|
||||
ESX = exports['es_extended']:getSharedObject()
|
||||
else
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil do
|
||||
TriggerEvent('esx:getSharedObject', function(obj)
|
||||
ESX = obj
|
||||
end)
|
||||
Citizen.Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while ESX == nil or ESX.GetPlayerData().job == nil do
|
||||
Citizen.Wait(10)
|
||||
end
|
||||
|
||||
ESX.PlayerData = ESX.GetPlayerData()
|
||||
PLAYER_JOB = ESX.PlayerData.job.name
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:setJob')
|
||||
AddEventHandler('esx:setJob', function(job)
|
||||
ESX.PlayerData.job = job
|
||||
PLAYER_JOB = job.name
|
||||
end)
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
if Config.qbSettings.enabled then
|
||||
QBCore = exports['qb-core']:GetCoreObject()
|
||||
|
||||
if QBCore.Functions.GetPlayerData() and QBCore.Functions.GetPlayerData().job then
|
||||
PLAYER_JOB = QBCore.Functions.GetPlayerData().job.name
|
||||
end
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded')
|
||||
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
|
||||
PLAYER_JOB = QBCore.Functions.GetPlayerData().job.name
|
||||
end)
|
||||
|
||||
|
||||
RegisterNetEvent('QBCore:Client:OnJobUpdate')
|
||||
AddEventHandler('QBCore:Client:OnJobUpdate', function(JobInfo)
|
||||
PLAYER_JOB = JobInfo.name
|
||||
end)
|
||||
end
|
||||
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/functions.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/functions.lua
Normal file
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/spawning.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/client/spawning.lua
Normal file
Binary file not shown.
315
resources/[framework]/[addons]/[kq]/kq_dyno/config.lua
Normal file
315
resources/[framework]/[addons]/[kq]/kq_dyno/config.lua
Normal file
@@ -0,0 +1,315 @@
|
||||
Config = {}
|
||||
|
||||
Config.debug = false
|
||||
|
||||
--- If you're testing the script and editing the values DO NOT simply restart the script. As this script is using custom models (dynos)
|
||||
--- it will crash if you just restart it. Instead use the `/kq_dyno_restart` command. It will safely restart the script without causing you to crash
|
||||
|
||||
|
||||
--- SETTINGS FOR ESX
|
||||
Config.esxSettings = {
|
||||
enabled = false,
|
||||
-- Whether or not to use the new ESX export method
|
||||
useNewESXExport = true,
|
||||
}
|
||||
|
||||
--- SETTINGS FOR QBCORE
|
||||
Config.qbSettings = {
|
||||
enabled = true,
|
||||
}
|
||||
|
||||
|
||||
--- BASIC
|
||||
|
||||
-- Torque units | 'nm' or 'lb-ft'
|
||||
Config.torqueUnits = 'nm'
|
||||
|
||||
|
||||
--- Horsepower and torque calculation formula
|
||||
-- If you're not using vanilla or vanilla-like handling:
|
||||
-- Try out different formulas and see what works best for your server.
|
||||
|
||||
-- 'vanilla' = Perfect setup for vanilla handling as well as handling files obeying the principles of vanilla GTA
|
||||
|
||||
-- 'highperformance1' = Good for servers using handling files which result in faster vehicles
|
||||
-- 'highperformance2' = Good for servers using handling files which result in faster vehicles (extra)
|
||||
-- 'highperformance3' = Good for servers using handling files which result in faster vehicles (extra)
|
||||
---------------------------------------------
|
||||
Config.dynoFormula = 'vanilla'
|
||||
|
||||
|
||||
|
||||
--- FRAMEWORK OPTIONS (MAKE SURE TO ENABLE YOUR FRAMEWORK IF USING ONE) <!>
|
||||
Config.jobWhitelist = {
|
||||
enabled = true,
|
||||
-- To configure the jobs, set them on each dyno individually
|
||||
}
|
||||
|
||||
|
||||
-- Time it takes for the screens to turn off after a dyno run (in seconds)
|
||||
Config.screenTimeout = 30
|
||||
|
||||
-- Whether to display the dyno sheet on the screen as UI
|
||||
Config.displaySheetOnScreen = true
|
||||
|
||||
-- Determines the location of the dyno sheet
|
||||
Config.screenSheetOffset = {
|
||||
x = 0.84,
|
||||
y = 0.833,
|
||||
}
|
||||
|
||||
-- Dynos setup
|
||||
-- coords = vector3 of the dyno location
|
||||
-- heading = heading of the dyno
|
||||
-- model = model defined in Config.dynoModels (By leaving this out, you will create a dyno without a model. Useful for MLOs with built-in dynos)
|
||||
-- displays = table of displays
|
||||
-- displayCoords = vector3 of the display location
|
||||
-- displayTilt = angle of the display tilt,
|
||||
-- displayHeading = heading of the display
|
||||
-- displayType = display defined in Config.displayTypes
|
||||
-- jobs = Table of jobs which are allowed to use the dyno (false or nil to allow everyone to use it)
|
||||
Config.dynos = {
|
||||
['bennys'] = {
|
||||
coords = vector3(-214.28, -1318.14, 30.9),
|
||||
heading = 180.0,
|
||||
|
||||
model = 'default_purple',
|
||||
|
||||
displays = {
|
||||
{
|
||||
displayCoords = vector3(-217.4, -1318.92, 32.55),
|
||||
displayHeading = 90.0,
|
||||
displayTilt = 3.0,
|
||||
displayType = 'wall_tv_2',
|
||||
},
|
||||
{
|
||||
displayCoords = vector3(-211.5, -1320.6, 30.89),
|
||||
displayHeading = 250.0,
|
||||
displayType = 'stand',
|
||||
}
|
||||
},
|
||||
|
||||
jobs = { 'mechanic' },
|
||||
},
|
||||
['lsc_harmony'] = {
|
||||
coords = vector3(1182.66, 2636.5, 37.78),
|
||||
heading = 0.0,
|
||||
|
||||
model = 'default_blue',
|
||||
|
||||
displays = {
|
||||
{
|
||||
displayCoords = vector3(1182.66, 2634.6, 39.3),
|
||||
displayHeading = 180.0,
|
||||
displayType = 'wall_tv',
|
||||
},
|
||||
},
|
||||
|
||||
jobs = { 'mechanic' },
|
||||
},
|
||||
['lsc_airport'] = {
|
||||
coords = vector3(-1164.45, -2018.8, 13.18),
|
||||
heading = 315.0,
|
||||
|
||||
model = 'default_red',
|
||||
|
||||
displays = {
|
||||
{
|
||||
displayCoords = vector3(-1164.3, -2014.53, 14.13),
|
||||
displayHeading = 45.0,
|
||||
displayType = 'wall_tv',
|
||||
},
|
||||
},
|
||||
|
||||
jobs = { 'mechanic' },
|
||||
},
|
||||
['import_export_garage'] = {
|
||||
coords = vector3(980.2, -3002.11, -39.65),
|
||||
heading = 90.0,
|
||||
|
||||
model = 'default_blue',
|
||||
|
||||
displays = {
|
||||
{
|
||||
displayCoords = vector3(978.5, -2999.35, -39.62),
|
||||
displayHeading = 0.0,
|
||||
displayType = 'stand',
|
||||
},
|
||||
},
|
||||
|
||||
jobs = { 'mechanic' },
|
||||
},
|
||||
--['no_model_liberty_walk_mlo'] = {
|
||||
-- coords = vector3(1148.40, -792.69, 57.5),
|
||||
-- heading = 90.0,
|
||||
--
|
||||
-- displays = {
|
||||
-- {
|
||||
-- displayCoords = vector3(1148.29, -795.0, 58.35),
|
||||
-- displayHeading = 190.0,
|
||||
-- displayType = 'monitor',
|
||||
-- },
|
||||
-- },
|
||||
--
|
||||
-- jobs = nil,
|
||||
--},
|
||||
}
|
||||
|
||||
|
||||
-- This is just used to fill the default dynos with their rollers
|
||||
Config.baseRollers = {
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(0.18, 0.6, -0.08),
|
||||
direction = -1,
|
||||
side = 1,
|
||||
},
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(-0.18, 0.6, -0.08),
|
||||
direction = -1,
|
||||
side = 1,
|
||||
},
|
||||
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(0.18, -1.18, -0.08),
|
||||
direction = -1,
|
||||
side = 2,
|
||||
},
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(-0.18, -1.18, -0.08),
|
||||
direction = -1,
|
||||
side = 2,
|
||||
},
|
||||
}
|
||||
|
||||
-- Dyno models
|
||||
Config.dynoModels = {
|
||||
['default_yellow'] = {
|
||||
base = 'kq_dyno2_yellow',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['default_red'] = {
|
||||
base = 'kq_dyno2_red',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['default_purple'] = {
|
||||
base = 'kq_dyno2_purple',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['default_green'] = {
|
||||
base = 'kq_dyno2_green',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['default_gray'] = {
|
||||
base = 'kq_dyno2_gray',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['default_blue'] = {
|
||||
base = 'kq_dyno2_blue',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, -0.04),
|
||||
rollers = Config.baseRollers,
|
||||
},
|
||||
['basic'] = {
|
||||
base = 'kq_dyno',
|
||||
textureVariation = 0,
|
||||
heading = -90.0,
|
||||
offset = vector3(0.0, 0.0, 0.0),
|
||||
rollers = {
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(0.18, 0.9, -0.08),
|
||||
direction = -1,
|
||||
side = 1,
|
||||
},
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(-0.18, 0.9, -0.08),
|
||||
direction = -1,
|
||||
side = 1,
|
||||
},
|
||||
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(0.18, -0.9, -0.08),
|
||||
direction = -1,
|
||||
side = 2,
|
||||
},
|
||||
{
|
||||
prop = 'kq_dyno_roller',
|
||||
rotation = vector3(0.0, 90.0, 0.0),
|
||||
offset = vector3(-0.18, -0.9, -0.08),
|
||||
direction = -1,
|
||||
side = 2,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
-- Display types
|
||||
-- prop = prop of the display
|
||||
-- offset = offset of the display (texture, not the prop)
|
||||
-- heading = heading of the display (texture, not the prop)
|
||||
-- size = size of the display
|
||||
Config.displayTypes = {
|
||||
['stand'] = {
|
||||
prop = 'prop_cs_tv_stand',
|
||||
offset = vector3(0.529, -0.08, 1.01),
|
||||
heading = 180.0,
|
||||
size = vector2(1.098, 0.54),
|
||||
},
|
||||
['monitor'] = {
|
||||
prop = 'prop_tv_flat_03',
|
||||
offset = vector3(0.35, -0.01, 0.025),
|
||||
heading = 180.0,
|
||||
size = vector2(0.7, 0.4),
|
||||
},
|
||||
['wall_tv'] = {
|
||||
prop = 'prop_tv_flat_01',
|
||||
offset = vector3(1.07, -0.06, -0.12),
|
||||
heading = 180.0,
|
||||
size = vector2(2.14, 1.2),
|
||||
},
|
||||
['wall_tv_2'] = {
|
||||
prop = 'xm_prop_x17_tv_flat_01',
|
||||
offset = vector3(0.798, -0.046, 0.152),
|
||||
heading = 180.0,
|
||||
size = vector2(1.5, 0.832),
|
||||
},
|
||||
}
|
||||
|
||||
-- https://docs.fivem.net/docs/game-references/controls/
|
||||
-- Use the input index for the "input" value
|
||||
Config.keybinds = {
|
||||
start = {
|
||||
label = 'E',
|
||||
name = 'INPUT_PICKUP',
|
||||
input = 38,
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
-- Discord webhook options
|
||||
Config.webhook = {
|
||||
enabled = false, -- Whether to send the dyno sheets to the discord webhook
|
||||
|
||||
-- To get the Discord webhook link, right click on a channel > Edit channel > Integrations > Webhooks > View webhooks > New webhook
|
||||
url = 'YOUR_WEBHOOK_URL_HERE',
|
||||
|
||||
-- Here you can add webhooks for specific dynos. Based on the dyno key/index name (same as in config.lua)
|
||||
dynoSpecific = {
|
||||
['bennys'] = 'DYNO_SPECIFIC_WEBHOOK_URL_HERE', -- remove this line if you don't want to use a dyno specific webhooks
|
||||
},
|
||||
|
||||
-- Replace this with the name of your server or a title you want on your dyno sheets
|
||||
title = 'Red Valley - DynoTech',
|
||||
|
||||
-- Whether to include certain parts of the users info in the webhook messages
|
||||
includeUserName = true,
|
||||
includeSteamId = true,
|
||||
|
||||
color = 16723456,
|
||||
}
|
||||
59
resources/[framework]/[addons]/[kq]/kq_dyno/fxmanifest.lua
Normal file
59
resources/[framework]/[addons]/[kq]/kq_dyno/fxmanifest.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Car dyno by KuzQuality'
|
||||
version '1.4.0'
|
||||
|
||||
ui_page 'html/blank.html'
|
||||
|
||||
data_file 'DLC_ITYP_REQUEST' 'stream/kq_dyno_props.ytyp'
|
||||
|
||||
files {
|
||||
'html/js/jquery.js',
|
||||
'html/js/chart.js',
|
||||
'html/js/chartjs-annotation.js',
|
||||
'html/js/html2canvas.js',
|
||||
'html/blank.html',
|
||||
'html/index.html',
|
||||
}
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
'config.lua',
|
||||
'config_server.lua',
|
||||
'locale.lua',
|
||||
'server/server.lua',
|
||||
'server/editable/editable.lua',
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'config.lua',
|
||||
'locale.lua',
|
||||
'client/editable/api.lua',
|
||||
'client/functions.lua',
|
||||
'client/cache.lua',
|
||||
'client/client.lua',
|
||||
'client/spawning.lua',
|
||||
'client/display.lua',
|
||||
'client/editable/client.lua',
|
||||
'client/editable/esx.lua',
|
||||
'client/editable/qb.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'config_server.lua',
|
||||
'locale.lua',
|
||||
'client/editable/*.lua',
|
||||
'server/editable/*.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
@@ -0,0 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<body style="background-color: transparent;">
|
||||
|
||||
</body>
|
||||
</html>
|
||||
228
resources/[framework]/[addons]/[kq]/kq_dyno/html/index.html
Normal file
228
resources/[framework]/[addons]/[kq]/kq_dyno/html/index.html
Normal file
@@ -0,0 +1,228 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<script src="js/jquery.js"></script>
|
||||
<script src="js/chart.js"></script>
|
||||
<script src="js/chartjs-annotation.js"></script>
|
||||
<script src="js/html2canvas.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="chart">
|
||||
<canvas id="chart"></canvas>
|
||||
<span class="watermark">Dyno Technology by KuzQuality.com</span>
|
||||
<span class="title" id="title"></span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(() => {
|
||||
let times = [];
|
||||
|
||||
let localeSet = false;
|
||||
let title = '';
|
||||
let peakHp = 'Peak HP';
|
||||
let peakTorque = 'Peak Torque';
|
||||
let torqueUnit = 'nm';
|
||||
|
||||
window.addEventListener('message', ({data}) => {
|
||||
if (data.event === 'update') {
|
||||
if (times.length > 600) {
|
||||
times.shift();
|
||||
}
|
||||
times.push({
|
||||
rpm: event.data.rpm,
|
||||
hp: event.data.hp,
|
||||
torque: event.data.torque,
|
||||
});
|
||||
|
||||
setChart();
|
||||
|
||||
if (!localeSet) {
|
||||
setLocale(data);
|
||||
}
|
||||
}
|
||||
if (data.event === 'capture-image') {
|
||||
captureImage(data.dynoKey);
|
||||
}
|
||||
});
|
||||
|
||||
function setLocale(data) {
|
||||
localeSet = true;
|
||||
|
||||
title = data.title;
|
||||
peakHp = data.peakHp;
|
||||
peakTorque = data.peakTorque;
|
||||
torqueUnit = data.torqueUnit;
|
||||
$('#title').html(title);
|
||||
}
|
||||
|
||||
function captureImage(dynoKey) {
|
||||
$('.chart').addClass('screenshot');
|
||||
$('.watermark').addClass('screenshot');
|
||||
$('.title').addClass('screenshot');
|
||||
html2canvas(document.querySelector(".chart")).then(canvas => {
|
||||
const base64 = canvas.toDataURL();
|
||||
fetch(`https://kq_dyno/SaveDynoImage`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({img: base64, dynoKey}),
|
||||
});
|
||||
|
||||
$('.chart').removeClass('screenshot');
|
||||
$('.watermark').removeClass('screenshot');
|
||||
$('.title').removeClass('screenshot');
|
||||
});
|
||||
}
|
||||
|
||||
function setChart() {
|
||||
const chart = Chart.getChart("chart");
|
||||
|
||||
// If the chart exists, destroy it
|
||||
if (chart) {
|
||||
chart.destroy();
|
||||
}
|
||||
|
||||
const xValues = times.map(({ rpm, hp, torque }) => rpm);
|
||||
const hpValues = times.map(({ rpm, hp, torque }) => parseInt(hp));
|
||||
const torqueValues = times.map(({ rpm, hp, torque }) => parseInt(torque));
|
||||
|
||||
const ctx = document.getElementById('chart').getContext('2d');
|
||||
|
||||
Chart.defaults.font.size = 33;
|
||||
new Chart(ctx, {
|
||||
type: 'line',
|
||||
data: {
|
||||
labels: xValues,
|
||||
datasets: [
|
||||
{
|
||||
data: hpValues,
|
||||
label: 'Horsepower',
|
||||
borderColor: 'red',
|
||||
fill: false
|
||||
},
|
||||
{
|
||||
data: torqueValues,
|
||||
label: 'Torque',
|
||||
borderColor: 'blue',
|
||||
fill: false
|
||||
},
|
||||
],
|
||||
},
|
||||
options: {
|
||||
animation: false,
|
||||
elements: {
|
||||
point: {
|
||||
radius: 1
|
||||
},
|
||||
},
|
||||
scales: {
|
||||
y: {
|
||||
display: true,
|
||||
min: 0,
|
||||
max: Math.ceil(Math.max(Math.max(...torqueValues), Math.max(...hpValues)) * 1.1),
|
||||
gridLines: {
|
||||
color: 'rgba(255,255,255,0.3)'
|
||||
},
|
||||
},
|
||||
x: {
|
||||
type: 'category',
|
||||
title: 'RPM',
|
||||
display: true,
|
||||
clip: true,
|
||||
ticks: {
|
||||
stepSize: 500, // Set the step size to 500
|
||||
}
|
||||
}
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
display: false,
|
||||
},
|
||||
annotation: {
|
||||
annotations: [
|
||||
{
|
||||
type: 'line',
|
||||
mode: 'horizontal',
|
||||
scaleID: 'y',
|
||||
value: Math.max(...hpValues), // Set the value to where you want the line
|
||||
borderColor: 'red', // Color of the line
|
||||
borderWidth: 2, // Width of the line
|
||||
borderDash: [20],
|
||||
label: {
|
||||
display: true,
|
||||
content: peakHp + ' ' + Math.max(...hpValues), // Set the label content
|
||||
enabled: true, // Show the label
|
||||
position: '45%', // Position of the label ('start', 'center', or 'end')
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'line',
|
||||
mode: 'horizontal',
|
||||
scaleID: 'y',
|
||||
value: Math.max(...torqueValues), // Set the value to where you want the line
|
||||
borderColor: 'blue', // Color of the line
|
||||
borderWidth: 2, // Width of the line
|
||||
borderDash: [20],
|
||||
label: {
|
||||
display: true,
|
||||
content: peakTorque + ' ' + Math.max(...torqueValues) + ' ' + torqueUnit, // Set the label content
|
||||
enabled: true, // Show the label
|
||||
position: '15%', // Position of the label ('start', 'center', or 'end')
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html {
|
||||
background-color: rgb(240, 240, 240);
|
||||
}
|
||||
|
||||
.chart {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.chart.screenshot {
|
||||
padding-top: 600px;
|
||||
height: 1280px;
|
||||
width: 1280px;
|
||||
}
|
||||
|
||||
.watermark.screenshot {
|
||||
bottom: -550px !important;
|
||||
}
|
||||
|
||||
.watermark {
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
font-size: 22px;
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-family: Tahoma, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
color: rgba(148, 19, 19, 1);
|
||||
font-size: 30px;
|
||||
position: absolute;
|
||||
bottom: 45px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-family: Tahoma, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.title.screenshot {
|
||||
bottom: 130px !important;
|
||||
font-size: 64px !important;
|
||||
}
|
||||
</style>
|
||||
20
resources/[framework]/[addons]/[kq]/kq_dyno/html/js/chart.js
Normal file
20
resources/[framework]/[addons]/[kq]/kq_dyno/html/js/chart.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
resources/[framework]/[addons]/[kq]/kq_dyno/html/js/jquery.js
vendored
Normal file
2
resources/[framework]/[addons]/[kq]/kq_dyno/html/js/jquery.js
vendored
Normal file
File diff suppressed because one or more lines are too long
22
resources/[framework]/[addons]/[kq]/kq_dyno/locale.lua
Normal file
22
resources/[framework]/[addons]/[kq]/kq_dyno/locale.lua
Normal file
@@ -0,0 +1,22 @@
|
||||
Locale = {
|
||||
['lb-ft'] = 'lb-ft',
|
||||
['nm'] = 'nm',
|
||||
['Press ~{INPUT}~ to start the dyno test'] = 'Apasa ~{INPUT}~ pentru a incepe testul dyno',
|
||||
['~r~This vehicle is FWD biased. Turn it around'] = '~r~Acest vehicul este cu tractiune fata. Intoarce-l',
|
||||
['~r~This vehicle is RWD biased. Turn it around'] = '~r~Acest vehicul este cu tractiune spate. Intoarce-l',
|
||||
['~r~The vehicle isn\'t aligned correctly'] = '~r~Vehiculul nu este aliniat corect',
|
||||
['~r~You are not allowed to perform dyno tests'] = '~r~Nu ai permisiunea sa efectuezi teste dyno',
|
||||
|
||||
['Peak HP'] = 'HP Maxim',
|
||||
['Peak torque'] = 'Cuplu Maxim',
|
||||
|
||||
-- Webhooks
|
||||
['Vehicle'] = 'Vehicul',
|
||||
['License plate'] = 'Numar de inmatriculare',
|
||||
['Date'] = 'Data',
|
||||
['User'] = 'Utilizator',
|
||||
['Dyno performance report'] = 'Raport de performanta dyno',
|
||||
|
||||
-- Display
|
||||
['KuzQuality - DynoTech'] = 'Red Valley - DynoTech',
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
|
||||
function GetDiscordDescription(model, license, player)
|
||||
local description = '- **' .. L('Vehicle') .. '**: ' .. model ..
|
||||
'\n- **' .. L('License plate') .. '**: ' .. license ..
|
||||
'\n- **' .. L('Date') .. '**: '.. os.date("%A, %m %B %Y - %H:%M")
|
||||
|
||||
if Config.webhook.includeUserName then
|
||||
description = description .. '\n\n'.. L('User') .. ': ' .. GetPlayerName(player)
|
||||
end
|
||||
if Config.webhook.includeSteamId then
|
||||
if not Config.webhook.includeUserName then
|
||||
description = description .. '\n'
|
||||
end
|
||||
description = description .. '\n*' .. GetIdentifier(player) .. '*'
|
||||
end
|
||||
|
||||
return description
|
||||
end
|
||||
|
||||
function GetIdentifier(player)
|
||||
for k, v in ipairs(GetPlayerIdentifiers(player)) do
|
||||
if string.match(v, 'license:') then
|
||||
return v:gsub('license:', '')
|
||||
end
|
||||
end
|
||||
return ''
|
||||
end
|
||||
|
||||
RegisterCommand('kq_dyno_restart', function(source)
|
||||
TriggerClientEvent('kq_dyno:client:prepareRestart', -1, source)
|
||||
end, true)
|
||||
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/server/server.lua
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/server/server.lua
Normal file
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/stream/kq_dyno.ydr
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_dyno/stream/kq_dyno.ydr
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
resources/[framework]/[addons]/[kq]/kq_wheeldamage/.fxap
Normal file
BIN
resources/[framework]/[addons]/[kq]/kq_wheeldamage/.fxap
Normal file
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,56 @@
|
||||
-- Wheel indexes:
|
||||
-- 0 = Front left
|
||||
-- 1 = Front right
|
||||
-- 2 = Rear left
|
||||
-- 3 = Rear right
|
||||
|
||||
|
||||
-- Damages a specific wheel (wheels have max 1000.0 hp)
|
||||
RegisterNetEvent('kq_wheeldamage:damageWheel')
|
||||
AddEventHandler('kq_wheeldamage:damageWheel', function(veh, wheel, damage)
|
||||
ApplyWheelDamage(veh, wheel, damage, indexToBone[wheel])
|
||||
end)
|
||||
|
||||
-- Removes the wheel without dropping it
|
||||
RegisterNetEvent('kq_wheeldamage:removeWheel')
|
||||
AddEventHandler('kq_wheeldamage:removeWheel', function(veh, wheel)
|
||||
SetVehicleWheelHealth(veh, wheel, 0.0)
|
||||
TriggerServerEvent('kq_wheeldamage:setState', NetworkGetNetworkIdFromEntity(veh), true)
|
||||
TriggerServerEvent('kq_wheeldamage:setBroken', NetworkGetNetworkIdFromEntity(veh), wheel, true)
|
||||
end)
|
||||
|
||||
|
||||
-- Fully repairs/reattaches a wheel
|
||||
RegisterNetEvent('kq_wheeldamage:fixWheel')
|
||||
AddEventHandler('kq_wheeldamage:fixWheel', function(veh, wheel)
|
||||
SetVehicleTyreFixed(veh, wheel)
|
||||
SetVehicleWheelHealth(veh, wheel, 1000.0)
|
||||
TriggerServerEvent('kq_wheeldamage:setBroken', NetworkGetNetworkIdFromEntity(veh), wheel, false)
|
||||
end)
|
||||
|
||||
-- Fully repairs all wheels of a vehicle
|
||||
RegisterNetEvent('kq_wheeldamage:fixCar')
|
||||
AddEventHandler('kq_wheeldamage:fixCar', function(veh)
|
||||
for wheel, bone in pairs(indexToBone) do
|
||||
if wheel <= GetVehicleNumberOfWheels(veh) -1 then
|
||||
SetVehicleTyreFixed(veh, wheel)
|
||||
SetVehicleWheelHealth(veh, wheel, 1000.0)
|
||||
TriggerServerEvent('kq_wheeldamage:setBroken', NetworkGetNetworkIdFromEntity(veh), wheel, false)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
function IsBlacklisted(veh)
|
||||
if Contains(Config.blacklist.classes, GetVehicleClass(veh)) then
|
||||
return true
|
||||
end
|
||||
|
||||
for k, model in pairs(Config.blacklist.models) do
|
||||
if GetEntityModel(veh) == GetHashKey(model) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
184
resources/[framework]/[addons]/[kq]/kq_wheeldamage/config.lua
Normal file
184
resources/[framework]/[addons]/[kq]/kq_wheeldamage/config.lua
Normal file
@@ -0,0 +1,184 @@
|
||||
Config = {}
|
||||
|
||||
Config.debug = false
|
||||
|
||||
-- Precise wheel rendering (This can fix the issue with broken wheels flashing in and out) If it doesn't happen on your server
|
||||
-- I wouldn't recommend enabling this as it will slightly increase the script resource usage (resmon)
|
||||
Config.increaseWheelRenderTiming = false
|
||||
|
||||
|
||||
-- Alternative method of the wheel breaking. This will make the actual model of the wheel fall off (same rim, tire etc.)
|
||||
-- Although it does look better it isn't properly synced (not possible at this moment)
|
||||
-- That's why it's disabled by default. Enable it if you don't care about the loose wheel prop not being synced and want it
|
||||
-- to look better for the driver
|
||||
Config.alternativeWheelBreak = false
|
||||
|
||||
-- The amount of damage the wheels will take on collisions (10-30 seems reasonable to me, for more realistic experience I'd recommend values between 50-100)
|
||||
Config.collisionDamageAmount = 20
|
||||
|
||||
-- If you define a model specific multiplier it will be used instead of the class multiplier
|
||||
-- Vehicle classes https://docs.fivem.net/natives/?_0x29439776AAA00A62
|
||||
Config.collisionDamageMultiplier = {
|
||||
models = {
|
||||
kuruma2 = 0.5
|
||||
},
|
||||
classes = {
|
||||
[0] = 1.2, -- Compacts
|
||||
[1] = 1, -- Sedans
|
||||
[2] = 0.8, -- SUVs
|
||||
[3] = 1, -- Coupes
|
||||
[4] = 1, -- Muscle
|
||||
[5] = 1.25, -- Sports Classics
|
||||
[6] = 1.2, -- Sports
|
||||
[7] = 1.2, -- Super
|
||||
[8] = 1.1, -- Motorcycles
|
||||
[9] = 0.5, -- Off-road
|
||||
[10] = 0.5, -- Industrial
|
||||
[11] = 0.5, -- Utility
|
||||
[12] = 1, -- Vans
|
||||
[13] = 0.5, -- Cycles
|
||||
[14] = 0, -- Boats
|
||||
[15] = 0, -- Helicopters
|
||||
[16] = 0, -- Planes
|
||||
[17] = 0.9, -- Service
|
||||
[18] = 0.7, -- Emergency
|
||||
[19] = 0.5, -- Military
|
||||
[20] = 0.5, -- Commercial
|
||||
[21] = 0, -- Trains
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-- The amount of damage the wheels will take on falls (10-30 seems reasonable to me, for more realistic experience I'd recommend values between 50-100)
|
||||
Config.fallDamageAmount = 25
|
||||
|
||||
-- Multiplier for the fall damage for vehicles that are using off-road tires/wheels
|
||||
Config.offroadTireFallDamageMultiplier = 0.7
|
||||
|
||||
-- Threshold of the fall speed required to deal wheel damage (3.8 by default. If you don't want smaller jumps to deal damage set it higher)
|
||||
Config.fallThreshold = 3.8
|
||||
|
||||
-- Minimum fall airtime (in seconds) for the wheels to get damaged. This only counts for the duration the car was falling (going downwards)
|
||||
Config.minimumAirTime = 0.5
|
||||
|
||||
-- If you define a model specific multiplier it will be used instead of the class multiplier
|
||||
-- Vehicle classes https://docs.fivem.net/natives/?_0x29439776AAA00A62
|
||||
Config.fallDamageMultiplier = {
|
||||
models = {
|
||||
bf400 = 0.4,
|
||||
sanchez = 0.4,
|
||||
sanchez2 = 0.4,
|
||||
manchez = 0.4,
|
||||
},
|
||||
classes = {
|
||||
[0] = 1, -- Compacts
|
||||
[1] = 1, -- Sedans
|
||||
[2] = 0.3, -- SUVs
|
||||
[3] = 1, -- Coupes
|
||||
[4] = 0.7, -- Muscle
|
||||
[5] = 1.3, -- Sports Classics
|
||||
[6] = 1.2, -- Sports
|
||||
[7] = 1.5, -- Super
|
||||
[8] = 0.6, -- Motorcycles
|
||||
[9] = 0.3, -- Off-road
|
||||
[10] = 0.7, -- Industrial
|
||||
[11] = 0.7, -- Utility
|
||||
[12] = 1.3, -- Vans
|
||||
[13] = 0.6, -- Cycles
|
||||
[14] = 0, -- Boats
|
||||
[15] = 0, -- Helicopters
|
||||
[16] = 0, -- Planes
|
||||
[17] = 0.9, -- Service
|
||||
[18] = 0.5, -- Emergency
|
||||
[19] = 0.2, -- Military
|
||||
[20] = 0.7, -- Commercial
|
||||
[21] = 0, -- Trains
|
||||
}
|
||||
}
|
||||
|
||||
-- Chance of the wheel falling off when it reaches critical damage (0 - 100)
|
||||
Config.fallOffChance = 35
|
||||
|
||||
-- Chance of the tire bursting when it reaches critical damage (0 - 100)
|
||||
Config.tireBurstChance = 100
|
||||
|
||||
-- Whether or not to respect bulletproof tires for popping (wheels will still fall off)
|
||||
Config.respectBulletproofTires = true
|
||||
|
||||
|
||||
-- Makes the car undriveable when at least one wheel falls off
|
||||
Config.setVehicleUndriveable = true
|
||||
|
||||
-- Some vehicles become really fast when a wheel falls off (blame Rockstar)
|
||||
-- To prevent abuse you can limit the vehicle speed when the wheels fall off
|
||||
Config.limitVehicleSpeed = true
|
||||
-- Speed limit in kmh
|
||||
Config.speedLimit = 40.0
|
||||
|
||||
-- There's a few decent wheel models to choose from https://gtahash.ru/?s=wheel
|
||||
-- the 'prop_wheel_01' might fit more popular rims but the 'prop_tornado_wheel' has bouncy physics
|
||||
Config.wheelModel = 'prop_wheel_01'
|
||||
Config.wheelRim = 'prop_wheel_rim_03'
|
||||
|
||||
-- Vehicle classes https://docs.fivem.net/natives/?_0x29439776AAA00A62
|
||||
Config.blacklist = {
|
||||
models = {
|
||||
'blazer',
|
||||
'blazer2',
|
||||
'blazer3',
|
||||
'blazer4',
|
||||
'blazer5',
|
||||
'monster',
|
||||
'monster3',
|
||||
'monster4',
|
||||
'monster5',
|
||||
},
|
||||
classes = {
|
||||
14, 15, 16, 21
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-- Fall damage based on the ground type the vehicle lands on
|
||||
|
||||
-- Surfaces which are counted as road (https://docs.fivem.net/natives/?_0xA7F04022)
|
||||
Config.roadSurfaces = {
|
||||
1, 3, 4, 12
|
||||
}
|
||||
|
||||
-- If you define a model specific multiplier it will be used instead of the class multiplier
|
||||
-- Multiplier that will be used for falls that land on dirt / non road(road like) material
|
||||
Config.offroadFallDamageMultiplier = {
|
||||
models = {
|
||||
bf400 = 0.3,
|
||||
sanchez = 0.3,
|
||||
sanchez2 = 0.3,
|
||||
manchez = 0.3,
|
||||
buggy = 0.7,
|
||||
},
|
||||
classes = {
|
||||
[0] = 1.0, -- Compacts
|
||||
[1] = 1.0, -- Sedans
|
||||
[2] = 0.9, -- SUVs
|
||||
[3] = 1, -- Coupes
|
||||
[4] = 0.9, -- Muscle
|
||||
[5] = 1.3, -- Sports Classics
|
||||
[6] = 1.3, -- Sports
|
||||
[7] = 1.3, -- Super
|
||||
[8] = 1.0, -- Motorcycles
|
||||
[9] = 0.7, -- Off-road
|
||||
[10] = 0.9, -- Industrial
|
||||
[11] = 1, -- Utility
|
||||
[12] = 1.2, -- Vans
|
||||
[13] = 0.6, -- Cycles
|
||||
[14] = 0, -- Boats
|
||||
[15] = 0, -- Helicopters
|
||||
[16] = 0, -- Planes
|
||||
[17] = 0.9, -- Service
|
||||
[18] = 0.5, -- Emergency
|
||||
[19] = 0.2, -- Military
|
||||
[20] = 0.7, -- Commercial
|
||||
[21] = 0, -- Trains
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
fx_version 'cerulean'
|
||||
games { 'gta5' }
|
||||
lua54 'yes'
|
||||
|
||||
author 'KuzQuality | Kuzkay'
|
||||
description 'Realistic wheel damage by KuzQuality'
|
||||
version '1.4.2'
|
||||
|
||||
|
||||
--
|
||||
-- Server
|
||||
--
|
||||
|
||||
server_scripts {
|
||||
'config.lua',
|
||||
'server/server.lua',
|
||||
}
|
||||
|
||||
--
|
||||
-- Client
|
||||
--
|
||||
|
||||
client_scripts {
|
||||
'config.lua',
|
||||
'client/client.lua',
|
||||
'client/editable/editable.lua',
|
||||
}
|
||||
|
||||
escrow_ignore {
|
||||
'config.lua',
|
||||
'client/editable/*.lua',
|
||||
}
|
||||
|
||||
dependency '/assetpacks'
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user