forked from Simnation/Main
Update client.lua
This commit is contained in:
parent
79e5103db6
commit
123e2c98c3
1 changed files with 216 additions and 112 deletions
|
@ -3,12 +3,12 @@ local inTDM = false
|
||||||
local currentTeam = nil
|
local currentTeam = nil
|
||||||
local currentGameId = nil
|
local currentGameId = nil
|
||||||
local currentField = nil
|
local currentField = nil
|
||||||
local currentLobbyField = nil -- Neue Variable für aktuelle Lobby
|
local currentLobbyField = nil
|
||||||
local tdmBlips = {} -- Mehrere Blips
|
local tdmBlips = {}
|
||||||
local teamZoneBlips = {}
|
local teamZoneBlips = {}
|
||||||
local isHit = false
|
local isHit = false
|
||||||
local activeGames = {}
|
local activeGames = {}
|
||||||
local spawnedNPCs = {} -- Gespawnte NPCs verwalten
|
local spawnedNPCs = {}
|
||||||
|
|
||||||
-- Spieler Statistiken
|
-- Spieler Statistiken
|
||||||
local playerStats = {
|
local playerStats = {
|
||||||
|
@ -17,7 +17,7 @@ local playerStats = {
|
||||||
gamesPlayed = 0
|
gamesPlayed = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Events (gleich wie vorher, nur leaveGame angepasst)
|
-- Events
|
||||||
RegisterNetEvent('tdm:updateGamesList', function(games)
|
RegisterNetEvent('tdm:updateGamesList', function(games)
|
||||||
activeGames = games
|
activeGames = games
|
||||||
end)
|
end)
|
||||||
|
@ -63,21 +63,32 @@ RegisterNetEvent('tdm:leaveGame', function()
|
||||||
currentField = nil
|
currentField = nil
|
||||||
isHit = false
|
isHit = false
|
||||||
|
|
||||||
-- Zurück zur entsprechenden Lobby (falls vorher in einem Spiel)
|
-- Sichere Rückkehr zur Lobby
|
||||||
if previousField and Config.gameFields[previousField] then
|
local lobbyPos = nil
|
||||||
local lobbyPos = Config.gameFields[previousField].lobby.pos
|
|
||||||
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
-- Versuche zuerst die vorherige Feld-Lobby
|
||||||
elseif currentLobbyField and Config.gameFields[currentLobbyField] then
|
if previousField and Config.gameFields[previousField] and Config.gameFields[previousField].lobby then
|
||||||
-- Zurück zur aktuellen Lobby
|
lobbyPos = Config.gameFields[previousField].lobby.pos
|
||||||
local lobbyPos = Config.gameFields[currentLobbyField].lobby.pos
|
-- Dann die aktuelle Lobby-Feld
|
||||||
|
elseif currentLobbyField and Config.gameFields[currentLobbyField] and Config.gameFields[currentLobbyField].lobby then
|
||||||
|
lobbyPos = Config.gameFields[currentLobbyField].lobby.pos
|
||||||
|
-- Fallback zur ersten verfügbaren Lobby
|
||||||
|
else
|
||||||
|
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||||
|
if fieldData.lobby and fieldData.lobby.pos then
|
||||||
|
lobbyPos = fieldData.lobby.pos
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Teleport zur Lobby (mit Fallback-Position)
|
||||||
|
if lobbyPos then
|
||||||
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
||||||
else
|
else
|
||||||
-- Fallback zur ersten Lobby
|
-- Notfall-Fallback Position (anpassen an deine Map)
|
||||||
local firstField = next(Config.gameFields)
|
SetEntityCoords(PlayerPedId(), -1042.4, -2745.8, 21.4)
|
||||||
if firstField then
|
print("^3[TDM WARNING]^7 Keine Lobby gefunden, Fallback-Position verwendet!")
|
||||||
local lobbyPos = Config.gameFields[firstField].lobby.pos
|
|
||||||
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Maske entfernen
|
-- Maske entfernen
|
||||||
|
@ -95,7 +106,6 @@ RegisterNetEvent('tdm:leaveGame', function()
|
||||||
})
|
})
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Alle anderen Events bleiben gleich...
|
|
||||||
RegisterNetEvent('tdm:joinRequest', function(gameId, playerName, playerId)
|
RegisterNetEvent('tdm:joinRequest', function(gameId, playerName, playerId)
|
||||||
local alert = lib.alertDialog({
|
local alert = lib.alertDialog({
|
||||||
header = 'Join Anfrage',
|
header = 'Join Anfrage',
|
||||||
|
@ -219,7 +229,7 @@ RegisterNetEvent('tdm:gameEnded', function(winnerTeam, team1Score, team2Score)
|
||||||
TriggerServerEvent('tdm:leaveGame')
|
TriggerServerEvent('tdm:leaveGame')
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Angepasste setTeamMask Funktion
|
-- Funktionen
|
||||||
function setTeamMask(team)
|
function setTeamMask(team)
|
||||||
local ped = PlayerPedId()
|
local ped = PlayerPedId()
|
||||||
local maskData = Config.teamMasks[team]
|
local maskData = Config.teamMasks[team]
|
||||||
|
@ -236,64 +246,66 @@ function setTeamMask(team)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Alternative Methode über QBCore Player Data
|
function createTeamZoneBlip(team, fieldConfig)
|
||||||
function setTeamMaskQB(team)
|
local zone = fieldConfig.teamZones[team]
|
||||||
local ped = PlayerPedId()
|
|
||||||
local Player = QBCore.Functions.GetPlayerData()
|
|
||||||
local maskData = Config.teamMasks[team]
|
|
||||||
|
|
||||||
if maskData and Player.charinfo then
|
local blip = AddBlipForRadius(zone.center.x, zone.center.y, zone.center.z, zone.radius)
|
||||||
-- Geschlecht aus QBCore Charinfo
|
SetBlipHighDetail(blip, true)
|
||||||
local playerGender = Player.charinfo.gender == 1 and "female" or "male"
|
SetBlipColour(blip, team == 'team1' and 1 or 3)
|
||||||
|
SetBlipAlpha(blip, 128)
|
||||||
|
|
||||||
-- Entsprechende Maske setzen
|
teamZoneBlips[team] = blip
|
||||||
local genderMask = maskData[playerGender]
|
end
|
||||||
if genderMask then
|
|
||||||
SetPedComponentVariation(ped, genderMask.component, genderMask.drawable, genderMask.texture, 0)
|
function removeTeamZoneBlips()
|
||||||
|
for team, blip in pairs(teamZoneBlips) do
|
||||||
|
if DoesBlipExist(blip) then
|
||||||
|
RemoveBlip(blip)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
teamZoneBlips = {}
|
||||||
|
end
|
||||||
|
|
||||||
|
function highlightTeamZone(team)
|
||||||
|
if teamZoneBlips[team] and DoesBlipExist(teamZoneBlips[team]) then
|
||||||
|
SetBlipFlashes(teamZoneBlips[team], true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Erweiterte Funktion mit Fallback
|
function showHitMarker()
|
||||||
function setTeamMaskAdvanced(team)
|
CreateThread(function()
|
||||||
local ped = PlayerPedId()
|
local startTime = GetGameTimer()
|
||||||
local maskData = Config.teamMasks[team]
|
|
||||||
|
|
||||||
if not maskData then return end
|
while GetGameTimer() - startTime < 500 do
|
||||||
|
Wait(0)
|
||||||
|
|
||||||
local playerGender = "male" -- Default
|
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)
|
||||||
|
|
||||||
-- Methode 1: Über Ped Model
|
SetTextFont(4)
|
||||||
if GetEntityModel(ped) == GetHashKey("mp_f_freemode_01") then
|
SetTextProportional(1)
|
||||||
playerGender = "female"
|
SetTextScale(0.5, 0.5)
|
||||||
end
|
SetTextColour(255, 0, 0, 255)
|
||||||
|
SetTextEntry("STRING")
|
||||||
-- Methode 2: Über QBCore (Fallback)
|
AddTextComponentString("TREFFER!")
|
||||||
if playerGender == "male" then
|
SetTextCentre(true)
|
||||||
local Player = QBCore.Functions.GetPlayerData()
|
DrawText(0.5, 0.45)
|
||||||
if Player.charinfo and Player.charinfo.gender == 1 then
|
|
||||||
playerGender = "female"
|
|
||||||
end
|
end
|
||||||
end
|
end)
|
||||||
|
|
||||||
-- Maske setzen
|
|
||||||
local genderMask = maskData[playerGender]
|
|
||||||
if genderMask then
|
|
||||||
SetPedComponentVariation(ped, genderMask.component, genderMask.drawable, genderMask.texture, 0)
|
|
||||||
|
|
||||||
lib.notify({
|
|
||||||
title = 'TeamDeathmatch',
|
|
||||||
description = 'Team-Maske (' .. playerGender .. ') angelegt!',
|
|
||||||
type = 'info',
|
|
||||||
duration = 2000
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
-- Angepasste Menü-Funktionen
|
|
||||||
function openMainMenu(fieldId)
|
function openMainMenu(fieldId)
|
||||||
currentLobbyField = fieldId -- Aktuelle Lobby merken
|
-- Sicherheitscheck
|
||||||
|
if not fieldId or not Config.gameFields[fieldId] then
|
||||||
|
lib.notify({
|
||||||
|
title = 'Fehler',
|
||||||
|
description = 'Ungültiges Spielfeld!',
|
||||||
|
type = 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
currentLobbyField = fieldId
|
||||||
TriggerServerEvent('tdm:requestGamesList')
|
TriggerServerEvent('tdm:requestGamesList')
|
||||||
|
|
||||||
Wait(100)
|
Wait(100)
|
||||||
|
@ -341,6 +353,15 @@ function openMainMenu(fieldId)
|
||||||
end
|
end
|
||||||
|
|
||||||
function openCreateGameMenu(fieldId)
|
function openCreateGameMenu(fieldId)
|
||||||
|
if not fieldId or not Config.gameFields[fieldId] then
|
||||||
|
lib.notify({
|
||||||
|
title = 'Fehler',
|
||||||
|
description = 'Ungültiges Spielfeld!',
|
||||||
|
type = 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local fieldData = Config.gameFields[fieldId]
|
local fieldData = Config.gameFields[fieldId]
|
||||||
|
|
||||||
local input = lib.inputDialog('Neues Spiel erstellen - ' .. fieldData.name, {
|
local input = lib.inputDialog('Neues Spiel erstellen - ' .. fieldData.name, {
|
||||||
|
@ -381,6 +402,15 @@ function openCreateGameMenu(fieldId)
|
||||||
end
|
end
|
||||||
|
|
||||||
function openJoinGameMenu(fieldId)
|
function openJoinGameMenu(fieldId)
|
||||||
|
if not fieldId or not Config.gameFields[fieldId] then
|
||||||
|
lib.notify({
|
||||||
|
title = 'Fehler',
|
||||||
|
description = 'Ungültiges Spielfeld!',
|
||||||
|
type = 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
TriggerServerEvent('tdm:requestGamesList')
|
TriggerServerEvent('tdm:requestGamesList')
|
||||||
|
|
||||||
Wait(200)
|
Wait(200)
|
||||||
|
@ -450,7 +480,7 @@ function openJoinGameMenu(fieldId)
|
||||||
lib.showContext('tdm_join_menu_' .. fieldId)
|
lib.showContext('tdm_join_menu_' .. fieldId)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Alle Threads bleiben gleich...
|
-- Zone Checker Thread
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
while true do
|
while true do
|
||||||
Wait(500)
|
Wait(500)
|
||||||
|
@ -480,6 +510,7 @@ CreateThread(function()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Zone Marker Renderer
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
while true do
|
while true do
|
||||||
Wait(0)
|
Wait(0)
|
||||||
|
@ -515,6 +546,7 @@ CreateThread(function()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Damage Handler
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
while true do
|
while true do
|
||||||
Wait(100)
|
Wait(100)
|
||||||
|
@ -541,6 +573,7 @@ CreateThread(function()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Death Handler
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
while true do
|
while true do
|
||||||
Wait(1000)
|
Wait(1000)
|
||||||
|
@ -564,58 +597,70 @@ CreateThread(function()
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Angepasstes NPC Setup für alle Felder
|
-- NPC Setup für alle Felder
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
-- Für jedes Spielfeld Blip und NPC erstellen
|
-- Für jedes Spielfeld Blip und NPC erstellen
|
||||||
for fieldId, fieldData in pairs(Config.gameFields) do
|
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||||
local lobbyPos = fieldData.lobby.pos
|
if fieldData.lobby and fieldData.lobby.pos and fieldData.lobby.npc then
|
||||||
local npcData = fieldData.lobby.npc
|
local lobbyPos = fieldData.lobby.pos
|
||||||
|
local npcData = fieldData.lobby.npc
|
||||||
|
|
||||||
-- Blip erstellen
|
-- Blip erstellen
|
||||||
local blip = AddBlipForCoord(lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
local blip = AddBlipForCoord(lobbyPos.x, lobbyPos.y, lobbyPos.z)
|
||||||
SetBlipSprite(blip, 432)
|
SetBlipSprite(blip, 432)
|
||||||
SetBlipDisplay(blip, 4)
|
SetBlipDisplay(blip, 4)
|
||||||
SetBlipScale(blip, 0.8)
|
SetBlipScale(blip, 0.8)
|
||||||
SetBlipColour(blip, 1)
|
SetBlipColour(blip, 1)
|
||||||
SetBlipAsShortRange(blip, true)
|
SetBlipAsShortRange(blip, true)
|
||||||
BeginTextCommandSetBlipName("STRING")
|
BeginTextCommandSetBlipName("STRING")
|
||||||
AddTextComponentString("TDM - " .. fieldData.name)
|
AddTextComponentString("TDM - " .. fieldData.name)
|
||||||
EndTextCommandSetBlipName(blip)
|
EndTextCommandSetBlipName(blip)
|
||||||
|
|
||||||
tdmBlips[fieldId] = blip
|
tdmBlips[fieldId] = blip
|
||||||
|
|
||||||
-- NPC erstellen
|
-- NPC erstellen
|
||||||
RequestModel(GetHashKey(npcData.model))
|
RequestModel(GetHashKey(npcData.model))
|
||||||
while not HasModelLoaded(GetHashKey(npcData.model)) do
|
while not HasModelLoaded(GetHashKey(npcData.model)) do
|
||||||
Wait(1)
|
Wait(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
local npc = CreatePed(4, GetHashKey(npcData.model), npcData.coords.x, npcData.coords.y, npcData.coords.z, npcData.coords.w, false, true)
|
local npc = CreatePed(4, GetHashKey(npcData.model), npcData.coords.x, npcData.coords.y, npcData.coords.z, npcData.coords.w, false, true)
|
||||||
SetEntityInvincible(npc, true)
|
SetEntityInvincible(npc, true)
|
||||||
FreezeEntityPosition(npc, true)
|
FreezeEntityPosition(npc, true)
|
||||||
SetBlockingOfNonTemporaryEvents(npc, true)
|
SetBlockingOfNonTemporaryEvents(npc, true)
|
||||||
|
|
||||||
spawnedNPCs[fieldId] = npc
|
spawnedNPCs[fieldId] = npc
|
||||||
|
|
||||||
-- Target für diesen NPC
|
-- Target für diesen NPC
|
||||||
exports['qb-target']:AddTargetEntity(npc, {
|
exports['qb-target']:AddTargetEntity(npc, {
|
||||||
options = {
|
options = {
|
||||||
{
|
{
|
||||||
type = "client",
|
type = "client",
|
||||||
event = "tdm:openFieldMenu",
|
event = "tdm:openFieldMenu",
|
||||||
icon = "fas fa-crosshairs",
|
icon = "fas fa-crosshairs",
|
||||||
label = "TeamDeathmatch - " .. fieldData.name,
|
label = "TeamDeathmatch - " .. fieldData.name,
|
||||||
fieldId = fieldId
|
fieldId = fieldId
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
distance = 2.5
|
||||||
distance = 2.5
|
})
|
||||||
})
|
else
|
||||||
|
print("^3[TDM WARNING]^7 Feld " .. fieldId .. " hat keine vollständige Lobby-Konfiguration!")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Event für Feld-spezifisches Menü
|
-- Event für Feld-spezifisches Menü
|
||||||
RegisterNetEvent('tdm:openFieldMenu', function(data)
|
RegisterNetEvent('tdm:openFieldMenu', function(data)
|
||||||
openMainMenu(data.fieldId)
|
if data and data.fieldId then
|
||||||
|
openMainMenu(data.fieldId)
|
||||||
|
else
|
||||||
|
lib.notify({
|
||||||
|
title = 'Fehler',
|
||||||
|
description = 'Keine Feld-ID übertragen!',
|
||||||
|
type = 'error'
|
||||||
|
})
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Chat Command zum Spiel verlassen
|
-- Chat Command zum Spiel verlassen
|
||||||
|
@ -638,3 +683,62 @@ end, false)
|
||||||
|
|
||||||
-- Keybind zum Spiel verlassen
|
-- Keybind zum Spiel verlassen
|
||||||
RegisterKeyMapping('leavetdm', 'TeamDeathmatch verlassen', 'keyboard', 'F7')
|
RegisterKeyMapping('leavetdm', 'TeamDeathmatch verlassen', 'keyboard', 'F7')
|
||||||
|
|
||||||
|
-- Debug Command zum Testen der Config
|
||||||
|
RegisterCommand('debugtdm', function()
|
||||||
|
print("^2[TDM DEBUG]^7 Aktuelle Werte:")
|
||||||
|
print("inTDM: " .. tostring(inTDM))
|
||||||
|
print("currentField: " .. tostring(currentField))
|
||||||
|
print("currentLobbyField: " .. tostring(currentLobbyField))
|
||||||
|
print("currentTeam: " .. tostring(currentTeam))
|
||||||
|
|
||||||
|
print("^2[TDM DEBUG]^7 Verfügbare Felder:")
|
||||||
|
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||||
|
local hasLobby = fieldData.lobby and fieldData.lobby.pos and "✅" or "❌"
|
||||||
|
print("- " .. fieldId .. ": " .. fieldData.name .. " " .. hasLobby)
|
||||||
|
end
|
||||||
|
end, false)
|
||||||
|
|
||||||
|
-- Debug Commands für Masken
|
||||||
|
RegisterCommand('testmask', function(source, args)
|
||||||
|
if not args[1] or not args[2] then
|
||||||
|
lib.notify({
|
||||||
|
title = 'Debug',
|
||||||
|
description = 'Verwendung: /testmask [team1/team2] [male/female]',
|
||||||
|
type = 'error'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local team = args[1]
|
||||||
|
local gender = args[2]
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
lib.notify({
|
||||||
|
title = 'Debug',
|
||||||
|
description = 'Maske gesetzt: ' .. team .. ' (' .. gender .. ')',
|
||||||
|
type = 'success'
|
||||||
|
})
|
||||||
|
else
|
||||||
|
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)
|
||||||
|
lib.notify({
|
||||||
|
title = 'Debug',
|
||||||
|
description = 'Maske entfernt!',
|
||||||
|
type = 'info'
|
||||||
|
})
|
||||||
|
end, false)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue