Scripts/resources/[standalone]/dpemotes/client/Syncing.lua

256 lines
10 KiB
Lua
Raw Normal View History

2024-12-29 20:02:20 +00:00
local isRequestAnim = false
local requestedemote = ''
local targetPlayerId = ''
-- Some of the work here was done by Super.Cool.Ninja / rubbertoe98
-- https://forum.fivem.net/t/release-nanimstarget/876709
-----------------------------------------------------------------------------------------------------
-- Commands / Events --------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
if Config.SharedEmotesEnabled then
RegisterCommand('nearby', function(source, args, raw)
if #args > 0 then
local emotename = string.lower(args[1])
target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
if RP.Shared[emotename] ~= nil then
dict, anim, ename = table.unpack(RP.Shared[emotename])
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), emotename)
SimpleNotify(Config.Languages[lang]['sentrequestto'] ..
GetPlayerName(target) .. " ~w~(~g~" .. ename .. "~w~)")
else
EmoteChatMessage("'" .. emotename .. "' " .. Config.Languages[lang]['notvalidsharedemote'] .. "")
end
else
SimpleNotify(Config.Languages[lang]['nobodyclose'])
end
else
NearbysOnCommand()
end
end, false)
end
RegisterNetEvent("SyncPlayEmote")
AddEventHandler("SyncPlayEmote", function(emote, player)
EmoteCancel()
Wait(300)
targetPlayerId = player
-- wait a little to make sure animation shows up right on both clients after canceling any previous emote
if RP.Shared[emote] ~= nil then
if RP.Shared[emote].AnimationOptions and RP.Shared[emote].AnimationOptions.Attachto then
-- We do not want to attach the player if the target emote already is attached to player
-- this would cause issue where both player would be attached to each other and fall under the map
local targetEmote = RP.Shared[emote][4]
if not targetEmote or not RP.Shared[targetEmote] or not RP.Shared[targetEmote].AnimationOptions or
not RP.Shared[targetEmote].AnimationOptions.Attachto then
local plyServerId = GetPlayerFromServerId(player)
local ply = PlayerPedId()
local pedInFront = GetPlayerPed(plyServerId ~= 0 and plyServerId or GetClosestPlayer())
local bone = RP.Shared[emote].AnimationOptions.bone or -1 -- No bone
local xPos = RP.Shared[emote].AnimationOptions.xPos or 0.0
local yPos = RP.Shared[emote].AnimationOptions.yPos or 0.0
local zPos = RP.Shared[emote].AnimationOptions.zPos or 0.0
local xRot = RP.Shared[emote].AnimationOptions.xRot or 0.0
local yRot = RP.Shared[emote].AnimationOptions.yRot or 0.0
local zRot = RP.Shared[emote].AnimationOptions.zRot or 0.0
AttachEntityToEntity(ply, pedInFront, GetPedBoneIndex(pedInFront, bone), xPos, yPos, zPos, xRot, yRot,
zRot, false, false, false, true, 1, true)
end
end
OnEmotePlay(RP.Shared[emote])
return
elseif RP.Dances[emote] ~= nil then
OnEmotePlay(RP.Dances[emote])
return
end
end)
RegisterNetEvent("SyncPlayEmoteSource")
AddEventHandler("SyncPlayEmoteSource", function(emote, player)
-- Thx to Poggu for this part!
local ply = PlayerPedId()
local plyServerId = GetPlayerFromServerId(player)
local pedInFront = GetPlayerPed(plyServerId ~= 0 and plyServerId or GetClosestPlayer())
local SyncOffsetFront = 1.0
local SyncOffsetSide = 0.0
local SyncOffsetHeight = 0.0
local SyncOffsetHeading = 180.1
local AnimationOptions = RP.Shared[emote] and RP.Shared[emote].AnimationOptions
if AnimationOptions then
if AnimationOptions.SyncOffsetFront then
SyncOffsetFront = AnimationOptions.SyncOffsetFront + 0.0
end
if AnimationOptions.SyncOffsetSide then
SyncOffsetSide = AnimationOptions.SyncOffsetSide + 0.0
end
if AnimationOptions.SyncOffsetHeight then
SyncOffsetHeight = AnimationOptions.SyncOffsetHeight + 0.0
end
if AnimationOptions.SyncOffsetHeading then
SyncOffsetHeading = AnimationOptions.SyncOffsetHeading + 0.0
end
-- There is a priority to the source attached, if it is not set, it will use the target
if (AnimationOptions.Attachto) then
local bone = AnimationOptions.bone or -1 -- No bone
local xPos = AnimationOptions.xPos or 0.0
local yPos = AnimationOptions.yPos or 0.0
local zPos = AnimationOptions.zPos or 0.0
local xRot = AnimationOptions.xRot or 0.0
local yRot = AnimationOptions.yRot or 0.0
local zRot = AnimationOptions.zRot or 0.0
AttachEntityToEntity(ply, pedInFront, GetPedBoneIndex(pedInFront, bone), xPos, yPos, zPos, xRot, yRot, zRot,
false, false, false, true, 1, true)
end
end
local coords = GetOffsetFromEntityInWorldCoords(pedInFront, SyncOffsetSide, SyncOffsetFront, SyncOffsetHeight)
local heading = GetEntityHeading(pedInFront)
SetEntityHeading(ply, heading - SyncOffsetHeading)
SetEntityCoordsNoOffset(ply, coords.x, coords.y, coords.z, 0)
EmoteCancel()
Wait(300)
targetPlayerId = player
if RP.Shared[emote] ~= nil then
OnEmotePlay(RP.Shared[emote])
return
elseif RP.Dances[emote] ~= nil then
OnEmotePlay(RP.Dances[emote])
return
end
end)
RegisterNetEvent("SyncCancelEmote")
AddEventHandler("SyncCancelEmote", function(player)
if targetPlayerId and targetPlayerId == player then
targetPlayerId = nil
EmoteCancel()
end
end)
function CancelSharedEmote(ply)
if targetPlayerId then
TriggerServerEvent("ServerEmoteCancel", targetPlayerId)
targetPlayerId = nil
end
end
RegisterNetEvent("ClientEmoteRequestReceive")
AddEventHandler("ClientEmoteRequestReceive", function(emotename, etype)
isRequestAnim = true
requestedemote = emotename
if etype == 'Dances' then
_, _, remote = table.unpack(RP.Dances[requestedemote])
else
_, _, remote = table.unpack(RP.Shared[requestedemote])
end
PlaySound(-1, "NAV", "HUD_AMMO_SHOP_SOUNDSET", 0, 0, 1)
SimpleNotify(Config.Languages[lang]['doyouwanna'] .. remote .. "~w~)")
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(5)
if IsControlJustPressed(1, 246) and isRequestAnim then
target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
if RP.Shared[requestedemote] ~= nil then
_, _, _, otheremote = table.unpack(RP.Shared[requestedemote])
elseif RP.Dances[requestedemote] ~= nil then
_, _, _, otheremote = table.unpack(RP.Dances[requestedemote])
end
if otheremote == nil then otheremote = requestedemote end
TriggerServerEvent("ServerValidEmote", GetPlayerServerId(target), requestedemote, otheremote)
isRequestAnim = false
else
SimpleNotify(Config.Languages[lang]['nobodyclose'])
end
elseif IsControlJustPressed(1, 182) and isRequestAnim then
SimpleNotify(Config.Languages[lang]['refuseemote'])
isRequestAnim = false
end
end
end)
-----------------------------------------------------------------------------------------------------
------ Functions and stuff --------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
function GetPlayerFromPed(ped)
for _, player in ipairs(GetActivePlayers()) do
if GetPlayerPed(player) == ped then
return player
end
end
return -1
end
function GetPedInFront()
local player = PlayerId()
local plyPed = GetPlayerPed(player)
local plyPos = GetEntityCoords(plyPed, false)
local plyOffset = GetOffsetFromEntityInWorldCoords(plyPed, 0.0, 1.3, 0.0)
local rayHandle = StartShapeTestCapsule(plyPos.x, plyPos.y, plyPos.z, plyOffset.x, plyOffset.y, plyOffset.z, 10.0, 12
, plyPed, 7)
local _, _, _, _, ped2 = GetShapeTestResult(rayHandle)
return ped2
end
function NearbysOnCommand(source, args, raw)
local NearbysCommand = ""
for a in pairsByKeys(RP.Shared) do
NearbysCommand = NearbysCommand .. "" .. a .. ", "
end
EmoteChatMessage(NearbysCommand)
EmoteChatMessage(Config.Languages[lang]['emotemenucmd'])
end
function SimpleNotify(message)
if Config.NotificationsAsChatMessage then
TriggerEvent("chat:addMessage", { color = { 255, 255, 255 }, args = { tostring(message) } })
else
BeginTextCommandThefeedPost("STRING")
AddTextComponentSubstringPlayerName(message)
EndTextCommandThefeedPostTicker(0, 1)
end
end
function GetClosestPlayer()
local players = GetPlayers()
local closestDistance = -1
local closestPlayer = -1
local ply = PlayerPedId()
local plyCoords = GetEntityCoords(ply, 0)
for index, value in ipairs(players) do
local target = GetPlayerPed(value)
if (target ~= ply) then
local targetCoords = GetEntityCoords(GetPlayerPed(value), 0)
local distance = GetDistanceBetweenCoords(targetCoords["x"], targetCoords["y"], targetCoords["z"],
plyCoords["x"], plyCoords["y"], plyCoords["z"], true)
if (closestDistance == -1 or closestDistance > distance) then
closestPlayer = value
closestDistance = distance
end
end
end
return closestPlayer, closestDistance
end
function GetPlayers()
local players = {}
for i = 0, 255 do
if NetworkIsPlayerActive(i) then
table.insert(players, i)
end
end
return players
end