FiveM Resource (opens in a new tab) that allows players to host various arcade lobbies, including team deathmatch, free for all deathmatch and gun game.
Dependencies
- ox_lib (opens in a new tab)
- ox_target (opens in a new tab) or qb-target (opens in a new tab)
- qb-core (opens in a new tab)
- ox_inventory (opens in a new tab) or qb-inventory (opens in a new tab)
Optional Dependencies
Installation
Configure your config
Configure qb-ambulancejob
Here you will need to edit it slightly to ensure the regular death functions don't run when the players in an arena.
If you are using qb-ambulancejob you will need to navigate qb-ambulancejob/client/dead.lua
If you are using another resource to handle player death, you can use it as an example to ensure the arcade works properly.
We're editing gameEventTriggered
and adding a check to see if the player is in an arena, and skipping the usualy QB death functions.
AddEventHandler('gameEventTriggered', function(event, data)
if event == "CEventNetworkEntityDamage" then
local victim, attacker, victimDied, weapon = data[1], data[2], data[4], data[7]
if not IsEntityAPed(victim) then return end
if victimDied and NetworkGetPlayerIndexFromPed(victim) == PlayerId() and IsEntityDead(PlayerPedId()) then
if not exports['ls-arcade']:isPlayerInArena() then -- HERE
if not InLaststand then
SetLaststand(true)
elseif InLaststand and not isDead then
SetLaststand(false)
local playerid = NetworkGetPlayerIndexFromPed(victim)
local playerName = GetPlayerName(playerid) .. " " .. "("..GetPlayerServerId(playerid)..")" or Lang:t('info.self_death')
local killerId = NetworkGetPlayerIndexFromPed(attacker)
local killerName = GetPlayerName(killerId) .. " " .. "("..GetPlayerServerId(killerId)..")" or Lang:t('info.self_death')
local weaponLabel = (QBCore.Shared.Weapons and QBCore.Shared.Weapons[weapon] and QBCore.Shared.Weapons[weapon].label) or 'Unknown'
local weaponName = (QBCore.Shared.Weapons and QBCore.Shared.Weapons[weapon] and QBCore.Shared.Weapons[weapon].name) or 'Unknown'
TriggerServerEvent("qb-log:server:CreateLog", "death", Lang:t('logs.death_log_title', {playername = playerName, playerid = GetPlayerServerId(playerid)}), "red", Lang:t('logs.death_log_message', {killername = killerName, playername = playerName, weaponlabel = weaponLabel, weaponname = weaponName}))
deathTime = Config.DeathTime
OnDeath()
DeathTimer()
end
else -- HERE
isDead = true
local killerId = NetworkGetPlayerIndexFromPed(attacker)
TriggerServerEvent('ls-arcade:server:playerKilled', GetPlayerServerId(killerId))
end -- HERE
end
end
end)
Still in the same file, find the function called DrawTxt
and edit as follows.
We're adding another check if the player is in an arena, and skipping the DrawTxt()
function.
local function DrawTxt(x, y, width, height, scale, text, r, g, b, a, _)
if exports['ls-arcade']:isPlayerInArena() then return end -- HERE
SetTextFont(4)
SetTextProportional(0)
SetTextScale(scale, scale)
SetTextColour(r, g, b, a)
SetTextDropShadow(0, 0, 0, 0,255)
SetTextEdge(2, 0, 0, 0, 255)
SetTextDropShadow()
SetTextOutline()
SetTextEntry("STRING")
AddTextComponentString(text)
DrawText(x - width/2, y - height/2 + 0.005)
end
Next we're gonna register a new net event and place it inside the qb-ambulancejob
, it doesn't matter where you put it, you can place it anywhere inside qb-ambulancejob/client/dead.lua
.
RegisterNetEvent('ls-arcade:client:revivePlayer', function(coords)
isDead = false
local ped = PlayerPedId()
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, GetEntityHeading(ped), true, false)
SetEntityInvincible(ped, true)
SetEntityAlpha(ped, 140)
TriggerEvent('ls-arcade:client:clearBleeding')
CreateThread(function()
Wait(1000)
while true do
local vel = GetEntityVelocity(ped)
if vel.x ~= 0 then
SetEntityInvincible(ped, false)
SetEntityAlpha(ped, 255)
return
end
DisablePlayerFiring(PlayerId(), true) -- Disable weapon firing
Wait(0)
end
end)
end)
Next we're gonna head over to qb-ambulancejob/client/main.lua
and register another net event at the bottom of the file.
This event is used so that any bleed damage a player has sustained will be reset up on respawning.
RegisterNetEvent('ls-arcade:client:clearBleeding', function()
isBleeding = 0
bleedTickTimer = 0
advanceBleedTimer = 0
fadeOutTimer = 0
blackoutTimer = 0
onDrugs = 0
wasOnDrugs = false
onPainKiller = 0
wasOnPainKillers = false
injured = {}
for k, v in pairs(BodyParts) do
v.isDamaged = false
v.severity = 0
end
TriggerServerEvent('hospital:server:SyncInjuries', {
limbs = BodyParts,
isBleeding = tonumber(isBleeding)
})
CurrentDamageList = {}
TriggerServerEvent('hospital:server:SetWeaponDamage', CurrentDamageList)
ProcessRunStuff(PlayerPedId())
TriggerServerEvent('hospital:server:SyncInjuries', {
limbs = BodyParts,
isBleeding = tonumber(isBleeding)
})
end)
Optional: Configure ox_inventory
If you are using ox_inventory
you need to add some logic so that you are able to be given weapons in the arena.
navigate to ox_inventory/client.lua
Inside the ox_inventory:setPlayerInventory
event, edit as follows.
Towards the bottom of the event, you'll find a function that looks like this:
client.interval = SetInterval(function()
end)
Replace that function with the one below. Don't worry, we're not editing any of overextended's logic, just adding our own.
client.interval = SetInterval(function()
if invOpen == false then
playerCoords = GetEntityCoords(playerPed)
if currentWeapon and IsPedUsingActionMode(playerPed) then
SetPedUsingActionMode(playerPed, false, -1, 'DEFAULT_ACTION')
end
elseif invOpen == true then
if not canOpenInventory() then
client.closeInventory()
else
playerCoords = GetEntityCoords(playerPed)
if currentInventory and not currentInventory.ignoreSecurityChecks then
if currentInventory.type == 'otherplayer' then
local id = GetPlayerFromServerId(currentInventory.id)
local ped = GetPlayerPed(id)
local pedCoords = GetEntityCoords(ped)
if not id or #(playerCoords - pedCoords) > 1.8 or not (client.hasGroup(shared.police) or canOpenTarget(ped)) then
client.closeInventory()
lib.notify({ id = 'inventory_lost_access', type = 'error', description = locale('inventory_lost_access') })
else
TaskTurnPedToFaceCoord(playerPed, pedCoords.x, pedCoords.y, pedCoords.z, 50)
end
elseif currentInventory.coords and (#(playerCoords - currentInventory.coords) > (currentInventory.distance or 2.0) or canOpenTarget(playerPed)) then
client.closeInventory()
lib.notify({ id = 'inventory_lost_access', type = 'error', description = locale('inventory_lost_access') })
end
end
end
end
if client.parachute and GetPedParachuteState(playerPed) ~= -1 then
Utils.DeleteEntity(client.parachute)
client.parachute = false
end
if EnableWeaponWheel then return end
local weaponHash = GetSelectedPedWeapon(playerPed)
if exports['ls-arcade']:isPlayerInArena() then goto skipWeaponCheck end --HERE
if currentWeapon then
if weaponHash ~= currentWeapon.hash and currentWeapon.timer then
local weaponCount = Items[currentWeapon.name]?.count
if weaponCount > 0 then
SetCurrentPedWeapon(playerPed, currentWeapon.hash, true)
SetAmmoInClip(playerPed, currentWeapon.hash, currentWeapon.metadata.ammo)
SetPedCurrentWeaponVisible(playerPed, true, false, false, false)
weaponHash = GetSelectedPedWeapon(playerPed)
end
if weaponHash ~= currentWeapon.hash then
currentWeapon = Weapon.Disarm(currentWeapon, true)
end
end
elseif client.weaponmismatch and not client.ignoreweapons[weaponHash] then
local weaponType = GetWeapontypeGroup(weaponHash)
if weaponType ~= 0 and weaponType ~= `GROUP_UNARMED` then
Weapon.Disarm(currentWeapon, true)
end
end
::skipWeaponCheck:: -- HERE
end, 200)
Optional: Configure qb-smallresources
If you are using qb-inventory
you can add some logic to skip any weapon draw animations while in the arcade.
Navigate to qb-smallresources/client/weapdraw.lua
and find the net event called weapons:client:DrawWeapon
and replace it with the code below.
Keep in mind, this is version 1.3.1, older or newer version may look different.
RegisterNetEvent('weapons:client:DrawWeapon', function()
if GetResourceState('qb-inventory') == 'missing' then return end -- This part is only made to work with qb-inventory, other inventories might conflict
local sleep
local weaponcheck = 0
while true do
if exports['ls-arcade']:isPlayerInArena() then goto skip end -- HERE
local ped = PlayerPedId()
sleep = 250
if DoesEntityExist(ped) and not IsEntityDead(ped) and not IsPedInParachuteFreeFall(ped) and not IsPedFalling(ped) and (GetPedParachuteState(ped) == -1 or GetPedParachuteState(ped) == 0) then
sleep = 0
if currWeapon ~= GetSelectedPedWeapon(ped) then
local pos = GetEntityCoords(ped, true)
local rot = GetEntityHeading(ped)
local newWeap = GetSelectedPedWeapon(ped)
SetCurrentPedWeapon(ped, currWeapon, true)
loadAnimDict("reaction@intimidation@1h")
loadAnimDict("reaction@intimidation@cop@unarmed")
loadAnimDict("rcmjosh4")
loadAnimDict("weapons@pistol@")
local HolsterVariant = GetPedDrawableVariation(ped, 8)
WearingHolster = false
for i = 1,#Config.HolsterVariant,1 do
if HolsterVariant == Config.HolsterVariant[i] then
WearingHolster = true
end
end
if CheckWeapon(newWeap) then
if holstered then
if WearingHolster then
--TaskPlayAnim(ped, "rcmjosh4", "josh_leadout_cop2", 8.0, 2.0, -1, 48, 10, 0, 0, 0 )
canFire = false
CeaseFire()
currentHolster = GetPedDrawableVariation(ped, 7)
currentHolsterTexture = GetPedTextureVariation(ped, 7)
TaskPlayAnimAdvanced(ped, "rcmjosh4", "josh_leadout_cop2", pos.x, pos.y, pos.z, 0, 0, rot, 3.0, 3.0, -1, 50, 0, 0, 0)
Wait(300)
SetCurrentPedWeapon(ped, newWeap, true)
if IsWeaponHolsterable(newWeap) then
SetPedComponentVariation(ped, 7, currentHolster == 8 and 2 or currentHolster == 1 and 3 or currentHolster == 6 and 5, currentHolsterTexture, 2)
end
currWeapon = newWeap
Wait(300)
ClearPedTasks(ped)
holstered = false
canFire = true
else
canFire = false
CeaseFire()
TaskPlayAnimAdvanced(ped, "reaction@intimidation@1h", "intro", pos.x, pos.y, pos.z, 0, 0, rot, 8.0, 3.0, -1, 50, 0, 0, 0)
Wait(1000)
SetCurrentPedWeapon(ped, newWeap, true)
currWeapon = newWeap
Wait(1400)
ClearPedTasks(ped)
holstered = false
canFire = true
end
elseif newWeap ~= currWeapon and CheckWeapon(currWeapon) then
if WearingHolster then
canFire = false
CeaseFire()
TaskPlayAnimAdvanced(ped, "reaction@intimidation@cop@unarmed", "intro", pos.x, pos.y, pos.z, 0, 0, rot, 3.0, 3.0, -1, 50, 0, 0, 0)
Wait(500)
if IsWeaponHolsterable(currWeapon) then
SetPedComponentVariation(ped, 7, currentHolster, currentHolsterTexture, 2)
end
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
currentHolster = GetPedDrawableVariation(ped, 7)
currentHolsterTexture = GetPedTextureVariation(ped, 7)
TaskPlayAnimAdvanced(ped, "rcmjosh4", "josh_leadout_cop2", pos.x, pos.y, pos.z, 0, 0, rot, 3.0, 3.0, -1, 50, 0, 0, 0)
Wait(300)
SetCurrentPedWeapon(ped, newWeap, true)
if IsWeaponHolsterable(newWeap) then
SetPedComponentVariation(ped, 7, currentHolster == 8 and 2 or currentHolster == 1 and 3 or currentHolster == 6 and 5, currentHolsterTexture, 2)
end
Wait(500)
currWeapon = newWeap
ClearPedTasks(ped)
holstered = false
canFire = true
else
canFire = false
CeaseFire()
TaskPlayAnimAdvanced(ped, "reaction@intimidation@1h", "outro", pos.x, pos.y, pos.z, 0, 0, rot, 8.0, 3.0, -1, 50, 0, 0, 0)
Wait(1600)
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
TaskPlayAnimAdvanced(ped, "reaction@intimidation@1h", "intro", pos.x, pos.y, pos.z, 0, 0, rot, 8.0, 3.0, -1, 50, 0, 0, 0)
Wait(1000)
SetCurrentPedWeapon(ped, newWeap, true)
currWeapon = newWeap
Wait(1400)
ClearPedTasks(ped)
holstered = false
canFire = true
end
else
if WearingHolster then
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
currentHolster = GetPedDrawableVariation(ped, 7)
currentHolsterTexture = GetPedTextureVariation(ped, 7)
TaskPlayAnimAdvanced(ped, "rcmjosh4", "josh_leadout_cop2", pos.x, pos.y, pos.z, 0, 0, rot, 3.0, 3.0, -1, 50, 0, 0, 0)
Wait(300)
SetCurrentPedWeapon(ped, newWeap, true)
if IsWeaponHolsterable(newWeap) then
SetPedComponentVariation(ped, 7, currentHolster == 8 and 2 or currentHolster == 1 and 3 or currentHolster == 6 and 5, currentHolsterTexture, 2)
end
currWeapon = newWeap
Wait(300)
ClearPedTasks(ped)
holstered = false
canFire = true
else
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
TaskPlayAnimAdvanced(ped, "reaction@intimidation@1h", "intro", pos.x, pos.y, pos.z, 0, 0, rot, 8.0, 3.0, -1, 50, 0, 0, 0)
Wait(1000)
SetCurrentPedWeapon(ped, newWeap, true)
currWeapon = newWeap
Wait(1400)
ClearPedTasks(ped)
holstered = false
canFire = true
end
end
else
if not holstered and CheckWeapon(currWeapon) then
if WearingHolster then
canFire = false
CeaseFire()
TaskPlayAnimAdvanced(ped, "reaction@intimidation@cop@unarmed", "intro", pos.x, pos.y, pos.z, 0, 0, rot, 3.0, 3.0, -1, 50, 0, 0, 0)
Wait(500)
if IsWeaponHolsterable(currWeapon) then
SetPedComponentVariation(ped, 7, currentHolster, currentHolsterTexture, 2)
end
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
ClearPedTasks(ped)
SetCurrentPedWeapon(ped, newWeap, true)
holstered = true
canFire = true
currWeapon = newWeap
else
canFire = false
CeaseFire()
TaskPlayAnimAdvanced(ped, "reaction@intimidation@1h", "outro", pos.x, pos.y, pos.z, 0, 0, rot, 8.0, 3.0, -1, 50, 0, 0, 0)
Wait(1400)
SetCurrentPedWeapon(ped, `WEAPON_UNARMED`, true)
ClearPedTasks(ped)
SetCurrentPedWeapon(ped, newWeap, true)
holstered = true
canFire = true
currWeapon = newWeap
end
else
SetCurrentPedWeapon(ped, newWeap, true)
holstered = false
canFire = true
currWeapon = newWeap
end
end
end
end
Wait(sleep)
if currWeapon == nil or currWeapon == `WEAPON_UNARMED` then
weaponcheck = weaponcheck + 1
if weaponcheck == 2 then
break
end
end
::skip::
end
end)
Optional: Configure Emergency Dispatch
It's recommended to configure whatever dispatch resource you may use, so that certain calls will be ignored while the player is in the arcade.
Use the isPlayerInArena export to disable certain calls from being triggered
Finished
If you have any issues at all with setting up the script, or run into any bugs, please do hesitate to join our discord (opens in a new tab) and create a ticket.