forked from Simnation/Main
244 lines
6.5 KiB
Lua
244 lines
6.5 KiB
Lua
Utils = {}
|
|
|
|
function Utils:CreateAndAttachWeapon(weaponName, weaponVal, coords, playerPed, isOtherPlayer)
|
|
if not isOtherPlayer and Sling.currentAttachedAmount >= Config.MaxWeaponsAttached then
|
|
Debug("warn", "Max weapons attached reached")
|
|
return false
|
|
end
|
|
|
|
if not weaponVal or not weaponVal.name then
|
|
Debug("error", "Invalid weapon data")
|
|
return false
|
|
end
|
|
|
|
-- Initialize the cached attachments for this weapon if it doesn't exist
|
|
if not Sling.cachedAttachments[weaponName] then
|
|
Sling.cachedAttachments[weaponName] = {}
|
|
end
|
|
|
|
local weaponObject = CreateWeaponObject(weaponVal.name, 0, coords.coords.x, coords.coords.y, coords.coords.z, true, 1.0, 0)
|
|
if not weaponObject then
|
|
Debug("error", "Failed to create weapon object")
|
|
return false
|
|
end
|
|
|
|
if NetworkGetEntityIsNetworked(weaponObject) then
|
|
NetworkUnregisterNetworkedEntity(weaponObject)
|
|
end
|
|
|
|
SetEntityCollision(weaponObject, false, false)
|
|
|
|
if not isOtherPlayer and Config.UseWeaponAttachments then
|
|
weaponVal.attachments = Inventory:GetWeaponAttachment(weaponName)
|
|
end
|
|
|
|
for _, component in pairs(weaponVal.attachments or {}) do
|
|
GiveWeaponComponentToWeaponObject(weaponObject, component)
|
|
end
|
|
|
|
lib.requestModel(weaponVal.model)
|
|
|
|
local placeholder = CreateObjectNoOffset(weaponVal.model, coords.coords.x, coords.coords.y, coords.coords.z, true, true, false)
|
|
SetEntityCollision(placeholder, false, false)
|
|
SetEntityAlpha(placeholder, 0, false)
|
|
|
|
local boneIndex = GetPedBoneIndex(playerPed, (coords.boneId or DEFAULT_BONE))
|
|
|
|
AttachEntityToEntity(placeholder, playerPed, boneIndex,
|
|
coords.coords.x, coords.coords.y, coords.coords.z,
|
|
coords.rot.x, coords.rot.y, coords.rot.z,
|
|
true, true, false, true, 2, true)
|
|
|
|
AttachEntityToEntity(weaponObject, placeholder, GetEntityBoneIndexByName(placeholder, "gun_root"),
|
|
0.0, 0.0, 0.0,
|
|
0.0, 0.0, 0.0,
|
|
true, true, false, true, 2, true)
|
|
|
|
Sling.cachedAttachments[weaponName].obj = weaponObject
|
|
Sling.cachedAttachments[weaponName].placeholder = placeholder
|
|
if not isOtherPlayer then
|
|
Sling.currentAttachedAmount = Sling.currentAttachedAmount + 1
|
|
end
|
|
|
|
SetModelAsNoLongerNeeded(weaponVal.model)
|
|
|
|
return true
|
|
end
|
|
|
|
function Utils:DeleteWeapon(weaponName)
|
|
if not Sling.cachedAttachments[weaponName] then return end
|
|
|
|
local attachment = Sling.cachedAttachments[weaponName]
|
|
|
|
if attachment.obj and DoesEntityExist(attachment.obj) then
|
|
if NetworkGetEntityIsNetworked(attachment.obj) then
|
|
NetworkUnregisterNetworkedEntity(attachment.obj)
|
|
end
|
|
DeleteObject(attachment.obj)
|
|
end
|
|
|
|
if attachment.placeholder then
|
|
if IsEntityAttachedToAnyPed(attachment.placeholder) then
|
|
DetachEntity(attachment.placeholder, true, false)
|
|
end
|
|
if DoesEntityExist(attachment.placeholder) then
|
|
DeleteObject(attachment.placeholder)
|
|
end
|
|
end
|
|
|
|
Sling.cachedAttachments[weaponName] = nil
|
|
|
|
-- Nur verringern, wenn es keine Waffe eines anderen Spielers ist
|
|
if not string.find(weaponName, '_') then
|
|
Sling.currentAttachedAmount = math.max(0, Sling.currentAttachedAmount - 1)
|
|
end
|
|
end
|
|
|
|
function Utils:Debug(type, message)
|
|
if not Config.Debug then return end
|
|
|
|
if type == "error" then
|
|
print("^1[ERROR] " .. message .. "^7")
|
|
elseif type == "success" then
|
|
print("^2[SUCCESS] " .. message .. "^7")
|
|
elseif type == "info" then
|
|
print("^5[INFO] " .. message .. "^7")
|
|
elseif type == "warn" then
|
|
print("^3[WARN] " .. message .. "^7")
|
|
end
|
|
end
|
|
|
|
function Utils:Round(num, numDecimalPlaces)
|
|
local mult = 10^(numDecimalPlaces or 0)
|
|
return math.floor(num * mult + 0.5) / mult
|
|
end
|
|
|
|
function Utils:TableContains(table, element)
|
|
for _, value in pairs(table) do
|
|
if value == element then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
function Utils:GetTableLength(table)
|
|
local count = 0
|
|
for _ in pairs(table) do
|
|
count = count + 1
|
|
end
|
|
return count
|
|
end
|
|
|
|
function Utils:DeepCopy(orig)
|
|
local orig_type = type(orig)
|
|
local copy
|
|
if orig_type == 'table' then
|
|
copy = {}
|
|
for orig_key, orig_value in next, orig, nil do
|
|
copy[Utils:DeepCopy(orig_key)] = Utils:DeepCopy(orig_value)
|
|
end
|
|
setmetatable(copy, Utils:DeepCopy(getmetatable(orig)))
|
|
else
|
|
copy = orig
|
|
end
|
|
return copy
|
|
end
|
|
|
|
function Utils:MergeTable(t1, t2)
|
|
for k, v in pairs(t2) do
|
|
if type(v) == "table" and type(t1[k] or false) == "table" then
|
|
Utils:MergeTable(t1[k], t2[k])
|
|
else
|
|
t1[k] = v
|
|
end
|
|
end
|
|
return t1
|
|
end
|
|
|
|
function Utils:GetDistance(coords1, coords2)
|
|
return #(coords1 - coords2)
|
|
end
|
|
|
|
function Utils:DrawText3D(coords, text)
|
|
local onScreen, _x, _y = World3dToScreen2d(coords.x, coords.y, coords.z)
|
|
local px, py, pz = table.unpack(GetGameplayCamCoords())
|
|
local dist = #(vector3(px, py, pz) - coords)
|
|
|
|
local scale = (1 / dist) * 2
|
|
local fov = (1 / GetGameplayCamFov()) * 100
|
|
local scale = scale * fov
|
|
|
|
if onScreen then
|
|
SetTextScale(0.0 * scale, 0.55 * scale)
|
|
SetTextFont(0)
|
|
SetTextProportional(1)
|
|
SetTextColour(255, 255, 255, 255)
|
|
SetTextDropshadow(0, 0, 0, 0, 255)
|
|
SetTextEdge(2, 0, 0, 0, 150)
|
|
SetTextDropShadow()
|
|
SetTextOutline()
|
|
SetTextEntry("STRING")
|
|
SetTextCentre(1)
|
|
AddTextComponentString(text)
|
|
DrawText(_x,_y)
|
|
end
|
|
end
|
|
|
|
function Utils:LoadAnimDict(dict)
|
|
while not HasAnimDictLoaded(dict) do
|
|
RequestAnimDict(dict)
|
|
Wait(5)
|
|
end
|
|
end
|
|
|
|
function Utils:PlayAnim(ped, dict, anim, settings)
|
|
if not settings then settings = {} end
|
|
|
|
Utils:LoadAnimDict(dict)
|
|
|
|
TaskPlayAnim(ped, dict, anim,
|
|
settings.blendInSpeed or 3.0,
|
|
settings.blendOutSpeed or 3.0,
|
|
settings.duration or -1,
|
|
settings.flag or 49,
|
|
settings.playbackRate or 0,
|
|
settings.lockX or false,
|
|
settings.lockY or false,
|
|
settings.lockZ or false
|
|
)
|
|
|
|
RemoveAnimDict(dict)
|
|
end
|
|
|
|
function Utils:CreateBlip(coords, sprite, color, text, scale, category)
|
|
local blip = AddBlipForCoord(coords.x, coords.y, coords.z)
|
|
SetBlipSprite(blip, sprite)
|
|
SetBlipDisplay(blip, 4)
|
|
SetBlipScale(blip, scale or 0.8)
|
|
SetBlipColour(blip, color)
|
|
SetBlipAsShortRange(blip, true)
|
|
if category then
|
|
SetBlipCategory(blip, category)
|
|
end
|
|
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentString(text)
|
|
EndTextCommandSetBlipName(blip)
|
|
|
|
return blip
|
|
end
|
|
|
|
function Utils:DrawMarker(type, coords, size, color, bobUpAndDown)
|
|
DrawMarker(
|
|
type,
|
|
coords.x, coords.y, coords.z,
|
|
0.0, 0.0, 0.0,
|
|
0.0, 0.0, 0.0,
|
|
size.x, size.y, size.z,
|
|
color.r, color.g, color.b, color.a,
|
|
false, bobUpAndDown or false, 2, false, nil, nil, false
|
|
)
|
|
end
|
|
|
|
|