ed
This commit is contained in:
		
							parent
							
								
									b743002467
								
							
						
					
					
						commit
						f192af7af6
					
				
					 3 changed files with 941 additions and 0 deletions
				
			
		
							
								
								
									
										347
									
								
								resources/[standalone]/nordi_tdm/server.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								resources/[standalone]/nordi_tdm/server.lua
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,347 @@
 | 
			
		|||
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, -- 'public' oder 'private'
 | 
			
		||||
        password = password,
 | 
			
		||||
        hasPassword = password ~= nil,
 | 
			
		||||
        status = 'waiting', -- waiting, active, finished
 | 
			
		||||
        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')
 | 
			
		||||
    
 | 
			
		||||
    -- Games Liste an alle senden
 | 
			
		||||
    updateGamesListForAll()
 | 
			
		||||
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
 | 
			
		||||
        -- Öffentliches Spiel - automatisch beitreten
 | 
			
		||||
        joinPlayerToGame(src, gameId)
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', src, 'Du bist dem öffentlichen Spiel beigetreten!', 'success')
 | 
			
		||||
    else
 | 
			
		||||
        -- Privates Spiel - Join Request an Admin senden
 | 
			
		||||
        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
 | 
			
		||||
    
 | 
			
		||||
    -- Spieler aus allen Spielen entfernen
 | 
			
		||||
    for gameId, game in pairs(activeGames) do
 | 
			
		||||
        removePlayerFromGame(src, gameId)
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    TriggerClientEvent('tdm:leaveGame', src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam)
 | 
			
		||||
    local src = source
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    -- Punkt für das andere Team
 | 
			
		||||
    local scoringTeam = victimTeam == 'team1' and 'team2' or 'team1'
 | 
			
		||||
    game.score[scoringTeam] = game.score[scoringTeam] + 1
 | 
			
		||||
    
 | 
			
		||||
    -- Score Update an alle Spieler
 | 
			
		||||
    updateScoreForGame(gameId)
 | 
			
		||||
    
 | 
			
		||||
    -- Prüfen ob Spiel gewonnen
 | 
			
		||||
    if game.score[scoringTeam] >= game.maxHits then
 | 
			
		||||
        endGame(gameId, scoringTeam)
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('tdm:playerDied', function(gameId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    removePlayerFromGame(src, gameId)
 | 
			
		||||
    checkGameEnd(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)
 | 
			
		||||
    
 | 
			
		||||
    TriggerClientEvent('tdm:joinGame', playerId, gameId, team, game.fieldId)
 | 
			
		||||
    
 | 
			
		||||
    -- Spiel starten wenn genug Spieler
 | 
			
		||||
    checkGameStart(gameId)
 | 
			
		||||
    
 | 
			
		||||
    updateGamesListForAll()
 | 
			
		||||
    updateScoreForGame(gameId)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function removePlayerFromGame(playerId, gameId)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    -- Aus Team 1 entfernen
 | 
			
		||||
    for i, id in ipairs(game.team1) do
 | 
			
		||||
        if id == playerId then
 | 
			
		||||
            table.remove(game.team1, i)
 | 
			
		||||
            break
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Aus Team 2 entfernen
 | 
			
		||||
    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 checkGameStart(gameId)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    local totalPlayers = #game.team1 + #game.team2
 | 
			
		||||
    
 | 
			
		||||
    if totalPlayers >= 2 and game.status == 'waiting' then
 | 
			
		||||
        startGame(gameId)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function startGame(gameId)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    game.status = 'active'
 | 
			
		||||
    game.startTime = os.time()
 | 
			
		||||
    game.score = {team1 = 0, team2 = 0}
 | 
			
		||||
    
 | 
			
		||||
    -- Nachricht an alle Spieler
 | 
			
		||||
    for _, playerId in ipairs(game.team1) do
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', playerId, 'Spiel gestartet!', 'success')
 | 
			
		||||
    end
 | 
			
		||||
    for _, playerId in ipairs(game.team2) do
 | 
			
		||||
        TriggerClientEvent('QBCore:Notify', playerId, 'Spiel gestartet!', 'success')
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    updateScoreForGame(gameId)
 | 
			
		||||
    updateGamesListForAll()
 | 
			
		||||
    
 | 
			
		||||
    -- Game Timer
 | 
			
		||||
    CreateThread(function()
 | 
			
		||||
        while activeGames[gameId] and activeGames[gameId].status == 'active' do
 | 
			
		||||
            Wait(1000)
 | 
			
		||||
            
 | 
			
		||||
            local currentTime = os.time()
 | 
			
		||||
            local elapsed = currentTime - game.startTime
 | 
			
		||||
            
 | 
			
		||||
            if elapsed >= game.maxTime then
 | 
			
		||||
                local winnerTeam = game.score.team1 > game.score.team2 and 'team1' or 'team2'
 | 
			
		||||
                endGame(gameId, winnerTeam, 'Zeit abgelaufen')
 | 
			
		||||
                break
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function endGame(gameId, winnerTeam, reason)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    game.status = 'finished'
 | 
			
		||||
    
 | 
			
		||||
    local message = reason or (winnerTeam and ('Team ' .. winnerTeam .. ' hat gewonnen!') or 'Spiel beendet')
 | 
			
		||||
    
 | 
			
		||||
    -- Nachricht an alle Spieler
 | 
			
		||||
    for _, playerId in ipairs(game.team1) do
 | 
			
		||||
        if winnerTeam then
 | 
			
		||||
            TriggerClientEvent('tdm:gameEnded', playerId, winnerTeam, game.score.team1, game.score.team2)
 | 
			
		||||
        else
 | 
			
		||||
            TriggerClientEvent('QBCore:Notify', playerId, message, 'error')
 | 
			
		||||
            TriggerClientEvent('tdm:leaveGame', playerId)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    for _, playerId in ipairs(game.team2) do
 | 
			
		||||
        if winnerTeam then
 | 
			
		||||
            TriggerClientEvent('tdm:gameEnded', playerId, winnerTeam, game.score.team1, game.score.team2)
 | 
			
		||||
        else
 | 
			
		||||
            TriggerClientEvent('QBCore:Notify', playerId, message, 'error')
 | 
			
		||||
            TriggerClientEvent('tdm:leaveGame', playerId)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    
 | 
			
		||||
    -- Spiel nach 15 Sekunden löschen
 | 
			
		||||
    CreateThread(function()
 | 
			
		||||
        Wait(15000)
 | 
			
		||||
        activeGames[gameId] = nil
 | 
			
		||||
        updateGamesListForAll()
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function checkGameEnd(gameId)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return 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
 | 
			
		||||
        -- Spiel löschen wenn keine Spieler mehr da sind
 | 
			
		||||
        activeGames[gameId] = nil
 | 
			
		||||
        updateGamesListForAll()
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function updateScoreForGame(gameId)
 | 
			
		||||
    local game = activeGames[gameId]
 | 
			
		||||
    if not game then return end
 | 
			
		||||
    
 | 
			
		||||
    -- Score an alle Spieler des Spiels senden
 | 
			
		||||
    for _, playerId in ipairs(game.team1) do
 | 
			
		||||
        TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2)
 | 
			
		||||
    end
 | 
			
		||||
    for _, playerId in ipairs(game.team2) do
 | 
			
		||||
        TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function updateGamesListForAll()
 | 
			
		||||
    -- Games Liste an alle Spieler senden
 | 
			
		||||
    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
 | 
			
		||||
    
 | 
			
		||||
    -- Spieler aus allen Spielen entfernen
 | 
			
		||||
    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
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue