diff --git a/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ydr b/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ydr new file mode 100644 index 000000000..6a6d34b3d Binary files /dev/null and b/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ydr differ diff --git a/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ytd b/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ytd new file mode 100644 index 000000000..fe5bfbf57 Binary files /dev/null and b/resources/[jobs]/[weapons]/weapons/stream/w_ar_carbinerifle_mag2.ytd differ diff --git a/resources/[tools]/pickle_throwables-1.0.1/README.md b/resources/[tools]/pickle_throwables-1.0.1/README.md new file mode 100644 index 000000000..1b8af097f --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/README.md @@ -0,0 +1,2 @@ +# pickle_throwables +A multi-framework and standalone throwing script, great for football, soccer and other sports. diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/baseball.png b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/baseball.png new file mode 100644 index 000000000..c0842b7ef Binary files /dev/null and b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/baseball.png differ diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/basketball.png b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/basketball.png new file mode 100644 index 000000000..3f9d52a67 Binary files /dev/null and b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/basketball.png differ diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/football.png b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/football.png new file mode 100644 index 000000000..0d8c0b246 Binary files /dev/null and b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/football.png differ diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/soccer.png b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/soccer.png new file mode 100644 index 000000000..8bf2dc82c Binary files /dev/null and b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Images/soccer.png differ diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_limit.sql b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_limit.sql new file mode 100644 index 000000000..ff5318d0d --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_limit.sql @@ -0,0 +1,6 @@ +INSERT INTO `items` (`name`, `label`, `limit`) VALUES + ('football', 'Football', 100), + ('basketball', 'Basketball', 100), + ('baseball', 'Baseball', 100), + ('soccer', 'Soccer Ball', 100), +; \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_weight.sql b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_weight.sql new file mode 100644 index 000000000..ea10f901a --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/esx_weight.sql @@ -0,0 +1,6 @@ +INSERT INTO `items` (`name`, `label`, `weight`) VALUES + ('football', 'Football', 100), + ('basketball', 'Basketball', 100), + ('baseball', 'Baseball', 100), + ('soccer', 'Soccer Ball', 100), +; \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/ox_inventory.lua b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/ox_inventory.lua new file mode 100644 index 000000000..1f2b346b0 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/ox_inventory.lua @@ -0,0 +1,24 @@ +["football"] = { + label = 'Football', + weight = 1, + stack = true, + description = "" +}, +["basketball"] = { + label = 'Basketball', + weight = 1, + stack = true, + description = "" +}, +["baseball"] = { + label = 'Baseball', + weight = 1, + stack = true, + description = "" +}, +["soccer"] = { + label = 'Soccer Ball', + weight = 1, + stack = true, + description = "" +}, \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/qbcore.lua b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/qbcore.lua new file mode 100644 index 000000000..390b4504a --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/_INSTALL/Items/qbcore.lua @@ -0,0 +1,4 @@ +["football"] = {["name"] = "football", ["label"] = "Football", ["weight"] = 1, ["type"] = "item", ["image"] = "football.png", ["unique"] = true, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = ""}, +["basketball"] = {["name"] = "basketball", ["label"] = "Basketball", ["weight"] = 1, ["type"] = "item", ["image"] = "basketball.png", ["unique"] = true, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = ""}, +["baseball"] = {["name"] = "baseball", ["label"] = "Baseball", ["weight"] = 1, ["type"] = "item", ["image"] = "baseball.png", ["unique"] = true, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = ""}, +["soccer"] = {["name"] = "soccer", ["label"] = "Soccer Ball", ["weight"] = 1, ["type"] = "item", ["image"] = "soccer.png", ["unique"] = true, ["useable"] = true, ["shouldClose"] = true, ["combinable"] = nil, ["description"] = ""}, \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/client.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/client.lua new file mode 100644 index 000000000..072f76b74 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/client.lua @@ -0,0 +1,32 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports.es_extended:getSharedObject() + +function ShowNotification(text) + ESX.ShowNotification(text) +end + +function ShowHelpNotification(text) + ESX.ShowHelpNotification(text) +end + +function ServerCallback(name, cb, ...) + ESX.TriggerServerCallback(name, cb, ...) +end + +function GetPlayersInArea(coords, maxDistance) + return ESX.Game.GetPlayersInArea(coords, maxDistance) +end + +function CanAccessGroup(data) + if not data then return true end + local pdata = ESX.GetPlayerData() + for k,v in pairs(data) do + if (pdata.job.name == k and pdata.job.grade >= v) then return true end + end + return false +end + +RegisterNetEvent(GetCurrentResourceName()..":showNotification", function(text) + ShowNotification(text) +end) \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/server.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/server.lua new file mode 100644 index 000000000..cb6289b4a --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/esx/server.lua @@ -0,0 +1,67 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports.es_extended:getSharedObject() + +function RegisterCallback(name, cb) + ESX.RegisterServerCallback(name, cb) +end + +function RegisterUsableItem(...) + ESX.RegisterUsableItem(...) +end + +function ShowNotification(target, text) + TriggerClientEvent(GetCurrentResourceName()..":showNotification", target, text) +end + +function Search(source, name) + local xPlayer = ESX.GetPlayerFromId(source) + if (name == "money") then + return xPlayer.getMoney() + elseif (name == "bank") then + return xPlayer.getAccount('bank').money + else + local item = xPlayer.getInventoryItem(name) + if item ~= nil then + return item.count + else + return 0 + end + end +end + +function AddItem(source, name, amount) + local xPlayer = ESX.GetPlayerFromId(source) + if (name == "money") then + return xPlayer.addMoney(amount) + elseif (name == "bank") then + return xPlayer.addAccountMoney('bank', amount) + else + return xPlayer.addInventoryItem(name, amount) + end +end + +function RemoveItem(source, name, amount) + local xPlayer = ESX.GetPlayerFromId(source) + if (name == "money") then + return xPlayer.removeMoney(amount) + elseif (name == "bank") then + return xPlayer.removeAccountMoney('bank', amount) + else + return xPlayer.removeInventoryItem(name, amount) + end +end + +function CanAccessGroup(source, data) + if not data then return true end + local pdata = ESX.GetPlayerFromId(source) + for k,v in pairs(data) do + if (pdata.job.name == k and pdata.job.grade >= v) then return true end + end + return false +end + +function GetIdentifier(source) + local xPlayer = ESX.GetPlayerFromId(source) + return xPlayer.identifier +end \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/client.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/client.lua new file mode 100644 index 000000000..5135c790e --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/client.lua @@ -0,0 +1,34 @@ +if GetResourceState('qb-core') ~= 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +function ServerCallback(name, cb, ...) + QBCore.Functions.TriggerCallback(name, cb, ...) +end + +function ShowNotification(text) + QBCore.Functions.Notify(text) +end + +function ShowHelpNotification(text) + AddTextEntry('qbHelpNotification', text) + BeginTextCommandDisplayHelp('qbHelpNotification') + EndTextCommandDisplayHelp(0, false, false, -1) +end + +function GetPlayersInArea(coords, maxDistance) + return QBCore.Functions.GetPlayersFromCoords(coords, maxDistance) +end + +function CanAccessGroup(data) + if not data then return true end + local pdata = QBCore.Functions.GetPlayerData() + for k,v in pairs(data) do + if (pdata.job.name == k and pdata.job.grade.level >= v) then return true end + end + return false +end + +RegisterNetEvent(GetCurrentResourceName()..":showNotification", function(text) + ShowNotification(text) +end) \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/server.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/server.lua new file mode 100644 index 000000000..1e8dde7b0 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/qb/server.lua @@ -0,0 +1,67 @@ +if GetResourceState('qb-core') ~= 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +function RegisterCallback(name, cb) + QBCore.Functions.CreateCallback(name, cb) +end + +function RegisterUsableItem(...) + QBCore.Functions.CreateUseableItem(...) +end + +function ShowNotification(target, text) + TriggerClientEvent(GetCurrentResourceName()..":showNotification", target, text) +end + +function Search(source, name) + local xPlayer = QBCore.Functions.GetPlayer(source) + if (name == "money") then + return xPlayer.PlayerData.money['cash'] + elseif (name == "bank") then + return xPlayer.PlayerData.money['cash'] -- If anyone knows how to get bank balance for QBCore, let me know. + else + local item = xPlayer.Functions.GetItemByName(name) + if item ~= nil then + return item.amount + else + return 0 + end + end +end + +function AddItem(source, name, amount) + local xPlayer = QBCore.Functions.GetPlayer(source) + if (name == "money") then + return xPlayer.Functions.AddMoney("cash", amount) + elseif (name == "bank") then + return xPlayer.Functions.AddMoney("cash", amount) -- If anyone knows how to add to bank balance for QBCore, let me know. + else + return xPlayer.Functions.AddItem(name, amount) + end +end + +function RemoveItem(source, name, amount) + local xPlayer = QBCore.Functions.GetPlayer(source) + if (name == "money") then + return xPlayer.Functions.RemoveMoney("cash", amount) + elseif (name == "bank") then + return xPlayer.Functions.RemoveMoney("cash", amount) -- If anyone knows how to remove from bank balance for QBCore, let me know. + else + return xPlayer.Functions.RemoveItem(name, amount) + end +end + +function CanAccessGroup(source, data) + if not data then return true end + local pdata = QBCore.Functions.GetPlayer(source).PlayerData + for k,v in pairs(data) do + if (pdata.job.name == k and pdata.job.grade.level >= v) then return true end + end + return false +end + +function GetIdentifier(source) + local xPlayer = QBCore.Functions.GetPlayer(source).PlayerData + return xPlayer.citizenid +end \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/client.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/client.lua new file mode 100644 index 000000000..89c1cd1ff --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/client.lua @@ -0,0 +1,4 @@ +if GetResourceState('es_extended') == 'started' then return end +if GetResourceState('qb-core') == 'started' then return end + +print("You are not using a supported framework, it will be required to make edits to the bridge files.") \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/server.lua b/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/server.lua new file mode 100644 index 000000000..89c1cd1ff --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/bridge/standalone/server.lua @@ -0,0 +1,4 @@ +if GetResourceState('es_extended') == 'started' then return end +if GetResourceState('qb-core') == 'started' then return end + +print("You are not using a supported framework, it will be required to make edits to the bridge files.") \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/config.lua b/resources/[tools]/pickle_throwables-1.0.1/config.lua new file mode 100644 index 000000000..c268f0451 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/config.lua @@ -0,0 +1,41 @@ +Config = {} + +Config.Debug = true + +Config.Language = "en" + +Config.RenderDistance = 20.0 +Config.CatchRadius = 2.5 + +Config.CommandSpawning = false -- Set this to true if you want to be able to get throwables without using items. + +Config.CommandSpawnCheck = function() + return true +end + +Config.Throwables = { + ["football"] = { + item = "football", + entityType = "object", -- "object", "vehicle", "ped" + model = `p_ld_am_ball_01`, + maxThrowingPower = 200 + }, + ["basketball"] = { + item = "basketball", + entityType = "object", -- "object", "vehicle", "ped" + model = `prop_bskball_01`, + maxThrowingPower = 200 + }, + ["baseball"] = { + item = "baseball", + entityType = "object", -- "object", "vehicle", "ped" + model = `w_am_baseball`, + maxThrowingPower = 200 + }, + ["soccer"] = { + item = "soccer", + entityType = "object", -- "object", "vehicle", "ped" + model = `p_ld_soc_ball_01`, + maxThrowingPower = 200 + }, +} \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/core/client.lua b/resources/[tools]/pickle_throwables-1.0.1/core/client.lua new file mode 100644 index 000000000..9d8d66a79 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/core/client.lua @@ -0,0 +1,70 @@ +function ModelRequest(modelHash) + if not IsModelInCdimage(modelHash) then return end + RequestModel(modelHash) + local loaded + for i=1, 100 do + if HasModelLoaded(modelHash) then + loaded = true + break + end + Wait(100) + end + return loaded +end + +function CreateVeh(modelHash, ...) + if not ModelRequest(modelHash) then + print("Couldn't load model: " .. modelHash) + return + end + local veh = CreateVehicle(modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return veh +end + +function CreateNPC(modelHash, ...) + if not ModelRequest(modelHash) then + print("Couldn't load model: " .. modelHash) + return + end + local ped = CreatePed(26, modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return ped +end + +function CreateProp(modelHash, ...) + if not ModelRequest(modelHash) then + print("Couldn't load model: " .. modelHash) + return + end + local obj = CreateObject(modelHash, ...) + SetModelAsNoLongerNeeded(modelHash) + return obj +end + +function PlayAnim(ped, dict, ...) + RequestAnimDict(dict) + while not HasAnimDictLoaded(dict) do Wait(0) end + TaskPlayAnim(ped, dict, ...) +end + +local interactTick = 0 +local interactThread = false +local interactText = nil + +function ShowInteractText(text) + interactTick = GetGameTimer() + lib.showTextUI(text) + if interactThread then return end + interactThread = true + CreateThread(function() + while interactThread do + if GetGameTimer() - interactTick > 20 then + interactThread = false + break + end + Citizen.Wait(150) + end + lib.hideTextUI() + end) +end \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/core/shared.lua b/resources/[tools]/pickle_throwables-1.0.1/core/shared.lua new file mode 100644 index 000000000..30e73a828 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/core/shared.lua @@ -0,0 +1,10 @@ +function v3(coords) return vec3(coords.x, coords.y, coords.z), coords.w end + +function GetRandomInt(min, max, exclude) + for i=1, 1000 do + local int = math.random(min, max) + if exclude == nil or exclude ~= int then + return int + end + end +end \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/fxmanifest.lua b/resources/[tools]/pickle_throwables-1.0.1/fxmanifest.lua new file mode 100644 index 000000000..2f591bfb1 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/fxmanifest.lua @@ -0,0 +1,28 @@ +fx_version 'cerulean' +lua54 'yes' +game 'gta5' + +name 'pickle_throwables' +version '1.0.0' +description 'A multi-framework and standalone throwing script, great for football, soccer and other sports.' +author 'Pickle Mods' + +shared_scripts { + '@ox_lib/init.lua', + 'config.lua', + 'core/shared.lua', + "locales/locale.lua", + "locales/translations/*.lua", + 'modules/**/shared.lua', +} + +server_scripts { + 'bridge/**/server.lua', + 'modules/**/server.lua', +} + +client_scripts { + 'core/client.lua', + 'bridge/**/client.lua', + 'modules/**/client.lua', +} \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/locales/locale.lua b/resources/[tools]/pickle_throwables-1.0.1/locales/locale.lua new file mode 100644 index 000000000..0cab5e5f0 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/locales/locale.lua @@ -0,0 +1,14 @@ +Language = {} + +function _L(name, ...) + if name then + local str = Language[Config.Language][name] + if str then + return string.format(str, ...) + else + return "ERR_TRANSLATE_"..(name).."_404" + end + else + return "ERR_TRANSLATE_404" + end +end \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/locales/translations/en.lua b/resources/[tools]/pickle_throwables-1.0.1/locales/translations/en.lua new file mode 100644 index 000000000..a8e884aad --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/locales/translations/en.lua @@ -0,0 +1,5 @@ +Language["en"] = { + throwable_interact = "[E] - Take Object \n [G] - Kick \n Power: %s", + throwable_list = "[E] - Throw \n [G] - Drop \n [H] - Handoff \n Power: %s", + throwable_list_alt = "[E] - Throw \n [G] - Drop \n [H] - Inventory \n Power: %s", +} \ No newline at end of file diff --git a/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/client.lua b/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/client.lua new file mode 100644 index 000000000..2bc9742b3 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/client.lua @@ -0,0 +1,225 @@ +local ThrowingPower = 1 +local Throwables = {} +local canInteract = true +local attemptingCatch = false +local holdingBall = nil + +function GetClosestPlayer(coords, radius) + local closest + local coords = coords or GetEntityCoords(PlayerPedId()) + local radius = radius or 2.0 + for _, player in ipairs(GetActivePlayers()) do + local ped = GetPlayerPed(player) + if PlayerPedId() ~= ped then + local pedCoords = GetEntityCoords(ped) + local distance = #(coords - pedCoords) + if distance < radius and (not closest or closest.distance > distance) then + closest = {player = player, distance = distance} + end + end + end + return closest?.player, closest?.distance +end + +function GetDirectionFromRotation(rotation) + local dm = (math.pi / 180) + return vector3(-math.sin(dm * rotation.z) * math.abs(math.cos(dm * rotation.x)), math.cos(dm * rotation.z) * math.abs(math.cos(dm * rotation.x)), math.sin(dm * rotation.x)) +end + +function PerformPhysics(throwType, entity, action) + local cfg = Config.Throwables[throwType] + local power = (ThrowingPower / 10) * cfg.maxThrowingPower + FreezeEntityPosition(entity, false) + local rot = GetGameplayCamRot(2) + local dir = GetDirectionFromRotation(rot) + SetEntityHeading(entity, rot.z + 90.0) + if not action or action == "throw" then + SetEntityVelocity(entity, dir.x * power, dir.y * power, dir.z * power) + else + SetEntityVelocity(entity, dir.x * power, dir.y * power, (dir.z * 1.75) * power) + end +end + +function CreateThrowable(throwType, attach) + local cfg = Config.Throwables[throwType] + local ped = PlayerPedId() + local model = cfg.model + local heading = GetEntityHeading(ped) + local coords = GetOffsetFromEntityInWorldCoords(ped, 0.0, 1.0, 0.5) + local prop + if cfg.entityType == "object" then + prop = CreateProp(model, coords.x, coords.y, coords.z, true, true, true) + elseif cfg.entityType == "vehicle" then + prop = CreateVeh(model, coords.x, coords.y, coords.z, true, true, true) + elseif cfg.entityType == "ped" then + prop = CreateNPC(model, coords.x, coords.y, coords.z, true, true, true) + end + if not prop then return end + if attach then + local off, rot = vector3(0.05, 0.0, -0.085), vector3(90.0, 90.0, 0.0) + AttachEntityToEntity(prop, ped, GetPedBoneIndex(ped, 28422), off.x, off.y, off.z, rot.x, rot.y, rot.z, false, false, false, true, 2, true) + else + local coords = GetOffsetFromEntityInWorldCoords(ped, 0.0, 1.0, -0.9) + SetEntityCoords(prop, coords.x, coords.y, coords.z) + end + return prop +end + +function HoldThrowable(throwType) + local ped = PlayerPedId() + if holdingBall then return end + local prop = CreateThrowable(throwType, true) + holdingBall = prop + CreateThread(function() + while holdingBall do + local player, dist = GetClosestPlayer() + if player then + ShowInteractText(_L("throwable_list", ThrowingPower .. "/" .. 10)) + else + ShowInteractText(_L("throwable_list_alt", ThrowingPower .. "/" .. 10)) + end + if IsControlJustPressed(1, 51) then + CreateThread(function() + PlayAnim(ped, "melee@thrown@streamed_core", "plyr_takedown_front", -8.0, 8.0, -1, 49) + Wait(600) + ClearPedTasks(ped) + end) + Wait(550) + DetachEntity(prop, false, true) + SetEntityCollision(prop, true, true) + SetEntityRecordsCollisions(prop, true) + TriggerServerEvent("pickle_throwables:throwObject", {throwType = throwType, net_id = ObjToNet(prop)}) + local coords = GetOffsetFromEntityInWorldCoords(ped, 0.0, 0.0, 1.0) + SetEntityCoords(prop, coords.x, coords.y, coords.z) + SetEntityHeading(prop, GetEntityHeading(ped) + 90.0) + PerformPhysics(throwType, prop) + holdingBall = nil + elseif IsControlJustPressed(1, 47) then + PlayAnim(ped, "pickup_object", "pickup_low", -8.0, 8.0, -1, 49, 1.0) + Wait(800) + DetachEntity(prop, true, true) + SetEntityCollision(prop, true, true) + SetEntityRecordsCollisions(prop, true) + ActivatePhysics(prop) + TriggerServerEvent("pickle_throwables:throwObject", {throwType = throwType, net_id = ObjToNet(prop)}) + Wait(800) + ClearPedTasks(ped) + holdingBall = nil + elseif IsControlJustPressed(1, 74) then + if player then + ServerCallback("pickle_throwables:giveObject", function(result) + if not result then return end + DeleteEntity(prop) + holdingBall = nil + PlayAnim(PlayerPedId(), "mp_common", "givetake1_b", -8.0, 8.0, -1, 49, 1.0) + Wait(1600) + ClearPedTasks(ped) + end, GetPlayerServerId(player)) + else + ServerCallback("pickle_throwables:storeObject", function(result) + if not result then return end + PlayAnim(PlayerPedId(), "pickup_object", "putdown_low", -8.0, 8.0, -1, 49, 1.0) + Wait(1600) + ClearPedTasks(ped) + DeleteEntity(prop) + holdingBall = nil + end) + end + end + PowerControls() + Wait(0) + end + end) +end + +function CatchObject(index, cb) + if attemptingCatch then return end + attemptingCatch = true + local data = Throwables[index] + local entity = NetToObj(data.net_id) + SetEntityCollision(entity, false, false) + DeleteEntity(entity) + ServerCallback("pickle_throwables:catchObject", cb, index) + Wait(100) + attemptingCatch = false +end + +function PowerControls() + if IsControlJustPressed(1, 181) then + ThrowingPower = (ThrowingPower + 1 > 10 and 10 or ThrowingPower + 1) + elseif IsControlJustPressed(1, 180) then + ThrowingPower = (ThrowingPower - 1 < 1 and 1 or ThrowingPower - 1) + end +end + +function 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[deepcopy(orig_key)] = deepcopy(orig_value) + end + setmetatable(copy, deepcopy(getmetatable(orig))) + else -- number, string, boolean, etc + copy = orig + end + return copy +end + +CreateThread(function() + while true do + local wait = 1000 + local ped = PlayerPedId() + local throwables = deepcopy(Throwables) + for k,v in pairs(throwables) do + if NetworkDoesNetworkIdExist(v.net_id) then + local entity = NetToObj(v.net_id) + local dist = #(GetEntityCoords(ped) - GetEntityCoords(entity)) + if dist < Config.RenderDistance then + wait = 0 + if not holdingBall and canInteract and dist < Config.CatchRadius and not ShowInteractText(_L("throwable_interact", ThrowingPower .. "/" .. 10)) then + if IsControlJustPressed(1, 51) then + CatchObject(k, function(result) + if not result then return end + HoldThrowable(v.throwType) + end) + elseif IsControlJustPressed(1, 47) then + CatchObject(k, function(result) + if not result then return end + canInteract = false + local prop = CreateThrowable(v.throwType, false) + TriggerServerEvent("pickle_throwables:throwObject", {throwType = v.throwType, net_id = ObjToNet(prop)}) + --FreezeEntityPosition(ped, true) + --PlayAnim(ped, "melee@unarmed@streamed_core", "ground_attack_0", -8.0, 8.0, -1, 33, 1.0) + --Wait(1000) + PerformPhysics(v.throwType, prop, "kick") + --Wait(600) + --ClearPedTasks(ped) + --FreezeEntityPosition(ped, false) + canInteract = true + end) + end + PowerControls() + end + end + end + end + Wait(wait) + end +end) + +RegisterNetEvent("pickle_throwables:giveObject", function(data) + HoldThrowable(data.throwType) +end) + +RegisterNetEvent("pickle_throwables:setObjectData", function(throwID, data) + Throwables[throwID] = data +end) + +AddEventHandler("onResourceStop", function(name) + if (GetCurrentResourceName() ~= name) then return end + for k,v in pairs(Throwables) do + DeleteEntity(NetToObj(v.net_id)) + end +end) diff --git a/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/server.lua b/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/server.lua new file mode 100644 index 000000000..7030fa7a4 --- /dev/null +++ b/resources/[tools]/pickle_throwables-1.0.1/modules/throwables/server.lua @@ -0,0 +1,73 @@ +local Throwables = {} +local Carrying = {} + +function GiveObject(source, data, timeout) + Carrying[source] = data + if timeout then + SetTimeout(1600, function() + TriggerClientEvent("pickle_throwables:giveObject", source, data) + end) + else + TriggerClientEvent("pickle_throwables:giveObject", source, data) + end +end + +RegisterNetEvent("pickle_throwables:throwObject", function(data) + local source = source + if not Carrying[source] then return end + Carrying[source] = nil + local throwID = nil + repeat + throwID = os.time() .. "_" .. math.random(1000, 9999) + until not Throwables[throwID] + Throwables[throwID] = data + TriggerClientEvent("pickle_throwables:setObjectData", -1, throwID, data) +end) + +RegisterCallback("pickle_throwables:catchObject", function(source, cb, throwID) + if Carrying[source] then return cb(false) end + if not Throwables[throwID] then return cb(false) end + local entity = NetworkGetEntityFromNetworkId(Throwables[throwID].net_id) + Carrying[source] = {throwType = Throwables[throwID].throwType} + DeleteEntity(entity) + Throwables[throwID] = nil + TriggerClientEvent("pickle_throwables:setObjectData", -1, throwID, nil) + cb(true) +end) + +RegisterCallback("pickle_throwables:storeObject", function(source, cb) + if not Carrying[source] then return cb(false) end + local data = Carrying[source] + local cfg = Config.Throwables[data.throwType] + Carrying[source] = nil + if cfg.item and not Config.CommandSpawning then + AddItem(source, cfg.item, 1) + end + cb(true) +end) + +RegisterCallback("pickle_throwables:giveObject", function(source, cb, target) + if not Carrying[source] or Carrying[target] then return cb(false) end + local data = Carrying[source] + GiveObject(target, {throwType = data.throwType}, true) + Carrying[source] = nil + cb(true) +end) + +if Config.CommandSpawning then + RegisterCommand("spawnthrowable", function(source, args, raw) + if not args[1] or not Config.Throwables[args[1]] then return end + if not Config.CommandSpawnCheck(source, args[1]) then return end + GiveObject(source, {throwType = args[1]}) + end) +else + for k,v in pairs(Config.Throwables) do + if v.item then + RegisterUsableItem(v.item, function(source) + if Carrying[source] then return end + RemoveItem(source, v.item, 1) + GiveObject(source, {throwType = k}) + end) + end + end +end \ No newline at end of file