├── README.md ├── client └── main.lua ├── fxmanifest.lua ├── server └── server.lua └── shared └── config.lua /README.md: -------------------------------------------------------------------------------- 1 | Fellow Community: https://discord.gg/8DCMzdpe96 Tebex: https://fellowcommunity.tebex.io/ -------------------------------------------------------------------------------- /client/main.lua: -------------------------------------------------------------------------------- 1 | local isHandcuffed, handcuffTimer = false, {} 2 | dragStatus = {} 3 | dragStatus.isDragged = false 4 | 5 | AddEventHandler('handcuff', function(data) 6 | local valid = false 7 | local count = exports.ox_inventory:Search('count', Config.Items) 8 | if count then 9 | for name, count in pairs(count) do 10 | if count ~= 0 then 11 | valid = true 12 | end 13 | end 14 | end 15 | if valid then 16 | TriggerServerEvent('fw_interact:handcuff', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))) 17 | else 18 | lib.notify({ 19 | description = Config.RequiredItem, 20 | style = { 21 | backgroundColor = '#000000', 22 | color = '#ffffff' 23 | }, 24 | icon = 'people-robbery', 25 | type = 'error' 26 | }) 27 | end 28 | end) 29 | 30 | 31 | RegisterNetEvent('fw_interact:handcuff') 32 | AddEventHandler('fw_interact:handcuff', function() 33 | isHandcuffed = not isHandcuffed 34 | if isHandcuffed then 35 | RequestAnimDict('mp_arresting') 36 | while not HasAnimDictLoaded('mp_arresting') do 37 | Wait(100) 38 | end 39 | TaskPlayAnim(cache.ped, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0) 40 | RemoveAnimDict('mp_arresting') 41 | SetEnableHandcuffs(cache.ped, true) 42 | DisablePlayerFiring(cache.ped, true) 43 | SetCurrentPedWeapon(cache.ped, `WEAPON_UNARMED`, true) 44 | SetPedCanPlayGestureAnims(cache.ped, false) 45 | DisplayRadar(false) 46 | if Config.EnableHandcuffTimer then 47 | if handcuffTimer.active then 48 | ESX.ClearTimeout(handcuffTimer.task) 49 | end 50 | StartHandcuffTimer() 51 | end 52 | else 53 | dragStatus.isDragged = false 54 | if Config.EnableHandcuffTimer and handcuffTimer.active then 55 | ESX.ClearTimeout(handcuffTimer.task) 56 | end 57 | ClearPedSecondaryTask(cache.ped) 58 | SetEnableHandcuffs(cache.ped, false) 59 | DisablePlayerFiring(cache.ped, false) 60 | SetPedCanPlayGestureAnims(cache.ped, true) 61 | DisplayRadar(true) 62 | end 63 | end) 64 | 65 | RegisterNetEvent('fw_interact:unrestrain') 66 | AddEventHandler('fw_interact:unrestrain', function() 67 | if isHandcuffed then 68 | isHandcuffed = false 69 | ClearPedSecondaryTask(cache.ped) 70 | SetEnableHandcuffs(cache.ped, false) 71 | DisablePlayerFiring(cache.ped, false) 72 | SetPedCanPlayGestureAnims(cache.ped, true) 73 | FreezeEntityPosition(cache.ped, false) 74 | DisplayRadar(true) 75 | if Config.EnableHandcuffTimer and handcuffTimer.active then 76 | ESX.ClearTimeout(handcuffTimer.task) 77 | end 78 | end 79 | end) 80 | 81 | CreateThread(function() 82 | while true do 83 | Wait(0) 84 | if isHandcuffed then 85 | DisableControlAction(0, 1, true) 86 | DisableControlAction(0, 2, true) 87 | DisableControlAction(0, 24, true) 88 | DisableControlAction(0, 257, true) 89 | DisableControlAction(0, 25, true) 90 | DisableControlAction(0, 263, true) 91 | DisableControlAction(0, 45, true) 92 | DisableControlAction(0, 22, true) 93 | DisableControlAction(0, 44, true) 94 | DisableControlAction(0, 37, true) 95 | DisableControlAction(0, 23, true) 96 | DisableControlAction(0, 288, true) 97 | DisableControlAction(0, 289, true) 98 | DisableControlAction(0, 170, true) 99 | DisableControlAction(0, 167, true) 100 | DisableControlAction(0, 0, true) 101 | DisableControlAction(0, 26, true) 102 | DisableControlAction(0, 73, true) 103 | DisableControlAction(2, 199, true) 104 | DisableControlAction(0, 59, true) 105 | DisableControlAction(0, 71, true) 106 | DisableControlAction(0, 72, true) 107 | DisableControlAction(2, 36, true) 108 | DisableControlAction(0, 47, true) 109 | DisableControlAction(0, 264, true) 110 | DisableControlAction(0, 257, true) 111 | DisableControlAction(0, 140, true) 112 | DisableControlAction(0, 141, true) 113 | DisableControlAction(0, 142, true) 114 | DisableControlAction(0, 143, true) 115 | DisableControlAction(0, 75, true) 116 | DisableControlAction(27, 75, true) 117 | if IsEntityPlayingAnim(cache.ped, 'mp_arresting', 'idle', 3) ~= 1 then 118 | ESX.Streaming.RequestAnimDict('mp_arresting', function() 119 | TaskPlayAnim(cache.ped, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0.0, false, false, false) 120 | RemoveAnimDict('mp_arresting') 121 | end) 122 | end 123 | else 124 | Wait(500) 125 | end 126 | end 127 | end) 128 | 129 | AddEventHandler('escort', function(data) 130 | TriggerServerEvent('fw_interact:escort', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))) 131 | end) 132 | 133 | RegisterNetEvent('fw_interact:escort')-- escort 134 | AddEventHandler('fw_interact:escort', function(dragger) 135 | if isHandcuffed or IsPedDeadOrDying(cache.ped, true) then 136 | dragStatus.isDragged = not dragStatus.isDragged 137 | dragStatus.dragger = dragger 138 | end 139 | end) 140 | 141 | CreateThread(function() 142 | local wasDragged 143 | while true do 144 | if isHandcuffed then 145 | TaskPlayAnim(cache.ped, 'mp_arresting', 'idle', 8.0, -8, -1, 49, 0, 0, 0, 0) 146 | end 147 | if dragStatus.isDragged then 148 | Sleep = 50 149 | 150 | local targetPed = GetPlayerPed(GetPlayerFromServerId(dragStatus.dragger)) 151 | if DoesEntityExist(targetPed) and IsPedOnFoot(targetPed) and (isHandcuffed or IsPedDeadOrDying(cache.ped, true)) then 152 | if not wasDragged then 153 | if Config.npwd then 154 | exports.npwd:setPhoneDisabled(true) 155 | end 156 | AttachEntityToEntity(ESX.PlayerData.ped, targetPed, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true) 157 | SetEntityCollision(ESX.PlayerData.ped, 1, 1) 158 | wasDragged = true 159 | else 160 | Wait(1000) 161 | end 162 | else 163 | wasDragged = false 164 | dragStatus.isDragged = false 165 | DetachEntity(ESX.PlayerData.ped, true, false) 166 | if Config.npwd then 167 | exports.npwd:setPhoneDisabled(false) 168 | end 169 | end 170 | elseif wasDragged then 171 | wasDragged = false 172 | DetachEntity(ESX.PlayerData.ped, true, false) 173 | if Config.npwd then 174 | exports.npwd:setPhoneDisabled(false) 175 | end 176 | 177 | end 178 | Wait(1500) 179 | end 180 | end) 181 | 182 | function StartHandcuffTimer() 183 | if Config.EnableHandcuffTimer and handcuffTimer.active then 184 | ESX.ClearTimeout(handcuffTimer.task) 185 | end 186 | 187 | handcuffTimer.active = true 188 | 189 | handcuffTimer.task = ESX.SetTimeout(Config.HandcuffTimer, function() 190 | lib.notify({ 191 | description = Config.Unrestrained_timer, 192 | style = { 193 | backgroundColor = '#000000', 194 | color = '#ffffff' 195 | }, 196 | icon = 'handcuffs', 197 | type = 'inform' 198 | }) 199 | TriggerEvent('fw_interact:unrestrain') 200 | handcuffTimer.active = false 201 | end) 202 | end 203 | 204 | -- Open inventory 205 | AddEventHandler('search', function(data) 206 | if IsEntityPlayingAnim(data.entity, "missminuteman_1ig_2", "handsup_base", 3) or IsEntityPlayingAnim(data.entity, "mp_arresting", "idle", 3) or IsPedDeadOrDying(data.entity) then 207 | exports.ox_inventory:openInventory('player', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))) 208 | else 209 | lib.notify({ 210 | description = Config.ShowNotificationText, 211 | style = { 212 | backgroundColor = '#000000', 213 | color = '#ffffff' 214 | }, 215 | icon = 'people-robbery', 216 | type = 'error' 217 | }) 218 | end 219 | end) 220 | 221 | -- Put in vehicle 222 | AddEventHandler('putveh', function(data) 223 | TriggerServerEvent('fw_interact:putInVehicle', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity))) 224 | end) 225 | 226 | RegisterNetEvent('fw_interact:putInVehicle') 227 | AddEventHandler('fw_interact:putInVehicle', function() 228 | if isHandcuffed then 229 | local vehicle, distance = ESX.Game.GetClosestVehicle() 230 | if vehicle and distance < 5 then 231 | local maxSeats, freeSeat = GetVehicleMaxNumberOfPassengers(vehicle) 232 | for i=maxSeats - 1, 0, -1 do 233 | if IsVehicleSeatFree(vehicle, i) then 234 | freeSeat = i 235 | break 236 | end 237 | end 238 | if freeSeat then 239 | TaskWarpPedIntoVehicle(cache.ped, vehicle, freeSeat) 240 | dragStatus.isDragged = false 241 | end 242 | end 243 | end 244 | end) 245 | 246 | AddEventHandler('outveh', function(data) 247 | local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer() 248 | if closestPlayer ~= -1 and closestDistance <= 3.0 then 249 | TriggerServerEvent('fw_interact:OutVehicle', GetPlayerServerId(closestPlayer)) 250 | end 251 | end) 252 | 253 | RegisterNetEvent('fw_interact:OutVehicle') 254 | AddEventHandler('fw_interact:OutVehicle', function() 255 | if IsPedSittingInAnyVehicle(cache.ped) then 256 | local vehicle = GetVehiclePedIsIn(cache.ped, false) 257 | TaskLeaveVehicle(cache.ped, vehicle, 64) 258 | end 259 | end) 260 | 261 | AddEventHandler('id', function(data) 262 | TriggerServerEvent('jsfour-idcard:open', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity)), GetPlayerServerId(PlayerId())) 263 | end) 264 | 265 | AddEventHandler('id-driver', function(data) 266 | TriggerServerEvent('jsfour-idcard:open', GetPlayerServerId(NetworkGetPlayerIndexFromPed(data.entity)), GetPlayerServerId(PlayerId()), 'driver') 267 | end) 268 | 269 | RegisterNetEvent('billing', function(data) 270 | local player = ESX.Game.GetClosestPlayer() 271 | if ESX.PlayerData.job and ESX.PlayerData.job.name == 'unemployed' then 272 | lib.notify({ 273 | description = Config.Unemployed, 274 | style = { 275 | backgroundColor = '#000000', 276 | color = '#ffffff' 277 | }, 278 | icon = 'fa-x', 279 | type = 'error' 280 | }) 281 | else 282 | local input = lib.inputDialog(Config.billing_title, {Config.input}) 283 | if input then 284 | local lockerNumber = tonumber(input[1]) 285 | TriggerServerEvent('esx_billing:sendBill', GetPlayerServerId(player), 'society_'..ESX.PlayerData.job.name, (ESX.PlayerData.job.label), lockerNumber) 286 | end 287 | end 288 | end) 289 | 290 | exports.ox_target:addGlobalPlayer({ 291 | { 292 | event = "search", 293 | icon = Config.search_img, 294 | label = Config.search, 295 | num = 1 296 | }, 297 | { 298 | event = "handcuff", 299 | icon = Config.handcuff_img, 300 | label = Config.handcuff, 301 | num = 2 302 | }, 303 | { 304 | event = "escort", 305 | icon = Config.escort_img, 306 | label = Config.escort, 307 | num = 3 308 | }, 309 | { 310 | event = "putveh", 311 | icon = Config.putveh_img, 312 | label = Config.putveh, 313 | num = 4 314 | }, 315 | { 316 | event = "id", 317 | icon = Config.ID_img, 318 | label = Config.ID, 319 | num = 5 320 | }, 321 | { 322 | event = "id-driver", 323 | icon = Config.ID_driver_img, 324 | label = Config.ID_driver, 325 | num = 6 326 | }, 327 | { 328 | event = "billing", 329 | icon = Config.billing_img, 330 | label = Config.billing, 331 | num = 7 332 | }, 333 | }) 334 | 335 | exports.ox_target:addGlobalVehicle({ 336 | { 337 | event = "outveh", 338 | icon = Config.outveh_img, 339 | label = Config.outveh, 340 | num = 1 341 | }, 342 | }) 343 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'adamant' 2 | 3 | game 'gta5' 4 | lua54 'yes' 5 | 6 | description 'FW Interact' 7 | 8 | version '1.0.0' 9 | 10 | shared_scripts { 11 | '@ox_lib/init.lua', 12 | '@es_extended/imports.lua', 13 | 'shared/*.lua' 14 | } 15 | 16 | server_scripts { 17 | 'server/*.lua' 18 | } 19 | 20 | client_scripts { 21 | 'client/*.lua' 22 | } 23 | -------------------------------------------------------------------------------- /server/server.lua: -------------------------------------------------------------------------------- 1 | RegisterNetEvent('fw_interact:handcuff') 2 | AddEventHandler('fw_interact:handcuff', function(target) 3 | TriggerClientEvent('fw_interact:handcuff', target) 4 | end) 5 | 6 | RegisterNetEvent('fw_interact:escort') 7 | AddEventHandler('fw_interact:escort', function(target) 8 | TriggerClientEvent('fw_interact:escort', target, source) 9 | end) 10 | 11 | RegisterNetEvent('fw_interact:putInVehicle') 12 | AddEventHandler('fw_interact:putInVehicle', function(target) 13 | local xPlayer = ESX.GetPlayerFromId(source) 14 | TriggerClientEvent('fw_interact:putInVehicle', target) 15 | end) 16 | 17 | RegisterNetEvent('fw_interact:OutVehicle') 18 | AddEventHandler('fw_interact:OutVehicle', function(target) 19 | local xPlayer = ESX.GetPlayerFromId(source) 20 | TriggerClientEvent('fw_interact:OutVehicle', target) 21 | end) 22 | -------------------------------------------------------------------------------- /shared/config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | 3 | Config.Items = {'handcuffs', 'rope'} 4 | 5 | Config.EnableHandcuffTimer = true -- Enable handcuff timer? will unrestrain player after the time ends. 6 | Config.HandcuffTimer = 10 * 60000 -- 10 minutes. 7 | Config.ShowNotificationText = "La personne doit être menottée où lever les bras" 8 | Config.RequiredItem = "Vous avez besoin de menotte ou d'une corde" 9 | Config.Unrestrained_timer = "Vous sentez que vos menottes deviennent fragiles" 10 | Config.search = "Fouiller" 11 | Config.search_img = "fa-solid fa-person" 12 | Config.handcuff = "Menotter" 13 | Config.handcuff_img = "fa-solid fa-handcuffs" 14 | Config.escort = "Escoter" 15 | Config.escort_img = "fa-solid fa-people-pulling" 16 | Config.putveh = "Mettre dans véhicule" 17 | Config.putveh_img = "fa-solid fa-people-pulling" 18 | Config.ID = "Regarder carte identité" 19 | Config.ID_img = "fa-solid fa-id-card" 20 | Config.ID_driver = "Regarder permis de conduite" 21 | Config.ID_driver_img = "fa-solid fa-id-card-clip" 22 | Config.outveh = "Sortir du véhicule" 23 | Config.outveh_img = "fa-solid fa-people-pulling" 24 | Config.billing_title = "Facture" 25 | Config.input = "Entrer une valeur" 26 | Config.billing = "Faire une facture" 27 | Config.billing_img = "fa-solid fa-euro-sign" 28 | Config.Unemployed = "Vous êtes pas dans une entreprise" 29 | --------------------------------------------------------------------------------