diff --git a/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/fxmanifest.lua b/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/fxmanifest.lua new file mode 100644 index 000000000..1338844be --- /dev/null +++ b/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/fxmanifest.lua @@ -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 ' +description 'Legion square map for FFA.' +repository 'https://github.com/citizenfx/cfx-server-data' + +resource_type 'map' { gameTypes = { ['ffa'] = true } } + +map 'map.lua' diff --git a/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/map.lua b/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/map.lua new file mode 100644 index 000000000..c9c7ef93f --- /dev/null +++ b/resources/[gamemodes]/[ffa]/[maps]/ffa-legion/map.lua @@ -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 } diff --git a/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/fxmanifest.lua b/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/fxmanifest.lua new file mode 100644 index 000000000..27d0d12c3 --- /dev/null +++ b/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/fxmanifest.lua @@ -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 ' +description 'Maze map for FFA.' +repository 'https://github.com/citizenfx/cfx-server-data' + +resource_type 'map' { gameTypes = { ['ffa'] = true } } + +map 'map.lua' diff --git a/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/map.lua b/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/map.lua new file mode 100644 index 000000000..032e8650b --- /dev/null +++ b/resources/[gamemodes]/[ffa]/[maps]/ffa-maze/map.lua @@ -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 } diff --git a/resources/[gamemodes]/[ffa]/ffa/cl_mapmanager.lua b/resources/[gamemodes]/[ffa]/ffa/cl_mapmanager.lua new file mode 100644 index 000000000..0457710e6 --- /dev/null +++ b/resources/[gamemodes]/[ffa]/ffa/cl_mapmanager.lua @@ -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) diff --git a/resources/[gamemodes]/[ffa]/ffa/cl_ui.lua b/resources/[gamemodes]/[ffa]/ffa/cl_ui.lua new file mode 100644 index 000000000..2153b491e --- /dev/null +++ b/resources/[gamemodes]/[ffa]/ffa/cl_ui.lua @@ -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 diff --git a/resources/[gamemodes]/[ffa]/ffa/fxmanifest.lua b/resources/[gamemodes]/[ffa]/ffa/fxmanifest.lua new file mode 100644 index 000000000..43e3ed833 --- /dev/null +++ b/resources/[gamemodes]/[ffa]/ffa/fxmanifest.lua @@ -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 ' +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' diff --git a/resources/[gamemodes]/[ffa]/ffa/sv_deathManager.lua b/resources/[gamemodes]/[ffa]/ffa/sv_deathManager.lua new file mode 100644 index 000000000..78c708226 --- /dev/null +++ b/resources/[gamemodes]/[ffa]/ffa/sv_deathManager.lua @@ -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