225 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			225 lines
		
	
	
	
		
			9.1 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| 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)
 | 
