Skip to content

Commit

Permalink
feat(ffa): Basic Free for All gamemode.
Browse files Browse the repository at this point in the history
Free for All gamemode witch integrates with mapmanger and spawnmanager. Also requires new scoreboard in PR citizenfx#159.

Co-Authored-By: Christopher Gjelten <[email protected]>
  • Loading branch information
The-Neco and itschip committed Mar 25, 2021
1 parent 860a4b2 commit d33edb9
Show file tree
Hide file tree
Showing 8 changed files with 272 additions and 0 deletions.
14 changes: 14 additions & 0 deletions resources/[gamemodes]/[ffa]/[maps]/ffa-legion/fxmanifest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.

fx_version 'cerulean'
game 'gta5'

version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Legion square map for FFA.'
repository 'https://github.com/citizenfx/cfx-server-data'

resource_type 'map' { gameTypes = { ['ffa'] = true } }

map 'map.lua'
8 changes: 8 additions & 0 deletions resources/[gamemodes]/[ffa]/[maps]/ffa-legion/map.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ffa_map 'Legion' { x = 193.06, y = -940.789, z = 30.6918, radius = 70.0}

spawnpoint 's_m_y_marine_03' { x = 199.575, y = -986.47, z = 30.0919 }
spawnpoint 's_m_y_marine_03' { x = 252.045, y = -878.664, z = 30.2922 }
spawnpoint 's_m_y_marine_03' { x = 179.474, y = -874.747, z = 31.1116 }
spawnpoint 's_m_y_marine_03' { x = 164.936, y = -914.063, z = 30.2001 }
spawnpoint 's_m_y_marine_03' { x = 219.208, y = -951.245, z = 30.0869 }
spawnpoint 's_m_y_marine_03' { x = 151.489, y = -973.849, z = 30.0919 }
14 changes: 14 additions & 0 deletions resources/[gamemodes]/[ffa]/[maps]/ffa-maze/fxmanifest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.

fx_version 'cerulean'
game 'gta5'

version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'Maze map for FFA.'
repository 'https://github.com/citizenfx/cfx-server-data'

resource_type 'map' { gameTypes = { ['ffa'] = true } }

map 'map.lua'
8 changes: 8 additions & 0 deletions resources/[gamemodes]/[ffa]/[maps]/ffa-maze/map.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ffa_map 'Maze' { x = -2298.247, y = 203.007, z = 167.6016, radius = 50.0}

spawnpoint 's_m_y_marine_03' { x = -2309.011, y = 242.1087, z = 169.6021 }
spawnpoint 's_m_y_marine_03' { x = -2312.823, y = 196.0172, z = 167.6016 }
spawnpoint 's_m_y_marine_03' { x = -2300.696, y = 169.3624, z = 167.6016 }
spawnpoint 's_m_y_marine_03' { x = -2282.443, y = 165.7654, z = 167.6016 }
spawnpoint 's_m_y_marine_03' { x = -2277.752, y = 198.2776, z = 167.6018 }
spawnpoint 's_m_y_marine_03' { x = -2284.595, y = 222.0139, z = 167.6018 }
67 changes: 67 additions & 0 deletions resources/[gamemodes]/[ffa]/ffa/cl_mapmanager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
local ffaMap
local firstSpawn = true

AddEventHandler('getMapDirectives', function(add)
add('ffa_map', function(state, mapName)
return function(opts)
ffaMap = {
coords = vec3(opts.x, opts.y, opts.z),
radius = opts.radius
}
state.add('map', mapName)
print(mapName .. " has been started.")
end
end, function(state, arg)
print(state.map .. " has been stopped.")
end)
end)

Citizen.CreateThread(function()
while ffaMap == nil or firstSpawn do
Citizen.Wait(100)
end
while true do
Citizen.Wait(100)
local distFromMap = #(ffaMap.coords - GetEntityCoords(PlayerPedId()))
if distFromMap >= ffaMap.radius then
local timer = 5
while distFromMap >= ffaMap.radius do
Citizen.Wait(1000)
distFromMap = #(ffaMap.coords - GetEntityCoords(PlayerPedId()))
countdown(timer, "Turn back!")
if timer == 0 and distFromMap >= ffaMap.radius then
SetEntityHealth(PlayerPedId(), 0)
end
timer = timer - 1
end
countdown(0)
end
end
end)

AddEventHandler("playerSpawned", function()
firstSpawn = false
GiveWeaponToPed(PlayerPedId(), `WEAPON_CARBINERIFLE`, 1000, false, true)
end)

NetworkSetFriendlyFireOption(true)
SetCanAttackFriendly(PlayerPedId(), true, true)
TriggerServerEvent("ffa:init")

AddEventHandler('onClientMapStart', function()
exports.spawnmanager:setAutoSpawn(true)
exports.spawnmanager:forceRespawn()
end)

RegisterNetEvent("ffa:onPlayerKilled")
AddEventHandler("ffa:onPlayerKilled", function()
SetEntityHealth(PlayerPedId(), 200)
end)

RegisterNetEvent("ffa:roundEnd")
AddEventHandler("ffa:roundEnd", function()
for i = 5, 0, -1 do
countdown(i, "Next round starts in:")
Citizen.Wait(1000)
end
end)
61 changes: 61 additions & 0 deletions resources/[gamemodes]/[ffa]/ffa/cl_ui.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
local position = {
"1st",
"2nd",
"3rd"
}
local timer = 0
local countdownMessage = ""

Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
SetPlayerWantedLevel(PlayerId(), 0, false)
local killsTab = getKills()
for i = 1, 3 do
if killsTab[i] ~= nil then
drawTxt(0.015, 0.7+(0.02*i), 0, 0.3, string.format("%s: %s (%s kills)", position[i], GetPlayerName(killsTab[i][1]), killsTab[i][2]), 255,255,255,255, true)
end
end
if timer > 0 then
drawTxt(0.5, 0.4, 7, 0.4, countdownMessage, 255,255,255,255, true, true)
drawTxt(0.5, 0.42, 7, 0.5, timer, 255,255,255,255, true, true)
end
end
end)

function countdown(value, message)
timer = value
if message then
countdownMessage = message
end
end

function getKills()
local playerKills = {}
local i = 1
for _, playerId in pairs(GetActivePlayers()) do
playerKills[i] = {playerId, Player(GetPlayerServerId(playerId)).state.kills}
i = i + 1
end
table.sort(playerKills, function(a, b)
if not a[2] or not b[2] then return end
return a[2] > b[2]
end)
return {playerKills[1], playerKills[2], playerKills[3]}
end
function drawTxt(x,y, font, scale, text, r,g,b,a, outline, centre)
SetTextFont(font)
SetTextProportional(0)
SetTextScale(scale, scale)
SetTextColour(r, g, b, a)
SetTextDropShadow(0, 0, 0, 0,255)
SetTextEdge(1, 0, 0, 0, 255)
SetTextCentre(centre)
SetTextDropShadow()
if(outline)then
SetTextOutline()
end
SetTextEntry("STRING")
AddTextComponentString(text)
DrawText(x, y)
end
21 changes: 21 additions & 0 deletions resources/[gamemodes]/[ffa]/ffa/fxmanifest.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
-- This resource is part of the default Cfx.re asset pack (cfx-server-data)
-- Altering or recreating for local use only is strongly discouraged.

fx_version 'cerulean'
game 'gta5'

version '1.0.0'
author 'Cfx.re <[email protected]>'
description 'A Free For All gamemode for FiveM.'
repository 'https://github.com/citizenfx/cfx-server-data'

resource_type 'gametype' { name = 'FFA' }

dependencies {
'baseevents'
}

client_script 'cl_mapmanager.lua'
client_script 'cl_ui.lua'

server_script 'sv_deathManager.lua'
79 changes: 79 additions & 0 deletions resources/[gamemodes]/[ffa]/ffa/sv_deathManager.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
RegisterNetEvent("baseevents:onPlayerKilled")
AddEventHandler("baseevents:onPlayerKilled", function(killedBy, data)
if source == killedBy then DropPlayer(source, "Nice try.") return end
local localPly = Player(source)
localPly.state.deaths = localPly.state.deaths + 1
updateScoreboard(source)
local killerPly = Player(killedBy)
killerPly.state.kills = killerPly.state.kills + 1
updateScoreboard(killedBy)
TriggerClientEvent("ffa:onPlayerKilled", killedBy)
if killerPly.state.kills == GetConvarInt("ffa_kill_threshold", 25) then
TriggerClientEvent("ffa:roundEnd", -1)
Citizen.Wait(5500)
for _, playerId in pairs(GetPlayers()) do
local ply = Player(playerId)
ply.state.kills = 0
ply.state.deaths = 0
updateScoreboard(tonumber(playerId))
end
exports["mapmanager"]:roundEnded()
end
end)

RegisterNetEvent("baseevents:onPlayerDied")
AddEventHandler('baseevents:onPlayerDied', function(killerType, pos)
local localPly = Player(source)
localPly.state.deaths = localPly.state.deaths + 1
updateScoreboard(source)
end)

RegisterNetEvent("baseevents:onPlayerWasted")
AddEventHandler('baseevents:onPlayerWasted', function(killerType, pos)
local localPly = Player(source)
localPly.state.deaths = localPly.state.deaths + 1
updateScoreboard(source)
end)

AddEventHandler('onResourceStart', function(resourceName)
if (GetCurrentResourceName() ~= resourceName) then
return
end
TriggerEvent("scoreboard:addColumn", "Kills", "Kills", 0, 2)
TriggerEvent("scoreboard:addColumn", "Deaths", "Deaths", 0, 3)
TriggerEvent("scoreboard:addColumn", "KD", "K/D", 0, 4)
TriggerEvent("scoreboard:addColumn", "Points", "Points", 0, 5)
end)

AddEventHandler('onResourceStop', function(resourceName)
if (GetCurrentResourceName() ~= resourceName) then
return
end
TriggerEvent("scoreboard:removeColumn", "Kills")
TriggerEvent("scoreboard:removeColumn", "Deaths")
TriggerEvent("scoreboard:removeColumn", "KD")
TriggerEvent("scoreboard:removeColumn", "Points")
end)

RegisterNetEvent("ffa:init")
AddEventHandler("ffa:init", function()
local localPly = Player(source)
localPly.state.kills = 0
localPly.state.deaths = 0
end)

--http://lua-users.org/wiki/SimpleRound
local function round(num, numDecimalPlaces)
local mult = 10^(numDecimalPlaces or 0)
return math.floor(num * mult + 0.5) / mult
end

function updateScoreboard(src)
local localPly = Player(src)
TriggerEvent("scoreboard:updateColumnValue", src, "Kills", localPly.state.kills)
TriggerEvent("scoreboard:updateColumnValue", src, "Deaths", localPly.state.deaths)
local kd = round(localPly.state.kills/localPly.state.deaths, 2)
if tostring(kd) == "inf" then kd = 0.0 end
TriggerEvent("scoreboard:updateColumnValue", src, "KD", kd)
TriggerEvent("scoreboard:updateColumnValue", src, "Points", 0)
end

0 comments on commit d33edb9

Please sign in to comment.