forked from Simnation/Main
ed
This commit is contained in:
parent
4485cc31df
commit
3afa513b4a
22 changed files with 1331 additions and 575 deletions
BIN
resources/[Developer]/[Nordi]/tgiann-weapons-on-back/.fxap
Normal file
BIN
resources/[Developer]/[Nordi]/tgiann-weapons-on-back/.fxap
Normal file
Binary file not shown.
|
@ -0,0 +1,28 @@
|
||||||
|
config.useDefaultInventory = true
|
||||||
|
|
||||||
|
local function log(msg)
|
||||||
|
print(string.format('\x1b[32m[tgiann-weapons-on-back]\x1b[0m %s', msg))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Chezza Studios inventory works fine with normal esx(don't add to the list)
|
||||||
|
local inventorys = {
|
||||||
|
"tgiann-inventory",
|
||||||
|
"mf-inventory",
|
||||||
|
"ox_inventory",
|
||||||
|
"core_inventory",
|
||||||
|
"qs-inventory",
|
||||||
|
"codem-inventory",
|
||||||
|
"origen_inventory"
|
||||||
|
}
|
||||||
|
|
||||||
|
for i = 1, #inventorys do
|
||||||
|
local inventory = inventorys[i]
|
||||||
|
local isStarted = GetResourceState(inventory) == "started"
|
||||||
|
if isStarted then
|
||||||
|
config[inventory] = true
|
||||||
|
config.useDefaultInventory = false
|
||||||
|
log(string.format("Started with %s inventory", inventory))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if config.useDefaultInventory then log(string.format("Started with %s default inventory", config.framework == "qb" and "QB" or "ESX")) end
|
|
@ -0,0 +1,89 @@
|
||||||
|
if not config["codem-inventory"] then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
SetTimeout(2000, function() -- some waiting time because the character's inventory data is loaded later
|
||||||
|
lastItems = exports['codem-inventory']:GetClientPlayerInventory()
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('codem-inventory:client:additem')
|
||||||
|
AddEventHandler('codem-inventory:client:additem', function(slot, data)
|
||||||
|
lastItems[tostring(slot)] = data
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('codem-inventory:client:removeitemtoclientInventory')
|
||||||
|
AddEventHandler('codem-inventory:client:removeitemtoclientInventory', function(slot, amount)
|
||||||
|
slot = tostring(slot)
|
||||||
|
if lastItems[slot] then
|
||||||
|
local itemAmount = lastItems[slot].count or lastItems[slot].amount
|
||||||
|
if itemAmount == amount then
|
||||||
|
lastItems[slot] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('codem-inventory:client:clearinventory')
|
||||||
|
AddEventHandler('codem-inventory:client:clearinventory', function()
|
||||||
|
lastItems = {}
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('codem-inventory:client:setitembyslot')
|
||||||
|
AddEventHandler('codem-inventory:client:setitembyslot', function(slot, itemData)
|
||||||
|
lastItems[tostring(slot)] = itemData
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if key == item.info?.serie or item.name then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and item.type == "weapon" then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item?.info?.serie or item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,116 @@
|
||||||
|
-- https://docs.c8re.store/core-inventory/api
|
||||||
|
if not config.core_inventory then return end
|
||||||
|
|
||||||
|
local function splitStr(str, delimiter)
|
||||||
|
local result = {}
|
||||||
|
local from = 1
|
||||||
|
local delim_from, delim_to = string.find(str, delimiter, from)
|
||||||
|
while delim_from do
|
||||||
|
result[#result + 1] = string.sub(str, from, delim_from - 1)
|
||||||
|
from = delim_to + 1
|
||||||
|
delim_from, delim_to = string.find(str, delimiter, from)
|
||||||
|
end
|
||||||
|
result[#result + 1] = string.sub(str, from)
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local invItems = {}
|
||||||
|
local playerItems = {}
|
||||||
|
|
||||||
|
local function getInventoryItems()
|
||||||
|
tgiCore.cbFunction('tgiann-weapons-on-back:core_inventory:server:getInventory', function(newPlayerItems)
|
||||||
|
playerItems = newPlayerItems
|
||||||
|
weaponCheck(true)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('core_inventory:client:sync', function(inventory, data)
|
||||||
|
local split = splitStr(inventory, '-')[1]
|
||||||
|
if config.enableInv[split] then
|
||||||
|
playerItems[split] = data.content
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
if not PlayerData then return end
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck(false)
|
||||||
|
end)
|
||||||
|
|
||||||
|
if config.framework == "qb" then
|
||||||
|
RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
if not config.enableInv["content"] then return end
|
||||||
|
playerItems["content"] = PlayerData?.items
|
||||||
|
weaponCheck(true)
|
||||||
|
end)
|
||||||
|
else
|
||||||
|
RegisterNetEvent('esx:addInventoryItem')
|
||||||
|
AddEventHandler('esx:addInventoryItem', function(job)
|
||||||
|
local PlayerData = exports["tgiann-core"]:getPlayerData()
|
||||||
|
if not PlayerData then return end
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:removeInventoryItem')
|
||||||
|
AddEventHandler('esx:removeInventoryItem', function(job)
|
||||||
|
local PlayerData = exports["tgiann-core"]:getPlayerData()
|
||||||
|
if not PlayerData then return end
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(invItems) do
|
||||||
|
if item and key == (item.metadata?.serial or item.name) then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck(updateData)
|
||||||
|
if updateData then
|
||||||
|
invItems = {}
|
||||||
|
for _, inv in pairs(playerItems) do
|
||||||
|
for _, item in pairs(inv) do
|
||||||
|
invItems[#invItems + 1] = item
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(invItems) do
|
||||||
|
if item and string.find(string.lower(item.name), "weapon") then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.metadata?.serial or item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)) or item.metadata.attachments,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,88 @@
|
||||||
|
if config.framework ~= "esx" then return end
|
||||||
|
if not config.useDefaultInventory then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
local function getInventoryItems()
|
||||||
|
tgiCore.cbFunction('tgiann-weapons-on-back:esx_inv:server:getInventory', function(playerItems, loadout)
|
||||||
|
local itemList = {}
|
||||||
|
-- ESX is suck
|
||||||
|
if loadout and #loadout > 0 then
|
||||||
|
for i = 1, #loadout do
|
||||||
|
itemList[#itemList + 1] = loadout[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if playerItems and #playerItems > 0 then
|
||||||
|
for i = 1, #playerItems do
|
||||||
|
if playerItems[i].count > 0 then
|
||||||
|
itemList[#itemList + 1] = playerItems[i]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
lastItems = itemList
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:addInventoryItem')
|
||||||
|
AddEventHandler('esx:addInventoryItem', function(job)
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:removeInventoryItem')
|
||||||
|
AddEventHandler('esx:removeInventoryItem', function(job)
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and key == item.name then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
Wait(100)
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and string.find(string.lower(item.name), "weapon") then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item?.info?.tgiattachments, joaat(item.name)) or item.components,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,99 @@
|
||||||
|
tgiCore = nil
|
||||||
|
CreateThread(function()
|
||||||
|
while not tgiCore do
|
||||||
|
tgiCore = tgiCoreExports:getCore()
|
||||||
|
Wait(200)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
local function LoadModel(model)
|
||||||
|
if HasModelLoaded(model) then return end
|
||||||
|
RequestModel(model)
|
||||||
|
while not HasModelLoaded(model) do Wait(0) end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.Functions.AddAttachments = function(entity, weaponName, weaponHash, attachments)
|
||||||
|
if not attachments then return end
|
||||||
|
if config.tgiann_attachments then
|
||||||
|
for _, data in pairs(attachments) do
|
||||||
|
local model = GetWeaponComponentTypeModel(data.component)
|
||||||
|
if model ~= 0 then
|
||||||
|
LoadModel(model)
|
||||||
|
GiveWeaponComponentToWeaponObject(entity, data.component)
|
||||||
|
SetModelAsNoLongerNeeded(data.component)
|
||||||
|
else
|
||||||
|
SetWeaponObjectTintIndex(entity, data.component)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif config.core_inventory then
|
||||||
|
for _, data in pairs(attachments) do
|
||||||
|
local model = GetWeaponComponentTypeModel(data.componentHash)
|
||||||
|
if model ~= 0 then
|
||||||
|
LoadModel(model)
|
||||||
|
GiveWeaponComponentToWeaponObject(entity, data.componentHash)
|
||||||
|
SetModelAsNoLongerNeeded(data.componentHash)
|
||||||
|
else
|
||||||
|
SetWeaponObjectTintIndex(entity, data.componentHash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif config.ox_inventory then
|
||||||
|
if not oxItems then oxItems = exports.ox_inventory:Items() end
|
||||||
|
for i = 1, #attachments do
|
||||||
|
local components = oxItems[attachments[i]].client.component
|
||||||
|
for v = 1, #components do
|
||||||
|
local component = components[v]
|
||||||
|
if DoesWeaponTakeWeaponComponent(weaponHash, component) then
|
||||||
|
local model = GetWeaponComponentTypeModel(component)
|
||||||
|
if model ~= 0 then
|
||||||
|
LoadModel(model)
|
||||||
|
GiveWeaponComponentToWeaponObject(entity, component)
|
||||||
|
SetModelAsNoLongerNeeded(component)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif config.framework == "qb" then
|
||||||
|
for _, data in pairs(attachments) do
|
||||||
|
local model = GetWeaponComponentTypeModel(data.component)
|
||||||
|
if model ~= 0 then
|
||||||
|
LoadModel(model)
|
||||||
|
GiveWeaponComponentToWeaponObject(entity, data.component)
|
||||||
|
SetModelAsNoLongerNeeded(data.component)
|
||||||
|
else
|
||||||
|
SetWeaponObjectTintIndex(entity, data.component)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--ESX is suck
|
||||||
|
for i = 1, #attachments do
|
||||||
|
local componentData = tgiCore.core.GetWeaponComponent(weaponName, attachments[i])
|
||||||
|
if componentData then
|
||||||
|
local hash = componentData.hash
|
||||||
|
local model = GetWeaponComponentTypeModel(hash)
|
||||||
|
if model ~= 0 then
|
||||||
|
LoadModel(model)
|
||||||
|
GiveWeaponComponentToWeaponObject(entity, hash)
|
||||||
|
SetModelAsNoLongerNeeded(hash)
|
||||||
|
else
|
||||||
|
SetWeaponObjectTintIndex(entity, hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function getTgiannAttachments(tgiattachments, weapon)
|
||||||
|
local invSettings = exports["tgiann-attachment"]:inventoryConfig()
|
||||||
|
if invSettings then
|
||||||
|
return tgiattachments
|
||||||
|
else
|
||||||
|
local returnVal = nil
|
||||||
|
local waitCb = true
|
||||||
|
tgiCore.cbFunction("tgiann-attachment:getAttachment", function(data)
|
||||||
|
returnVal = data
|
||||||
|
waitCb = false
|
||||||
|
end, weapon)
|
||||||
|
while waitCb do Wait(10) end
|
||||||
|
return returnVal
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,77 @@
|
||||||
|
if not config["mf-inventory"] then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
local function getInventoryItems(identifier)
|
||||||
|
exports["mf-inventory"]:getInventoryItems(identifier, function(items)
|
||||||
|
lastItems = items
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:playerLoaded')
|
||||||
|
AddEventHandler('esx:playerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:addInventoryItem')
|
||||||
|
AddEventHandler('esx:addInventoryItem', function(job)
|
||||||
|
local PlayerData = exports["tgiann-core"]:getPlayerData()
|
||||||
|
if not PlayerData then return end
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:removeInventoryItem')
|
||||||
|
AddEventHandler('esx:removeInventoryItem', function(job)
|
||||||
|
local PlayerData = exports["tgiann-core"]:getPlayerData()
|
||||||
|
if not PlayerData then return end
|
||||||
|
getInventoryItems(PlayerData.identifier)
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and key == item.name then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved(lastItems)
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and string.find(string.lower(item.name), "weapon") then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)),
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,79 @@
|
||||||
|
if not config.origen_inventory then return end
|
||||||
|
|
||||||
|
local origen_inventory = exports.origen_inventory
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
local function getInventoryItems()
|
||||||
|
lastItems = origen_inventory:GetInventory()
|
||||||
|
weaponCheck()
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
--QB
|
||||||
|
RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
--ESX
|
||||||
|
RegisterNetEvent('esx:addInventoryItem')
|
||||||
|
AddEventHandler('esx:addInventoryItem', function()
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:removeInventoryItem')
|
||||||
|
AddEventHandler('esx:removeInventoryItem', function()
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if key == item.info.serie then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and item.type == "weapon" then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.info.serie,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
if not config.ox_inventory then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
lastItems = exports.ox_inventory:GetPlayerItems() or {}
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
AddEventHandler('ox_inventory:updateInventory', function(changes)
|
||||||
|
for i, value in pairs(changes) do
|
||||||
|
lastItems[i] = value or nil
|
||||||
|
end
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and key == (item.metadata.serial or item.name) then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and string.find(string.lower(item.name), "weapon") then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.metadata.serial or item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.metadata.tgiattachments, joaat(item.name)) or item.metadata.components,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,64 @@
|
||||||
|
if config.framework ~= "qb" then return end
|
||||||
|
if not config.useDefaultInventory then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
lastItems = PlayerData?.items
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
lastItems = PlayerData?.items
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if key == item.info.serie then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and item.type == "weapon" then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.info.serie,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info.attachments,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,89 @@
|
||||||
|
if not config["qs-inventory"] then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
local isBussy = false
|
||||||
|
|
||||||
|
local function getInventoryItems()
|
||||||
|
if isBussy then return end
|
||||||
|
isBussy = true
|
||||||
|
while exports['qs-inventory']:inInventory() do Wait(10) end -- getUserInventory not updating when inventory is open
|
||||||
|
Wait(1000) -- getUserInventory is updating late
|
||||||
|
lastItems = exports['qs-inventory']:getUserInventory()
|
||||||
|
weaponCheck(playerJob, true)
|
||||||
|
isBussy = false
|
||||||
|
end
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
--ESX
|
||||||
|
RegisterNetEvent('esx:addInventoryItem')
|
||||||
|
AddEventHandler('esx:addInventoryItem', function()
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('esx:removeInventoryItem')
|
||||||
|
AddEventHandler('esx:removeInventoryItem', function()
|
||||||
|
getInventoryItems()
|
||||||
|
end)
|
||||||
|
|
||||||
|
--QB
|
||||||
|
RegisterNetEvent('QBCore:Player:SetPlayerData', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
lastItems = PlayerData?.items
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck(playerJob)
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and key == (item.info?.serie or item.name) then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item then
|
||||||
|
local isWeapon = string.find(string.lower(item.name), "weapon")
|
||||||
|
debug(item.name .. " Check For Add Weapon", "isWeapon: " .. tostring(isWeapon))
|
||||||
|
if isWeapon then
|
||||||
|
debug(item.name .. " Added")
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = item.name,
|
||||||
|
key = item.info?.serie or item.name,
|
||||||
|
attachments = config.tgiann_attachments and
|
||||||
|
getTgiannAttachments(item.info.tgiattachments, joaat(item.name)) or item.info?.attachments,
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,62 @@
|
||||||
|
if not config["tgiann-inventory"] then return end
|
||||||
|
|
||||||
|
local playerJob = ""
|
||||||
|
local lastItems = {}
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLogout', function()
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnPlayerLoaded')
|
||||||
|
AddEventHandler('tgiCore:Client:OnPlayerLoaded', function(PlayerData)
|
||||||
|
playerJob = PlayerData.job.name
|
||||||
|
lastItems = exports["tgiann-inventory"]:GetPlayerItems()
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiann-inventory:inventoryUpdated')
|
||||||
|
AddEventHandler('tgiann-inventory:inventoryUpdated', function(items)
|
||||||
|
lastItems = items
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
RegisterNetEvent('tgiCore:Client:OnJobUpdate')
|
||||||
|
AddEventHandler('tgiCore:Client:OnJobUpdate', function(job)
|
||||||
|
self.Functions.RemoveAllWeapons()
|
||||||
|
playerJob = job.name
|
||||||
|
weaponCheck()
|
||||||
|
end)
|
||||||
|
|
||||||
|
self.Functions.CheckWeaponIsRemoved = function()
|
||||||
|
if not next(self.weapons) then return end
|
||||||
|
for key, _ in pairs(self.weapons) do
|
||||||
|
local success = false
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if key == item?.info?.serie then
|
||||||
|
success = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not success then
|
||||||
|
self.Functions.RemoveWeapon(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function weaponCheck()
|
||||||
|
if not lastItems then return end
|
||||||
|
Wait(100)
|
||||||
|
self.Functions.CheckWeaponIsRemoved()
|
||||||
|
local isMale = GetEntityModel(PlayerPedId()) == `mp_m_freemode_01`
|
||||||
|
for _, item in pairs(lastItems) do
|
||||||
|
if item and item.type == "weapon" then
|
||||||
|
self.Functions.AddWeapon({
|
||||||
|
weapon = string.gsub(item.name, "_police", ""),
|
||||||
|
key = item?.info?.serie or item.name,
|
||||||
|
attachments = item?.info?.tgiattachments or {},
|
||||||
|
playerJob = playerJob,
|
||||||
|
isMale = isMale
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Binary file not shown.
|
@ -0,0 +1,12 @@
|
||||||
|
function canShow(targetPed)
|
||||||
|
local isEntityVisible = IsEntityVisible(targetPed)
|
||||||
|
local getEntityAlpha = GetEntityAlpha(targetPed)
|
||||||
|
local pedIsVisible = isEntityVisible and getEntityAlpha == 255
|
||||||
|
debug("pedIsVisible: " .. tostring(pedIsVisible), "ped:" .. targetPed, "isEntityVisible: " .. tostring(isEntityVisible), "getEntityAlpha: " .. getEntityAlpha)
|
||||||
|
return pedIsVisible
|
||||||
|
end
|
||||||
|
|
||||||
|
function debug(...)
|
||||||
|
if not config.debug then return end
|
||||||
|
print(...)
|
||||||
|
end
|
|
@ -0,0 +1,206 @@
|
||||||
|
--[[
|
||||||
|
- this script needs tgiann-core script to work, you can download the script from your keymaster account
|
||||||
|
Start tgiann-core script after es_extented/qb-core script and before tgiann-* scripts
|
||||||
|
Adjust the tgiann-core config file according to the framework you are using
|
||||||
|
|
||||||
|
https://tgiann.gitbook.io/tgiann/scripts/tgiann-weapons-on-back
|
||||||
|
|
||||||
|
Note: If you want the weapons to be invisible while in Noclip, the character must be completely invisible. If your character is invisible to other players, other players cannot see these weapons.
|
||||||
|
If you want to edit this, take a look at client/editable.lua
|
||||||
|
]]
|
||||||
|
|
||||||
|
tgiCoreExports = exports["tgiann-core"]
|
||||||
|
config = tgiCoreExports:getConfig()
|
||||||
|
config.debug = false
|
||||||
|
|
||||||
|
config.tgiann_attachments = GetResourceState("tgiann-attachment") ~= "missing" -- https://tgiann.tebex.io/package/5399235
|
||||||
|
|
||||||
|
-- Weapon positions for male and female characters. You can add additional positions here if you like.
|
||||||
|
config.positions = {
|
||||||
|
male = {
|
||||||
|
back = { -- We have set 3 positions for the back. You can add or remove extra positions if you like. This setting also applies to other positions.
|
||||||
|
{ -- position 1
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.17, 0.13),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
},
|
||||||
|
{ -- position 2
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.17, 0.0),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
},
|
||||||
|
{ -- position 3
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.17, -0.13),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
front = {
|
||||||
|
{
|
||||||
|
bone = 24818,
|
||||||
|
offset = vector3(-0.03, 0.19, 0.0),
|
||||||
|
rot = vector3(-10.0, 40.0, 5.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
right = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.01, 0.02, 0.215),
|
||||||
|
rot = vector3(-100.0, 60.0, 45.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rLegBack = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.15, -0.11, 0.22),
|
||||||
|
rot = vector3(0.0, 95.0, 180.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
waist = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.07, -0.13, 0.05),
|
||||||
|
rot = vector3(180.0, -30.0, 10.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
-- You can add extra positions here if you like.
|
||||||
|
-- The positions you add can be used in the `config.weaponPositions`, `config.weaponGroupPositions` and `config.weaponGroupJobPositions` settings.
|
||||||
|
--[[ exampleCustomName = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.07, -0.13, 0.05),
|
||||||
|
rot = vector3(180.0, -30.0, 10.0),
|
||||||
|
}
|
||||||
|
}, ]]
|
||||||
|
},
|
||||||
|
female = {
|
||||||
|
back = {
|
||||||
|
{
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.15, 0.13),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.15, 0.0),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.285, -0.15, -0.13),
|
||||||
|
rot = vector3(0.0, 170.0, 0.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
front = {
|
||||||
|
{
|
||||||
|
bone = 24818,
|
||||||
|
offset = vector3(-0.03, 0.21, 0.0),
|
||||||
|
rot = vector3(-10.0, 40.0, 5.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
right = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.09, 0.03, 0.18),
|
||||||
|
rot = vector3(-105.0, 75.0, 45.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rLegBack = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.15, -0.11, 0.22),
|
||||||
|
rot = vector3(0.0, 95.0, 180.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
waist = {
|
||||||
|
{
|
||||||
|
bone = 11816,
|
||||||
|
offset = vector3(-0.07, -0.09, 0.05),
|
||||||
|
rot = vector3(180.0, -30.0, 10.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Weapons in the list do not appear on the character
|
||||||
|
config.disabledWeapons = {
|
||||||
|
weapon_flashlight = true,
|
||||||
|
weapon_knuckle = true,
|
||||||
|
weapon_bottle = true,
|
||||||
|
weapon_snowball = true,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- adjusts the location of the weapon regardless of its group
|
||||||
|
config.weaponPositions = {
|
||||||
|
--weapon_pistol = "right",
|
||||||
|
}
|
||||||
|
|
||||||
|
-- adjusts the position of the weapon regardless of its group
|
||||||
|
config.weaponCustomPositions = {
|
||||||
|
male = {
|
||||||
|
weapon_bat = {
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.0, -0.15, 0.03),
|
||||||
|
rot = vector3(0.0, 80.0, 0.0),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
female = {
|
||||||
|
weapon_bat = {
|
||||||
|
bone = 24816,
|
||||||
|
offset = vector3(0.0, -0.15, 0.03),
|
||||||
|
rot = vector3(0.0, 80.0, 0.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
--"waist" - "back" - "front" - "rigt" - "rLegBack" - "none"
|
||||||
|
config.weaponGroupPostions = {
|
||||||
|
[3539449195] = "back", --GROUP_DIGISCANNER
|
||||||
|
[-37788308] = "rLegBack", --GROUP_FIREEXTINGUISHER
|
||||||
|
[1175761940] = "none", --GROUP_HACKINGDEVICE
|
||||||
|
[2725924767] = "back", --GROUP_HEAVY
|
||||||
|
[-728555052] = "back", --GROUP_MELEE
|
||||||
|
[3759491383] = "none", --GROUP_METALDETECTOR
|
||||||
|
[1159398588] = "back", --GROUP_MG
|
||||||
|
[3493187224] = "none", --GROUP_NIGHTVISION
|
||||||
|
[431593103] = "none", --GROUP_PARACHUTE
|
||||||
|
[1595662460] = "none", --GROUP_PETROLCAN
|
||||||
|
[416676503] = "waist", --GROUP_PISTOL
|
||||||
|
[970310034] = "back", --GROUP_RIFLE
|
||||||
|
[860033945] = "back", --GROUP_SHOTGUN
|
||||||
|
[-957766203] = "front", --GROUP_SMG
|
||||||
|
[-1212426201] = "back", --GROUP_SNIPER
|
||||||
|
[690389602] = "none", --GROUP_STUNGUN
|
||||||
|
[1548507267] = "none", --GROUP_THROWN
|
||||||
|
[75159441] = "back", --GROUP_TRANQILIZER
|
||||||
|
[2685387236] = "none", --GROUP_UNARMED
|
||||||
|
}
|
||||||
|
|
||||||
|
-- weapon locations for jobs
|
||||||
|
config.weaponGroupJobPostions = {
|
||||||
|
{
|
||||||
|
jobs = { "police" }, -- u can add multible job name
|
||||||
|
postions = {
|
||||||
|
[3539449195] = "back", --GROUP_DIGISCANNER
|
||||||
|
[-37788308] = "rLegBack", --GROUP_FIREEXTINGUISHER
|
||||||
|
[1175761940] = "none", --GROUP_HACKINGDEVICE
|
||||||
|
[2725924767] = "back", --GROUP_HEAVY
|
||||||
|
[-728555052] = "back", --GROUP_MELEE
|
||||||
|
[3759491383] = "none", --GROUP_METALDETECTOR
|
||||||
|
[1159398588] = "back", --GROUP_MG
|
||||||
|
[3493187224] = "none", --GROUP_NIGHTVISION
|
||||||
|
[431593103] = "none", --GROUP_PARACHUTE
|
||||||
|
[1595662460] = "none", --GROUP_PETROLCAN
|
||||||
|
[416676503] = "right", --GROUP_PISTOL
|
||||||
|
[970310034] = "back", --GROUP_RIFLE
|
||||||
|
[860033945] = "back", --GROUP_SHOTGUN
|
||||||
|
[-957766203] = "front", --GROUP_SMG
|
||||||
|
[-1212426201] = "back", --GROUP_SNIPER
|
||||||
|
[690389602] = "none", --GROUP_STUNGUN
|
||||||
|
[1548507267] = "none", --GROUP_THROWN
|
||||||
|
[75159441] = "back", --GROUP_TRANQILIZER
|
||||||
|
[2685387236] = "none", --GROUP_UNARMED
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
config.enableInv = {
|
||||||
|
["content"] = true,
|
||||||
|
["primary"] = true,
|
||||||
|
["secondry"] = true,
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
fx_version 'cerulean'
|
||||||
|
game 'gta5'
|
||||||
|
version '1.0.1'
|
||||||
|
|
||||||
|
lua54 'yes'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
'tgiann-core',
|
||||||
|
}
|
||||||
|
|
||||||
|
escrow_ignore {
|
||||||
|
'configs/*.lua',
|
||||||
|
'checkInv.lua',
|
||||||
|
'client/bridge/*.lua',
|
||||||
|
'client/editable.lua',
|
||||||
|
'server/bridge/*.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_script {
|
||||||
|
'configs/*.lua',
|
||||||
|
'checkInv.lua',
|
||||||
|
}
|
||||||
|
|
||||||
|
client_scripts {
|
||||||
|
'client/*.lua',
|
||||||
|
'client/bridge/*.lua'
|
||||||
|
}
|
||||||
|
|
||||||
|
server_scripts {
|
||||||
|
"server/server.lua",
|
||||||
|
'server/bridge/*.lua',
|
||||||
|
}
|
||||||
|
|
||||||
|
dependency '/assetpacks'
|
|
@ -0,0 +1,13 @@
|
||||||
|
if not config.core_inventory then return end
|
||||||
|
|
||||||
|
tgiCore.cbFunction('tgiann-weapons-on-back:core_inventory:server:getInventory', function(source, cb)
|
||||||
|
local src = source
|
||||||
|
local xPlayer = tgiCore.getPlayer(src)
|
||||||
|
if not xPlayer then return end
|
||||||
|
local citizenid = tgiCore.getCid(xPlayer)
|
||||||
|
local playerItems = {}
|
||||||
|
for inv, canAdd in pairs(config.enableInv) do
|
||||||
|
if canAdd then playerItems[inv] = exports['core_inventory']:getInventory(string.format("%s-%s", inv, citizenid)) end
|
||||||
|
end
|
||||||
|
cb(playerItems)
|
||||||
|
end)
|
|
@ -0,0 +1,10 @@
|
||||||
|
if config.framework ~= "esx" then return end
|
||||||
|
if not config.useDefaultInventory then return end
|
||||||
|
|
||||||
|
-- esx is very bad, I can't access current inventory data from client
|
||||||
|
tgiCore.cbFunction('tgiann-weapons-on-back:esx_inv:server:getInventory', function(source, cb)
|
||||||
|
local src = source
|
||||||
|
local xPlayer = tgiCore.getPlayer(src)
|
||||||
|
if not xPlayer then return end
|
||||||
|
cb(xPlayer.getInventory(), xPlayer.getLoadout())
|
||||||
|
end)
|
Binary file not shown.
|
@ -25,19 +25,6 @@ local function debugPrint(message)
|
||||||
print("^2[TDM DEBUG]^7 " .. message)
|
print("^2[TDM DEBUG]^7 " .. message)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Funktion zum Prüfen, ob eine Waffe eine Airsoft-Waffe ist
|
|
||||||
function isAirsoftWeapon(weaponHash)
|
|
||||||
return Config.airsoftWeapons[weaponHash] or Config.treatAllWeaponsAsAirsoft
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Enhanced function to check if a player is in ragdoll state
|
|
||||||
function isPedInRagdoll(ped)
|
|
||||||
return IsPedRagdoll(ped) or
|
|
||||||
IsPedFalling(ped) or
|
|
||||||
IsPedDiving(ped) or
|
|
||||||
(not IsPedStill(ped) and IsPedOnFoot(ped) and not IsPedWalking(ped) and not IsPedRunning(ped) and not IsPedSprinting(ped))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Helper function to dump tables for debugging
|
-- Helper function to dump tables for debugging
|
||||||
function dumpTable(table, indent)
|
function dumpTable(table, indent)
|
||||||
if not indent then indent = 0 end
|
if not indent then indent = 0 end
|
||||||
|
@ -52,6 +39,19 @@ function dumpTable(table, indent)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Funktion zum Prüfen, ob eine Waffe eine Airsoft-Waffe ist
|
||||||
|
function isAirsoftWeapon(weaponHash)
|
||||||
|
return Config.airsoftWeapons[weaponHash] or Config.treatAllWeaponsAsAirsoft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Enhanced function to check if a player is in ragdoll state
|
||||||
|
function isPedInRagdoll(ped)
|
||||||
|
return IsPedRagdoll(ped) or
|
||||||
|
IsPedFalling(ped) or
|
||||||
|
IsPedDiving(ped) or
|
||||||
|
(not IsPedStill(ped) and IsPedOnFoot(ped) and not IsPedWalking(ped) and not IsPedRunning(ped) and not IsPedSprinting(ped))
|
||||||
|
end
|
||||||
|
|
||||||
-- Events
|
-- Events
|
||||||
RegisterNetEvent('tdm:updateGamesList', function(games)
|
RegisterNetEvent('tdm:updateGamesList', function(games)
|
||||||
activeGames = games
|
activeGames = games
|
||||||
|
@ -791,570 +791,189 @@ CreateThread(function()
|
||||||
if inTDM and not isHit then
|
if inTDM and not isHit then
|
||||||
local ped = PlayerPedId()
|
local ped = PlayerPedId()
|
||||||
|
|
||||||
|
-- Prüfe, ob der Spieler im Ragdoll-Zustand ist
|
||||||
|
if
|
||||||
-- Prüfe, ob der Spieler im Ragdoll-Zustand ist
|
-- Prüfe, ob der Spieler im Ragdoll-Zustand ist
|
||||||
if isPedInRagdoll(ped) then
|
if isPedInRagdoll(ped) then
|
||||||
-- Bestimme den Angreifer (verwende den letzten Angreifer, wenn innerhalb von 3 Sekunden)
|
-- Bestimme den Angreifer (verwende den letzten Angreifer, wenn innerhalb von 3 Sekunden)
|
||||||
local attacker = nil
|
local attacker = nil
|
||||||
if lastDamager and (GetGameTimer() -
|
if lastDamager and (GetGameTimer() - lastDamageTime) < 3000 then
|
||||||
local QBCore = exports['qb-core']:GetCoreObject()
|
attacker = lastDamager
|
||||||
|
|
||||||
-- Game Management
|
-- Prüfe ob die Waffe eine Airsoft-Waffe ist
|
||||||
local activeGames = {}
|
if isAirsoftWeapon(lastDamageWeapon) then
|
||||||
local gameIdCounter = 1
|
debugPrint("Ragdoll durch Airsoft-Waffe - Zählt als Tod durch: " .. attacker)
|
||||||
|
|
||||||
-- Debug-Funktion für Konsole
|
-- Lokale Stats sofort updaten
|
||||||
local function debugPrint(message)
|
playerStats.deaths = playerStats.deaths + 1
|
||||||
print("^2[TDM SERVER]^7 " .. message)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Events
|
-- Treffer-Events auslösen
|
||||||
RegisterNetEvent('tdm:createGame', function(gameName, fieldId, gameType, password)
|
TriggerEvent('tdm:playerHit')
|
||||||
local src = source
|
TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam, attacker)
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
|
||||||
|
|
||||||
if not Player then
|
-- Zurücksetzen des letzten Angreifers
|
||||||
debugPrint("Spielerstellung fehlgeschlagen - Spieler nicht gefunden: " .. src)
|
lastDamager = nil
|
||||||
return
|
lastDamageWeapon = 0
|
||||||
end
|
|
||||||
|
|
||||||
-- Prüfen ob Spielfeld bereits belegt
|
-- Warten um mehrfache Auslösung zu verhindern
|
||||||
for gameId, gameData in pairs(activeGames) do
|
|
||||||
if gameData.fieldId == fieldId then
|
|
||||||
debugPrint("Spielerstellung abgelehnt - Feld bereits belegt: " .. fieldId)
|
|
||||||
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,
|
|
||||||
password = password,
|
|
||||||
hasPassword = password ~= nil,
|
|
||||||
status = 'waiting',
|
|
||||||
team1 = {},
|
|
||||||
team2 = {},
|
|
||||||
score = {team1 = 0, team2 = 0},
|
|
||||||
startTime = nil,
|
|
||||||
maxTime = Config.maxGameTime,
|
|
||||||
maxHits = Config.maxHits,
|
|
||||||
playerStats = {} -- Spieler-Statistiken initialisieren
|
|
||||||
}
|
|
||||||
|
|
||||||
local typeText = gameType == 'public' and 'öffentliches' or 'privates'
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Dein ' .. typeText .. ' Spiel "' .. gameName .. '" wurde erstellt!', 'success')
|
|
||||||
|
|
||||||
updateGamesListForAll()
|
|
||||||
debugPrint("Spiel erstellt: " .. gameId .. " von " .. Player.PlayerData.name .. " (Feld: " .. fieldId .. ")")
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:requestGamesList', function()
|
|
||||||
local src = source
|
|
||||||
debugPrint("Spiele-Liste angefordert von: " .. src)
|
|
||||||
TriggerClientEvent('tdm:updateGamesList', src, activeGames)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:requestJoinGame', function(gameId, password)
|
|
||||||
local src = source
|
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
|
||||||
|
|
||||||
if not Player or not activeGames[gameId] then
|
|
||||||
debugPrint("Spielbeitritt fehlgeschlagen - Spieler oder Spiel nicht gefunden: " .. src .. ", " .. gameId)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
local playerName = Player.PlayerData.charinfo.firstname .. ' ' .. Player.PlayerData.charinfo.lastname
|
|
||||||
|
|
||||||
debugPrint("Beitrittsanfrage von " .. playerName .. " (ID: " .. src .. ") für Spiel " .. gameId)
|
|
||||||
|
|
||||||
-- Passwort prüfen falls vorhanden
|
|
||||||
if game.hasPassword and game.password ~= password then
|
|
||||||
debugPrint("Beitritt abgelehnt - Falsches Passwort")
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Falsches Passwort!', 'error')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Spieler bereits im Spiel?
|
|
||||||
for _, playerId in ipairs(game.team1) do
|
|
||||||
if playerId == src then
|
|
||||||
debugPrint("Beitritt abgelehnt - Spieler bereits in Team 1")
|
|
||||||
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
|
|
||||||
debugPrint("Beitritt abgelehnt - Spieler bereits in Team 2")
|
|
||||||
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
|
|
||||||
debugPrint("Beitritt abgelehnt - Spiel ist voll")
|
|
||||||
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
|
|
||||||
debugPrint("Beitritt abgelehnt - Admin nicht online")
|
|
||||||
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
|
|
||||||
debugPrint("Öffentliches Spiel - Direkter Beitritt")
|
|
||||||
joinPlayerToGame(src, gameId)
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Du bist dem öffentlichen Spiel beigetreten!', 'success')
|
|
||||||
else
|
|
||||||
debugPrint("Privates Spiel - Sende Anfrage an Admin")
|
|
||||||
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
|
|
||||||
debugPrint("Join-Anfrage Bearbeitung fehlgeschlagen - Ungültiges Spiel oder nicht Admin")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if approved then
|
|
||||||
debugPrint("Join-Anfrage genehmigt für Spieler " .. playerId .. " in Spiel " .. gameId)
|
|
||||||
joinPlayerToGame(playerId, gameId)
|
|
||||||
TriggerClientEvent('tdm:joinRequestResult', playerId, true, game.name)
|
|
||||||
else
|
|
||||||
debugPrint("Join-Anfrage abgelehnt für Spieler " .. playerId .. " in Spiel " .. gameId)
|
|
||||||
TriggerClientEvent('tdm:joinRequestResult', playerId, false, game.name)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:leaveGame', function()
|
|
||||||
local src = source
|
|
||||||
debugPrint("Spieler " .. src .. " möchte alle Spiele verlassen")
|
|
||||||
|
|
||||||
for gameId, game in pairs(activeGames) do
|
|
||||||
removePlayerFromGame(src, gameId)
|
|
||||||
end
|
|
||||||
|
|
||||||
TriggerClientEvent('tdm:leaveGame', src)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, attackerId)
|
|
||||||
local victim = source
|
|
||||||
|
|
||||||
if not activeGames[gameId] then
|
|
||||||
debugPrint("Hit registriert, aber Spiel " .. gameId .. " existiert nicht!")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
|
|
||||||
debugPrint("Hit registriert - Opfer: " .. victim .. " (Team: " .. victimTeam .. "), Angreifer: " .. (attackerId or "Unbekannt"))
|
|
||||||
|
|
||||||
-- Spieler Stats initialisieren falls nicht vorhanden
|
|
||||||
if not game.playerStats then
|
|
||||||
game.playerStats = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
if not game.playerStats[victim] then
|
|
||||||
game.playerStats[victim] = {hits = 0, deaths = 0}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wichtig: Nur wenn ein Angreifer identifiziert wurde, zähle den Kill
|
|
||||||
if attackerId then
|
|
||||||
if not game.playerStats[attackerId] then
|
|
||||||
game.playerStats[attackerId] = {hits = 0, deaths = 0}
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Stats updaten
|
|
||||||
game.playerStats[victim].deaths = (game.playerStats[victim].deaths or 0) + 1
|
|
||||||
game.playerStats[attackerId].hits = (game.playerStats[attackerId].hits or 0) + 1
|
|
||||||
|
|
||||||
-- Benachrichtigung an den Angreifer senden
|
|
||||||
TriggerClientEvent('tdm:hitRegistered', attackerId)
|
|
||||||
debugPrint("Treffer von " .. attackerId .. " gegen " .. victim .. " registriert")
|
|
||||||
|
|
||||||
-- Team Score erhöhen
|
|
||||||
if victimTeam == 'team1' then
|
|
||||||
game.score.team2 = game.score.team2 + 1
|
|
||||||
debugPrint("Punkt für Team 2 - Neuer Score: " .. game.score.team2)
|
|
||||||
else
|
|
||||||
game.score.team1 = game.score.team1 + 1
|
|
||||||
debugPrint("Punkt für Team 1 - Neuer Score: " .. game.score.team1)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
debugPrint("Treffer gegen " .. victim .. " von unbekanntem Angreifer registriert - Kein Punkt vergeben")
|
|
||||||
end
|
|
||||||
|
|
||||||
TriggerClientEvent('tdm:deathRegistered', victim)
|
|
||||||
|
|
||||||
-- Score an alle Spieler senden
|
|
||||||
updateScoreForGame(gameId)
|
|
||||||
|
|
||||||
-- Spiel beenden prüfen
|
|
||||||
if game.score.team1 >= game.maxHits or game.score.team2 >= game.maxHits then
|
|
||||||
local winnerTeam = game.score.team1 >= game.maxHits and 'team1' or 'team2'
|
|
||||||
debugPrint("Max Punkte erreicht - Beende Spiel. Gewinner: " .. winnerTeam)
|
|
||||||
endGame(gameId, winnerTeam)
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:playerDied', function(gameId)
|
|
||||||
local src = source
|
|
||||||
debugPrint("Spieler " .. src .. " ist gestorben in Spiel " .. gameId)
|
|
||||||
removePlayerFromGame(src, gameId)
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:requestScoreUpdate', function(gameId)
|
|
||||||
local src = source
|
|
||||||
|
|
||||||
if activeGames[gameId] then
|
|
||||||
debugPrint("Score-Update angefordert von " .. src .. " für Spiel " .. gameId)
|
|
||||||
updateScoreForGame(gameId)
|
|
||||||
else
|
|
||||||
debugPrint("Score-Update fehlgeschlagen - Spiel " .. gameId .. " nicht gefunden")
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
RegisterNetEvent('tdm:debugPlayerStats', function(gameId)
|
|
||||||
local src = source
|
|
||||||
if activeGames[gameId] and activeGames[gameId].playerStats and activeGames[gameId].playerStats[src] then
|
|
||||||
local stats = activeGames[gameId].playerStats[src]
|
|
||||||
debugPrint("Stats für Spieler " .. src .. ": Hits=" .. (stats.hits or 0) .. ", Deaths=" .. (stats.deaths or 0))
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Server Stats - Hits: ' .. (stats.hits or 0) .. ', Deaths: ' .. (stats.deaths or 0), 'info')
|
|
||||||
else
|
|
||||||
debugPrint("Keine Stats gefunden für Spieler " .. src .. " in Spiel " .. gameId)
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Keine Stats gefunden!', 'error')
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Funktionen
|
|
||||||
function joinPlayerToGame(playerId, gameId)
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
if not game then
|
|
||||||
debugPrint("Spielbeitritt fehlgeschlagen - Spiel nicht gefunden: " .. gameId)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Team mit weniger Spielern wählen
|
|
||||||
local team = #game.team1 <= #game.team2 and 'team1' or 'team2'
|
|
||||||
|
|
||||||
table.insert(game[team], playerId)
|
|
||||||
|
|
||||||
-- Spieler-Stats initialisieren
|
|
||||||
if not game.playerStats then
|
|
||||||
game.playerStats = {}
|
|
||||||
end
|
|
||||||
|
|
||||||
game.playerStats[playerId] = {hits = 0, deaths = 0}
|
|
||||||
|
|
||||||
-- Spiel starten wenn mindestens 2 Spieler
|
|
||||||
if #game.team1 + #game.team2 >= 2 and game.status == 'waiting' then
|
|
||||||
game.status = 'active'
|
|
||||||
game.startTime = os.time()
|
|
||||||
debugPrint("Spiel " .. gameId .. " gestartet - Mindestens 2 Spieler erreicht")
|
|
||||||
|
|
||||||
-- Game Timer starten
|
|
||||||
startGameTimer(gameId)
|
|
||||||
end
|
|
||||||
|
|
||||||
TriggerClientEvent('tdm:joinGame', playerId, gameId, team, game.fieldId)
|
|
||||||
updateScoreForGame(gameId)
|
|
||||||
updateGamesListForAll()
|
|
||||||
|
|
||||||
debugPrint("Spieler " .. playerId .. " ist Spiel " .. gameId .. " beigetreten (Team: " .. team .. ")")
|
|
||||||
end
|
|
||||||
|
|
||||||
function removePlayerFromGame(playerId, gameId)
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
if not game then return end
|
|
||||||
|
|
||||||
-- Spieler aus Teams entfernen
|
|
||||||
local removed = false
|
|
||||||
|
|
||||||
for i, id in ipairs(game.team1) do
|
|
||||||
if id == playerId then
|
|
||||||
table.remove(game.team1, i)
|
|
||||||
debugPrint("Spieler " .. playerId .. " aus Team 1 entfernt")
|
|
||||||
removed = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not removed then
|
|
||||||
for i, id in ipairs(game.team2) do
|
|
||||||
if id == playerId then
|
|
||||||
table.remove(game.team2, i)
|
|
||||||
debugPrint("Spieler " .. playerId .. " aus Team 2 entfernt")
|
|
||||||
removed = true
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if not removed then
|
|
||||||
debugPrint("Spieler " .. playerId .. " nicht in Spiel " .. gameId .. " gefunden")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Wenn Admin das Spiel verlässt, Spiel beenden
|
|
||||||
if game.admin == playerId then
|
|
||||||
debugPrint("Admin hat das Spiel verlassen - Beende Spiel " .. gameId)
|
|
||||||
endGame(gameId, nil, 'Admin hat das Spiel verlassen')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
checkGameEnd(gameId)
|
|
||||||
updateGamesListForAll()
|
|
||||||
end
|
|
||||||
|
|
||||||
function endGame(gameId, winnerTeam, reason)
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
if not game then
|
|
||||||
debugPrint("Spielende fehlgeschlagen - Spiel nicht gefunden: " .. gameId)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
game.status = 'finished'
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
-- Game End Event an alle Spieler
|
|
||||||
for _, playerId in ipairs(allPlayers) do
|
|
||||||
debugPrint("Sende Spielende-Event an Spieler " .. playerId)
|
|
||||||
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()
|
|
||||||
debugPrint("Spiel " .. gameId .. " aus der Liste entfernt")
|
|
||||||
end)
|
|
||||||
|
|
||||||
if reason then
|
|
||||||
debugPrint("Spiel " .. gameId .. " beendet: " .. reason)
|
|
||||||
else
|
|
||||||
debugPrint("Spiel " .. gameId .. " beendet. Gewinner: " .. (winnerTeam or "Unentschieden"))
|
|
||||||
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()
|
|
||||||
|
|
||||||
debugPrint("Timer für Spiel " .. gameId .. " gestartet. Maximale Zeit: " .. maxTime .. " Sekunden")
|
|
||||||
|
|
||||||
while game and game.status == 'active' and (os.time() - startTime) < maxTime do
|
|
||||||
Wait(1000)
|
Wait(1000)
|
||||||
game = activeGames[gameId] -- Refresh game data
|
|
||||||
|
|
||||||
-- Alle 30 Sekunden Debug-Info
|
|
||||||
if (os.time() - startTime) % 30 == 0 then
|
|
||||||
debugPrint("Spiel " .. gameId .. " läuft seit " .. (os.time() - startTime) .. " Sekunden")
|
|
||||||
end
|
end
|
||||||
end
|
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
|
|
||||||
debugPrint("Spielzeit abgelaufen - Beende Spiel " .. gameId)
|
|
||||||
endGame(gameId, winnerTeam, 'Zeit abgelaufen')
|
|
||||||
end
|
end
|
||||||
end)
|
else
|
||||||
end
|
Wait(500)
|
||||||
|
|
||||||
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
|
|
||||||
debugPrint("Zu wenig Spieler - Beende Spiel " .. gameId)
|
|
||||||
endGame(gameId, nil, 'Zu wenig Spieler')
|
|
||||||
elseif totalPlayers == 0 then
|
|
||||||
activeGames[gameId] = nil
|
|
||||||
updateGamesListForAll()
|
|
||||||
debugPrint("Spiel " .. gameId .. " gelöscht (keine Spieler)")
|
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
function updateScoreForGame(gameId)
|
|
||||||
local game = activeGames[gameId]
|
|
||||||
if not game then
|
|
||||||
debugPrint("Score-Update fehlgeschlagen - Spiel nicht gefunden: " .. gameId)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
debugPrint("Score Update für Spiel " .. gameId .. ": Team1=" .. game.score.team1 .. ", Team2=" .. game.score.team2)
|
|
||||||
|
|
||||||
for _, playerId in ipairs(game.team1) do
|
|
||||||
local playerStats = game.playerStats[playerId] or {hits = 0, deaths = 0}
|
|
||||||
TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2, {
|
|
||||||
hits = playerStats.hits or 0,
|
|
||||||
deaths = playerStats.deaths or 0
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, playerId in ipairs(game.team2) do
|
|
||||||
local playerStats = game.playerStats[playerId] or {hits = 0, deaths = 0}
|
|
||||||
TriggerClientEvent('tdm:updateScore', playerId, game.score.team1, game.score.team2, {
|
|
||||||
hits = playerStats.hits or 0,
|
|
||||||
deaths = playerStats.deaths or 0
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function updateGamesListForAll()
|
|
||||||
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
|
|
||||||
|
|
||||||
for gameId, game in pairs(activeGames) do
|
|
||||||
removePlayerFromGame(src, gameId)
|
|
||||||
end
|
|
||||||
|
|
||||||
debugPrint("Spieler " .. src .. " hat den Server verlassen - aus allen Spielen entfernt")
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Server Start - Games Liste leeren
|
|
||||||
AddEventHandler('onResourceStart', function(resourceName)
|
|
||||||
if GetCurrentResourceName() == resourceName then
|
|
||||||
activeGames = {}
|
|
||||||
gameIdCounter = 1
|
|
||||||
debugPrint("TeamDeathmatch System gestartet!")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
-- Direkter Waffen-Schaden Monitor für zusätzliche Zuverlässigkeit
|
||||||
|
CreateThread(function()
|
||||||
|
while true do
|
||||||
|
Wait(0)
|
||||||
|
if inTDM and not isHit then
|
||||||
|
local ped = PlayerPedId()
|
||||||
|
|
||||||
|
-- Prüfe auf Projektil-Treffer
|
||||||
|
if HasEntityBeenDamagedByWeapon(ped, 0, 2) then -- 2 = Projektilwaffen
|
||||||
|
debugPrint("Projektil-Treffer erkannt")
|
||||||
|
|
||||||
|
-- Schaden zurücksetzen
|
||||||
|
ClearEntityLastDamageEntity(ped)
|
||||||
|
ClearPedLastWeaponDamage(ped)
|
||||||
|
SetEntityHealth(ped, GetEntityMaxHealth(ped))
|
||||||
|
|
||||||
|
-- Lokale Stats sofort updaten
|
||||||
|
playerStats.deaths = playerStats.deaths + 1
|
||||||
|
|
||||||
|
-- Treffer-Events auslösen
|
||||||
|
TriggerEvent('tdm:playerHit')
|
||||||
|
TriggerServerEvent('tdm:playerWasHit', currentGameId, currentTeam, lastDamager)
|
||||||
|
|
||||||
|
-- Warten um mehrfache Auslösung zu verhindern
|
||||||
|
Wait(500)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Wait(500)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Function to spawn NPCs for all fields
|
||||||
|
function spawnFieldNPCs()
|
||||||
|
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||||
|
if fieldData.lobby and fieldData.lobby.npc then
|
||||||
|
local npcData = fieldData.lobby.npc
|
||||||
|
local model = GetHashKey(npcData.model)
|
||||||
|
|
||||||
|
-- Request the model
|
||||||
|
RequestModel(model)
|
||||||
|
while not HasModelLoaded(model) do
|
||||||
|
Wait(10)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create the NPC
|
||||||
|
local npc = CreatePed(4, model, npcData.coords.x, npcData.coords.y, npcData.coords.z, npcData.coords.w, false, true)
|
||||||
|
SetEntityAsMissionEntity(npc, true, true)
|
||||||
|
SetBlockingOfNonTemporaryEvents(npc, true)
|
||||||
|
FreezeEntityPosition(npc, true)
|
||||||
|
SetEntityInvincible(npc, true)
|
||||||
|
|
||||||
|
-- Add to spawned NPCs table
|
||||||
|
table.insert(spawnedNPCs, npc)
|
||||||
|
|
||||||
|
-- Add target interaction
|
||||||
|
exports['qb-target']:AddTargetEntity(npc, {
|
||||||
|
options = {
|
||||||
|
{
|
||||||
|
type = "client",
|
||||||
|
event = "tdm:openMenu",
|
||||||
|
icon = "fas fa-gamepad",
|
||||||
|
label = "TeamDeathmatch Menu",
|
||||||
|
fieldId = fieldId
|
||||||
|
}
|
||||||
|
},
|
||||||
|
distance = 2.0
|
||||||
|
})
|
||||||
|
|
||||||
|
debugPrint("Spawned NPC for field: " .. fieldId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register event handler for NPC interaction
|
||||||
|
RegisterNetEvent('tdm:openMenu', function(data)
|
||||||
|
if data.fieldId then
|
||||||
|
openMainMenu(data.fieldId)
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Spawn NPCs when resource starts
|
||||||
|
CreateThread(function()
|
||||||
|
Wait(1000) -- Wait for everything to load
|
||||||
|
spawnFieldNPCs()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Function to create blips for all TDM lobbies
|
||||||
|
function createTDMBlips()
|
||||||
|
for fieldId, fieldData in pairs(Config.gameFields) do
|
||||||
|
if fieldData.lobby and fieldData.lobby.pos then
|
||||||
|
local blip = AddBlipForCoord(fieldData.lobby.pos.x, fieldData.lobby.pos.y, fieldData.lobby.pos.z)
|
||||||
|
SetBlipSprite(blip, 156) -- You can change this to any appropriate sprite
|
||||||
|
SetBlipDisplay(blip, 4)
|
||||||
|
SetBlipScale(blip, 0.8)
|
||||||
|
SetBlipColour(blip, 3)
|
||||||
|
SetBlipAsShortRange(blip, true)
|
||||||
|
BeginTextCommandSetBlipName("STRING")
|
||||||
|
AddTextComponentString("TDM: " .. fieldData.name)
|
||||||
|
EndTextCommandSetBlipName(blip)
|
||||||
|
|
||||||
|
table.insert(tdmBlips, blip)
|
||||||
|
debugPrint("Created blip for TDM field: " .. fieldId)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Call this function when the resource starts
|
||||||
|
CreateThread(function()
|
||||||
|
Wait(2000) -- Wait for everything to load
|
||||||
|
createTDMBlips()
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Cleanup function
|
||||||
|
function cleanupResources()
|
||||||
|
-- Remove NPCs
|
||||||
|
for _, npc in ipairs(spawnedNPCs) do
|
||||||
|
if DoesEntityExist(npc) then
|
||||||
|
DeleteEntity(npc)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
spawnedNPCs = {}
|
||||||
|
|
||||||
|
-- Remove blips
|
||||||
|
for _, blip in ipairs(tdmBlips) do
|
||||||
|
if DoesBlipExist(blip) then
|
||||||
|
RemoveBlip(blip)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
tdmBlips = {}
|
||||||
|
|
||||||
|
debugPrint("Cleaned up all NPCs and blips")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Register cleanup when resource stops
|
||||||
AddEventHandler('onResourceStop', function(resourceName)
|
AddEventHandler('onResourceStop', function(resourceName)
|
||||||
if GetCurrentResourceName() == resourceName then
|
if GetCurrentResourceName() == resourceName then
|
||||||
-- Alle Spieler aus TDM entfernen
|
cleanupResources()
|
||||||
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 = {}
|
|
||||||
debugPrint("TeamDeathmatch System gestoppt!")
|
|
||||||
end
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
-- Admin-Befehle
|
-- Helper function for table.count
|
||||||
RegisterCommand('tdmreset', function(source, args)
|
if not table.count then
|
||||||
local src = source
|
table.count = function(tbl)
|
||||||
if src > 0 then -- Spieler
|
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
|
||||||
if not Player or not Player.PlayerData.job or Player.PlayerData.job.name ~= 'admin' then
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung!', 'error')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- 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 = {}
|
|
||||||
gameIdCounter = 1
|
|
||||||
|
|
||||||
debugPrint("TeamDeathmatch System zurückgesetzt!")
|
|
||||||
|
|
||||||
if src > 0 then
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'TDM System zurückgesetzt!', 'success')
|
|
||||||
end
|
|
||||||
end, true)
|
|
||||||
|
|
||||||
-- Debug-Befehl für Server-Status
|
|
||||||
RegisterCommand('tdmstatus', function(source, args)
|
|
||||||
local src = source
|
|
||||||
if src > 0 then -- Spieler
|
|
||||||
local Player = QBCore.Functions.GetPlayer(src)
|
|
||||||
if not Player or not Player.PlayerData.job or Player.PlayerData.job.name ~= 'admin' then
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'Du hast keine Berechtigung!', 'error')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
debugPrint("=== TDM STATUS ===")
|
|
||||||
debugPrint("Aktive Spiele: " .. table.count(activeGames))
|
|
||||||
|
|
||||||
for gameId, game in pairs(activeGames) do
|
|
||||||
debugPrint("Spiel: " .. gameId .. " - " .. game.name)
|
|
||||||
debugPrint(" Status: " .. game.status)
|
|
||||||
debugPrint(" Feld: " .. game.fieldId)
|
|
||||||
debugPrint(" Team 1: " .. #game.team1 .. " Spieler, Score: " .. game.score.team1)
|
|
||||||
debugPrint(" Team 2: " .. #game.team2 .. " Spieler, Score: " .. game.score.team2)
|
|
||||||
end
|
|
||||||
|
|
||||||
if src > 0 then
|
|
||||||
TriggerClientEvent('QBCore:Notify', src, 'TDM Status in Server-Konsole', 'info')
|
|
||||||
end
|
|
||||||
end, true)
|
|
||||||
|
|
||||||
-- Hilfsfunktion für table.count
|
|
||||||
table.count = function(tbl)
|
|
||||||
local count = 0
|
local count = 0
|
||||||
for _, _ in pairs(tbl) do
|
for _, _ in pairs(tbl) do
|
||||||
count = count + 1
|
count = count + 1
|
||||||
end
|
end
|
||||||
return count
|
return count
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -183,20 +183,19 @@ RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, attackerId)
|
||||||
game.playerStats[victim] = {hits = 0, deaths = 0}
|
game.playerStats[victim] = {hits = 0, deaths = 0}
|
||||||
end
|
end
|
||||||
|
|
||||||
if attackerId and not game.playerStats[attackerId] then
|
-- Wichtig: Nur wenn ein Angreifer identifiziert wurde, zähle den Kill
|
||||||
|
if attackerId then
|
||||||
|
if not game.playerStats[attackerId] then
|
||||||
game.playerStats[attackerId] = {hits = 0, deaths = 0}
|
game.playerStats[attackerId] = {hits = 0, deaths = 0}
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Stats updaten
|
-- Stats updaten
|
||||||
game.playerStats[victim].deaths = (game.playerStats[victim].deaths or 0) + 1
|
game.playerStats[victim].deaths = (game.playerStats[victim].deaths or 0) + 1
|
||||||
|
|
||||||
if attackerId then
|
|
||||||
game.playerStats[attackerId].hits = (game.playerStats[attackerId].hits or 0) + 1
|
game.playerStats[attackerId].hits = (game.playerStats[attackerId].hits or 0) + 1
|
||||||
|
|
||||||
|
-- Benachrichtigung an den Angreifer senden
|
||||||
TriggerClientEvent('tdm:hitRegistered', attackerId)
|
TriggerClientEvent('tdm:hitRegistered', attackerId)
|
||||||
debugPrint("Treffer von " .. attackerId .. " gegen " .. victim .. " registriert")
|
debugPrint("Treffer von " .. attackerId .. " gegen " .. victim .. " registriert")
|
||||||
else
|
|
||||||
debugPrint("Treffer gegen " .. victim .. " von unbekanntem Angreifer registriert")
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Team Score erhöhen
|
-- Team Score erhöhen
|
||||||
if victimTeam == 'team1' then
|
if victimTeam == 'team1' then
|
||||||
|
@ -206,6 +205,9 @@ RegisterNetEvent('tdm:playerWasHit', function(gameId, victimTeam, attackerId)
|
||||||
game.score.team1 = game.score.team1 + 1
|
game.score.team1 = game.score.team1 + 1
|
||||||
debugPrint("Punkt für Team 1 - Neuer Score: " .. game.score.team1)
|
debugPrint("Punkt für Team 1 - Neuer Score: " .. game.score.team1)
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
debugPrint("Treffer gegen " .. victim .. " von unbekanntem Angreifer registriert - Kein Punkt vergeben")
|
||||||
|
end
|
||||||
|
|
||||||
TriggerClientEvent('tdm:deathRegistered', victim)
|
TriggerClientEvent('tdm:deathRegistered', victim)
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue