forked from Simnation/Main
348 lines
10 KiB
Lua
348 lines
10 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, -- '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)
|
||
|
|
||
|
|