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) -- In server.lua hinzufügen RegisterNetEvent('tdm:requestScoreUpdate', function(gameId) local src = source if activeGames[gameId] then local game = activeGames[gameId] -- Score an alle Spieler senden for _, playerId in pairs(game.team1) do TriggerClientEvent('tdm:updateScore', playerId, game.team1Score, game.team2Score, { hits = game.playerStats[playerId] and game.playerStats[playerId].hits or 0, deaths = game.playerStats[playerId] and game.playerStats[playerId].deaths or 0 }) end for _, playerId in pairs(game.team2) do TriggerClientEvent('tdm:updateScore', playerId, game.team1Score, game.team2Score, { hits = game.playerStats[playerId] and game.playerStats[playerId].hits or 0, deaths = game.playerStats[playerId] and game.playerStats[playerId].deaths or 0 }) end end end) -- Erweiterte playerWasHit Event RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, attackerId) local victim = source if not activeGames[gameId] then return end local game = activeGames[gameId] -- Spieler Stats initialisieren falls nicht vorhanden if not game.playerStats then game.playerStats = {} end if not game.playerStats[victim] then game.playerStats[victim] = {hits = 0, deaths = 0} end if attackerId and not game.playerStats[attackerId] then game.playerStats[attackerId] = {hits = 0, deaths = 0} end -- Stats updaten game.playerStats[victim].deaths = game.playerStats[victim].deaths + 1 if attackerId then game.playerStats[attackerId].hits = game.playerStats[attackerId].hits + 1 TriggerClientEvent('tdm:hitRegistered', attackerId) end -- Team Score erhöhen if victimTeam == 'team1' then game.team2Score = game.team2Score + 1 else game.team1Score = game.team1Score + 1 end TriggerClientEvent('tdm:deathRegistered', victim) -- Score an alle Spieler senden local allPlayers = {} for _, playerId in pairs(game.team1) do table.insert(allPlayers, playerId) end for _, playerId in pairs(game.team2) do table.insert(allPlayers, playerId) end for _, playerId in pairs(allPlayers) do TriggerClientEvent('tdm:updateScore', playerId, game.team1Score, game.team2Score, { hits = game.playerStats[playerId] and game.playerStats[playerId].hits or 0, deaths = game.playerStats[playerId] and game.playerStats[playerId].deaths or 0 }) end -- Spiel beenden prüfen if game.team1Score >= Config.maxHits or game.team2Score >= Config.maxHits then local winnerTeam = game.team1Score >= Config.maxHits and 'team1' or 'team2' endGame(gameId, winnerTeam) end end)