├── .gitignore ├── LICENSE ├── README.md ├── client └── main.lua ├── fxmanifest.lua └── server └── main.lua /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Lua sources 2 | luac.out 3 | 4 | # luarocks build files 5 | *.src.rock 6 | *.zip 7 | *.tar.gz 8 | 9 | # Object files 10 | *.o 11 | *.os 12 | *.ko 13 | *.obj 14 | *.elf 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | *.def 26 | *.exp 27 | 28 | # Shared objects (inc. Windows DLLs) 29 | *.dll 30 | *.so 31 | *.so.* 32 | *.dylib 33 | 34 | # Executables 35 | *.exe 36 | *.out 37 | *.app 38 | *.i*86 39 | *.x86_64 40 | *.hex 41 | 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ademo93 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qb-hostage 2 | A simple fivem script to make work hostage option from qb-radialmenu 3 | -------------------------------------------------------------------------------- /client/main.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | 3 | local hostageAllowedWeapons = { 4 | "weapon_pistol", 5 | "weapon_combatpistol", 6 | "weapon_pistol50", 7 | "weapon_snspistol", 8 | "weapon_vintagepistol", 9 | "vweapon_heavypistol", 10 | "weapon_revolver", 11 | "weapon_ceramicpistol", 12 | "weapon_navyrevolver", 13 | "weapon_marksmanpistol", 14 | "weapon_snspistol_mk2", 15 | "weapon_pistol_mk2", 16 | "weapon_machinepistol" 17 | } 18 | local holdingHostageInProgress = false 19 | local takeHostageAnimNamePlaying = "" 20 | local takeHostageAnimDictPlaying = "" 21 | local takeHostageControlFlagPlaying = 0 22 | local NoWeapon = false 23 | 24 | RegisterNetEvent('A5:Client:TakeHostage') 25 | AddEventHandler('A5:Client:TakeHostage', function() 26 | takeHostage() 27 | end) 28 | function takeHostage() 29 | local src = source 30 | local closestPlayer = GetClosestPlayer(2) 31 | target = GetPlayerServerId(closestPlayer) 32 | print(target) 33 | if closestPlayer ~= nil and closestPlayer ~= -1 then 34 | ClearPedSecondaryTask(GetPlayerPed(-1)) 35 | DetachEntity(GetPlayerPed(-1), true, false) 36 | for i=1, #hostageAllowedWeapons do 37 | if HasPedGotWeapon(GetPlayerPed(-1), GetHashKey(hostageAllowedWeapons[i]), false) then 38 | if GetAmmoInPedWeapon(GetPlayerPed(-1), GetHashKey(hostageAllowedWeapons[i])) > 0 then 39 | foundWeapon = GetHashKey(hostageAllowedWeapons[i]) 40 | NoWeapon = false 41 | break 42 | else 43 | TriggerClientEvent('QBCore:Notify', src, 'Vous n\'avez pas de munitions !', 'error') 44 | return 45 | end 46 | else 47 | NoWeapon = true 48 | end 49 | end 50 | 51 | if NoWeapon then 52 | TriggerClientEvent('QBCore:Notify', src, 'Vous ne pouvez pas utiliser cette arme pour prendre des otages !', 'error') 53 | return 54 | end 55 | 56 | if not holdingHostageInProgress then 57 | local player = PlayerPedId() 58 | lib = 'anim@gangops@hostage@' 59 | anim1 = 'perp_idle' 60 | lib2 = 'anim@gangops@hostage@' 61 | anim2 = 'victim_idle' 62 | distans = 0.11 --Higher = closer to camera 63 | distans2 = -0.24 --higher = left 64 | height = 0.0 65 | spin = 0.0 66 | length = 100000 67 | controlFlagMe = 49 68 | controlFlagTarget = 49 69 | animFlagTarget = 50 70 | attachFlag = true 71 | SetCurrentPedWeapon(GetPlayerPed(-1), foundWeapon, true) 72 | holdingHostageInProgress = true 73 | holdingHostage = true 74 | TriggerServerEvent('cmg3_animations:sync', closestPlayer, lib,lib2, anim1, anim2, distans, distans2, height,target,length,spin,controlFlagMe,controlFlagTarget,animFlagTarget,attachFlag, false) 75 | end 76 | else 77 | TriggerClientEvent('QBCore:Notify', src, 'Personne aux alentours !', 'error') 78 | end 79 | canTakeHostage = false 80 | end 81 | 82 | RegisterNetEvent('cmg3_animations:syncTarget') 83 | AddEventHandler('cmg3_animations:syncTarget', function(target, animationLib, animation2, distans, distans2, height, length,spin,controlFlag,animFlagTarget,attach, emote) 84 | local playerPed = GetPlayerPed(-1) 85 | local targetPed = GetPlayerPed(GetPlayerFromServerId(target)) 86 | if holdingHostageInProgress then 87 | holdingHostageInProgress = false 88 | else 89 | holdingHostageInProgress = true 90 | end 91 | beingHeldHostage = true 92 | RequestAnimDict(animationLib) 93 | 94 | while not HasAnimDictLoaded(animationLib) do 95 | Citizen.Wait(10) 96 | end 97 | if spin == nil then spin = 180.0 end 98 | if attach then 99 | AttachEntityToEntity(GetPlayerPed(-1), targetPed, 0, distans2, distans, height, 0.5, 0.5, spin, false, false, false, false, 2, false) 100 | else 101 | end 102 | 103 | if controlFlag == nil then controlFlag = 0 end 104 | 105 | if animation2 == "victim_fail" then 106 | SetEntityHealth(GetPlayerPed(-1),0) 107 | DetachEntity(GetPlayerPed(-1), true, false) 108 | TaskPlayAnim(playerPed, animationLib, animation2, 8.0, -8.0, length, controlFlag, 0, false, false, false) 109 | beingHeldHostage = false 110 | holdingHostageInProgress = false 111 | elseif animation2 == "shoved_back" then 112 | holdingHostageInProgress = false 113 | DetachEntity(GetPlayerPed(-1), true, false) 114 | TaskPlayAnim(playerPed, animationLib, animation2, 8.0, -8.0, length, controlFlag, 0, false, false, false) 115 | beingHeldHostage = false 116 | else 117 | TaskPlayAnim(playerPed, animationLib, animation2, 8.0, -8.0, length, controlFlag, 0, false, false, false) 118 | end 119 | takeHostageAnimNamePlaying = animation2 120 | takeHostageAnimDictPlaying = animationLib 121 | takeHostageControlFlagPlaying = controlFlag 122 | TriggerEvent('animations:ToggleCanDoAnims', emote) 123 | end) 124 | 125 | RegisterNetEvent('cmg3_animations:syncMe') 126 | AddEventHandler('cmg3_animations:syncMe', function(animationLib, animation,length,controlFlag,animFlag) 127 | local playerPed = GetPlayerPed(-1) 128 | ClearPedSecondaryTask(GetPlayerPed(-1)) 129 | RequestAnimDict(animationLib) 130 | while not HasAnimDictLoaded(animationLib) do 131 | Citizen.Wait(10) 132 | end 133 | if controlFlag == nil then controlFlag = 0 end 134 | TaskPlayAnim(playerPed, animationLib, animation, 8.0, -8.0, length, controlFlag, 0, false, false, false) 135 | takeHostageAnimNamePlaying = animation 136 | takeHostageAnimDictPlaying = animationLib 137 | takeHostageControlFlagPlaying = controlFlag 138 | if animation == "perp_fail" then 139 | SetPedShootsAtCoord(GetPlayerPed(-1), 0.0, 0.0, 0.0, 0) 140 | holdingHostageInProgress = false 141 | end 142 | if animation == "shove_var_a" then 143 | Wait(900) 144 | ClearPedSecondaryTask(GetPlayerPed(-1)) 145 | holdingHostageInProgress = false 146 | end 147 | end) 148 | 149 | RegisterNetEvent('cmg3_animations:cl_stop') 150 | AddEventHandler('cmg3_animations:cl_stop', function() 151 | holdingHostageInProgress = false 152 | beingHeldHostage = false 153 | holdingHostage = false 154 | ClearPedSecondaryTask(GetPlayerPed(-1)) 155 | DetachEntity(GetPlayerPed(-1), true, false) 156 | end) 157 | 158 | Citizen.CreateThread(function() 159 | while true do 160 | if holdingHostage or beingHeldHostage then 161 | while not IsEntityPlayingAnim(GetPlayerPed(-1), takeHostageAnimDictPlaying, takeHostageAnimNamePlaying, 3) do 162 | TaskPlayAnim(GetPlayerPed(-1), takeHostageAnimDictPlaying, takeHostageAnimNamePlaying, 8.0, -8.0, 100000, takeHostageControlFlagPlaying, 0, false, false, false) 163 | Citizen.Wait(0) 164 | end 165 | end 166 | Wait(0) 167 | end 168 | end) 169 | 170 | function GetPlayers() 171 | local players = {} 172 | 173 | for _, i in ipairs(GetActivePlayers()) do 174 | table.insert(players, i) 175 | end 176 | 177 | return players 178 | end 179 | 180 | function GetClosestPlayer(radius) 181 | local players = GetPlayers() 182 | local closestDistance = -1 183 | local closestPlayer = -1 184 | local ply = GetPlayerPed(-1) 185 | local plyCoords = GetEntityCoords(ply, 0) 186 | 187 | for index,value in ipairs(players) do 188 | local target = GetPlayerPed(value) 189 | if(target ~= ply) then 190 | local targetCoords = GetEntityCoords(GetPlayerPed(value), 0) 191 | local distance = GetDistanceBetweenCoords(targetCoords['x'], targetCoords['y'], targetCoords['z'], plyCoords['x'], plyCoords['y'], plyCoords['z'], true) 192 | if(closestDistance == -1 or closestDistance > distance) then 193 | closestPlayer = value 194 | closestDistance = distance 195 | end 196 | end 197 | end 198 | if closestDistance <= radius then 199 | return closestPlayer 200 | else 201 | return nil 202 | end 203 | end 204 | 205 | Citizen.CreateThread(function() 206 | while true do 207 | if holdingHostage then 208 | if IsEntityDead(GetPlayerPed(-1)) then 209 | holdingHostage = false 210 | holdingHostageInProgress = false 211 | local closestPlayer = GetClosestPlayer(2) 212 | target = GetPlayerServerId(closestPlayer) 213 | TriggerServerEvent("cmg3_animations:stop",target) 214 | Wait(100) 215 | releaseHostage() 216 | end 217 | DisableControlAction(0,24,true) -- disable attack 218 | DisableControlAction(0,25,true) -- disable aim 219 | DisableControlAction(0,47,true) -- disable weapon 220 | DisableControlAction(0,58,true) -- disable weapon 221 | DisablePlayerFiring(GetPlayerPed(-1),true) 222 | local playerCoords = GetEntityCoords(GetPlayerPed(-1)) 223 | DrawText3D(playerCoords.x,playerCoords.y,playerCoords.z,"[G] libérer, [H] Abattre") 224 | if IsDisabledControlJustPressed(0,47) then --release 225 | holdingHostage = false 226 | holdingHostageInProgress = false 227 | local closestPlayer = GetClosestPlayer(2) 228 | target = GetPlayerServerId(closestPlayer) 229 | TriggerServerEvent("cmg3_animations:stop",target) 230 | Wait(100) 231 | releaseHostage() 232 | elseif IsDisabledControlJustPressed(0,74) then --kill 233 | holdingHostage = false 234 | holdingHostageInProgress = false 235 | local closestPlayer = GetClosestPlayer(2) 236 | target = GetPlayerServerId(closestPlayer) 237 | TriggerServerEvent("cmg3_animations:stop",target) 238 | killHostage() 239 | end 240 | end 241 | if beingHeldHostage then 242 | DisableControlAction(0,21,true) -- disable sprint 243 | DisableControlAction(0,24,true) -- disable attack 244 | DisableControlAction(0,25,true) -- disable aim 245 | DisableControlAction(0,47,true) -- disable weapon 246 | DisableControlAction(0,58,true) -- disable weapon 247 | DisableControlAction(0,263,true) -- disable melee 248 | DisableControlAction(0,264,true) -- disable melee 249 | DisableControlAction(0,257,true) -- disable melee 250 | DisableControlAction(0,140,true) -- disable melee 251 | DisableControlAction(0,141,true) -- disable melee 252 | DisableControlAction(0,142,true) -- disable melee 253 | DisableControlAction(0,143,true) -- disable melee 254 | DisableControlAction(0,75,true) -- disable exit vehicle 255 | DisableControlAction(27,75,true) -- disable exit vehicle 256 | DisableControlAction(0,22,true) -- disable jump 257 | DisableControlAction(0,32,true) -- disable move up 258 | DisableControlAction(0,268,true) 259 | DisableControlAction(0,33,true) -- disable move down 260 | DisableControlAction(0,269,true) 261 | DisableControlAction(0,34,true) -- disable move left 262 | DisableControlAction(0,270,true) 263 | DisableControlAction(0,35,true) -- disable move right 264 | DisableControlAction(0,271,true) 265 | end 266 | Wait(0) 267 | end 268 | end) 269 | 270 | function DrawText3D(x, y, z, text) 271 | SetTextScale(0.35, 0.35) 272 | SetTextFont(4) 273 | SetTextProportional(1) 274 | SetTextColour(255, 255, 255, 215) 275 | SetTextEntry("STRING") 276 | SetTextCentre(true) 277 | AddTextComponentString(text) 278 | SetDrawOrigin(x,y,z, 0) 279 | DrawText(0.0, 0.0) 280 | local factor = (string.len(text)) / 370 281 | DrawRect(0.0, 0.0+0.0125, 0.017+ factor, 0.03, 0, 0, 0, 75) 282 | ClearDrawOrigin() 283 | end 284 | 285 | function releaseHostage() 286 | local player = PlayerPedId() 287 | lib = 'reaction@shove' 288 | anim1 = 'shove_var_a' 289 | lib2 = 'reaction@shove' 290 | anim2 = 'shoved_back' 291 | distans = 0.11 --Higher = closer to camera 292 | distans2 = -0.24 --higher = left 293 | height = 0.0 294 | spin = 0.0 295 | length = 100000 296 | controlFlagMe = 120 297 | controlFlagTarget = 0 298 | animFlagTarget = 1 299 | attachFlag = false 300 | local closestPlayer = GetClosestPlayer(2) 301 | target = GetPlayerServerId(closestPlayer) 302 | if closestPlayer ~= 0 then 303 | TriggerServerEvent('cmg3_animations:sync', closestPlayer, lib,lib2, anim1, anim2, distans, distans2, height,target,length,spin,controlFlagMe,controlFlagTarget,animFlagTarget,attachFlag, true) 304 | end 305 | end 306 | 307 | function killHostage() 308 | local player = PlayerPedId() 309 | lib = 'anim@gangops@hostage@' 310 | anim1 = 'perp_fail' 311 | lib2 = 'anim@gangops@hostage@' 312 | anim2 = 'victim_fail' 313 | distans = 0.11 314 | distans2 = -0.24 315 | height = 0.0 316 | spin = 0.0 317 | length = 0.2 318 | controlFlagMe = 168 319 | controlFlagTarget = 0 320 | animFlagTarget = 1 321 | attachFlag = false 322 | local closestPlayer = GetClosestPlayer(2) 323 | target = GetPlayerServerId(closestPlayer) 324 | if target ~= 0 then 325 | TriggerServerEvent('cmg3_animations:sync', closestPlayer, lib,lib2, anim1, anim2, distans, distans2, height,target,length,spin,controlFlagMe,controlFlagTarget,animFlagTarget,attachFlag, true) 326 | end 327 | end 328 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | client_script { 5 | 'client/main.lua' 6 | } 7 | server_script { 8 | 'server/main.lua' 9 | } 10 | 11 | lua54 'yes' 12 | -------------------------------------------------------------------------------- /server/main.lua: -------------------------------------------------------------------------------- 1 | RegisterServerEvent('cmg3_animations:sync') 2 | AddEventHandler('cmg3_animations:sync', function(target, animationLib,animationLib2, animation, animation2, distans, distans2, height,targetSrc,length,spin,controlFlagSrc,controlFlagTarget,animFlagTarget,attachFlag, emote) 3 | TriggerClientEvent('cmg3_animations:syncTarget', targetSrc, source, animationLib2, animation2, distans, distans2, height, length,spin,controlFlagTarget,animFlagTarget,attachFlag, emote) 4 | TriggerClientEvent('cmg3_animations:syncMe', source, animationLib, animation,length,controlFlagSrc,animFlagTarget) 5 | end) 6 | 7 | RegisterServerEvent('cmg3_animations:stop') 8 | AddEventHandler('cmg3_animations:stop', function(targetSrc) 9 | TriggerClientEvent('cmg3_animations:cl_stop', targetSrc) 10 | end) 11 | --------------------------------------------------------------------------------