forked from Simnation/Main
ed
This commit is contained in:
parent
eec7910283
commit
7def30a2ec
2 changed files with 216 additions and 109 deletions
|
@ -8,6 +8,13 @@ local teamZoneBlips = {}
|
|||
local isHit = false
|
||||
local activeGames = {}
|
||||
|
||||
-- Spieler Statistiken
|
||||
local playerStats = {
|
||||
hits = 0,
|
||||
deaths = 0,
|
||||
gamesPlayed = 0
|
||||
}
|
||||
|
||||
-- Events
|
||||
RegisterNetEvent('tdm:updateGamesList', function(games)
|
||||
activeGames = games
|
||||
|
@ -20,6 +27,11 @@ RegisterNetEvent('tdm:joinGame', function(gameId, team, fieldId)
|
|||
inTDM = true
|
||||
isHit = false
|
||||
|
||||
-- Stats zurücksetzen
|
||||
playerStats.hits = 0
|
||||
playerStats.deaths = 0
|
||||
playerStats.gamesPlayed = playerStats.gamesPlayed + 1
|
||||
|
||||
local fieldConfig = Config.gameFields[fieldId]
|
||||
|
||||
-- Teleport zu Team Spawn
|
||||
|
@ -57,6 +69,8 @@ RegisterNetEvent('tdm:leaveGame', function()
|
|||
-- Zone Blips entfernen
|
||||
removeTeamZoneBlips()
|
||||
|
||||
lib.hideTextUI()
|
||||
|
||||
lib.notify({
|
||||
title = 'TeamDeathmatch',
|
||||
description = 'Du hast das Spiel verlassen!',
|
||||
|
@ -123,19 +137,64 @@ RegisterNetEvent('tdm:playerHit', function()
|
|||
highlightTeamZone(currentTeam)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('tdm:updateScore', function(team1Score, team2Score)
|
||||
lib.showTextUI('[Team 1: ' .. team1Score .. '] VS [Team 2: ' .. team2Score .. ']', {
|
||||
RegisterNetEvent('tdm:updateScore', function(team1Score, team2Score, gameStats)
|
||||
local displayText = string.format(
|
||||
'[Team 1: %d] VS [Team 2: %d] | Deine Treffer: %d | Tode: %d',
|
||||
team1Score,
|
||||
team2Score,
|
||||
playerStats.hits,
|
||||
playerStats.deaths
|
||||
)
|
||||
|
||||
lib.showTextUI(displayText, {
|
||||
position = "top-center",
|
||||
icon = 'crosshairs'
|
||||
})
|
||||
end)
|
||||
|
||||
RegisterNetEvent('tdm:hitRegistered', function()
|
||||
playerStats.hits = playerStats.hits + 1
|
||||
|
||||
lib.notify({
|
||||
title = 'Treffer!',
|
||||
description = 'Du hast einen Gegner getroffen! (+1 Punkt)',
|
||||
type = 'success',
|
||||
duration = 2000
|
||||
})
|
||||
|
||||
showHitMarker()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('tdm:deathRegistered', function()
|
||||
playerStats.deaths = playerStats.deaths + 1
|
||||
end)
|
||||
|
||||
RegisterNetEvent('tdm:gameEnded', function(winnerTeam, team1Score, team2Score)
|
||||
lib.hideTextUI()
|
||||
|
||||
local wonGame = (currentTeam == 'team1' and winnerTeam == 'team1') or (currentTeam == 'team2' and winnerTeam == 'team2')
|
||||
local resultText = wonGame and '🏆 GEWONNEN!' or '💀 VERLOREN!'
|
||||
|
||||
local statsText = string.format(
|
||||
'%s\n\n' ..
|
||||
'Endergebnis:\n' ..
|
||||
'Team 1: %d Punkte\n' ..
|
||||
'Team 2: %d Punkte\n\n' ..
|
||||
'Deine Statistiken:\n' ..
|
||||
'🎯 Treffer: %d\n' ..
|
||||
'💀 Tode: %d\n' ..
|
||||
'📊 K/D: %.2f',
|
||||
resultText,
|
||||
team1Score,
|
||||
team2Score,
|
||||
playerStats.hits,
|
||||
playerStats.deaths,
|
||||
playerStats.deaths > 0 and (playerStats.hits / playerStats.deaths) or playerStats.hits
|
||||
)
|
||||
|
||||
local alert = lib.alertDialog({
|
||||
header = 'Spiel beendet!',
|
||||
content = 'Team ' .. winnerTeam .. ' hat gewonnen!\n\nTeam 1: ' .. team1Score .. '\nTeam 2: ' .. team2Score,
|
||||
content = statsText,
|
||||
centered = true,
|
||||
cancel = false
|
||||
})
|
||||
|
@ -180,10 +239,34 @@ function highlightTeamZone(team)
|
|||
end
|
||||
end
|
||||
|
||||
function showHitMarker()
|
||||
CreateThread(function()
|
||||
local startTime = GetGameTimer()
|
||||
|
||||
while GetGameTimer() - startTime < 500 do
|
||||
Wait(0)
|
||||
|
||||
-- Rotes X in der Mitte des Bildschirms
|
||||
DrawRect(0.5, 0.5, 0.02, 0.002, 255, 0, 0, 255) -- Horizontale Linie
|
||||
DrawRect(0.5, 0.5, 0.002, 0.02, 255, 0, 0, 255) -- Vertikale Linie
|
||||
|
||||
-- Text
|
||||
SetTextFont(4)
|
||||
SetTextProportional(1)
|
||||
SetTextScale(0.5, 0.5)
|
||||
SetTextColour(255, 0, 0, 255)
|
||||
SetTextEntry("STRING")
|
||||
AddTextComponentString("TREFFER!")
|
||||
SetTextCentre(true)
|
||||
DrawText(0.5, 0.45)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function openMainMenu()
|
||||
TriggerServerEvent('tdm:requestGamesList')
|
||||
|
||||
Wait(100) -- Kurz warten für Server Response
|
||||
Wait(100)
|
||||
|
||||
local options = {
|
||||
{
|
||||
|
@ -228,7 +311,6 @@ end
|
|||
function openCreateGameMenu()
|
||||
local fieldOptions = {}
|
||||
|
||||
-- Spielfelder zu Options hinzufügen
|
||||
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||
table.insert(fieldOptions, {
|
||||
value = fieldId,
|
||||
|
@ -273,7 +355,7 @@ function openCreateGameMenu()
|
|||
|
||||
local gameName = input[1]
|
||||
local fieldId = input[2]
|
||||
local gameType = input[3] -- 'public' oder 'private'
|
||||
local gameType = input[3]
|
||||
local password = input[4] and input[4] ~= '' and input[4] or nil
|
||||
|
||||
if gameName and fieldId and gameType then
|
||||
|
@ -348,7 +430,6 @@ function openJoinGameMenu()
|
|||
lib.showContext('tdm_join_menu')
|
||||
end
|
||||
|
||||
|
||||
-- Zone Checker Thread
|
||||
CreateThread(function()
|
||||
while true do
|
||||
|
@ -424,9 +505,19 @@ CreateThread(function()
|
|||
local ped = PlayerPedId()
|
||||
|
||||
if HasEntityBeenDamagedByAnyPed(ped) then
|
||||
local damager = GetPedSourceOfDeath(ped)
|
||||
local damagerPlayer = nil
|
||||
|
||||
for _, player in pairs(GetActivePlayers()) do
|
||||
if GetPlayerPed(player) == damager then
|
||||
damagerPlayer = GetPlayerServerId(player)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
ClearEntityLastDamageEntity(ped)
|
||||
TriggerEvent('tdm:playerHit')
|
||||
TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam)
|
||||
TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam, damagerPlayer)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,10 +28,10 @@ RegisterNetEvent('tdm:createGame', function(gameName, fieldId, gameType, passwor
|
|||
fieldId = fieldId,
|
||||
admin = src,
|
||||
adminName = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname,
|
||||
gameType = gameType, -- 'public' oder 'private'
|
||||
gameType = gameType,
|
||||
password = password,
|
||||
hasPassword = password ~= nil,
|
||||
status = 'waiting', -- waiting, active, finished
|
||||
status = 'waiting',
|
||||
team1 = {},
|
||||
team2 = {},
|
||||
score = {team1 = 0, team2 = 0},
|
||||
|
@ -43,10 +43,14 @@ RegisterNetEvent('tdm:createGame', function(gameName, fieldId, gameType, passwor
|
|||
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: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)
|
||||
|
@ -96,17 +100,14 @@ RegisterNetEvent('tdm:requestJoinGame', function(gameId, password)
|
|||
|
||||
-- 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]
|
||||
|
@ -124,7 +125,6 @@ end)
|
|||
RegisterNetEvent('tdm:leaveGame', function()
|
||||
local src = source
|
||||
|
||||
-- Spieler aus allen Spielen entfernen
|
||||
for gameId, game in pairs(activeGames) do
|
||||
removePlayerFromGame(src, gameId)
|
||||
end
|
||||
|
@ -132,29 +132,50 @@ RegisterNetEvent('tdm:leaveGame', function()
|
|||
TriggerClientEvent('tdm:leaveGame', src)
|
||||
end)
|
||||
|
||||
RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam)
|
||||
RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, shooterId)
|
||||
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
|
||||
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
|
||||
|
||||
-- Score Update an alle Spieler
|
||||
updateScoreForGame(gameId)
|
||||
|
||||
-- Prüfen ob Spiel gewonnen
|
||||
if game.score[scoringTeam] >= game.maxHits then
|
||||
endGame(gameId, scoringTeam)
|
||||
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)
|
||||
checkGameEnd(gameId)
|
||||
end)
|
||||
|
||||
-- Funktionen
|
||||
|
@ -167,20 +188,25 @@ function joinPlayerToGame(playerId, gameId)
|
|||
|
||||
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)
|
||||
|
||||
-- Spiel starten wenn genug Spieler
|
||||
checkGameStart(gameId)
|
||||
|
||||
updateGamesListForAll()
|
||||
updateScoreForGame(gameId)
|
||||
updateGamesListForAll()
|
||||
end
|
||||
|
||||
function removePlayerFromGame(playerId, gameId)
|
||||
local game = activeGames[gameId]
|
||||
if not game then return end
|
||||
|
||||
-- Aus Team 1 entfernen
|
||||
-- Spieler aus Teams entfernen
|
||||
for i, id in ipairs(game.team1) do
|
||||
if id == playerId then
|
||||
table.remove(game.team1, i)
|
||||
|
@ -188,7 +214,6 @@ function removePlayerFromGame(playerId, gameId)
|
|||
end
|
||||
end
|
||||
|
||||
-- Aus Team 2 entfernen
|
||||
for i, id in ipairs(game.team2) do
|
||||
if id == playerId then
|
||||
table.remove(game.team2, i)
|
||||
|
@ -206,90 +231,58 @@ function removePlayerFromGame(playerId, 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
|
||||
local allPlayers = {}
|
||||
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
|
||||
table.insert(allPlayers, playerId)
|
||||
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
|
||||
table.insert(allPlayers, playerId)
|
||||
end
|
||||
|
||||
-- Spiel nach 15 Sekunden löschen
|
||||
CreateThread(function()
|
||||
Wait(15000)
|
||||
-- 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
|
||||
function checkGameEnd(gameId)
|
||||
local game = activeGames[gameId]
|
||||
if not game then return end
|
||||
|
@ -299,7 +292,6 @@ function checkGameEnd(gameId)
|
|||
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
|
||||
|
@ -309,17 +301,20 @@ function updateScoreForGame(gameId)
|
|||
local game = activeGames[gameId]
|
||||
if not game then return end
|
||||
|
||||
-- Score an alle Spieler des Spiels senden
|
||||
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)
|
||||
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)
|
||||
TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2, gameStats)
|
||||
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)
|
||||
|
@ -330,7 +325,6 @@ end
|
|||
AddEventHandler('playerDropped', function()
|
||||
local src = source
|
||||
|
||||
-- Spieler aus allen Spielen entfernen
|
||||
for gameId, game in pairs(activeGames) do
|
||||
removePlayerFromGame(src, gameId)
|
||||
end
|
||||
|
@ -341,7 +335,29 @@ 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)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue