1
0
Fork 0
forked from Simnation/Main
This commit is contained in:
Nordi98 2025-07-26 07:01:07 +02:00
parent 9b0de65e94
commit 79e5103db6
2 changed files with 288 additions and 175 deletions

View file

@ -3,10 +3,12 @@ local inTDM = false
local currentTeam = nil local currentTeam = nil
local currentGameId = nil local currentGameId = nil
local currentField = nil local currentField = nil
local tdmBlip = nil local currentLobbyField = nil -- Neue Variable für aktuelle Lobby
local tdmBlips = {} -- Mehrere Blips
local teamZoneBlips = {} local teamZoneBlips = {}
local isHit = false local isHit = false
local activeGames = {} local activeGames = {}
local spawnedNPCs = {} -- Gespawnte NPCs verwalten
-- Spieler Statistiken -- Spieler Statistiken
local playerStats = { local playerStats = {
@ -15,7 +17,7 @@ local playerStats = {
gamesPlayed = 0 gamesPlayed = 0
} }
-- Events -- Events (gleich wie vorher, nur leaveGame angepasst)
RegisterNetEvent('tdm:updateGamesList', function(games) RegisterNetEvent('tdm:updateGamesList', function(games)
activeGames = games activeGames = games
end) end)
@ -55,13 +57,28 @@ end)
RegisterNetEvent('tdm:leaveGame', function() RegisterNetEvent('tdm:leaveGame', function()
inTDM = false inTDM = false
local previousField = currentField
currentTeam = nil currentTeam = nil
currentGameId = nil currentGameId = nil
currentField = nil currentField = nil
isHit = false isHit = false
-- Zurück zur Lobby -- Zurück zur entsprechenden Lobby (falls vorher in einem Spiel)
SetEntityCoords(PlayerPedId(), Config.lobbyPos.x, Config.lobbyPos.y, Config.lobbyPos.z) if previousField and Config.gameFields[previousField] then
local lobbyPos = Config.gameFields[previousField].lobby.pos
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
elseif currentLobbyField and Config.gameFields[currentLobbyField] then
-- Zurück zur aktuellen Lobby
local lobbyPos = Config.gameFields[currentLobbyField].lobby.pos
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
else
-- Fallback zur ersten Lobby
local firstField = next(Config.gameFields)
if firstField then
local lobbyPos = Config.gameFields[firstField].lobby.pos
SetEntityCoords(PlayerPedId(), lobbyPos.x, lobbyPos.y, lobbyPos.z)
end
end
-- Maske entfernen -- Maske entfernen
SetPedComponentVariation(PlayerPedId(), 1, 0, 0, 0) SetPedComponentVariation(PlayerPedId(), 1, 0, 0, 0)
@ -78,6 +95,7 @@ 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',
@ -119,7 +137,6 @@ RegisterNetEvent('tdm:playerHit', function()
isHit = true isHit = true
local ped = PlayerPedId() local ped = PlayerPedId()
-- Arme hochnehmen Animation
RequestAnimDict("random@mugging3") RequestAnimDict("random@mugging3")
while not HasAnimDictLoaded("random@mugging3") do while not HasAnimDictLoaded("random@mugging3") do
Wait(1) Wait(1)
@ -133,7 +150,6 @@ RegisterNetEvent('tdm:playerHit', function()
type = 'error' type = 'error'
}) })
-- Zone Marker hervorheben
highlightTeamZone(currentTeam) highlightTeamZone(currentTeam)
end) end)
@ -203,78 +219,94 @@ RegisterNetEvent('tdm:gameEnded', function(winnerTeam, team1Score, team2Score)
TriggerServerEvent('tdm:leaveGame') TriggerServerEvent('tdm:leaveGame')
end) end)
-- Funktionen -- Angepasste setTeamMask Funktion
function setTeamMask(team) function setTeamMask(team)
local ped = PlayerPedId() local ped = PlayerPedId()
local maskData = Config.teamMasks[team] local maskData = Config.teamMasks[team]
if maskData then if maskData then
SetPedComponentVariation(ped, maskData.component, maskData.drawable, maskData.texture, 0) -- Geschlecht des Spielers ermitteln
end local playerGender = GetEntityModel(ped) == GetHashKey("mp_f_freemode_01") and "female" or "male"
end
function createTeamZoneBlip(team, fieldConfig) -- Entsprechende Maske setzen
local zone = fieldConfig.teamZones[team] local genderMask = maskData[playerGender]
if genderMask then
local blip = AddBlipForRadius(zone.center.x, zone.center.y, zone.center.z, zone.radius) SetPedComponentVariation(ped, genderMask.component, genderMask.drawable, genderMask.texture, 0)
SetBlipHighDetail(blip, true)
SetBlipColour(blip, team == 'team1' and 1 or 3)
SetBlipAlpha(blip, 128)
teamZoneBlips[team] = blip
end
function removeTeamZoneBlips()
for team, blip in pairs(teamZoneBlips) do
if DoesBlipExist(blip) then
RemoveBlip(blip)
end end
end end
teamZoneBlips = {}
end end
function highlightTeamZone(team) -- Alternative Methode über QBCore Player Data
if teamZoneBlips[team] and DoesBlipExist(teamZoneBlips[team]) then function setTeamMaskQB(team)
SetBlipFlashes(teamZoneBlips[team], true) local ped = PlayerPedId()
local Player = QBCore.Functions.GetPlayerData()
local maskData = Config.teamMasks[team]
if maskData and Player.charinfo then
-- Geschlecht aus QBCore Charinfo
local playerGender = Player.charinfo.gender == 1 and "female" or "male"
-- Entsprechende Maske setzen
local genderMask = maskData[playerGender]
if genderMask then
SetPedComponentVariation(ped, genderMask.component, genderMask.drawable, genderMask.texture, 0)
end
end end
end end
function showHitMarker() -- Erweiterte Funktion mit Fallback
CreateThread(function() function setTeamMaskAdvanced(team)
local startTime = GetGameTimer() local ped = PlayerPedId()
local maskData = Config.teamMasks[team]
while GetGameTimer() - startTime < 500 do if not maskData then return end
Wait(0)
-- Rotes X in der Mitte des Bildschirms local playerGender = "male" -- Default
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 -- 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
function openMainMenu()
-- Angepasste Menü-Funktionen
function openMainMenu(fieldId)
currentLobbyField = fieldId -- Aktuelle Lobby merken
TriggerServerEvent('tdm:requestGamesList') TriggerServerEvent('tdm:requestGamesList')
Wait(100) Wait(100)
local fieldName = Config.gameFields[fieldId].name
local options = { local options = {
{ {
title = 'Neues Spiel erstellen', title = 'Neues Spiel erstellen',
description = 'Erstelle ein neues TeamDeathmatch Spiel', description = 'Erstelle ein neues Spiel für ' .. fieldName,
icon = 'plus', icon = 'plus',
onSelect = function() onSelect = function()
openCreateGameMenu() openCreateGameMenu(fieldId)
end end
}, },
{ {
@ -282,7 +314,7 @@ function openMainMenu()
description = 'Trete einem laufenden Spiel bei', description = 'Trete einem laufenden Spiel bei',
icon = 'users', icon = 'users',
onSelect = function() onSelect = function()
openJoinGameMenu() openJoinGameMenu(fieldId)
end end
} }
} }
@ -300,25 +332,18 @@ function openMainMenu()
end end
lib.registerContext({ lib.registerContext({
id = 'tdm_main_menu', id = 'tdm_main_menu_' .. fieldId,
title = 'TeamDeathmatch', title = 'TeamDeathmatch - ' .. fieldName,
options = options options = options
}) })
lib.showContext('tdm_main_menu') lib.showContext('tdm_main_menu_' .. fieldId)
end end
function openCreateGameMenu() function openCreateGameMenu(fieldId)
local fieldOptions = {} local fieldData = Config.gameFields[fieldId]
for fieldId, fieldData in pairs(Config.gameFields) do local input = lib.inputDialog('Neues Spiel erstellen - ' .. fieldData.name, {
table.insert(fieldOptions, {
value = fieldId,
label = fieldData.name .. ' (Max: ' .. fieldData.maxPlayers .. ')'
})
end
local input = lib.inputDialog('Neues Spiel erstellen', {
{ {
type = 'input', type = 'input',
label = 'Spiel Name', label = 'Spiel Name',
@ -326,13 +351,6 @@ function openCreateGameMenu()
required = true, required = true,
max = 30 max = 30
}, },
{
type = 'select',
label = 'Spielfeld',
description = 'Wähle ein Spielfeld',
required = true,
options = fieldOptions
},
{ {
type = 'select', type = 'select',
label = 'Spiel Typ', label = 'Spiel Typ',
@ -354,83 +372,85 @@ function openCreateGameMenu()
if not input then return end if not input then return end
local gameName = input[1] local gameName = input[1]
local fieldId = input[2] local gameType = input[2]
local gameType = input[3] local password = input[3] and input[3] ~= '' and input[3] or nil
local password = input[4] and input[4] ~= '' and input[4] or nil
if gameName and fieldId and gameType then if gameName and gameType then
TriggerServerEvent('tdm:createGame', gameName, fieldId, gameType, password) TriggerServerEvent('tdm:createGame', gameName, fieldId, gameType, password)
end end
end end
function openJoinGameMenu() function openJoinGameMenu(fieldId)
TriggerServerEvent('tdm:requestGamesList') TriggerServerEvent('tdm:requestGamesList')
Wait(200) Wait(200)
local options = {} local options = {}
local fieldName = Config.gameFields[fieldId].name
-- Nur Spiele für dieses Feld anzeigen
for gameId, gameData in pairs(activeGames) do for gameId, gameData in pairs(activeGames) do
local playerCount = #gameData.team1 + #gameData.team2 if gameData.fieldId == fieldId then
local maxPlayers = Config.gameFields[gameData.fieldId].maxPlayers local playerCount = #gameData.team1 + #gameData.team2
local fieldName = Config.gameFields[gameData.fieldId].name local maxPlayers = Config.gameFields[gameData.fieldId].maxPlayers
local statusText = gameData.status == 'waiting' and 'Wartend' or 'Läuft' local statusText = gameData.status == 'waiting' and 'Wartend' or 'Läuft'
local typeText = gameData.gameType == 'public' and '🌐 Öffentlich' or '🔒 Privat' local typeText = gameData.gameType == 'public' and '🌐 Öffentlich' or '🔒 Privat'
local passwordIcon = gameData.hasPassword and ' 🔑' or '' local passwordIcon = gameData.hasPassword and ' 🔑' or ''
table.insert(options, { table.insert(options, {
title = gameData.name .. passwordIcon, title = gameData.name .. passwordIcon,
description = typeText .. ' | Feld: ' .. fieldName .. ' | Spieler: ' .. playerCount .. '/' .. maxPlayers .. ' | Status: ' .. statusText, description = typeText .. ' | Spieler: ' .. playerCount .. '/' .. maxPlayers .. ' | Status: ' .. statusText,
icon = gameData.gameType == 'public' and 'globe' or 'lock', icon = gameData.gameType == 'public' and 'globe' or 'lock',
iconColor = gameData.gameType == 'public' and 'green' or 'orange', iconColor = gameData.gameType == 'public' and 'green' or 'orange',
args = { args = {
gameId = gameId, gameId = gameId,
hasPassword = gameData.hasPassword, hasPassword = gameData.hasPassword,
gameType = gameData.gameType gameType = gameData.gameType
}, },
onSelect = function(args) onSelect = function(args)
if args.hasPassword then if args.hasPassword then
local input = lib.inputDialog('Passwort eingeben', { local input = lib.inputDialog('Passwort eingeben', {
{ {
type = 'input', type = 'input',
label = 'Passwort', label = 'Passwort',
description = 'Gib das Spiel-Passwort ein', description = 'Gib das Spiel-Passwort ein',
required = true, required = true,
password = true password = true
} }
}) })
if input and input[1] then if input and input[1] then
TriggerServerEvent('tdm:requestJoinGame', args.gameId, input[1]) TriggerServerEvent('tdm:requestJoinGame', args.gameId, input[1])
end
else
TriggerServerEvent('tdm:requestJoinGame', args.gameId)
end end
else
TriggerServerEvent('tdm:requestJoinGame', args.gameId)
end end
end })
}) end
end end
if #options == 0 then if #options == 0 then
table.insert(options, { table.insert(options, {
title = 'Keine Spiele verfügbar', title = 'Keine Spiele verfügbar',
description = 'Erstelle ein neues Spiel', description = 'Erstelle ein neues Spiel für ' .. fieldName,
icon = 'info', icon = 'info',
disabled = true disabled = true
}) })
end end
lib.registerContext({ lib.registerContext({
id = 'tdm_join_menu', id = 'tdm_join_menu_' .. fieldId,
title = 'Spiel beitreten', title = 'Spiel beitreten - ' .. fieldName,
menu = 'tdm_main_menu', menu = 'tdm_main_menu_' .. fieldId,
options = options options = options
}) })
lib.showContext('tdm_join_menu') lib.showContext('tdm_join_menu_' .. fieldId)
end end
-- Zone Checker Thread -- Alle Threads bleiben gleich...
CreateThread(function() CreateThread(function()
while true do while true do
Wait(500) Wait(500)
@ -460,7 +480,6 @@ CreateThread(function()
end end
end) end)
-- Zone Marker Renderer
CreateThread(function() CreateThread(function()
while true do while true do
Wait(0) Wait(0)
@ -496,7 +515,6 @@ CreateThread(function()
end end
end) end)
-- Damage Handler
CreateThread(function() CreateThread(function()
while true do while true do
Wait(100) Wait(100)
@ -523,7 +541,6 @@ CreateThread(function()
end end
end) end)
-- Death Handler
CreateThread(function() CreateThread(function()
while true do while true do
Wait(1000) Wait(1000)
@ -547,44 +564,77 @@ CreateThread(function()
end end
end) end)
-- NPC Setup -- Angepasstes NPC Setup für alle Felder
CreateThread(function() CreateThread(function()
-- Blip erstellen -- Für jedes Spielfeld Blip und NPC erstellen
tdmBlip = AddBlipForCoord(Config.lobbyPos.x, Config.lobbyPos.y, Config.lobbyPos.z) for fieldId, fieldData in pairs(Config.gameFields) do
SetBlipSprite(tdmBlip, 432) local lobbyPos = fieldData.lobby.pos
SetBlipDisplay(tdmBlip, 4) local npcData = fieldData.lobby.npc
SetBlipScale(tdmBlip, 0.8)
SetBlipColour(tdmBlip, 1)
SetBlipAsShortRange(tdmBlip, true)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString("TeamDeathmatch")
EndTextCommandSetBlipName(tdmBlip)
-- NPC erstellen -- Blip erstellen
RequestModel(GetHashKey(Config.gameNPC.model)) local blip = AddBlipForCoord(lobbyPos.x, lobbyPos.y, lobbyPos.z)
while not HasModelLoaded(GetHashKey(Config.gameNPC.model)) do SetBlipSprite(blip, 432)
Wait(1) 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 HasModelLoaded(GetHashKey(npcData.model)) do
Wait(1)
end
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
})
end end
local npc = CreatePed(4, GetHashKey(Config.gameNPC.model), Config.gameNPC.coords.x, Config.gameNPC.coords.y, Config.gameNPC.coords.z, Config.gameNPC.coords.w, false, true)
SetEntityInvincible(npc, true)
FreezeEntityPosition(npc, true)
SetBlockingOfNonTemporaryEvents(npc, true)
end) end)
-- Target für NPC -- Event für Feld-spezifisches Menü
exports['qb-target']:AddTargetModel(Config.gameNPC.model, { RegisterNetEvent('tdm:openFieldMenu', function(data)
options = { openMainMenu(data.fieldId)
{
type = "client",
event = "tdm:openMainMenu",
icon = "fas fa-crosshairs",
label = "TeamDeathmatch",
},
},
distance = 2.5
})
RegisterNetEvent('tdm:openMainMenu', function()
openMainMenu()
end) end)
-- Chat Command zum Spiel verlassen
RegisterCommand('leavetdm', function()
if inTDM then
TriggerServerEvent('tdm:leaveGame')
lib.notify({
title = 'TeamDeathmatch',
description = 'Du hast das Spiel über Command verlassen!',
type = 'info'
})
else
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')

View file

@ -6,7 +6,7 @@ Config.lobbyPos = vector3(2019.5784, 2841.1104, 50.3052)
-- NPC für Game Management -- NPC für Game Management
Config.gameNPC = { Config.gameNPC = {
model = 'S_M_Y_ArmyMech_01', model = 'S_M_Y_ArmyMech_01',
coords = vector4(2019.5784, 2841.1104, 50.3052, 240.4603) coords = vector4(2019.5784, 2841.1104, 49.3052, 240.4603)
} }
-- Spielfelder Konfiguration -- Spielfelder Konfiguration
@ -48,6 +48,15 @@ Config.gameFields = {
name = "Arena 2", name = "Arena 2",
maxPlayers = 16, maxPlayers = 16,
-- Eigene Lobby für dieses Feld
lobby = {
pos = vector3(-1500.0, -3000.0, 21.4),
npc = {
model = 's_m_y_cop_01',
coords = vector4(-1500.0, -3000.0, 20.4, 180.0)
}
},
teamSpawns = { teamSpawns = {
team1 = { team1 = {
vector3(-2000.0, -2700.0, 25.0), vector3(-2000.0, -2700.0, 25.0),
@ -73,20 +82,74 @@ Config.gameFields = {
color = {r = 0, g = 0, b = 255, a = 100} color = {r = 0, g = 0, b = 255, a = 100}
} }
} }
},
field3 = {
name = "Desert Arena",
maxPlayers = 24,
-- Eigene Lobby für dieses Feld
lobby = {
pos = vector3(1500.0, 3000.0, 40.0),
npc = {
model = 's_m_y_cop_01',
coords = vector4(1500.0, 3000.0, 39.0, 90.0)
}
},
teamSpawns = {
team1 = {
vector3(1400.0, 2900.0, 40.0),
vector3(1395.0, 2905.0, 40.0),
vector3(1405.0, 2895.0, 40.0)
},
team2 = {
vector3(1600.0, 3100.0, 40.0),
vector3(1605.0, 3105.0, 40.0),
vector3(1595.0, 3095.0, 40.0)
}
},
teamZones = {
team1 = {
center = vector3(1380.0, 2880.0, 40.0),
radius = 12.0,
color = {r = 255, g = 0, b = 0, a = 100}
},
team2 = {
center = vector3(1620.0, 3120.0, 40.0),
radius = 12.0,
color = {r = 0, g = 0, b = 255, a = 100}
}
}
} }
} }
-- Team Masken
Config.teamMasks = { Config.teamMasks = {
team1 = { team1 = {
component = 1, male = {
drawable = 52, component = 1,
texture = 0 drawable = 52,
texture = 0
},
female = {
component = 1,
drawable = 169,
texture = 4
}
}, },
team2 = { team2 = {
component = 1, male = {
drawable = 54, component = 1,
texture = 0 drawable = 54,
texture = 0
},
female = {
component = 1,
drawable = 169,
texture = 3
}
} }
} }