1
0
Fork 0
forked from Simnation/Main
Main/resources/[standalone]/nordi_tdm/server.lua
2025-07-26 06:36:06 +02:00

363 lines
11 KiB
Lua

local QBCore = exports['qb-core']:GetCoreObject()
-- Game Management
local activeGames = {}
local gameIdCounter = 1
-- Events
RegisterNetEvent('tdm:createGame', function(gameName, fieldId, gameType, password)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
-- Prüfen ob Spielfeld bereits belegt
for gameId, gameData in pairs(activeGames) do
if gameData.fieldId == fieldId then
TriggerClientEvent('QBCore:Notify', src, 'Dieses Spielfeld ist bereits belegt!', 'error')
return
end
end
local gameId = 'game_' .. gameIdCounter
gameIdCounter = gameIdCounter + 1
activeGames[gameId] = {
id = gameId,
name = gameName,
fieldId = fieldId,
admin = src,
adminName = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
gameType = gameType,
password = password,
hasPassword = password ~= nil,
status = 'waiting',
team1 = {},
team2 = {},
score = {team1 = 0, team2 = 0},
startTime = nil,
maxTime = Config.maxGameTime,
maxHits = Config.maxHits
}
local typeText = gameType == 'public' and 'öffentliches' or 'privates'
TriggerClientEvent('QBCore:Notify', src, 'Dein ' .. typeText .. ' Spiel "' .. gameName .. '" wurde erstellt!', 'success')
updateGamesListForAll()
end)
RegisterNetEvent('tdm:requestGamesList', function()
local src = source
TriggerClientEvent('tdm:updateGamesList', src, activeGames)
end)
RegisterNetEvent('tdm:requestJoinGame', function(gameId, password)
local src = source
local Player = QBCore.Functions.GetPlayer(src)
if not Player or not activeGames[gameId] then return end
local game = activeGames[gameId]
local playerName = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname
-- Passwort prüfen falls vorhanden
if game.hasPassword and game.password ~= password then
TriggerClientEvent('QBCore:Notify', src, 'Falsches Passwort!', 'error')
return
end
-- Spieler bereits im Spiel?
for _, playerId in ipairs(game.team1) do
if playerId == src then
TriggerClientEvent('QBCore:Notify', src, 'Du bist bereits in diesem Spiel!', 'error')
return
end
end
for _, playerId in ipairs(game.team2) do
if playerId == src then
TriggerClientEvent('QBCore:Notify', src, 'Du bist bereits in diesem Spiel!', 'error')
return
end
end
-- Max Spieler erreicht?
local currentPlayers = #game.team1 + #game.team2
local maxPlayers = Config.gameFields[game.fieldId].maxPlayers
if currentPlayers >= maxPlayers then
TriggerClientEvent('QBCore:Notify', src, 'Spiel ist voll!', 'error')
return
end
-- Prüfen ob Admin online ist (für private Spiele)
if game.gameType == 'private' then
local AdminPlayer = QBCore.Functions.GetPlayer(game.admin)
if not AdminPlayer then
TriggerClientEvent('QBCore:Notify', src, 'Der Spiel-Admin ist nicht online!', 'error')
return
end
end
-- Join Logic basierend auf Spiel Typ
if game.gameType == 'public' then
joinPlayerToGame(src, gameId)
TriggerClientEvent('QBCore:Notify', src, 'Du bist dem öffentlichen Spiel beigetreten!', 'success')
else
TriggerClientEvent('tdm:joinRequest', game.admin, gameId, playerName, src)
TriggerClientEvent('QBCore:Notify', src, 'Join-Anfrage gesendet an ' .. game.adminName, 'info')
end
end)
RegisterNetEvent('tdm:approveJoinRequest', function(gameId, playerId, approved)
local src = source
local game = activeGames[gameId]
if not game or game.admin ~= src then return end
if approved then
joinPlayerToGame(playerId, gameId)
TriggerClientEvent('tdm:joinRequestResult', playerId, true, game.name)
else
TriggerClientEvent('tdm:joinRequestResult', playerId, false, game.name)
end
end)
RegisterNetEvent('tdm:leaveGame', function()
local src = source
for gameId, game in pairs(activeGames) do
removePlayerFromGame(src, gameId)
end
TriggerClientEvent('tdm:leaveGame', src)
end)
RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, shooterId)
local src = source
local game = activeGames[gameId]
if not game then return end
local shooterTeam = nil
if shooterId then
for _, playerId in ipairs(game.team1) do
if playerId == shooterId then
shooterTeam = 'team1'
break
end
end
if not shooterTeam then
for _, playerId in ipairs(game.team2) do
if playerId == shooterId then
shooterTeam = 'team2'
break
end
end
end
end
if shooterTeam and shooterTeam ~= victimTeam then
game.score[shooterTeam] = game.score[shooterTeam] + 1
if shooterId then
TriggerClientEvent('tdm:hitRegistered', shooterId)
end
TriggerClientEvent('tdm:deathRegistered', src)
updateScoreForGame(gameId)
if game.score[shooterTeam] >= game.maxHits then
endGame(gameId, shooterTeam)
end
end
end)
RegisterNetEvent('tdm:playerDied', function(gameId)
local src = source
removePlayerFromGame(src, gameId)
end)
-- Funktionen
function joinPlayerToGame(playerId, gameId)
local game = activeGames[gameId]
if not game then return end
-- Team mit weniger Spielern wählen
local team = #game.team1 <= #game.team2 and 'team1' or 'team2'
table.insert(game[team], playerId)
-- Spiel starten wenn mindestens 2 Spieler
if #game.team1 + #game.team2 >= 2 and game.status == 'waiting' then
game.status = 'active'
game.startTime = os.time()
-- Game Timer starten
startGameTimer(gameId)
end
TriggerClientEvent('tdm:joinGame', playerId, gameId, team, game.fieldId)
updateScoreForGame(gameId)
updateGamesListForAll()
end
function removePlayerFromGame(playerId, gameId)
local game = activeGames[gameId]
if not game then return end
-- Spieler aus Teams entfernen
for i, id in ipairs(game.team1) do
if id == playerId then
table.remove(game.team1, i)
break
end
end
for i, id in ipairs(game.team2) do
if id == playerId then
table.remove(game.team2, i)
break
end
end
-- Wenn Admin das Spiel verlässt, Spiel beenden
if game.admin == playerId then
endGame(gameId, nil, 'Admin hat das Spiel verlassen')
return
end
checkGameEnd(gameId)
updateGamesListForAll()
end
function endGame(gameId, winnerTeam, reason)
local game = activeGames[gameId]
if not game then return end
game.status = 'finished'
local allPlayers = {}
for _, playerId in ipairs(game.team1) do
table.insert(allPlayers, playerId)
end
for _, playerId in ipairs(game.team2) do
table.insert(allPlayers, playerId)
end
-- Game End Event an alle Spieler
for _, playerId in ipairs(allPlayers) do
TriggerClientEvent('tdm:gameEnded', playerId, winnerTeam, game.score.team1, game.score.team2)
end
-- Spiel nach 10 Sekunden löschen
SetTimeout(10000, function()
activeGames[gameId] = nil
updateGamesListForAll()
end)
if reason then
print('[TDM] Spiel ' .. gameId .. ' beendet: ' .. reason)
end
end
function startGameTimer(gameId)
CreateThread(function()
local game = activeGames[gameId]
if not game then return end
local maxTime = game.maxTime
local startTime = os.time()
while game and game.status == 'active' and (os.time() - startTime) < maxTime do
Wait(1000)
game = activeGames[gameId] -- Refresh game data
end
-- Zeit abgelaufen
if game and game.status == 'active' then
local winnerTeam = game.score.team1 > game.score.team2 and 'team1' or
game.score.team2 > game.score.team1 and 'team2' or nil
endGame(gameId, winnerTeam, 'Zeit abgelaufen')
end
end)
end
function checkGameEnd(gameId)
local game = activeGames[gameId]
if not game then return end
local totalPlayers = #game.team1 + #game.team2
if totalPlayers < 2 and game.status == 'active' then
endGame(gameId, nil, 'Zu wenig Spieler')
elseif totalPlayers == 0 then
activeGames[gameId] = nil
updateGamesListForAll()
end
end
function updateScoreForGame(gameId)
local game = activeGames[gameId]
if not game then return end
local gameStats = {
totalHits = game.score.team1 + game.score.team2,
gameTime = game.startTime and (os.time() - game.startTime) or 0
}
for _, playerId in ipairs(game.team1) do
TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2, gameStats)
end
for _, playerId in ipairs(game.team2) do
TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2, gameStats)
end
end
function updateGamesListForAll()
local players = QBCore.Functions.GetPlayers()
for _, playerId in pairs(players) do
TriggerClientEvent('tdm:updateGamesList', playerId, activeGames)
end
end
-- Player Disconnect Handler
AddEventHandler('playerDropped', function()
local src = source
for gameId, game in pairs(activeGames) do
removePlayerFromGame(src, gameId)
end
end)
-- Server Start - Games Liste leeren
AddEventHandler('onResourceStart', function(resourceName)
if GetCurrentResourceName() == resourceName then
activeGames = {}
gameIdCounter = 1
print('[TDM] TeamDeathmatch System gestartet!')
end
end)
AddEventHandler('onResourceStop', function(resourceName)
if GetCurrentResourceName() == resourceName then
-- Alle Spieler aus TDM entfernen
for gameId, game in pairs(activeGames) do
local allPlayers = {}
for _, playerId in ipairs(game.team1) do
table.insert(allPlayers, playerId)
end
for _, playerId in ipairs(game.team2) do
table.insert(allPlayers, playerId)
end
for _, playerId in ipairs(allPlayers) do
TriggerClientEvent('tdm:leaveGame', playerId)
end
end
activeGames = {}
print('[TDM] TeamDeathmatch System gestoppt!')
end
end)