local QBCore = exports['qb-core']:GetCoreObject() local inTDM = false local currentTeam = nil local currentGameId = nil local currentField = nil local currentLobbyField = nil local tdmBlips = {} local teamZoneBlips = {} local isHit = false local activeGames = {} local spawnedNPCs = {} -- Spieler Statistiken local playerStats = { hits = 0, deaths = 0, gamesPlayed = 0 } -- Debug-Funktion für Konsole local function debugPrint(message) print("^2[TDM DEBUG]^7 " .. message) end -- Events RegisterNetEvent('tdm:updateGamesList', function(games) debugPrint("Spiele-Liste aktualisiert - Anzahl: " .. (games and #games or "0")) activeGames = games end) RegisterNetEvent('tdm:joinGame', function(gameId, team, fieldId) debugPrint("Join Game Event empfangen: GameID=" .. gameId .. ", Team=" .. team .. ", FieldID=" .. fieldId) currentGameId = gameId currentTeam = team currentField = fieldId inTDM = true isHit = false -- Stats zurücksetzen playerStats.hits = 0 playerStats.deaths = 0 playerStats.gamesPlayed = playerStats.gamesPlayed + 1 local fieldConfig = Config.gameFields[fieldId] if not fieldConfig then debugPrint("FEHLER: Feldkonfiguration nicht gefunden für ID " .. fieldId) return end -- Teleport zu Team Spawn local spawnPoints = fieldConfig.teamSpawns[team] if not spawnPoints or #spawnPoints == 0 then debugPrint("FEHLER: Keine Spawn-Punkte für Team " .. team) return end local randomSpawn = spawnPoints[math.random(#spawnPoints)] debugPrint("Teleportiere zu: " .. randomSpawn.x .. ", " .. randomSpawn.y .. ", " .. randomSpawn.z) SetEntityCoords(PlayerPedId(), randomSpawn.x, randomSpawn.y, randomSpawn.z) -- Team Maske setzen setTeamMask(team) -- Team Zone Blip erstellen createTeamZoneBlip(team, fieldConfig) lib.notify({ title = 'TeamDeathmatch', description = 'Du bist dem Spiel beigetreten! Team: ' .. team, type = 'success' }) debugPrint("Spiel beigetreten: " .. gameId .. ", Team: " .. team .. ", Feld: " .. fieldId) end) RegisterNetEvent('tdm:leaveGame', function() debugPrint("Leave Game Event empfangen") inTDM = false local previousField = currentField currentTeam = nil currentGameId = nil currentField = nil isHit = false -- Sichere Rückkehr zur Lobby local lobbyPos = nil -- Versuche zuerst die vorherige Feld-Lobby if previousField and Config.gameFields[previousField] and Config.gameFields[previousField].lobby then lobbyPos = Config.gameFields[previousField].lobby.pos debugPrint("Verwende vorherige Feld-Lobby für Teleport") -- Dann die aktuelle Lobby-Feld elseif currentLobbyField and Config.gameFields[currentLobbyField] and Config.gameFields[currentLobbyField].lobby then lobbyPos = Config.gameFields[currentLobbyField].lobby.pos debugPrint("Verwende aktuelle Lobby-Feld für Teleport") -- Fallback zur ersten verfügbaren Lobby else debugPrint("Suche nach verfügbarer Lobby für Teleport") for fieldId, fieldData in pairs(Config.gameFields) do if fieldData.lobby and fieldData.lobby.pos then lobbyPos = fieldData.lobby.pos debugPrint("Fallback-Lobby gefunden: " .. fieldId) break end end end -- Teleport zur Lobby (mit Fallback-Position) if lobbyPos then debugPrint("Teleportiere zur Lobby: " .. lobbyPos.x .. ", " .. lobbyPos.y .. ", " .. lobbyPos.z) SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z) else -- Notfall-Fallback Position debugPrint("WARNUNG: Keine Lobby gefunden, verwende Fallback-Position") SetEntityCoords(PlayerPedId(), -1042.4, -2745.8, 21.4) end -- Maske entfernen SetPedComponentVariation(PlayerPedId(), 1, 0, 0, 0) debugPrint("Maske entfernt") -- Zone Blips entfernen removeTeamZoneBlips() lib.hideTextUI() lib.notify({ title = 'TeamDeathmatch', description = 'Du hast das Spiel verlassen!', type = 'error' }) debugPrint("Spiel verlassen - Cleanup abgeschlossen") end) RegisterNetEvent('tdm:joinRequest', function(gameId, playerName, playerId) debugPrint("Join-Anfrage erhalten von: " .. playerName .. " (ID: " .. playerId .. ") für Spiel " .. gameId) local alert = lib.alertDialog({ header = 'Join Anfrage', content = playerName .. ' möchte deinem Spiel beitreten.\n\nErlauben?', centered = true, cancel = true, labels = { cancel = 'Ablehnen', confirm = 'Erlauben' } }) if alert == 'confirm' then debugPrint("Join-Anfrage von " .. playerName .. " akzeptiert") TriggerServerEvent('tdm:approveJoinRequest', gameId, playerId, true) else debugPrint("Join-Anfrage von " .. playerName .. " abgelehnt") TriggerServerEvent('tdm:approveJoinRequest', gameId, playerId, false) end end) RegisterNetEvent('tdm:joinRequestResult', function(approved, gameName) if approved then debugPrint("Join-Anfrage für Spiel '" .. gameName .. "' wurde akzeptiert") lib.notify({ title = 'TeamDeathmatch', description = 'Deine Anfrage wurde angenommen!', type = 'success' }) else debugPrint("Join-Anfrage für Spiel '" .. gameName .. "' wurde abgelehnt") lib.notify({ title = 'TeamDeathmatch', description = 'Deine Anfrage für "' .. gameName .. '" wurde abgelehnt!', type = 'error' }) end end) RegisterNetEvent('tdm:playerHit', function() if not inTDM then debugPrint("WARNUNG: Hit-Event empfangen, aber nicht im TDM!") return end if isHit then debugPrint("WARNUNG: Hit-Event empfangen, aber bereits getroffen!") return end debugPrint("Spieler wurde getroffen - Starte Respawn-Sequenz") isHit = true local ped = PlayerPedId() -- Benachrichtigung lib.notify({ title = 'TeamDeathmatch', description = 'Du wurdest getroffen! Respawn in 3 Sekunden...', type = 'error' }) -- Verbesserte Respawn-Logik SetTimeout(3000, function() if not inTDM then debugPrint("Respawn abgebrochen - nicht mehr im TDM") return end debugPrint("Respawn wird ausgeführt...") -- Respawn zum Team Spawn local fieldConfig = Config.gameFields[currentField] if not fieldConfig then debugPrint("FEHLER: Feldkonfiguration nicht gefunden für Respawn!") return end local spawnPoints = fieldConfig.teamSpawns[currentTeam] if not spawnPoints or #spawnPoints == 0 then debugPrint("FEHLER: Keine Spawn-Punkte gefunden für Respawn!") return end local randomSpawn = spawnPoints[math.random(#spawnPoints)] debugPrint("Respawn-Position: " .. randomSpawn.x .. ", " .. randomSpawn.y .. ", " .. randomSpawn.z) -- Teleport zum Spawn mit Fade DoScreenFadeOut(500) Wait(600) -- Stellen Sie sicher, dass der Spieler lebt NetworkResurrectLocalPlayer(randomSpawn.x, randomSpawn.y, randomSpawn.z, 0.0, true, false) debugPrint("Spieler wiederbelebt") -- Alle Animationen stoppen ClearPedTasksImmediately(ped) -- Teleport SetEntityCoords(ped, randomSpawn.x, randomSpawn.y, randomSpawn.z) SetEntityHealth(ped, GetEntityMaxHealth(ped)) -- Spieler ist wieder aktiv isHit = false debugPrint("Respawn abgeschlossen - Spieler ist wieder aktiv") Wait(100) DoScreenFadeIn(500) lib.notify({ title = 'TeamDeathmatch', description = 'Du bist wieder im Spiel!', type = 'success' }) end) end) RegisterNetEvent('tdm:updateScore', function(team1Score, team2Score, gameStats) debugPrint("Score Update empfangen: Team1=" .. team1Score .. ", Team2=" .. team2Score) if gameStats then debugPrint("GameStats: Hits=" .. (gameStats.hits or "nil") .. ", Deaths=" .. (gameStats.deaths or "nil")) end -- Verwende gameStats falls verfügbar, sonst lokale Stats local myHits = gameStats and gameStats.hits or playerStats.hits local myDeaths = gameStats and gameStats.deaths or playerStats.deaths local displayText = string.format( '[Team 1: %d] VS [Team 2: %d] | Deine Treffer: %d | Tode: %d', team1Score, team2Score, myHits, myDeaths ) lib.showTextUI(displayText, { position = "top-center", icon = 'crosshairs' }) end) RegisterNetEvent('tdm:hitRegistered', function() debugPrint("Treffer registriert! Aktualisiere lokale Stats") playerStats.hits = playerStats.hits + 1 lib.notify({ title = 'Treffer!', description = 'Du hast einen Gegner getroffen! (+1 Punkt)', type = 'success', duration = 2000 }) -- Spiele einen Sound ab PlaySoundFrontend(-1, "WEAPON_PURCHASE", "HUD_AMMO_SHOP_SOUNDSET", true) showHitMarker() -- Score sofort aktualisieren if currentGameId then debugPrint("Fordere Score-Update an für Spiel " .. currentGameId) TriggerServerEvent('tdm:requestScoreUpdate', currentGameId) end debugPrint("Treffer registriert! Neue Hits: " .. playerStats.hits) end) RegisterNetEvent('tdm:deathRegistered', function() debugPrint("Tod registriert! Aktualisiere lokale Stats") playerStats.deaths = playerStats.deaths + 1 -- Score sofort aktualisieren if currentGameId then debugPrint("Fordere Score-Update an für Spiel " .. currentGameId) TriggerServerEvent('tdm:requestScoreUpdate', currentGameId) end debugPrint("Tod registriert! Neue Deaths: " .. playerStats.deaths) end) RegisterNetEvent('tdm:gameEnded', function(winnerTeam, team1Score, team2Score) debugPrint("Spiel beendet! Gewinner: " .. (winnerTeam or "Unentschieden")) 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 = statsText, centered = true, cancel = false }) Wait(5000) debugPrint("Verlasse Spiel nach Ende") TriggerServerEvent('tdm:leaveGame') end) -- Funktionen function setTeamMask(team) local ped = PlayerPedId() local maskData = Config.teamMasks[team] if maskData then -- Geschlecht des Spielers ermitteln local playerGender = GetEntityModel(ped) == GetHashKey("mp_f_freemode_01") and "female" or "male" -- Entsprechende Maske setzen local genderMask = maskData[playerGender] if genderMask then SetPedComponentVariation(ped, genderMask.component, genderMask.drawable, genderMask.texture, 0) debugPrint("Maske gesetzt: " .. team .. " (" .. playerGender .. ")") else debugPrint("Keine Maske für " .. team .. " (" .. playerGender .. ") gefunden!") end else debugPrint("Keine Masken-Daten für Team " .. team .. " gefunden!") end end function createTeamZoneBlip(team, fieldConfig) local zone = fieldConfig.teamZones[team] local blip = AddBlipForRadius(zone.center.x, zone.center.y, zone.center.z, zone.radius) SetBlipHighDetail(blip, true) SetBlipColour(blip, team == 'team1' and 1 or 3) SetBlipAlpha(blip, 128) teamZoneBlips[team] = blip debugPrint("Team Zone Blip erstellt für " .. team) end function removeTeamZoneBlips() for team, blip in pairs(teamZoneBlips) do if DoesBlipExist(blip) then RemoveBlip(blip) end end teamZoneBlips = {} debugPrint("Team Zone Blips entfernt") end function highlightTeamZone(team) if teamZoneBlips[team] and DoesBlipExist(teamZoneBlips[team]) then SetBlipFlashes(teamZoneBlips[team], true) end end function showHitMarker() debugPrint("Zeige Hit-Marker an") CreateThread(function() local startTime = GetGameTimer() local duration = 500 -- 500ms display while GetGameTimer() - startTime < duration do Wait(0) -- Draw hit marker DrawRect(0.5, 0.5, 0.02, 0.002, 255, 0, 0, 255) DrawRect(0.5, 0.5, 0.002, 0.02, 255, 0, 0, 255) -- Draw hit 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 debugPrint("Hit-Marker ausgeblendet") end) end function openMainMenu(fieldId) -- Sicherheitscheck if not fieldId or not Config.gameFields[fieldId] then debugPrint("FEHLER: Ungültiges Spielfeld für Menü: " .. tostring(fieldId)) lib.notify({ title = 'Fehler', description = 'Ungültiges Spielfeld!', type = 'error' }) return end debugPrint("Öffne Hauptmenü für Feld: " .. fieldId) currentLobbyField = fieldId TriggerServerEvent('tdm:requestGamesList') Wait(100) local fieldName = Config.gameFields[fieldId].name local options = { { title = 'Neues Spiel erstellen', description = 'Erstelle ein neues Spiel für ' .. fieldName, icon = 'plus', onSelect = function() debugPrint("Öffne Menü zum Erstellen eines neuen Spiels") openCreateGameMenu(fieldId) end }, { title = 'Spiel beitreten', description = 'Trete einem laufenden Spiel bei', icon = 'users', onSelect = function() debugPrint("Öffne Menü zum Beitreten eines Spiels") openJoinGameMenu(fieldId) end } } if inTDM then table.insert(options, { title = 'Aktuelles Spiel verlassen', description = 'Verlasse das laufende Spiel', icon = 'door-open', iconColor = 'red', onSelect = function() debugPrint("Verlasse aktuelles Spiel über Menü") TriggerServerEvent('tdm:leaveGame') end }) end lib.registerContext({ id = 'tdm_main_menu_' .. fieldId, title = 'TeamDeathmatch - ' .. fieldName, options = options }) lib.showContext('tdm_main_menu_' .. fieldId) end function openCreateGameMenu(fieldId) if not fieldId or not Config.gameFields[fieldId] then debugPrint("FEHLER: Ungültiges Spielfeld für Erstellungsmenü: " .. tostring(fieldId)) lib.notify({ title = 'Fehler', description = 'Ungültiges Spielfeld!', type = 'error' }) return end debugPrint("Öffne Spiel-Erstellungsmenü für Feld: " .. fieldId) local fieldData = Config.gameFields[fieldId] local input = lib.inputDialog('Neues Spiel erstellen - ' .. fieldData.name, { { type = 'input', label = 'Spiel Name', description = 'Gib deinem Spiel einen Namen', required = true, max = 30 }, { type = 'select', label = 'Spiel Typ', description = 'Wähle den Spiel Typ', required = true, options = { {value = 'public', label = 'Öffentlich (Jeder kann beitreten)'}, {value = 'private', label = 'Privat (Nur mit Genehmigung)'} } }, { type = 'input', label = 'Passwort (Optional)', description = 'Passwort für das Spiel (leer lassen für kein Passwort)', password = true } }) if not input then debugPrint("Spiel-Erstellung abgebrochen") return end local gameName = input[1] local gameType = input[2] local password = input[3] and input[3] ~= '' and input[3] or nil if gameName and gameType then debugPrint("Erstelle Spiel: " .. gameName .. " (Typ: " .. gameType .. ", Passwort: " .. (password and "Ja" or "Nein") .. ")") TriggerServerEvent('tdm:createGame', gameName, fieldId, gameType, password) end end function openJoinGameMenu(fieldId) if not fieldId or not Config.gameFields[fieldId] then debugPrint("FEHLER: Ungültiges Spielfeld für Join-Menü: " .. tostring(fieldId)) lib.notify({ title = 'Fehler', description = 'Ungültiges Spielfeld!', type = 'error' }) return end debugPrint("Öffne Spiel-Beitrittsmenü für Feld: " .. fieldId) TriggerServerEvent('tdm:requestGamesList') Wait(200) local options = {} local fieldName = Config.gameFields[fieldId].name -- Nur Spiele für dieses Feld anzeigen local gamesCount = 0 for gameId, gameData in pairs(activeGames) do if gameData.fieldId == fieldId then gamesCount = gamesCount + 1 local playerCount = #gameData.team1 + #gameData.team2 local maxPlayers = Config.gameFields[gameData.fieldId].maxPlayers local statusText = gameData.status == 'waiting' and 'Wartend' or 'Läuft' local typeText = gameData.gameType == 'public' and '🌐 Öffentlich' or '🔒 Privat' local passwordIcon = gameData.hasPassword and ' 🔑' or '' table.insert(options, { title = gameData.name .. passwordIcon, description = typeText .. ' | Spieler: ' .. playerCount .. '/' .. maxPlayers .. ' | Status: ' .. statusText, icon = gameData.gameType == 'public' and 'globe' or 'lock', iconColor = gameData.gameType == 'public' and 'green' or 'orange', args = { gameId = gameId, hasPassword = gameData.hasPassword, gameType = gameData.gameType }, onSelect = function(args) debugPrint("Versuche Spiel beizutreten: " .. gameId) if args.hasPassword then debugPrint("Spiel erfordert Passwort") local input = lib.inputDialog('Passwort eingeben', { { type = 'input', label = 'Passwort', description = 'Gib das Spiel-Passwort ein', required = true, password = true } }) if input and input[1] then debugPrint("Passwort eingegeben, sende Beitrittsanfrage") TriggerServerEvent('tdm:requestJoinGame', args.gameId, input[1]) else debugPrint("Passwort-Eingabe abgebrochen") end else debugPrint("Kein Passwort erforderlich, sende Beitrittsanfrage") TriggerServerEvent('tdm:requestJoinGame', args.gameId) end end }) end end debugPrint("Gefundene Spiele für Feld " .. fieldId .. ": " .. gamesCount) if #options == 0 then table.insert(options, { title = 'Keine Spiele verfügbar', description = 'Erstelle ein neues Spiel für ' .. fieldName, icon = 'info', disabled = true }) end lib.registerContext({ id = 'tdm_join_menu_' .. fieldId, title = 'Spiel beitreten - ' .. fieldName, menu = 'tdm_main_menu_' .. fieldId, options = options }) lib.showContext('tdm_join_menu_' .. fieldId) end -- Zone Marker Renderer CreateThread(function() while true do Wait(0) if inTDM and currentTeam and currentField then local zone = Config.gameFields[currentField].teamZones[currentTeam] local color = zone.color DrawMarker( 1, zone.center.x, zone.center.y, zone.center.z - 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, zone.radius * 2, zone.radius * 2, 1.0, color.r, color.g, color.b, color.a, false, true, 2, false, nil, nil, false ) if isHit then DrawMarker( 2, zone.center.x, zone.center.y, zone.center.z + 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 255, 255, 0, 200, true, true, 2, false, nil, nil, false ) end else Wait(1000) end end end) -- Verbesserte Damage Handler CreateThread(function() while true do if inTDM and not isHit then local ped = PlayerPedId() if HasEntityBeenDamagedByAnyPed(ped) then debugPrint("Schaden erkannt - Identifiziere Angreifer") local damager = nil local damagerPlayer = nil -- Versuche den Angreifer zu identifizieren for _, player in ipairs(GetActivePlayers()) do local playerPed = GetPlayerPed(player) if HasPedBeenDamagedBy(ped, playerPed) then damager = playerPed damagerPlayer = GetPlayerServerId(player) debugPrint("Angreifer identifiziert: " .. damagerPlayer) break end end -- Schaden zurücksetzen ClearEntityLastDamageEntity(ped) ClearPedLastWeaponDamage(ped) SetEntityHealth(ped, GetEntityMaxHealth(ped)) -- Lokale Stats sofort updaten playerStats.deaths = playerStats.deaths + 1 debugPrint("Getroffen von: " .. (damagerPlayer or "Unbekannt")) TriggerEvent('tdm:playerHit') TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam, damagerPlayer) -- Warten um mehrfache Auslösung zu verhindern Wait(500) end Wait(0) else Wait(500) end end end) -- Death Handler CreateThread(function() while true do Wait(1000) if inTDM then local ped = PlayerPedId() if IsEntityDead(ped) then debugPrint("Spieler ist tot!") TriggerServerEvent('tdm:playerDied', currentGameId) lib.notify({ title = 'TeamDeathmatch', description = 'Du bist ausgeschieden!', type = 'error' }) Wait(3000) TriggerServerEvent('tdm:leaveGame') end end end end) -- NPC Setup für alle Felder CreateThread(function() -- Für jedes Spielfeld Blip und NPC erstellen for fieldId, fieldData in pairs(Config.gameFields) do if fieldData.lobby and fieldData.lobby.pos and fieldData.lobby.npc then local lobbyPos = fieldData.lobby.pos local npcData = fieldData.lobby.npc debugPrint("Erstelle Blip und NPC für Feld " .. fieldId) -- Blip erstellen local blip = AddBlipForCoord(lobbyPos.x, lobbyPos.y, lobbyPos.z) SetBlipSprite(blip, 432) SetBlipDisplay(blip, 4) SetBlipScale(blip, 0.8) SetBlipColour(blip, 1) SetBlipAsShortRange(blip, true) BeginTextCommandSetBlipName("STRING") AddTextComponentString("TDM - " .. fieldData.name) EndTextCommandSetBlipName(blip) tdmBlips[fieldId] = blip -- NPC erstellen RequestModel(GetHashKey(npcData.model)) while not HasModel -- NPC erstellen RequestModel(GetHashKey(npcData.model)) while not HasModelLoaded(GetHashKey(npcData.model)) do Wait(1) end debugPrint("NPC-Modell geladen für " .. fieldId) local npc = CreatePed(4, GetHashKey(npcData.model), npcData.coords.x, npcData.coords.y, npcData.coords.z, npcData.coords.w, false, true) SetEntityInvincible(npc, true) FreezeEntityPosition(npc, true) SetBlockingOfNonTemporaryEvents(npc, true) spawnedNPCs[fieldId] = npc -- Target für diesen NPC exports['qb-target']:AddTargetEntity(npc, { options = { { type = "client", event = "tdm:openFieldMenu", icon = "fas fa-crosshairs", label = "TeamDeathmatch - " .. fieldData.name, fieldId = fieldId }, }, distance = 2.5 }) debugPrint("NPC und Blip für Feld " .. fieldId .. " erstellt") else debugPrint("WARNUNG: Feld " .. fieldId .. " hat keine vollständige Lobby-Konfiguration!") end end end) -- Event für Feld-spezifisches Menü RegisterNetEvent('tdm:openFieldMenu', function(data) if data and data.fieldId then debugPrint("Öffne Feldmenü für: " .. data.fieldId) openMainMenu(data.fieldId) else debugPrint("FEHLER: Keine Feld-ID übertragen!") lib.notify({ title = 'Fehler', description = 'Keine Feld-ID übertragen!', type = 'error' }) end end) -- Chat Command zum Spiel verlassen RegisterCommand('leavetdm', function() if inTDM then debugPrint("Verlasse Spiel über Command") TriggerServerEvent('tdm:leaveGame') lib.notify({ title = 'TeamDeathmatch', description = 'Du hast das Spiel über Command verlassen!', type = 'info' }) else debugPrint("Command 'leavetdm' ausgeführt, aber nicht in einem Spiel") lib.notify({ title = 'TeamDeathmatch', description = 'Du bist in keinem Spiel!', type = 'error' }) end end, false) -- Keybind zum Spiel verlassen RegisterKeyMapping('leavetdm', 'TeamDeathmatch verlassen', 'keyboard', 'F7') -- Debug Command zum Testen der Config RegisterCommand('debugtdm', function() debugPrint("Aktuelle Werte:") debugPrint("inTDM: " .. tostring(inTDM)) debugPrint("currentField: " .. tostring(currentField)) debugPrint("currentLobbyField: " .. tostring(currentLobbyField)) debugPrint("currentTeam: " .. tostring(currentTeam)) debugPrint("currentGameId: " .. tostring(currentGameId)) debugPrint("isHit: " .. tostring(isHit)) debugPrint("Hits: " .. playerStats.hits) debugPrint("Deaths: " .. playerStats.deaths) debugPrint("Verfügbare Felder:") for fieldId, fieldData in pairs(Config.gameFields) do local hasLobby = fieldData.lobby and fieldData.lobby.pos and "✅" or "❌" debugPrint("- " .. fieldId .. ": " .. fieldData.name .. " " .. hasLobby) end lib.notify({ title = 'Debug Info', description = 'Debug-Informationen wurden in die Konsole geschrieben', type = 'info' }) end, false) -- Debug Commands für Masken RegisterCommand('testmask', function(source, args) if not args[1] or not args[2] then debugPrint("Ungültige Parameter für testmask") lib.notify({ title = 'Debug', description = 'Verwendung: /testmask [team1/team2] [male/female]', type = 'error' }) return end local team = args[1] local gender = args[2] debugPrint("Teste Maske: Team=" .. team .. ", Gender=" .. gender) if Config.teamMasks[team] and Config.teamMasks[team][gender] then local maskData = Config.teamMasks[team][gender] local ped = PlayerPedId() SetPedComponentVariation(ped, maskData.component, maskData.drawable, maskData.texture, 0) debugPrint("Maske gesetzt: " .. team .. " (" .. gender .. ")") lib.notify({ title = 'Debug', description = 'Maske gesetzt: ' .. team .. ' (' .. gender .. ')', type = 'success' }) else debugPrint("Maske nicht gefunden: " .. team .. " (" .. gender .. ")") lib.notify({ title = 'Debug', description = 'Maske nicht gefunden!', type = 'error' }) end end, false) -- Command zum Entfernen der Maske RegisterCommand('removemask', function() SetPedComponentVariation(PlayerPedId(), 1, 0, 0, 0) debugPrint("Maske entfernt") lib.notify({ title = 'Debug', description = 'Maske entfernt!', type = 'info' }) end, false) -- Debug-Funktion für Respawn RegisterCommand('forcetdmrespawn', function() if inTDM and currentTeam and currentField then debugPrint("Manueller Respawn ausgelöst") local ped = PlayerPedId() local fieldConfig = Config.gameFields[currentField] local spawnPoints = fieldConfig.teamSpawns[currentTeam] local randomSpawn = spawnPoints[math.random(#spawnPoints)] DoScreenFadeOut(500) Wait(600) ClearPedTasksImmediately(ped) NetworkResurrectLocalPlayer(randomSpawn.x, randomSpawn.y, randomSpawn.z, 0.0, true, false) SetEntityCoords(ped, randomSpawn.x, randomSpawn.y, randomSpawn.z) SetEntityHealth(ped, GetEntityMaxHealth(ped)) isHit = false Wait(100) DoScreenFadeIn(500) debugPrint("Manueller Respawn abgeschlossen") lib.notify({ title = 'Debug', description = 'Manueller Respawn durchgeführt!', type = 'success' }) else debugPrint("Manueller Respawn fehlgeschlagen - nicht in einem TDM-Spiel") lib.notify({ title = 'Debug', description = 'Du bist nicht in einem TDM-Spiel!', type = 'error' }) end end, false) -- Debug-Funktion für Stats RegisterCommand('showstats', function() if inTDM then debugPrint("Lokale Stats:") debugPrint("Hits: " .. playerStats.hits) debugPrint("Deaths: " .. playerStats.deaths) if currentGameId then TriggerServerEvent('tdm:debugPlayerStats', currentGameId) end lib.notify({ title = 'Debug', description = 'Lokale Stats - Hits: ' .. playerStats.hits .. ', Deaths: ' .. playerStats.deaths, type = 'info' }) else debugPrint("Stats-Anzeige fehlgeschlagen - nicht in einem TDM-Spiel") lib.notify({ title = 'Debug', description = 'Du bist nicht in einem TDM-Spiel!', type = 'error' }) end end, false) -- Debug-Funktion für manuellen Hit RegisterCommand('testhit', function() if inTDM then debugPrint("Test-Hit ausgelöst") TriggerEvent('tdm:playerHit') lib.notify({ title = 'Debug', description = 'Test-Hit ausgelöst!', type = 'info' }) else debugPrint("Test-Hit fehlgeschlagen - nicht in einem TDM-Spiel") lib.notify({ title = 'Debug', description = 'Du bist nicht in einem TDM-Spiel!', type = 'error' }) end end, false) -- Debug-Funktion für manuellen Treffer RegisterCommand('testtreff', function() if inTDM then debugPrint("Test-Treffer ausgelöst") TriggerEvent('tdm:hitRegistered') lib.notify({ title = 'Debug', description = 'Test-Treffer registriert!', type = 'info' }) else debugPrint("Test-Treffer fehlgeschlagen - nicht in einem TDM-Spiel") lib.notify({ title = 'Debug', description = 'Du bist nicht in einem TDM-Spiel!', type = 'error' }) end end, false) -- Neuer Debug-Command für Damage-Test RegisterCommand('tdmtesthit', function() if inTDM then debugPrint("Sende Test-Hit zum Server") local targetTeam = currentTeam == 'team1' and 'team2' or 'team1' TriggerServerEvent('tdm:playerWasHit', currentGameId, targetTeam, GetPlayerServerId(PlayerId())) lib.notify({ title = 'Debug', description = 'Test-Hit zum Server gesendet', type = 'info' }) else debugPrint("Server-Hit-Test fehlgeschlagen - nicht in einem TDM-Spiel") lib.notify({ title = 'Debug', description = 'Du musst in einem TDM-Spiel sein!', type = 'error' }) end end, false) -- Neuer Event-Handler für Waffen-Schaden AddEventHandler('gameEventTriggered', function(name, args) if name == "CEventNetworkEntityDamage" then local victimId = args[1] local attackerId = args[2] local isDead = args[4] == 1 local weaponHash = args[5] local isMelee = args[10] == 1 if inTDM and not isHit and victimId == PlayerPedId() then local attackerServerId = nil -- Versuche den Angreifer zu identifizieren for _, player in ipairs(GetActivePlayers()) do if GetPlayerPed(player) == attackerId then attackerServerId = GetPlayerServerId(player) break end end debugPrint("Schaden-Event erkannt: Angreifer=" .. (attackerServerId or "NPC/Unbekannt") .. ", Waffe=" .. weaponHash) if attackerServerId then -- Lokale Stats sofort updaten playerStats.deaths = playerStats.deaths + 1 TriggerEvent('tdm:playerHit') TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam, attackerServerId) end end end end)