fixes etc

This commit is contained in:
Nordi98 2025-06-12 03:36:12 +02:00
parent 4a0c8c6204
commit 453b281a4b
644 changed files with 1907 additions and 2456 deletions

View file

@ -141,6 +141,19 @@ Config.VendingMachines = {
},
}
},
['beer'] = { -- Category: energy
['Label'] = 'Bier',
['Items'] = {
[1] = {
['name'] = 'pißwasser',
['price'] = 10,
['amount'] = 50,
['info'] = {},
['type'] = 'item',
['slot'] = 1
},
}
},
['water'] = { -- Category: Water
['Label'] = 'Wasser',
['Items'] = {
@ -205,5 +218,9 @@ Config.Vendings = {
['Model'] = 'prop_vend_fags_01a', -- Cig vending machine
['Category'] = 'cig' -- Linked to cig category
},
[13] = {
['Model'] = 'bzzz_prop_beer_machine', -- Beer vending machine
['Category'] = 'cig' -- Linked to cig category
},
}

View file

@ -32,7 +32,7 @@ ClientConfig = {
-- control_id: https://docs.fivem.net/docs/game-references/controls/)
-- control_key: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/
OPEN_SELF_MENU = { enabled = true, control_id = 246, input_parameter = "Y" }, -- Y Key
OPEN_SELF_MENU = { enabled = true, control_id = 246, input_parameter = "Z" }, -- Z Key
OPEN_OTHER_MENU = { enabled = true, control_id = 74, input_parameter = "H" }, -- H Key
EMERGENCY_DISPATCH = { enabled = true, control_id = 47, input_parameter = "G" }, -- G Key
CANCEL_INTERACTION = { enabled = true, control_id = 73, input_parameter = "X" }, -- X Key

File diff suppressed because it is too large Load diff

View file

@ -1,65 +0,0 @@
if not Config.Keybinding then return end
-----------------------------------------------------------------------------------------------------
-- Commands / Events --------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
for i = 1, #Config.KeybindKeys do
local cmd = string.format('emoteSelect%s', i)
RegisterCommand(cmd, function()
local emote = GetResourceKvpString(string.format('%s_emob%s', Config.keybindKVP, i))
if emote and emote ~= "" then
EmoteCommandStart(nil, { emote, 0 })
end
end, false)
RegisterKeyMapping(cmd, string.format('Emote bind %s', i), 'keyboard', Config.KeybindKeys[i])
end
-----------------------------------------------------------------------------------------------------
------ Functions and stuff --------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
function EmoteBindStart(source, args, raw)
if #args > 0 then
local numkey = tonumber(args[1])
local emote = string.lower(args[2])
if type(numkey) == "number" then
if RP.Emotes[emote] ~= nil
or RP.Dances[emote] ~= nil
or RP.PropEmotes[emote] ~= nil
or RP.AnimalEmotes[emote] ~= nil
then
SetResourceKvp(string.format('%s_emob%s', Config.keybindKVP, numkey), emote)
else
EmoteChatMessage("'" .. emote .. "' " .. Translate('notvalidemote') .. "")
end
else
EmoteChatMessage("'" .. numkey .. "' " .. Translate('notvalidkey'))
end
else
DebugPrint('Invalid number of arguments to \'EmoteBindStart\'')
end
end
function ListKeybinds()
for i = 1, #Config.KeybindKeys do
local emote = GetResourceKvpString(string.format('%s_emob%s', Config.keybindKVP, i))
if emote then
EmoteChatMessage(string.format('Emote %s : %s',i, emote))
end
end
end
function DeleteEmote(args)
if #args > 0 then
local numkey = tonumber(args[1])
if type(numkey) == "number" then
DeleteResourceKvp(string.format('%s_emob%s', Config.keybindKVP, numkey))
else
EmoteChatMessage("'" .. numkey .. "' " .. Translate('notvalidkey'))
end
else
DebugPrint("invalid")
end
end

View file

@ -1,100 +0,0 @@
if Config.Framework ~= 'esx' then return end
local framework = 'es_extended'
local state = GetResourceState(framework)
if state == 'missing' or state == "unknown" then
-- Framework can't be used if it's missing or unknown
return
end
ESX, PlayerData, IsLoggedIn = nil, nil, false
-- ESX core parts
ESX = exports[framework]:getSharedObject()
PlayerData = ESX.GetPlayerData()
IsLoggedIn = false
RegisterNetEvent('esx:onPlayerSpawn', function()
PlayerData = ESX.GetPlayerData()
IsLoggedIn = true
end)
-- This is here to get the player data when the resource is restarted instead of having to log out and back in each time
-- This won't set the player data too early as this only triggers when the server side is started and not the client side
AddEventHandler('onResourceStart', function(resource)
if resource == GetCurrentResourceName() then
Wait(200)
PlayerData = ESX.GetPlayerData()
IsLoggedIn = true
end
end)
function CanUseFavKeyBind()
return not ESX.PlayerData.dead
end
-- Added events
RegisterNetEvent('animations:client:PlayEmote', function(args)
if not ESX.PlayerData.dead then
EmoteCommandStart(source, args)
end
end)
if Config.Keybinding then
RegisterNetEvent('animations:client:BindEmote', function(args)
if not ESX.PlayerData.dead then
EmoteBindStart(nil, args)
end
end)
RegisterNetEvent('animations:client:EmoteBinds', function()
if not ESX.PlayerData.dead then
ListKeybinds()
end
end)
RegisterNetEvent('animations:client:EmoteDelete', function(args)
if not ESX.PlayerData.dead then
DeleteEmote(args)
end
end)
end
RegisterNetEvent('animations:client:EmoteMenu', function()
if not ESX.PlayerData.dead then
OpenEmoteMenu()
end
end)
RegisterNetEvent('animations:client:ListEmotes', function()
if not ESX.PlayerData.dead then
EmotesOnCommand()
end
end)
RegisterNetEvent('animations:client:Walk', function(args)
if not ESX.PlayerData.dead then
WalkCommandStart(args)
end
end)
RegisterNetEvent('animations:client:ListWalks', function()
if not ESX.PlayerData.dead then
WalksOnCommand()
end
end)
-- Added by https://github.dev/qbcore-framework/dpemotes/
CanDoEmote = true
RegisterNetEvent('animations:ToggleCanDoAnims', function(bool)
CanDoEmote = bool
end)
RegisterNetEvent('animations:client:EmoteCommandStart', function(args)
if CanDoEmote then
EmoteCommandStart(source, args)
end
end)

View file

@ -1,108 +0,0 @@
if Config.Framework ~= 'qb-core' then return end
local framework = 'qb-core'
local state = GetResourceState(framework)
if state == 'missing' or state == "unknown" then
-- Framework can't be used if it's missing or unknown
return
end
QBCore, PlayerData, isLoggedIn = nil, nil, false
-- QB core parts
QBCore = exports[framework]:GetCoreObject()
PlayerData = QBCore.Functions.GetPlayerData()
isLoggedIn = false
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
isLoggedIn = true
end)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
PlayerData = {}
isLoggedIn = false
end)
RegisterNetEvent('QBCore:Player:SetPlayerData', function(val)
PlayerData = val
end)
-- This is here to get the player data when the resource is restarted instead of having to log out and back in each time
-- This won't set the player data too early as this only triggers when the server side is started and not the client side
AddEventHandler('onResourceStart', function(resource)
if resource == GetCurrentResourceName() then
Wait(200)
PlayerData = QBCore.Functions.GetPlayerData()
isLoggedIn = true
end
end)
function CanUseFavKeyBind()
return not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead']
end
-- Added events
RegisterNetEvent('animations:client:PlayEmote', function(args)
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
EmoteCommandStart(source, args)
end
end)
if Config.Keybinding then
RegisterNetEvent('animations:client:BindEmote', function(args)
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
EmoteBindStart(nil, args)
end
end)
RegisterNetEvent('animations:client:EmoteBinds', function()
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
ListKeybinds()
end
end)
RegisterNetEvent('animations:client:EmoteDelete', function(args)
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
DeleteEmote(args)
end
end)
end
RegisterNetEvent('animations:client:EmoteMenu', function()
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
OpenEmoteMenu()
end
end)
RegisterNetEvent('animations:client:ListEmotes', function()
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
EmotesOnCommand()
end
end)
RegisterNetEvent('animations:client:Walk', function(args)
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
WalkCommandStart(source, args)
end
end)
RegisterNetEvent('animations:client:ListWalks', function()
if not PlayerData.metadata['inlaststand'] and not PlayerData.metadata['isdead'] then
WalksOnCommand()
end
end)
-- Added by https://github.dev/qbcore-framework/dpemotes/
CanDoEmote = true
RegisterNetEvent('animations:ToggleCanDoAnims', function(bool)
CanDoEmote = bool
end)
RegisterNetEvent('animations:client:EmoteCommandStart', function(args)
if CanDoEmote then
EmoteCommandStart(source, args)
end
end)

View file

@ -1,145 +0,0 @@
Config = {
-- Menu Options
MenuLanguage = 'de', -- Change the language of the menu here!.
DebugDisplay = false, -- Set this to true to enable some extra prints
EnableCancelKeybind = true, -- Set this to false if you have something else on X, and then just use /e c to cancel emotes.
CancelEmoteKey = 'x', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
MenuKeybindEnabled = true,
MenuKeybind = 'f4', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
FavKeybindEnabled = true, -- You can disable the Favorite emote keybinding here.
FavKeybind = 'capital', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
Keybinding = false, -- enable this to turn on keybinding.
keybindKVP = "rpemotes", -- The keybind KVP name
NotificationsAsChatMessage = false, -- If you don't like native GTA 5 notifications, you can disable them here to have messages in the chat.
Framework = 'qb-core', -- Used for few framework-dependent things. Accepted values: 'qb-core', 'esx' or false
Search = true, -- Used to enable or disable the search feature in the menu.
CancelPreviousEmote = false, -- If turned on, playing an emote will cancel the previous one.
DisableControls = false, -- Disable specific controls when menu is open, can be configured in NativeUI.lua:2452 (approximately)
-- Menu Customization Options
MenuTitle = '', -- You can change the name of the menu here or leave it blank to remove the text in front of the custom banners
TitleOutline = false,
TitleColour = {R = 255, G = 0, B = 255, A = 255}, --- The colour of the menu banner text in RGB. This is white by default aka 255, 255, 255. See https://www.rapidtables.com/web/color/RGB_Color.html for colours.
MenuPosition = 'right', -- You can change the menu position here. Use 'left' or 'right'
CustomMenuEnabled = true, -- You can change the header image for the menu here, Note this might cause an issue of the image getting stuck on people's screens
-- Combat Car, and Player Movement Options
DisarmPlayer = false, -- Set this to true if you want to disarm the player when they play an emote.
AllowPunching = false, -- Set this to true if you want to allow people punching while emotes are playing
AllowedInCars = true, -- Set this if you really wanna disable emotes in cars, as of 1.7.2 they only play the upper body part if in a vehicle
-- You can disable the menu here / change the keybind. It is currently set to F4
-- The keybind you set here will be server-sided for new players. existing players can set their own in the ESC menu keybind settings
AllowInWater = false, -- If turned off, opening the menu and playing an emote will not be possible while swimming
-- Ragdoll options
RagdollEnabled = true, -- You can enable or disable the Ragdoll keybinding here.
RagdollKeybind = 'u', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
-- You can enable or disable Ragdoll as Toggle here. Only works if RagdollEnabled is set to true.
RagdollAsToggle = true,
-- Expressions, Walks, and More Menu Options
ExpressionsEnabled = true, -- You can disable the Facial Expressions menu here.
PersistentExpression = true, -- Saves expression style to client and applies them on joining
WalkingStylesEnabled = true, -- You can disable the Walking Styles menu here.
PersistentWalk = true, -- Saves walk styles to client and applies them on joining
SharedEmotesEnabled = true, -- You can disable the Shared Emotes here.
AdultEmotesDisabled = false, -- You can disable the Adult Emotes here.
AnimalEmotesEnabled = true, -- You can disable the Animal Emotes here.
-- Hands Up Options
HandsupEnabled = false, -- You can disable the handsup here / change the keybind. It is currently set to Y
HandsupKeybind = 'Y', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
HandsupKeybindEnabled = false,
HandsupKeybindInCarEnabled = false,
PersistentEmoteAfterHandsup = true, -- If true, you will play the emote you were playing previously after you stop handsup.
HoldToHandsUp = false, -- Hands-up action occurs only while holding the button down
-- Pointing Options
PointingEnabled = true, -- You can disable the finger pointing here / change the keybind. It is currently set to B
PointingKeybindEnabled = true,
PointingKeybind = 'B', -- Get the button string here https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
PointingKeybindInCarEnabled = false,
PersistentEmoteAfterPointing = true, -- If true, you will play the emote you were playing previously after you stop pointing.
-- Crouching Options
CrouchEnabled = false, -- If crouching should be enabled.
CrouchKeybindEnabled = true, -- If true, crouching will use keybinds.
CrouchKeybind = 'lcontrol', -- The default crouch keybind, get the button string here: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
CrouchOverrideStealthMode = false, -- If true, you won't enter stealth mode even if the crouch key and the 'duck' key are the same.
FpsMode = false, -- set this to true if you have first-person shooting to disable the ability to crouch and shoot in third-person
-- Crawling Options
CrawlEnabled = true, -- If crawling should be enabled.
CrawlKeybindEnabled = true, -- If true, crawling will use keybinds.
CrawlKeybind = 'rcontrol', -- The default crawl keybind, get the button string here: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
-- Binocular Options
BinocularsEnabled = false, -- If set to true, the /binoculars command will be enabled.
AllowVisionsToggling = false, -- If set to true, you'll be able to toggle between different vision modes in the binoculars
-- News Camera Options
NewscamEnabled = false, -- If set to true, the /newscam command will be enabled.
NoIdleCam = true, -- Controls wether the idle cam can be disabled by players or not
-- Preview Ped Options
PreviewPed = true, -- Shows a preview of the emote on the player's ped next to the emote menu. Note that resmon will increase when this when emotes are being previewed.
CheckForUpdates = true
}
Config.KeybindKeys = {
'NUMPAD1',
'NUMPAD2',
'NUMPAD3',
'NUMPAD4',
'NUMPAD5',
'NUMPAD6',
'NUMPAD7',
'NUMPAD8',
'NUMPAD9'
}
Config.Credits = {
{title = "<b>Thanks to the community<b>", subtitle = "For supporting and using RP Emotes!"},
{title = "Thanks <font color=\"#ff451d\">Enzo2991 🇧🇪 </font>", subtitle = "<font color=\"#ff451d\">Enzo2991 🇧🇪 </font> for creating the ped preview functionality, keybind with kvp"},
{title = "Thanks ~o~DullPear 🍐~s~", subtitle = "~o~DullPear~s~ for the original dpemotes ❤️"},
{title = "Thanks <b>Kibook 🐩</b>", subtitle = "<b>Kibook</b> for the addition of Animal Emotes 🐩 submenu."},
{title = "Thanks ~y~AvaN0x 🇫🇷~s~", subtitle = "~y~AvaN0x~s~ 🇫🇷 for reformatting and assisting with code and additional features 🙏"},
{title = "Thanks <font color=\"#0e64ed\">Mads 🤖</font>", subtitle = "<font color=\"#0e64ed\">Mads 🤖</font> for the addition of Exit Emotes, Crouch & Crawl ⚙️"},
{title = "Thanks <font color=\"#ff451d\">Mathu_lmn 🇫🇷 </font>", subtitle = "<font color=\"#ff451d\">Mathu_lmn 🇫🇷</font> Additional features and fixes 🛠️"},
{title = "Thanks <font color=\"#1C9369\">northsqrd ⚙️</font>", subtitle = "<font color=\"#1C9369\">northsqrd</font> for assisting with search feature and phone colours 🔎"},
{title = "Thanks <font color=\"#15BCEC\">GeekGarage 🤓</font>", subtitle = "<font color=\"#15BCEC\">GeekGarage</font> for assisting with code and features"},
{title = "Thanks <font color=\"#3b8eea\">SMGMissy 🪖</font>", subtitle = "<font color=\"#3b8eea\">SMGMissy</font> for the custom pride flags 🏳️‍🌈."},
{title = "Thanks <font color=\"#a356fa\">Dollie 👧</font>", subtitle = "<font color=\"#a356fa\">DollieMods</font> for the custom emotes 💜."},
{title = "Thanks <font color=\"#ff00c3\">Tigerle 🐯</font>", subtitle = "<font color=\"#ff00c3\">Tigerle</font> for assisting with attached Shared Emotes ⚙️."},
{title = "Thanks <font color=\"#7dbf7b\">MissSnowie 🐰</font>", subtitle = "<font color=\"#7dbf7b\">MissSnowie</font> for the custom emotes 🐇."},
{title = "Thanks <font color=\"#FF6100\">Smokey 💨</font>", subtitle = "<font color=\"#FF6100\">Smokey</font> for the custom emotes 🤙🏼."},
{title = "Thanks ~b~Ultrahacx 🧑‍💻~s~", subtitle = "~b~Ultrahacx~s~ for the custom emotes ☺️."},
{title = "Thanks <font color=\"#37DA00\">BzZzi 🤭</font>", subtitle = "<font color=\"#37DA00\">BzZzi</font> for the custom props 🍩."},
{title = "Thanks <font color=\"#C40A7D\">Natty3d 🍭</font>", subtitle = "<font color=\"#C40A7D\">Natty3d</font> for the custom lollipop props 🍭."},
{title = "Thanks <font color=\"#ff61a0\">Amnilka 🇵🇱</font>", subtitle = "<font color=\"#ff61a0\">Amnilka</font> for the custom emotes ☺️."},
{title = "Thanks <font color=\"#ff058f\">LittleSpoon 🥄</font>", subtitle = "<font color=\"#ff058f\">LittleSpoon</font> for the custom emotes 💗."},
{title = "Thanks <font color=\"#1a88c9\">Pupppy 🐶</font>", subtitle = "<font color=\"#1a88c9\">Pupppy</font> for the custom emotes 🦴."},
{title = "Thanks <font color=\"#53ba04\">SapphireMods</font>", subtitle = "<font color=\"#53ba04\">SapphireMods</font> for the custom emotes ✨."},
{title = "Thanks <font color=\"#8526f0\">QueenSisters Animations 👭</font>", subtitle = "<font color=\"#8526f0\">QueenSistersAnimations</font> for the custom emotes 🍧"},
{title = "Thanks <font color=\"#0acf52\">BoringNeptune 👽</font>", subtitle = "<font color=\"#0acf52\">BoringNeptune</font> for the custom emotes 🕺"},
{title = "Thanks <font color=\"#edae00\">Moses 🐮</font>", subtitle = "<font color=\"#edae00\">-Moses-</font> for the custom emotes 🧡" },
{title = "Thanks <font color=\"#D71196\">PataMods 🍓</font>", subtitle = "<font color=\"#D71196\">PataMods</font> for the custom props 🍕"},
{title = "Thanks <font color=\"#FB7403\">Crowded1337 👜</font>", subtitle = "<font color=\"#FB7403\">Crowded1337</font> for the custom Gucci bag 👜"},
{title = "Thanks <font color=\"#8180E5\">EnchantedBrownie 🍪</font>", subtitle = "<font color=\"#8180E5\">EnchantedBrownie 🍪</font> for the custom animations 🍪"},
{title = "Thanks <font color=\"#eb540e\">Copofiscool 🇦🇺</font>", subtitle = "<font color=\"#eb540e\">Copofiscool</font> for the Favorite Emote keybind toggle fix 🇦🇺"},
{title = "Thanks <font color=\"#40E0D0\">iSentrie </font>", subtitle = "<font color=\"#40E0D0\">iSentrie</font> for assisting with code 🛠️"},
{title = "Thanks <font color=\"#7B3F00\">Chocoholic Animations 🍫</font>", subtitle = "<font color=\"#7B3F00\">Chocoholic Animations</font> for the custom emotes 🍫"},
{title = "Thanks <font color=\"#34cf5d\">CrunchyCat 🐱</font>", subtitle = "<font color=\"#34cf5d\">CrunchyCat 🐱</font> for the custom emotes 🐱"},
{title = "Thanks <font color=\"#d10870\">KayKayMods</font>", subtitle = "<font color=\"#d10870\">KayKayMods</font> for the custom props 🧋"},
{title = "Thanks <font color=\"#de1846\">Dark Animations</font>", subtitle = "<font color=\"#de1846\">Dark Animations</font> for the custom animations 🖤"},
{title = "Thanks <font color=\"#00FF12\">Brum 🇬🇧</font>", subtitle = "<font color=\"#00FF12\">Brum</font> for the custom props 🇬🇧"},
{title = "Thanks <font color=\"#017a05\">Chico 💀</font>", subtitle = "<font color=\"#017a05\">Chico 💀</font> for fixing persistent walkstyles and moods for QB-Core and ESX." },
{title = "Thanks <font color=\"#194ce6\">-EcLiPsE- ✌🏻</font>", subtitle = "<font color=\"#194ce6\">-EcLiPsE- ✌🏻 </font> for NPC prop sets and GTA Online biker animations"},
{title = "Thanks <font color=\"#3488c8\">MrWitt 🦑️</font>", subtitle = "<font color=\"#3488c8\">MrWitt 🦑</font> for the custom animations."},
{title = "Thanks <font color=\"#ff96b6\">AdoredRose 🌹</font>", subtitle = "<font color=\"#ff96b6\">AdoredRose 🌹</font> for assistance with adding animations."},
{title = "Thanks <font color=\"#ff451d\">DRX Animations 👑</font>", subtitle = "<font color=\"#ff451d\">DRX Animations 👑</font> for the custom animations"},
{title = "Thanks <font color=\"#12ab0a\">Radial 🫡</font>", subtitle = "<font color=\"#12ab0a\">Radial</font> on discord for contributing animations code"},
{title = "<font color=\"#FF25B1\"><b>TayMcKenzieNZ 🇳🇿<b></font>", subtitle = "<font color=\"#FF25B1\">TayMcKenzieNZ 🇳🇿</font> Previous maintainer of RP Emotes."},
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

View file

@ -1,177 +0,0 @@
-----------------------------------------------------------------------------------------------------
-- Shared Emotes Syncing ---------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------
RegisterNetEvent("ServerEmoteRequest", function(target, emotename, etype)
if not Player(source).state.canEmote then return end
local ped = GetPlayerPed(source)
if target == -1 then
return
end
local tped = GetPlayerPed(target)
local pedcoord = GetEntityCoords(ped)
local targetcoord = GetEntityCoords(tped)
local distance = #(pedcoord - targetcoord)
if distance > 3 then
return
end
TriggerClientEvent("ClientEmoteRequestReceive", target, emotename, etype, source)
end)
RegisterNetEvent("ServerValidEmote", function(target, requestedemote, otheremote)
local ped = GetPlayerPed(source)
if target == -1 then
return
end
local tped = GetPlayerPed(target)
local pedcoord = GetEntityCoords(ped)
local targetcoord = GetEntityCoords(tped)
local distance = #(pedcoord - targetcoord)
if distance > 3 then
return
end
TriggerClientEvent("SyncPlayEmote", source, otheremote, target)
TriggerClientEvent("SyncPlayEmoteSource", target, requestedemote, source)
end)
RegisterNetEvent("ServerEmoteCancel", function(target)
TriggerClientEvent("SyncCancelEmote", target, source)
end)
--#region ptfx
RegisterNetEvent("rpemotes:ptfx:sync", function(asset, name, offset, rot, bone, scale, color)
if type(asset) ~= "string" or type(name) ~= "string" or type(offset) ~= "vector3" or type(rot) ~= "vector3" then
print("[rpemotes] ptfx:sync: invalid arguments for source:", source)
return
end
local srcPlayerState = Player(source).state
srcPlayerState:set("ptfxAsset", asset, true)
srcPlayerState:set("ptfxName", name, true)
srcPlayerState:set("ptfxOffset", offset, true)
srcPlayerState:set("ptfxRot", rot, true)
srcPlayerState:set("ptfxBone", bone, true)
srcPlayerState:set("ptfxScale", scale, true)
srcPlayerState:set("ptfxColor", color, true)
srcPlayerState:set("ptfxPropNet", false, true)
srcPlayerState:set("ptfx", false, true)
end)
RegisterNetEvent("rpemotes:ptfx:syncProp", function(propNet)
local srcPlayerState = Player(source).state
if propNet then
-- Prevent infinite loop to get entity
local waitForEntityToExistCount = 0
while waitForEntityToExistCount <= 100 and not DoesEntityExist(NetworkGetEntityFromNetworkId(propNet)) do
Wait(10)
waitForEntityToExistCount = waitForEntityToExistCount + 1
end
-- If below 100 then we could find the loaded entity
if waitForEntityToExistCount < 100 then
srcPlayerState:set("ptfxPropNet", propNet, true)
return
end
end
-- If we reach this point then we couldn"t find the entity
srcPlayerState:set("ptfxPropNet", false, true)
end)
--#endregion ptfx
-- Emote props extractor
local function ExtractEmoteProps(format)
local format = tonumber(format)
local xt, c, total = "", "", 0
if format == 1 then
print("Selected format: ^2\"prop_name\",")
xt = "\""; c = ","
elseif format == 2 then
print("Selected format: ^2\"prop_name\",")
xt = "\""; c = ","
elseif format == 3 then
print("Selected format: ^2prop_name,")
elseif format == 4 then
print("Selected to calculate ^2total amount of emotes^0.")
else
print(
"\n### RPEmotes - Props Extractor ###\n\n^3Select output format^0\nAvailable formats:\n^11^0 - ^2\"prop_name\",\n^12^0 - ^2\"prop_name\",\n^13^0 - ^2prop_name\n^14^0 - ^2calculate total emotes\n\n^0Command usage example: ^5emoteextract 1^0\n")
return
end
local animationFile = LoadResourceFile(GetCurrentResourceName(), "client/AnimationList.lua")
if not animationFile then return nil end
local f, err = load(animationFile .. " return RP")
if err then return nil end
local success, res = pcall(f)
if not success then return nil end
if format == 4 then
local emoteTypes = { "Shared", "Dances", "AnimalEmotes", "Emotes", "PropEmotes", "Expressions", "Walks" }
local countEmotesWith = 0
local countEmotes = 0
for i = 1, #emoteTypes do
local emoteType = emoteTypes[i]
for _, _ in pairs(res[emoteType]) do
if emoteType == "Expressions" or emoteType == "Walks" then
countEmotesWith += 1
else
countEmotes += 1
end
end
end
local totalEmotes = countEmotesWith + countEmotes
print("Total Expressions and Walks: ^3" .. countEmotesWith .. "^0")
print("Total Emotes without Expressions and Walks: ^3" .. countEmotes .. "^0")
print("Total Emotes: ^3" .. totalEmotes .. "^0")
else
-- table to keep track of exported values
local exportedValues = {}
-- open file for writing
local file = assert(io.open(GetResourcePath(GetCurrentResourceName()) .. "/prop_list.lua", "w"))
-- tables that has props:
-- RP.PropEmotes
-- RP.Shared (most likely all props mentioned in here is used in PropEmotes, so I don"t check it)
for _, value in pairs(res.PropEmotes) do
-- check if the current value is a table and has an AnimationOptions field
if type(value) == "table" and value.AnimationOptions then
-- extract the Prop and SecondProp values and check if they"re nil and not already exported
local propValue = value.AnimationOptions.Prop
local secondPropValue = value.AnimationOptions.SecondProp
if propValue and not exportedValues[propValue] then
file:write(xt .. propValue .. xt .. c .. "\n")
exportedValues[propValue] = true
total += 1
end
if secondPropValue and not exportedValues[secondPropValue] then
file:write(xt .. secondPropValue .. c .. "\n")
exportedValues[secondPropValue] = true
total += 1
end
end
end
print("Exported props: " .. total)
file:close()
end
end
RegisterCommand("emoteextract", function(source, args)
if source > 0 then return end
ExtractEmoteProps(args[1])
end, true)

View file

@ -1,59 +0,0 @@
if Config.Framework ~= 'esx' then return end
local framework = 'esx'
local state = GetResourceState(framework)
if state == 'missing' or state == "unknown" then
-- Framework can't be used if it's missing or unknown
return
end
local ESX = exports['es_extended']:getSharedObject()
ESX.RegisterCommand('e', 'Play an emote', {{ name="emotename", help="dance, camera, sit or any valid emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:PlayEmote', source, args)
end)
ESX.RegisterCommand('emote', 'Play an emote', {{ name="emotename", help="dance, camera, sit or any valid emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:PlayEmote', source, args)
end)
if Config.Keybinding then
ESX.RegisterCommand('emotebind', 'user', function(xPlayer, args)
local arg = {args.key, args.emotename}
xPlayer.triggerEvent('animations:client:BindEmote', arg)
end, false, {help = Translate('link_emote_keybind'), arguments= {{name = "key", help= "1, 2, 3, 4, 5, 6", type='number'}, {name="emotename", help="dance, camera, sit or any valid emote.", type='string'}}})
ESX.RegisterCommand('emotebinds', 'user', function(xPlayer)
xPlayer.triggerEvent('animations:client:EmoteBinds')
end, false, {help = Translate('show_emote_keybind')})
ESX.RegisterCommand('emotedelete', 'user', function(xPlayer, args)
local arg = {args.key}
xPlayer.triggerEvent('animations:client:EmoteDelete', arg)
end, false, {help = Translate('remove_emote_keybind'), arguments={{name = "key", help= "1, 2, 3, 4, 5, 6", type='number'}}})
end
ESX.RegisterCommand('emotemenu', 'Open rpemotes menu (F3) by default.', {}, false, function(source)
TriggerClientEvent('animations:client:EmoteMenu', source)
end)
ESX.RegisterCommand('em', 'Open rpemotes menu (F3) by default.', {}, false, function(source)
TriggerClientEvent('animations:client:EmoteMenu', source)
end)
ESX.RegisterCommand('emotes', 'List available emotes.', {}, false, function(source)
TriggerClientEvent('animations:client:ListEmotes', source)
end)
ESX.RegisterCommand('walk', 'Set your walkingstyle.', {{ name="style", help="/walks for a list of valid styles"}}, true, function(source, args)
TriggerClientEvent('animations:client:Walk', source, args)
end)
ESX.RegisterCommand('walks', 'List available walking styles.', {}, false, function(source)
TriggerClientEvent('animations:client:ListWalks', source)
end)
ESX.RegisterCommand('nearby', 'Share emote with a nearby player.', {{ name="emotename", help="hug, handshake, bro or any valid shared emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:Nearby', source, args)
end)

View file

@ -1,58 +0,0 @@
if Config.Framework ~= 'qb-core' then return end
local framework = 'qb-core'
local state = GetResourceState(framework)
if state == 'missing' or state == "unknown" then
-- Framework can't be used if it's missing or unknown
return
end
local QBCore = exports['qb-core']:GetCoreObject()
-- https://github.com/qbcore-framework/dpemotes/blob/master/Server/Server.lua#L101-L141
QBCore.Commands.Add('e', 'Play an emote', {{ name="emotename", help="dance, camera, sit or any valid emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:PlayEmote', source, args)
end)
QBCore.Commands.Add('emote', 'Play an emote', {{ name="emotename", help="dance, camera, sit or any valid emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:PlayEmote', source, args)
end)
if Config.Keybinding then
QBCore.Commands.Add('emotebind', 'Bind an emote', {{ name="key", help="num4, num5, num6, num7. num8, num9. Numpad 4-9!"}, { name="emotename", help="dance, camera, sit or any valid emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:BindEmote', source, args)
end)
QBCore.Commands.Add('emotebinds', 'Check your currently bound emotes.', {}, false, function(source)
TriggerClientEvent('animations:client:EmoteBinds', source)
end)
QBCore.Commands.Add('emotedelete', Translate('remove_emote_keybind'), {}, false, function(source, args)
TriggerClientEvent('animations:client:EmoteDelete', source, args)
end)
end
QBCore.Commands.Add('emotemenu', 'Open rpemotes menu (F3) by default.', {}, false, function(source)
TriggerClientEvent('animations:client:EmoteMenu', source)
end)
QBCore.Commands.Add('em', 'Open rpemotes menu (F3) by default.', {}, false, function(source)
TriggerClientEvent('animations:client:EmoteMenu', source)
end)
QBCore.Commands.Add('emotes', 'List available emotes.', {}, false, function(source)
TriggerClientEvent('animations:client:ListEmotes', source)
end)
QBCore.Commands.Add('walk', 'Set your walkingstyle.', {{ name="style", help="/walks for a list of valid styles"}}, true, function(source, args)
TriggerClientEvent('animations:client:Walk', source, args)
end)
QBCore.Commands.Add('walks', 'List available walking styles.', {}, false, function(source)
TriggerClientEvent('animations:client:ListWalks', source)
end)
QBCore.Commands.Add('nearby', 'Share emote with a nearby player.', {{ name="emotename", help="hug, handshake, bro or any valid shared emote."}}, true, function(source, args)
TriggerClientEvent('animations:client:Nearby', source, args)
end)

View file

@ -477,14 +477,14 @@ function GetByteCount(str)
local bytes = 0
for c in str:gmatch("[%z\1-\127\194-\244][\128-\191]*") do
local a, b, c, d = c:byte(1, -1)
local a, b, cc, d = c:byte(1, -1)
if a ~= nil then
bytes = bytes + 1
end
if b ~= nil then
bytes = bytes + 1
end
if c ~= nil then
if cc ~= nil then
bytes = bytes + 1
end
if d ~= nil then
@ -2376,7 +2376,7 @@ end
--]]
function UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName)
local X, Y = tonumber(X) or 0, tonumber(Y) or 0
X, Y = tonumber(X) or 0, tonumber(Y) or 0
if Title ~= nil then Title = tostring(Title) or "" else Title = "" end
if Subtitle ~= nil then Subtitle = tostring(Subtitle) or "" else Subtitle = "" end
if TxtDictionary ~= nil then TxtDictionary = tostring(TxtDictionary) or "commonmenu" else TxtDictionary = "commonmenu" end
@ -2444,7 +2444,7 @@ function UIMenu.New(Title, Subtitle, X, Y, TxtDictionary, TxtName)
ResetCursorOnOpen = false,
MouseControlsEnabled = false,
MouseEdgeEnabled = false,
ControlDisablingEnabled = Config.DisableControls,
ControlDisablingEnabled = Config.DisableControlsInMenu,
Audio = {
Library = "HUD_FRONTEND_DEFAULT_SOUNDSET",
UpDown = "NAV_UP_DOWN",

View file

@ -89,9 +89,7 @@ Example Banner:
Find our documentation [here](https://rpemotes-reborn.gitbook.io/guide)
When using our emote menu with other scripts, using the `TriggerEvent('animations:client:EmoteCommandStart` won't do anything because the events do not exist. These have simply been replaced with the following exports:
**Note for legacy use of rpemotes:** if you have resources dependent on or currently using exports from rpemotes, rename rpemotes-reborn's folder to rpemotes to maintain functionality. Or, rename all exports from exports["rpemotes"] to exports["rpemotes-reborn"]
The rpemotes-reborn resource has the following exports:
```lua
exports["rpemotes-reborn"]:EmoteCommandStart(emoteName, textureVariation)
@ -99,15 +97,17 @@ exports["rpemotes-reborn"]:EmoteCancel(forceCancel) forceCancel is optional
exports["rpemotes-reborn"]:CanCancelEmote(state)
exports["rpemotes-reborn"]:IsPlayerCrouched()
exports["rpemotes-reborn"]:IsPlayerProne()
exports["rpemotes-reborn"]:StopPlayerProne(force) -- force is optional
exports["rpemotes-reborn"]:GetPlayerProneType() -- returns the type of prone the player is in, either "onfront" or "onback"
exports["rpemotes-reborn"]:IsPlayerCrawling()
exports["rpemotes-reborn"]:IsPlayerPointing()
exports["rpemotes-reborn"]:IsPlayerInAnim() -- returns current animation name or nil
exports["rpemotes-reborn"]:IsPlayerInHandsUp()
exports["rpemotes-reborn"]:toggleWalkstyle(bool, message) -- bool to allow the user to change their walkstyle in the menu or not / message to show the user (optional, default is :"You are unable to change your walking style right now.")"
exports["rpemotes-reborn"]:toggleBinoculars()
exports["rpemotes-reborn"]:toggleNewscam()
exports["rpemotes-reborn"]:getWalkstyle() -- Gets walk style of player, used to detect certain walk. useful for applying effects while doing certain walks like tripping or other "funny" effects.
exports["rpemotes-reborn"]:setWalkstyle(name, force) -- name = "move_m@alien" or any other, force = optional bool. Lets you set or force a walk style, useful for scripts like retrieving a style before drinking and restoring it after sobering up.
exports["rpemotes-reborn"]:toggleWalkstyle(bool, message) -- bool to allow the user to change their walkstyle in the menu or not / message to show the user (optional, default is :"You are unable to change your walking style right now.")"
```
Having issues with players using emotes when/where they're not supposed to? Use the following where you need. This would be somewhere like if you want to disable emotes in jail or when someone is handcuffed/escorted:
@ -133,7 +133,7 @@ Alternatively, the player base can set their menu keybind to open rpemotes-rebor
`Esc > settings > keybinds > fivem`
- More keybinds are now using key mappings which means that they are now available in your FiveM settings to change (`FavKeybind` and `RagdollKeybind`)
- More keybinds are now using key mappings which means that they are now available in your FiveM settings to change (`RagdollKeybind`)
# Keybinds 🎛️
@ -260,12 +260,6 @@ No Idle Cam allows players to disable the idle camera animation on foot and in v
<img src="https://forum.cfx.re/uploads/default/optimized/4X/5/4/e/54e47db5ae45f5afa4b84c2ae4858bc9ab0a8187_2_690x388.jpeg" width="600" height="auto">
# Favorite Emote
Players can search for an emote (so long as search is enabled) and press LEFT SHIFT and CAPLOCKS on their keyboard to add it to their 'Favorites'. Pressing CAPLOCKS will toggle the emote.
Alternatively, you can use the 🌟 Favorite menu to find an emote and press enter.
# Exit Emotes
Exit Emotes are used to make cancelling an animation more smoother and dynamic, such as getting up off a chair or throwing a cigarette out instead of dropping it.
@ -466,59 +460,57 @@ All animation creators have **_specifically_** asked that their content remain f
**A huge thank you the following people for their amazing contributions to the menu:**
- the FiveM community for using RP and updating rpemotes-reborn!
### Developers:
- [The Popcorn RP community](https://discord.gg/popcornroleplay) for putting up with all my emote menu testing and troubleshooting issues with me
- [Mathu_lmn](https://github.com/Mathu-lmn) for maintaining the menu and adding features
- [enzo2991](https://github.com/enzo2991) for creating the ped preview functionality, keybind with kvp
- [DerDevHD](https://forum.cfx.re/t/fixed-remove-prop-after-scenario-animation/5002332/8) for the insight on deleting scenario props.
- [iSentrie](https://forum.cfx.re/u/isentrie/) for additional code, support, and joining the RPEmotes project
- [Kibook](https://github.com/kibook) for the addition of the Animal Emotes sub-menu
- [AvaN0x](https://github.com/AvaN0x) for reformatting and assisting with code, additional features, and figuring out shared particle effects
- [Mads](https://github.com/MadsLeander) for joining the team as Co-Developer
- [Mathu_lmn](https://github.com/Mathu-lmn) for joining the team as Co-Developer
- [Tigerle](https://forum.cfx.re/u/tigerle_studios) for providing the additional code required to make Shared Emotes work to its full extent
- [SMGMissy](https://jenscreations.tebex.io/) for creating the pride flag props
- [MissSnowie](https://www.gta5-mods.com/users/MissySnowie) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord and for the motivational and overall moral support
- [GeekGarage](https://github.com/geekgarage) for their knowledge, time, and dedication, helping to bring new and exciting features to the menu
- [Smokey](https://www.gta5-mods.com/users/struggleville) for the Explicit Usage Rights Agreement to add free custom animations either publicly available on their discord
- [BzZzi](https://forum.cfx.re/u/bzzzi/summary) for the Explicit Usage Rights Agreement to add free donuts, croissants and fire torch props
- [Natty3d](https://forum.cfx.re/u/natty3d/summary) for the Explicit Usage Rights Agreement to add free lollipop props
- [northsqrd](https://github.com/0sqrd) for adding the search function, Animal Emotes config, mobile phone prop texture variants, and general contributions
- Crusopaul and Eki for discussing KVP and initializing it to the menu for persistent walk styles
- [Amnilka](https://www.gta5-mods.com/users/frabi) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord
- [LittleSpoon](https://discord.gg/safeword) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord
- [LadyyShamrockk](https://www.gta5-mods.com/users/LadyyShamrockk) For allowing us to include their emotes in rpemotes-reborn
- [Pupppy](https://discord.gg/rsN35X4s4N) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord
- [SapphireMods](https://discord.gg/Hf8F4nTyzt) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord
- [QueenSisters Animations](https://discord.gg/qbPtGwQuep) for the Explicit Usage Rights Agreement to add free custom animations either publicly available or on their discord
- [Kri's Graphic House](https://discord.gg/JueRG3fCy6) for the custom banners
- !MWooM#0597 on Discord for the custom banners
- DurtyFree for his work on particle effects and cataloging GTA-related information [DurtyFree GTA V Dump](https://github.com/DurtyFree/gta-v-data-dumps/blob/master/particleEffectsCompact.json).
- [BoringNeptune](https://www.gta5-mods.com/users/BoringNeptune) for the custom dance emotes
- [CMG Mods](https://www.gta5-mods.com/users/-moses-) for the custom emotes
- [prue 颜](discord.gg/lunyxmods) for being a great friend and providing us with exclusive custom animations
- [PataMods](https://forum.cfx.re/u/Pata_PataMods) for the custom props
- [Crowded1337](https://www.gta5-mods.com/users/crowded1337) for the custom Gucci bag. I have removed the Gucci logo to comply with Rockstar Games & TakeTwo Interactive
- [EnchantedBrownie](https://www.gta5-mods.com/users/EnchantedBrownie) for the custom animations
- [Copofiscool](https://forum.cfx.re/u/copofiscool/) for adding a toggle to the Favorite Keybinds
- [iSentrie](https://forum.cfx.re/u/isentrie/) for additional code, support, and joining the RPEmotes project
- Chocoholic Animations for the custom animations
- [CrunchyCat](https://www.gta5-mods.com/users/crunchycat) for the custom animations
- [KayKayMods](https://discord.gg/5bYQVWVaxG) for the custom props
- [MonkeyWhisper](https://github.com/MonkeyWhisper) and [Project Sloth](https://github.com/Project-Sloth) for the custom props
- [Brummieee](https://forum.cfx.re/u/brummieee_maps/summary) for the custom props
- [Dark Animations](https://www.gta5-mods.com/users/Darks%20Animations) for the custom animations.
- [Chico](https://forum.cfx.re/u/chico) for implementing natives to reapply persistent moods and walk styles for ESX and QB-Core frameworks
- [-EcLiPsE-](https://www.gta5-mods.com/users/-EcLiPsE-) for allowing me to implement [Improved Prop Sets](https://www.gta5-mods.com/misc/improved-propsets-meta) and [GTA Online Biker Idle Anims](https://www.gta5-mods.com/misc/bike-idle-animations)
- [MrWitt](https://www.gta5-mods.com/users/MrWitt)for the custom animations
- [AdoredRose](https://forum.cfx.re/u/adoredrose/summary) for assisting with animations
- [Vedere](https://discord.gg/XMywAMQ8Ef) for the custom props
- [DRX Animations](https://www.gta5-mods.com/users/DRX%2DAnimations) for the custom animations
- [VNSIanims](https://discord.gg/cTNrjYSXXG) for the custom animations
- [PNWParksFan](https://www.gta5-mods.com/users/PNWParksFan) for the custom props
- [LSPDFR member Sam](https://www.lcpdfr.com/downloads/gta5mods/misc/23386-lspd-police-badge/) for their Custom LSPD police badge
- [GTA5Mods user Sladus_Slawonkus](https://www.gta5-mods.com/misc/lspd-police-badge-replace-sladus_slawonkus) for their reskinned LSPD badge
- [Scully](https://github.com/Scullyy/) for their past work on rpemotes
- [EP](https://github.com/EpKouhia) for their ice fishing props and emotes, originally used in scully_emotemenu
- [TayMcKenzieNZ](https://github.com/TayMcKenzieNZ) for their past work maintaining RP Emotes
- [ESX](https://github.com/esx-framework) for the creation of the translation system
- [41anims](https://www.gta5-mods.com/users/41anims) for allowing us to use their custom emotes in rpemotes-reborn
- [corbs](https://www.gta5-mods.com/users/corbs) for allowing us to use their custom emotes and poses in rpemotes-reborn
- [jaysigx](https://www.gta5-mods.com/misc/improved-umbrella) for allowing us to use their improved umbrella prop
- Crusopaul and Eki for discussing KVP and initializing it to the menu for persistent walk styles
### Emote & Props Creators:
- [SMGMissy](https://jenscreations.tebex.io/) for creating the pride flag props
- [MissSnowie](https://www.gta5-mods.com/users/MissySnowie)
- [Smokey](https://www.gta5-mods.com/users/struggleville)
- [BzZzi](https://forum.cfx.re/u/bzzzi/summary)
- [Natty3d](https://forum.cfx.re/u/natty3d/summary)
- [Amnilka](https://www.gta5-mods.com/users/frabi)
- [LittleSpoon](https://discord.gg/safeword)
- [LadyyShamrockk](https://www.gta5-mods.com/users/LadyyShamrockk)
- [Pupppy](https://discord.gg/rsN35X4s4N)
- [SapphireMods](https://discord.gg/Hf8F4nTyzt)
- [QueenSisters Animations](https://discord.gg/qbPtGwQuep)
- DurtyFree for his work on particle effects and cataloging GTA-related information [DurtyFree GTA V Dump](https://github.com/DurtyFree/gta-v-data-dumps/blob/master/particleEffectsCompact.json)
- [BoringNeptune](https://www.gta5-mods.com/users/BoringNeptune)
- [CMG Mods](https://www.gta5-mods.com/users/-moses-)
- [prue 颜](discord.gg/lunyxmods)
- [PataMods](https://forum.cfx.re/u/Pata_PataMods)
- [Crowded1337](https://www.gta5-mods.com/users/crowded1337)
- [EnchantedBrownie](https://www.gta5-mods.com/users/EnchantedBrownie)
- Chocoholic Animations
- [CrunchyCat](https://www.gta5-mods.com/users/crunchycat)
- [KayKayMods](https://discord.gg/5bYQVWVaxG)
- [MonkeyWhisper](https://github.com/MonkeyWhisper) and [Project Sloth](https://github.com/Project-Sloth)
- [Brummieee](https://forum.cfx.re/u/brummieee_maps/summary)
- [Dark Animations](https://www.gta5-mods.com/users/Darks%20Animations).
- [-EcLiPsE-](https://www.gta5-mods.com/users/-EcLiPsE-) for allowing me to implement [Improved Prop Sets](https://www.gta5-mods.com/misc/improved-propsets-meta) and [GTA Online Biker Idle Anims](https://www.gta5-mods.com/misc/bike-idle-animations)
- [MrWitt](https://www.gta5-mods.com/users/MrWitt)
- [Vedere](https://discord.gg/XMywAMQ8Ef)
- [DRX Animations](https://www.gta5-mods.com/users/DRX%2DAnimations)
- [VNSIanims](https://discord.gg/cTNrjYSXXG)
- [PNWParksFan](https://www.gta5-mods.com/users/PNWParksFan)
- [LSPDFR member Sam](https://www.lcpdfr.com/downloads/gta5mods/misc/23386-lspd-police-badge/)
- [GTA5Mods user Sladus_Slawonkus](https://www.gta5-mods.com/misc/lspd-police-badge-replace-sladus_slawonkus)
- [EP](https://github.com/EpKouhia)
- [TayMcKenzieNZ](https://github.com/TayMcKenzieNZ)
- [41anims](https://www.gta5-mods.com/users/41anims)
- [corbs](https://www.gta5-mods.com/users/corbs)
- [jaysigx](https://www.gta5-mods.com/misc/improved-umbrella)

View file

@ -4,7 +4,7 @@ BigDogs = {
"a_c_retriever",
"a_c_shepherd",
"a_c_rottweiler",
"ft-groe"
"ft-groe"
}
SmallDogs = {

View file

@ -246,26 +246,26 @@ RP.Walks = {
["Dreyfuss"] = {
"move_dreyfuss"
},
["Drunk"] = {
["DrunkWalk"] = {
"move_m@drunk@a"
},
["Drunk2"] = {
["DrunkWalk2"] = {
"move_m@buzzed",
"Drunk 2 - Buzzed"
},
["Drunk3"] = {
["DrunkWalk3"] = {
"move_m@drunk@moderatedrunk",
"Drunk 3 - Moderate"
},
["Drunk4"] = {
["DrunkWalk4"] = {
"move_m@drunk@moderatedrunk_head_up",
"Drunk 4 - Moderate 2"
},
["Drunk5"] = {
["DrunkWalk5"] = {
"move_m@drunk@slightlydrunk",
"Drunk 5 - Slightly Drunk"
},
["Drunk6"] = {
["DrunkWalk6"] = {
"move_m@drunk@verydrunk",
"Drunk 6 - Very Drunk"
},
@ -442,11 +442,11 @@ RP.Walks = {
"move_f@hurry@b",
"Hurry Female 2"
},
["Injured"] = {
["InjuredWalk"] = {
"move_m@injured",
"Injured"
},
["Injured2"] = {
["InjuredWalk2"] = {
"move_f@injured",
"Injured 2 - Female"
},
@ -6664,7 +6664,7 @@ RP.Emotes = {
EmoteMoving = true
}
},
["handshake"] = {
["solo_handshake"] = {
"mp_ped_interaction",
"handshake_guy_a",
"Handshake",
@ -6673,7 +6673,7 @@ RP.Emotes = {
EmoteDuration = 3000
}
},
["handshake2"] = {
["solo_handshake2"] = {
"mp_ped_interaction",
"handshake_guy_b",
"Handshake 2",
@ -8026,7 +8026,7 @@ RP.Emotes = {
EmoteMoving = true
}
},
["stickup"] = {
["solo_stickup"] = {
"random@countryside_gang_fight",
"biker_02_stickup_loop",
"Stick Up",
@ -8665,7 +8665,7 @@ RP.Emotes = {
EmoteMoving = true,
}
},
["slap"] = {
["solo_slap"] = {
"melee@unarmed@streamed_variations",
"plyr_takedown_front_slap",
"Slap",
@ -8675,7 +8675,7 @@ RP.Emotes = {
EmoteDuration = 2000
}
},
["headbutt"] = {
["solo_headbutt"] = {
"melee@unarmed@streamed_variations",
"plyr_takedown_front_headbutt",
"Headbutt"
@ -10807,15 +10807,6 @@ RP.Emotes = {
EmoteLoop = true,
EmoteMoving = false,
}
},
["femaleposeq"] = { -- Custom Emote By DRX Animations
"drx@femalestand13",
"xrd",
"Female Pose Q",
AnimationOptions = {
EmoteLoop = true,
EmoteMoving = false
}
},
["femaleposer"] = { -- Custom Emote By DRX Animations
"drx@femalestand14",

View file

@ -162,7 +162,7 @@ if Config.BinocularsEnabled then
end
end)
exports('toggleBinoculars', function()
CreateExport('toggleBinoculars', function()
UseBinocular()
end)
end

View file

@ -0,0 +1,107 @@
Framework = 'standalone'
PlayerLoaded, PlayerData = nil, {}
local function InitializeFramework()
if GetResourceState('es_extended') == 'started' then
ESX = exports['es_extended']:getSharedObject()
Framework = 'esx'
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
PlayerLoaded = true
end)
RegisterNetEvent('esx:onPlayerLogout', function()
PlayerData = {}
PlayerLoaded = false
end)
AddEventHandler('esx:setPlayerData', function(key, value)
PlayerData[key] = value
end)
AddEventHandler('onResourceStart', function(resourceName)
if GetCurrentResourceName() ~= resourceName then return end
PlayerData = ESX.GetPlayerData()
PlayerLoaded = true
end)
elseif GetResourceState('qb-core') == 'started' then
QBCore = exports['qb-core']:GetCoreObject()
Framework = 'qb'
AddEventHandler('QBCore:Client:OnPlayerLoaded', function()
PlayerData = QBCore.Functions.GetPlayerData()
end)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
PlayerData = {}
end)
AddEventHandler('onResourceStart', function(resourceName)
if GetCurrentResourceName() ~= resourceName then return end
PlayerData = QBCore.Functions.GetPlayerData()
end)
end
print('[RPEmotes-Reborn] Framework initialized: ' .. Framework)
end
function CanDoAction()
if Framework == 'esx' then
return PlayerLoaded and not PlayerData.dead
elseif Framework == 'qb' then
return LocalPlayer.state.isLoggedIn and not (PlayerData.metadata.inlaststand or PlayerData.metadata.isdead)
end
-- here you can implement your own standalone framework check
return true
end
InitializeFramework()
-- EVENTS
RegisterNetEvent('animations:client:PlayEmote', function(args)
if CanDoAction() then
EmoteCommandStart(args)
end
end)
if Config.Keybinding then
RegisterNetEvent('animations:client:BindEmote', function(args)
if CanDoAction() then
EmoteBindStart(nil, args)
end
end)
RegisterNetEvent('animations:client:EmoteBinds', function()
if CanDoAction() then
ListKeybinds()
end
end)
RegisterNetEvent('animations:client:EmoteDelete', function(args)
if CanDoAction() then
DeleteEmote(args)
end
end)
end
RegisterNetEvent('animations:client:EmoteMenu', function()
if CanDoAction() then
OpenEmoteMenu()
end
end)
RegisterNetEvent('animations:client:Walk', function(args)
if CanDoAction() then
WalkCommandStart(args)
end
end)
RegisterNetEvent('animations:client:ListWalks', function()
if CanDoAction() then
WalksOnCommand()
end
end)

View file

@ -17,10 +17,17 @@ local function ResetCrouch()
SetPedCanPlayAmbientAnims(playerPed, true)
local walkstyle = GetResourceKvpString("walkstyle")
if walkstyle ~= nil then
RequestWalking(walkstyle)
SetPedMovementClipset(PlayerPedId(), walkstyle, 0.5)
RemoveClipSet(walkstyle)
if walkstyle then
local toApply = RP[walkstyle]
if not toApply or type(toApply) ~= "table" or toApply.category ~= "Walks" then
ResetPedMovementClipset(playerPed, 0.5)
DeleteResourceKvp("walkstyle")
DebugPrint('Invalid walkstyle found in KVP, resetting to default.')
return
end
RequestWalking(toApply[1])
SetPedMovementClipset(PlayerPedId(), toApply[1], 0.5)
RemoveClipSet(toApply[1])
else
ResetPedMovementClipset(playerPed, 0.5)
end
@ -462,36 +469,33 @@ if Config.CrawlEnabled then
TriggerEvent('chat:addSuggestion', '/crawl', Translate('crawl'))
end
-- Exports --
---Returns if the player is crouched
---@return boolean
local function IsPlayerCrouched()
return isCrouched
end
exports('IsPlayerCrouched', IsPlayerCrouched)
CreateExport('IsPlayerCrouched', IsPlayerCrouched)
---Returns if the player is prone (both when laying still and when moving)
---@return boolean
local function IsPlayerProne()
return IsProne
end
exports('IsPlayerProne', IsPlayerProne)
CreateExport('IsPlayerProne', IsPlayerProne)
---Returns if the player is crawling (only when moving forward/backward)
---@return boolean
local function IsPlayerCrawling()
return isCrawling
end
exports('IsPlayerCrawling', IsPlayerCrawling)
CreateExport('IsPlayerCrawling', IsPlayerCrawling)
---Returns either "onfront" or "onback", this can be used to check if the player is on his back or on his stomach. NOTE: This will still return a string even if the player is not prone. Use IsPlayerProne() to check if the player is prone.
---@return string
local function GetPlayerProneType()
return proneType
end
exports('GetPlayerProneType', GetPlayerProneType)
CreateExport('GetPlayerProneType', GetPlayerProneType)
-- Useful to call if the player gets handcuffed etc.
exports('StopPlayerProne', stopPlayerProne)
CreateExport('StopPlayerProne', stopPlayerProne)

View file

@ -0,0 +1,895 @@
-- You probably shouldn't touch these.
IsInAnimation = false
CurrentAnimationName = nil
CurrentTextureVariation = nil
InHandsup = false
CONVERTED = false
local ChosenDict = ""
local CurrentAnimOptions = false
local PlayerGender = "male"
local PlayerProps = {}
local PreviewPedProps = {}
local PtfxNotif = false
local PtfxPrompt = false
local AnimationThreadStatus = false
local CheckStatus = false
local CanCancel = true
local InExitEmote = false
local ExitAndPlay = false
local EmoteCancelPlaying = false
local currentEmote = {}
local attachedProp
local scenarioObjects = {
`p_amb_coffeecup_01`,
`p_amb_joint_01`,
`p_cs_ciggy_01`,
`p_cs_ciggy_01b_s`,
`p_cs_clipboard`,
`prop_curl_bar_01`,
`p_cs_joint_01`,
`p_cs_joint_02`,
`prop_acc_guitar_01`,
`prop_amb_ciggy_01`,
`prop_amb_phone`,
`prop_beggers_sign_01`,
`prop_beggers_sign_02`,
`prop_beggers_sign_03`,
`prop_beggers_sign_04`,
`prop_bongos_01`,
`prop_cigar_01`,
`prop_cigar_02`,
`prop_cigar_03`,
`prop_cs_beer_bot_40oz_02`,
`prop_cs_paper_cup`,
`prop_cs_trowel`,
`prop_fib_clipboard`,
`prop_fish_slice_01`,
`prop_fishing_rod_01`,
`prop_fishing_rod_02`,
`prop_notepad_02`,
`prop_parking_wand_01`,
`prop_rag_01`,
`prop_scn_police_torch`,
`prop_sh_cigar_01`,
`prop_sh_joint_01`,
`prop_tool_broom`,
`prop_tool_hammer`,
`prop_tool_jackham`,
`prop_tennis_rack_01`,
`prop_weld_torch`,
`w_me_gclub`,
`p_amb_clipboard_01`
}
if not Config.AnimalEmotesEnabled then
RP.AnimalEmotes = {}
end
CreateThread(function()
LocalPlayer.state:set('canEmote', true, true)
end)
local function RunAnimationThread()
local pPed = PlayerPedId()
if AnimationThreadStatus then return end
AnimationThreadStatus = true
CreateThread(function()
local sleep
while AnimationThreadStatus and (IsInAnimation or PtfxPrompt) do
sleep = 500
if IsInAnimation then
sleep = 0
if IsPlayerAiming(pPed) then
EmoteCancel()
end
if not Config.AllowPunchingDuringEmote then
DisableControlAction(2, 140, true)
DisableControlAction(2, 141, true)
DisableControlAction(2, 142, true)
end
end
if PtfxPrompt and CurrentAnimOptions then
sleep = 0
if not PtfxNotif then
SimpleNotify(CurrentAnimOptions.PtfxInfo or Translate('ptfxinfo'))
PtfxNotif = true
end
if IsControlPressed(0, 47) then
PtfxStart()
Wait(CurrentAnimOptions.PtfxWait)
if CurrentAnimOptions.PtfxCanHold then
while IsControlPressed(0, 47) and IsInAnimation and AnimationThreadStatus do
Wait(5)
end
end
PtfxStop()
end
end
Wait(sleep)
end
end)
end
local function CheckStatusThread(dict, anim)
CreateThread(function()
if CheckStatus then
CheckStatus = false
Wait(10)
end
CheckStatus = true
while not IsEntityPlayingAnim(PlayerPedId(), dict, anim, 3) do
Wait(5)
end
while CheckStatus and IsInAnimation do
if not IsEntityPlayingAnim(PlayerPedId(), dict, anim, 3) then
DebugPrint("Animation ended")
DestroyAllProps()
EmoteCancel()
break
end
Wait(0)
end
end)
end
local function cleanScenarioObjects(isClone)
local ped = isClone and ClonedPed or PlayerPedId()
local playerCoords = GetEntityCoords(ped)
for i = 1, #scenarioObjects do
local deleteScenarioObject = GetClosestObjectOfType(playerCoords.x, playerCoords.y, playerCoords.z, 1.0,
scenarioObjects[i], false, true, true)
if DoesEntityExist(deleteScenarioObject) then
SetEntityAsMissionEntity(deleteScenarioObject, false, false)
DeleteObject(deleteScenarioObject)
end
end
end
function EmoteCancel(force)
LocalPlayer.state:set('currentEmote', nil, true)
EmoteCancelPlaying = true
if InExitEmote then
return
end
if not CanCancel and not force then return end
if ChosenDict == "MaleScenario" and IsInAnimation then
ClearPedTasksImmediately(PlayerPedId())
IsInAnimation = false
DebugPrint("Forced scenario exit")
elseif ChosenDict == "Scenario" and IsInAnimation then
ClearPedTasksImmediately(PlayerPedId())
IsInAnimation = false
DebugPrint("Forced scenario exit")
end
PtfxNotif = false
PtfxPrompt = false
Pointing = false
if IsInAnimation then
local ped = PlayerPedId()
if LocalPlayer.state.ptfx then
PtfxStop()
end
DetachEntity(ped, true, false)
CancelSharedEmote()
if CurrentAnimOptions and CurrentAnimOptions.ExitEmote then
local options = CurrentAnimOptions
local ExitEmoteType = options.ExitEmoteType or "Emotes"
if not RP[options.ExitEmote] then
DebugPrint("Exit emote was invalid")
IsInAnimation = false
ClearPedTasks(ped)
return
end
OnEmotePlay(options.ExitEmote)
DebugPrint("Playing exit animation")
local animationOptions = RP[options.ExitEmote].AnimationOptions
if animationOptions and animationOptions.EmoteDuration then
InExitEmote = true
SetTimeout(animationOptions.EmoteDuration, function()
InExitEmote = false
DestroyAllProps()
ClearPedTasks(ped)
EmoteCancelPlaying = false
end)
return
end
else
IsInAnimation = false
ClearPedTasks(ped)
EmoteCancelPlaying = false
end
DestroyAllProps()
end
cleanScenarioObjects(false)
AnimationThreadStatus = false
CheckStatus = false
end
function EmoteMenuStart(name, category, textureVariation)
local emote = RP[name]
if not emote then
return
end
if emote.category ~= category then
DebugPrint("Emote category mismatch : " .. emote.category .. " vs " .. category)
return
end
if category == "Expressions" then
SetPlayerPedExpression(name, true)
return
end
if emote.category == "AnimalEmotes" then
CheckAnimalAndOnEmotePlay(name)
return
end
OnEmotePlay(name, textureVariation)
end
function EmoteMenuStartClone(name, category)
if not Config.PreviewPed then return end
if not DoesEntityExist(ClonedPed) then return end
local emote = RP[name]
if not emote then
return
end
if emote.category ~= category then
DebugPrint("Emote category mismatch : " .. emote.category .. " vs " .. category)
return
end
if category == "Expressions" then
SetFacialIdleAnimOverride(ClonedPed, emote[1], true)
return
end
OnEmotePlayClone(name)
end
function EmoteCommandStart(args)
if #args > 0 then
if IsEntityDead(PlayerPedId()) or IsPedRagdoll(PlayerPedId()) or IsPedGettingUp(PlayerPedId()) or IsPedInMeleeCombat(PlayerPedId()) then
TriggerEvent('chat:addMessage', {
color = { 255, 0, 0 },
multiline = true,
args = { "RPEmotes", Translate('dead') }
})
return
end
if (IsPedSwimming(PlayerPedId()) or IsPedSwimmingUnderWater(PlayerPedId())) and not Config.AllowInWater then
TriggerEvent('chat:addMessage', {
color = { 255, 0, 0 },
multiline = true,
args = { "RPEmotes", Translate('swimming') }
})
return
end
local name = string.lower(args[1])
if name == "c" then
if IsInAnimation then
EmoteCancel()
else
EmoteChatMessage(Translate('nocancel'))
end
return
end
local emote = RP[name]
if emote then
if emote.category == "AnimalEmotes" then
if Config.AnimalEmotesEnabled then
CheckAnimalAndOnEmotePlay(name)
else
EmoteChatMessage(Translate('animaldisabled'))
end
return
end
if emote.category == "PropEmotes" and emote.AnimationOptions.PropTextureVariations then
if #args > 1 then
local textureVariation = tonumber(args[2])
if emote.AnimationOptions.PropTextureVariations[textureVariation] then
OnEmotePlay(name, textureVariation - 1)
return
else
local str = ""
for k, v in ipairs(emote.AnimationOptions.PropTextureVariations) do
str = str .. string.format("\n(%s) - %s", k, v.Name)
end
EmoteChatMessage(string.format(Translate('invalidvariation'), str), true)
OnEmotePlay(name, 0)
return
end
end
end
OnEmotePlay(name)
else
EmoteChatMessage("'" .. name .. "' " .. Translate('notvalidemote') .. "")
end
end
end
function CheckAnimalAndOnEmotePlay(name)
local playerPed = PlayerPedId()
local isValidPet = false
if string.sub(name, 1, 4) == "bdog" then
for _, model in ipairs(BigDogs) do
if IsPedModel(playerPed, GetHashKey(model)) then
isValidPet = true
break
end
end
elseif string.sub(name, 1, 4) == "sdog" then
for _, model in ipairs(SmallDogs) do
if IsPedModel(playerPed, GetHashKey(model)) then
isValidPet = true
break
end
end
end
if isValidPet then
OnEmotePlay(name)
else
EmoteChatMessage(Translate('notvalidpet'))
end
end
---@param isClone? boolean
function DestroyAllProps(isClone)
if isClone then
for _, v in pairs(PreviewPedProps) do
DeleteEntity(v)
end
PreviewPedProps = {}
else
for _, v in pairs(PlayerProps) do
DeleteEntity(v)
end
PlayerProps = {}
end
DebugPrint("Destroyed Props for " .. (isClone and "clone" or "player"))
end
---@param data table
---@return boolean
function AddProp(data)
assert(data.prop1, 'no prop1 passed')
assert(data.bone, 'no bone passed')
data.off1 = data.off1 or 0.0
data.off2 = data.off2 or 0.0
data.off3 = data.off3 or 0.0
data.rot1 = data.rot1 or 0.0
data.rot2 = data.rot2 or 0.0
data.rot3 = data.rot3 or 0.0
assert(data.noCollision == nil or type(data.noCollision) == "boolean", 'noCollision must be a boolean')
local target = data.isClone and ClonedPed or PlayerPedId()
local x, y, z = table.unpack(GetEntityCoords(target))
if not IsModelValid(data.prop1) then
DebugPrint(tostring(data.prop1) .. " is not a valid model!")
return false
end
LoadPropDict(data.prop1)
attachedProp = CreateObject(GetHashKey(data.prop1), x, y, z + 0.2, not data.isClone, true, true)
if data.textureVariation ~= nil then
SetObjectTextureVariation(attachedProp, data.textureVariation)
end
if data.noCollision then
SetEntityCollision(attachedProp, false, false)
end
AttachEntityToEntity(attachedProp, target, GetPedBoneIndex(target, data.bone), data.off1, data.off2, data.off3, data.rot1, data.rot2, data.rot3,
true, true, false, true, 1, true)
if data.isClone then
table.insert(PreviewPedProps, attachedProp)
else
table.insert(PlayerProps, attachedProp)
end
SetModelAsNoLongerNeeded(data.prop1)
DebugPrint("Added prop to " .. (data.isClone and "clone" or "player"))
return true
end
function CheckGender()
PlayerGender = "male"
if GetEntityModel(PlayerPedId()) == GetHashKey("mp_f_freemode_01") then
PlayerGender = "female"
end
DebugPrint("Set gender to " .. PlayerGender)
end
RegisterNetEvent('animations:ToggleCanDoAnims', function(value)
LocalPlayer.state:set('canEmote', value, true)
end)
function OnEmotePlay(name, textureVariation)
local emoteData = RP[name]
if not emoteData then
EmoteChatMessage("'" .. name .. "' " .. Translate('notvalidemote') .. "")
return
end
if not LocalPlayer.state.canEmote then return end
if not DoesEntityExist(PlayerPedId()) then
return false
end
cleanScenarioObjects(false)
InVehicle = IsPedInAnyVehicle(PlayerPedId(), true)
Pointing = false
if not Config.AllowEmoteInVehicle and InVehicle then
return
end
if Config.AdultEmotesDisabled and emoteData.AdultAnimation then
return EmoteChatMessage(Translate('adultemotedisabled'))
end
if InExitEmote then
return false
end
if Config.CancelPreviousEmote and IsInAnimation and not ExitAndPlay and not EmoteCancelPlaying then
ExitAndPlay = true
DebugPrint("Canceling previous emote and playing next emote")
PlayExitAndEnterEmote(name, textureVariation)
return
end
local animOption = emoteData.AnimationOptions
if InVehicle then
if animOption and animOption.NotInVehicle then
return EmoteChatMessage(Translate('not_in_a_vehicle'))
end
elseif animOption and animOption.onlyInVehicle then
return EmoteChatMessage(Translate('in_a_vehicle'))
end
if CurrentAnimOptions and CurrentAnimOptions.ExitEmote and animOption and animOption.ExitEmote then
if not (animOption and CurrentAnimOptions.ExitEmote == animOption.ExitEmote) and RP[CurrentAnimOptions.ExitEmote][2] ~= emoteData[2] then
return
end
end
if IsInActionWithErrorMessage() then
return false
end
ChosenDict = emoteData[1]
local anim = emoteData[2]
CurrentAnimationName = name
LocalPlayer.state:set('currentEmote', name, true)
CurrentTextureVariation = textureVariation
CurrentAnimOptions = animOption
if Config.DisarmPlayerOnEmote then
if IsPedArmed(PlayerPedId(), 7) then
SetCurrentPedWeapon(PlayerPedId(), GetHashKey('WEAPON_UNARMED'), true)
end
end
if animOption and animOption.Prop then
DestroyAllProps()
end
if ChosenDict == "MaleScenario" or ChosenDict == "Scenario" or ChosenDict == "ScenarioObject" then
if InVehicle then return end
CheckGender()
ClearPedTasks(PlayerPedId())
DestroyAllProps()
if ChosenDict == "MaleScenario" then
if PlayerGender == "male" then
TaskStartScenarioInPlace(PlayerPedId(), anim, 0, true)
DebugPrint("Playing scenario = (" .. anim .. ")")
else
EmoteCancel()
EmoteChatMessage(Translate('maleonly'))
return
end
elseif ChosenDict == "ScenarioObject" then
local BehindPlayer = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, -0.5, -0.5)
TaskStartScenarioAtPosition(PlayerPedId(), anim, BehindPlayer.x, BehindPlayer.y, BehindPlayer.z, GetEntityHeading(PlayerPedId()), 0, true, false)
DebugPrint("Playing scenario = (" .. anim .. ")")
else
TaskStartScenarioInPlace(PlayerPedId(), anim, 0, true)
DebugPrint("Playing scenario = (" .. anim .. ")")
end
IsInAnimation = true
RunAnimationThread()
return
end
-- Small delay at the start
if animOption and animOption.StartDelay then
Wait(animOption.StartDelay)
end
if not LoadAnim(ChosenDict) then
EmoteChatMessage("'" .. name .. "' " .. Translate('notvalidemote') .. "")
return
end
local movementType = 0
if InVehicle then
if animOption and animOption.FullBody then
movementType = 35
else
movementType = 51
end
elseif animOption then
if animOption.EmoteMoving then
movementType = 51
elseif animOption.EmoteLoop then
movementType = 1
elseif animOption.EmoteStuck then
movementType = 50
end
end
DebugPrint("Animation flag = (" .. movementType .. ")")
if animOption then
if animOption.PtfxAsset then
Ptfx1, Ptfx2, Ptfx3, Ptfx4, Ptfx5, Ptfx6, PtfxScale = table.unpack(animOption.PtfxPlacement)
PtfxNotif = false
PtfxPrompt = true
RunAnimationThread()
TriggerServerEvent("rpemotes:ptfx:sync", animOption.PtfxAsset, animOption.PtfxName, vector3(Ptfx1, Ptfx2, Ptfx3),
vector3(Ptfx4, Ptfx5, Ptfx6), animOption.PtfxBone, PtfxScale, animOption.PtfxColor)
else
PtfxPrompt = false
end
end
if IsPedUsingAnyScenario(PlayerPedId()) or IsPedActiveInScenario(PlayerPedId()) then
ClearPedTasksImmediately(PlayerPedId())
end
TaskPlayAnim(PlayerPedId(), ChosenDict, anim, animOption?.BlendInSpeed or 5.0, animOption?.BlendOutSpeed or 5.0, animOption?.EmoteDuration or -1, animOption?.Flag or movementType, 0, false, false,
false)
RemoveAnimDict(ChosenDict)
IsInAnimation = true
RunAnimationThread()
if not (animOption and animOption.Prop) then
CheckStatusThread(ChosenDict, anim)
end
local currentEmoteTable = emoteData
for _, tabledata in pairs(RP) do
for command, emotedata in pairs(tabledata) do
if emotedata == emoteData then
table.insert(currentEmoteTable, command)
break
end
end
end
currentEmote = currentEmoteTable
if animOption and animOption.Prop then
PropPl1, PropPl2, PropPl3, PropPl4, PropPl5, PropPl6 = table.unpack(animOption.PropPlacement)
Wait(animOption and animOption.EmoteDuration or 0)
if not AddProp({
prop1 = animOption.Prop,
bone = animOption.PropBone,
off1 = PropPl1, off2 = PropPl2, off3 = PropPl3,
rot1 = PropPl4, rot2 = PropPl5, rot3 = PropPl6,
textureVariation = textureVariation,
isClone = false,
noCollision = animOption.PropNoCollision
}) then return end
if animOption.SecondProp then
SecondPropPl1, SecondPropPl2, SecondPropPl3, SecondPropPl4, SecondPropPl5, SecondPropPl6 = table.unpack(animOption.SecondPropPlacement)
if not AddProp({
prop1 = animOption.SecondProp,
bone = animOption.SecondPropBone,
off1 = SecondPropPl1, off2 = SecondPropPl2, off3 = SecondPropPl3,
rot1 = SecondPropPl4, rot2 = SecondPropPl5, rot3 = SecondPropPl6,
textureVariation = textureVariation,
isClone = false,
noCollision = animOption.SecondPropNoCollision
}) then
DestroyAllProps()
return
end
end
-- Ptfx is on the prop, then we need to sync it
if not animOption then return end
if animOption.PtfxAsset and not animOption.PtfxNoProp then
TriggerServerEvent("rpemotes:ptfx:syncProp", ObjToNet(attachedProp))
end
end
end
function OnEmotePlayClone(name)
if not Config.PreviewPed then return end
cleanScenarioObjects(true)
if not DoesEntityExist(ClonedPed) then
return false
end
if InExitEmote then
return false
end
if Config.CancelPreviousEmote and not ExitAndPlay and not EmoteCancelPlaying then
ExitAndPlay = true
DebugPrint("Canceling previous emote and playing next emote")
return
end
local emoteData = RP[name]
local animOption = emoteData.AnimationOptions
local dict, anim = table.unpack(emoteData)
if animOption and animOption.Prop then
DestroyAllProps(true)
end
if dict == "MaleScenario" or dict == "Scenario" or dict == "ScenarioObject" then
CheckGender()
ClearPedTasks(ClonedPed)
DestroyAllProps(true)
if dict == "MaleScenario" then
if PlayerGender == "male" then
TaskStartScenarioInPlace(ClonedPed, anim, 0, true)
end
elseif dict == "ScenarioObject" then
local BehindPlayer = GetOffsetFromEntityInWorldCoords(ClonedPed, 0.0, -0.5, -0.5)
TaskStartScenarioAtPosition(ClonedPed, anim, BehindPlayer.x, BehindPlayer.y, BehindPlayer.z, GetEntityHeading(ClonedPed), 0, true, false)
elseif dict == "Scenario" then
TaskStartScenarioInPlace(ClonedPed, anim, 0, true)
end
return
end
if not LoadAnim(dict) then
EmoteChatMessage("'" .. name .. "' " .. Translate('notvalidemote') .. "")
return
end
local movementType = 0
if animOption then
if animOption.EmoteMoving then
movementType = 51
elseif animOption.EmoteLoop then
movementType = 1
elseif animOption.EmoteStuck then
movementType = 50
end
end
if IsPedUsingAnyScenario(ClonedPed) or IsPedActiveInScenario(ClonedPed) then
ClearPedTasksImmediately(ClonedPed)
end
TaskPlayAnim(ClonedPed, dict, anim, 5.0, 5.0, animOption and animOption.EmoteDuration or -1, animOption?.Flag or movementType, 0, false, false, false)
RemoveAnimDict(dict)
if animOption and animOption.Prop then
local PropPl1, PropPl2, PropPl3, PropPl4, PropPl5, PropPl6 = table.unpack(animOption.PropPlacement)
Wait(animOption and animOption.EmoteDuration or 0)
if not AddProp({
prop1 = animOption.Prop,
bone = animOption.PropBone,
off1 = PropPl1, off2 = PropPl2, off3 = PropPl3,
rot1 = PropPl4, rot2 = PropPl5, rot3 = PropPl6,
isClone = true,
noCollision = animOption.PropNoCollision
}) then return end
if animOption.SecondProp then
local SecondPropPl1, SecondPropPl2, SecondPropPl3, SecondPropPl4, SecondPropPl5, SecondPropPl6 = table.unpack(animOption.SecondPropPlacement)
if not AddProp({
prop1 = animOption.SecondProp,
bone = animOption.SecondPropBone,
off1 = SecondPropPl1, off2 = SecondPropPl2, off3 = SecondPropPl3,
rot1 = SecondPropPl4, rot2 = SecondPropPl5, rot3 = SecondPropPl6,
isClone = true,
noCollision = animOption.SecondPropNoCollision
}) then
DestroyAllProps(true)
return
end
end
end
end
function PlayExitAndEnterEmote(name, textureVariation)
local ped = PlayerPedId()
if not CanCancel then return end
if ChosenDict == "MaleScenario" and IsInAnimation then
ClearPedTasksImmediately(ped)
IsInAnimation = false
DebugPrint("Forced scenario exit")
elseif ChosenDict == "Scenario" and IsInAnimation then
ClearPedTasksImmediately(ped)
IsInAnimation = false
DebugPrint("Forced scenario exit")
end
PtfxNotif = false
PtfxPrompt = false
Pointing = false
if LocalPlayer.state.ptfx then
PtfxStop()
end
DetachEntity(ped, true, false)
CancelSharedEmote()
if CurrentAnimOptions?.ExitEmote then
local options = CurrentAnimOptions or {}
if not RP[options.ExitEmote] then
DebugPrint("Exit emote was invalid")
ClearPedTasks(ped)
IsInAnimation = false
return
end
OnEmotePlay(options.ExitEmote)
DebugPrint("Playing exit animation")
local animationOptions = RP[options.ExitEmote].AnimationOptions
if animationOptions and animationOptions.EmoteDuration then
InExitEmote = true
SetTimeout(animationOptions.EmoteDuration, function()
InExitEmote = false
DestroyAllProps(true)
ClearPedTasks(ped)
OnEmotePlay(name, textureVariation)
ExitAndPlay = false
end)
return
end
else
ClearPedTasks(ped)
IsInAnimation = false
ExitAndPlay = false
DestroyAllProps(true)
OnEmotePlay(name, CurrentTextureVariation)
end
end
RegisterNetEvent('animations:client:EmoteCommandStart', function(args)
EmoteCommandStart(args)
end)
CreateExport("EmoteCommandStart", function(emoteName, textureVariation)
EmoteCommandStart({ emoteName, textureVariation })
end)
CreateExport("EmoteCancel", EmoteCancel)
CreateExport("CanCancelEmote", function(State)
CanCancel = State == true
end)
CreateExport('IsPlayerInAnim', function()
return LocalPlayer.state.currentEmote
end)
CreateExport('getCurrentEmote', function()
return currentEmote
end)
-- Door stuff
local openingDoor = false
AddEventHandler('CEventOpenDoor', function(unk1)
if unk1[1] ~= PlayerPedId() then return end
if ShowPed then
return
end
if not IsInAnimation then
return
end
if openingDoor then
return
end
openingDoor = true
while IsPedOpeningADoor(PlayerPedId()) do
Wait(100)
end
openingDoor = false
Wait(200)
ClearPedTasks(PlayerPedId())
DestroyAllProps()
OnEmotePlay(CurrentAnimationName, CurrentTextureVariation)
end)
local isBumpingPed = false
local timeout = 500
AddEventHandler("CEventPlayerCollisionWithPed", function(unk1)
if unk1[1] ~= PlayerPedId() then return end
if not IsInAnimation then
return
end
if isBumpingPed then
timeout = 500
return
end
isBumpingPed = true
timeout = 500
-- We wait a bit to avoid collision with the ped resetting the animation again
while timeout > 0 do
Wait(100)
timeout = timeout - 100
end
if not IsInAnimation then
return
end
isBumpingPed = false
ClearPedTasks(PlayerPedId())
Wait(125)
DestroyAllProps()
OnEmotePlay(CurrentAnimationName, CurrentTextureVariation)
end)
AddEventHandler('onResourceStop', function(resource)
if resource ~= GetCurrentResourceName() then return end
local ped = PlayerPedId()
ClosePedMenu()
DestroyAllProps()
ClearPedTasksImmediately(ped)
DetachEntity(ped, true, false)
ResetPedMovementClipset(ped, 0.8)
end)

View file

@ -27,39 +27,16 @@ local _menuPool = NativeUI.CreatePool()
local mainMenu = NativeUI.CreateMenu(Config.MenuTitle or "", "", menuPosition["x"], menuPosition["y"], menuHeader, menuHeader)
_menuPool:Add(mainMenu)
local sharemenu, shareddancemenu, favmenu, infomenu
local sharemenu, shareddancemenu, infomenu
local EmoteTable = {}
local FavEmoteTable = {}
local DanceTable = {}
local AnimalTable = {}
local PropETable = {}
local PropTable = {}
local WalkTable = {}
local FaceTable = {}
local ShareTable = {}
local FavoriteEmote = ""
if Config.FavKeybindEnabled then
RegisterCommand('emotefav', function() FavKeybind() end, false)
RegisterKeyMapping("emotefav", Translate("register_fav_anim"), "keyboard", Config.FavKeybind)
local doingFavoriteEmote = false
function FavKeybind()
if doingFavoriteEmote == false then
doingFavoriteEmote = true
if not IsPedSittingInAnyVehicle(PlayerPedId()) then
if FavoriteEmote ~= "" and (not CanUseFavKeyBind or CanUseFavKeyBind()) then
EmoteCommandStart(nil, { FavoriteEmote, 0 })
Wait(500)
end
end
else
EmoteCancel()
doingFavoriteEmote = false
end
end
end
function AddEmoteMenu(menu)
local submenu = _menuPool:AddSubMenu(menu, Translate('emotes'), "", true, true)
@ -85,17 +62,7 @@ function AddEmoteMenu(menu)
table.insert(EmoteTable, Translate('shareemotes'))
end
-- Temp var to be able to sort every emotes in the fav list
local favEmotes = {}
if not Config.Keybinding then
favmenu = _menuPool:AddSubMenu(submenu, Translate('favoriteemotes'), Translate('favoriteinfo'), true, true)
favmenu:AddItem(NativeUI.CreateItem(Translate('prop2info'), ""))
favmenu:AddItem(NativeUI.CreateItem(Translate('rfavorite'), Translate('rfavorite')))
-- Add two elements as offset
table.insert(FavEmoteTable, Translate('rfavorite'))
table.insert(FavEmoteTable, Translate('rfavorite'))
table.insert(EmoteTable, Translate('favoriteemotes'))
else
if Config.Keybinding then
table.insert(EmoteTable, "keybinds")
submenu:AddItem(NativeUI.CreateItem(Translate('keybinds'), Translate('keybindsinfo') .. " /emotebind [~y~num4-9~w~] [~g~emotename~w~]"))
end
@ -104,120 +71,84 @@ function AddEmoteMenu(menu)
local x, y, z = table.unpack(b)
submenu:AddItem(NativeUI.CreateItem(z, "/e (" .. a .. ")"))
table.insert(EmoteTable, a)
if not Config.Keybinding then
favEmotes[a] = z
end
end
for a, b in PairsByKeys(RP.Dances) do
local x, y, z = table.unpack(b)
dancemenu:AddItem(NativeUI.CreateItem(z, "/e (" .. a .. ")"))
local name = '🤼 ' .. b[3]
dancemenu:AddItem(NativeUI.CreateItem(name, "/e (" .. a .. ")"))
if Config.SharedEmotesEnabled then
shareddancemenu:AddItem(NativeUI.CreateItem(z, "/nearby (" .. a .. ")"))
shareddancemenu:AddItem(NativeUI.CreateItem(name, "/nearby (" .. a .. ")"))
end
table.insert(DanceTable, a)
if not Config.Keybinding then
favEmotes[a] = z
end
end
if Config.AnimalEmotesEnabled then
for a, b in PairsByKeys(RP.AnimalEmotes) do
local x, y, z = table.unpack(b)
animalmenu:AddItem(NativeUI.CreateItem(z, "/e (" .. a .. ")"))
local name = '🐶 ' .. b[3]
animalmenu:AddItem(NativeUI.CreateItem(name, "/e (" .. a .. ")"))
table.insert(AnimalTable, a)
if not Config.Keybinding then
favEmotes[a] = z
end
end
end
if Config.SharedEmotesEnabled then
for a, b in PairsByKeys(RP.Shared) do
local x, y, z, otheremotename = table.unpack(b)
local shareitem = NativeUI.CreateItem(z, "/nearby (~g~" .. a .. "~w~)" .. (otheremotename and " " .. Translate('makenearby') .. " (~y~" .. otheremotename .. "~w~)" or ""))
local name = b[3]
local shareitem = NativeUI.CreateItem(name, "/nearby (~g~" .. a .. "~w~)" .. (otheremotename and " " .. Translate('makenearby') .. " (~y~" .. otheremotename .. "~w~)" or ""))
sharemenu:AddItem(shareitem)
table.insert(ShareTable, a)
end
end
for a, b in PairsByKeys(RP.PropEmotes) do
local x, y, z = table.unpack(b)
local name = '📦 ' .. b[3]
local propitem = b.AnimationOptions.PropTextureVariations and
NativeUI.CreateListItem(z, b.AnimationOptions.PropTextureVariations, 1, "/e (" .. a .. ")") or
NativeUI.CreateItem(z, "/e (" .. a .. ")")
NativeUI.CreateListItem(name, b.AnimationOptions.PropTextureVariations, 1, "/e (" .. a .. ")") or
NativeUI.CreateItem(name, "/e (" .. a .. ")")
propmenu:AddItem(propitem)
table.insert(PropETable, a)
if not Config.Keybinding then
favEmotes[a] = z
end
table.insert(PropTable, a)
end
if not Config.Keybinding then
-- Add the emotes to the fav menu
for emoteName, emoteLabel in PairsByKeys(favEmotes) do
favmenu:AddItem(NativeUI.CreateItem(emoteLabel, Translate('set') .. emoteLabel .. Translate('setboundemote')))
table.insert(FavEmoteTable, emoteName)
end
favmenu.OnItemSelect = function(sender, item, index)
if FavEmoteTable[index] == Translate('rfavorite') then
FavoriteEmote = ""
SimpleNotify(Translate('rfavorite'))
return
end
if Config.FavKeybindEnabled then
FavoriteEmote = FavEmoteTable[index]
SimpleNotify("~o~" .. FirstToUpper(FavoriteEmote) .. Translate('newsetemote'))
end
end
end
favEmotes = nil
-- Ped Emote on Change Index
dancemenu.OnIndexChange = function(menu, newindex)
dancemenu.OnIndexChange = function(_, newindex)
ClearPedTaskPreview()
EmoteMenuStartClone(DanceTable[newindex], "dances")
EmoteMenuStartClone(DanceTable[newindex], "Dances")
end
propmenu.OnIndexChange = function(menu, newindex)
propmenu.OnIndexChange = function(_, newindex)
ClearPedTaskPreview()
EmoteMenuStartClone(PropETable[newindex], "props")
EmoteMenuStartClone(PropTable[newindex], "PropEmotes")
end
submenu.OnIndexChange = function(menu, newindex)
if newindex > 6 then
submenu.OnIndexChange = function(_, newindex)
if newindex > 5 then
ClearPedTaskPreview()
EmoteMenuStartClone(EmoteTable[newindex], "emotes")
EmoteMenuStartClone(EmoteTable[newindex], "Emotes")
end
end
dancemenu.OnMenuClosed = function(menu)
dancemenu.OnMenuClosed = function()
ClearPedTaskPreview()
end
--------
dancemenu.OnItemSelect = function(sender, item, index)
EmoteMenuStart(DanceTable[index], "dances")
dancemenu.OnItemSelect = function(_, _, index)
EmoteMenuStart(DanceTable[index], "Dances")
end
if Config.AnimalEmotesEnabled then
animalmenu.OnItemSelect = function(sender, item, index)
EmoteMenuStart(AnimalTable[index], "animals")
animalmenu.OnItemSelect = function(_, _, index)
EmoteMenuStart(AnimalTable[index], "AnimalEmotes")
end
end
if Config.SharedEmotesEnabled then
sharemenu.OnItemSelect = function(sender, item, index)
sharemenu.OnItemSelect = function(_, _, index)
if ShareTable[index] ~= 'none' then
local target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), ShareTable[index])
TriggerServerEvent("rpemotes:server:requestEmote", GetPlayerServerId(target), ShareTable[index])
SimpleNotify(Translate('sentrequestto') .. GetPlayerName(target))
else
SimpleNotify(Translate('nobodyclose'))
@ -225,10 +156,10 @@ function AddEmoteMenu(menu)
end
end
shareddancemenu.OnItemSelect = function(sender, item, index)
shareddancemenu.OnItemSelect = function(_, _, index)
local target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), DanceTable[index], 'Dances')
TriggerServerEvent("rpemotes:server:requestEmote", GetPlayerServerId(target), DanceTable[index], 'Dances')
SimpleNotify(Translate('sentrequestto') .. GetPlayerName(target))
else
SimpleNotify(Translate('nobodyclose'))
@ -236,23 +167,23 @@ function AddEmoteMenu(menu)
end
end
propmenu.OnItemSelect = function(sender, item, index)
EmoteMenuStart(PropETable[index], "props")
propmenu.OnItemSelect = function(_, _, index)
EmoteMenuStart(PropTable[index], "PropEmotes")
end
propmenu.OnListSelect = function(menu, item, itemIndex, listIndex)
EmoteMenuStart(PropETable[itemIndex], "props", item:IndexToItem(listIndex).Value)
propmenu.OnListSelect = function(_, item, itemIndex, listIndex)
EmoteMenuStart(PropTable[itemIndex], "PropEmotes", item:IndexToItem(listIndex).Value)
end
submenu.OnItemSelect = function(sender, item, index)
submenu.OnItemSelect = function(_, _, index)
if Config.Search and EmoteTable[index] == Translate('searchemotes') then
EmoteMenuSearch(submenu)
elseif EmoteTable[index] ~= Translate('favoriteemotes') then
EmoteMenuStart(EmoteTable[index], "emotes")
else
EmoteMenuStart(EmoteTable[index], "Emotes")
end
end
submenu.OnMenuClosed = function(menu)
submenu.OnMenuClosed = function()
if not isSearching then
ClosePedMenu()
end
@ -269,7 +200,6 @@ if Config.Search then
function EmoteMenuSearch(lastMenu)
ClosePedMenu()
local favEnabled = not Config.Keybinding and Config.FavKeybindEnabled
AddTextEntry("PM_NAME_CHALL", Translate('searchinputtitle'))
DisplayOnscreenKeyboard(1, "PM_NAME_CHALL", "", "", "", "", "", 30)
while UpdateOnscreenKeyboard() == 0 do
@ -279,12 +209,10 @@ if Config.Search then
local input = GetOnscreenKeyboardResult()
if input ~= nil then
local results = {}
for k, v in pairs(RP) do
if not ignoredCategories[k] then
for a, b in pairs(v) do
if string.find(string.lower(a), string.lower(input)) or (b[3] ~= nil and string.find(string.lower(b[3]), string.lower(input))) then
table.insert(results, {table = k, name = a, data = b})
end
for a, b in pairs(RP) do
if not ignoredCategories[b.category] then
if string.find(string.lower(a), string.lower(input)) or (b[3] ~= nil and string.find(string.lower(b[3]), string.lower(input))) then
table.insert(results, { table = b.category, name = a, data = b })
end
end
end
@ -294,9 +222,6 @@ if Config.Search then
local searchMenu = _menuPool:AddSubMenu(lastMenu, string.format('%s '..Translate('searchmenudesc')..' ~r~%s~w~', #results, input), "", true, true)
local sharedDanceMenu
if favEnabled then
searchMenu:AddItem(NativeUI.CreateItem(Translate('rfavorite'), Translate('rfavorite')))
end
if Config.SharedEmotesEnabled then
sharedDanceMenu = _menuPool:AddSubMenu(searchMenu, Translate('sharedanceemotes'), "", true, true)
@ -313,7 +238,7 @@ if Config.Search then
desc = "/nearby (~g~" .. v.name .. "~w~) " .. Translate('makenearby') .. " (~y~" .. otheremotename .. "~w~)"
end
else
desc = "/e (" .. v.name .. ")" .. (favEnabled and "\n" .. Translate('searchshifttofav') or "")
desc = "/e (" .. v.name .. ")"
end
if v.data.AnimationOptions and v.data.AnimationOptions.PropTextureVariations then
@ -327,79 +252,52 @@ if Config.Search then
end
end
if favEnabled then
table.insert(results, 1, Translate('rfavorite'))
end
searchMenu.OnMenuChanged = function(menu, newmenu, forward)
searchMenu.OnMenuChanged = function()
isSearching = false
ShowPedMenu()
end
searchMenu.OnIndexChange = function(menu, newindex)
searchMenu.OnIndexChange = function(_, newindex)
local data = results[newindex]
ClearPedTaskPreview()
if data.table == "Emotes" or data.table == "Dances" then
EmoteMenuStartClone(data.name, string.lower(data.table))
elseif data.table == "PropEmotes" then
EmoteMenuStartClone(data.name, "props")
elseif data.table == "AnimalEmotes" then
EmoteMenuStartClone(data.name, "animals")
end
EmoteMenuStartClone(data.name, data.data.category)
end
searchMenu.OnItemSelect = function(sender, item, index)
searchMenu.OnItemSelect = function(_, _, index)
local data = results[index]
if data == Translate('sharedanceemotes') then return end
if data == Translate('rfavorite') then
FavoriteEmote = ""
SimpleNotify(Translate('rfavorite'))
return
end
if favEnabled and IsControlPressed(0, 21) then
if data.table ~= "Shared" then
FavoriteEmote = data.name
SimpleNotify("~o~" .. FirstToUpper(data.name) .. Translate('newsetemote'))
else
SimpleNotify(Translate('searchcantsetfav'))
end
elseif data.table == "Emotes" or data.table == "Dances" then
EmoteMenuStart(data.name, string.lower(data.table))
elseif data.table == "PropEmotes" then
EmoteMenuStart(data.name, "props")
elseif data.table == "AnimalEmotes" then
EmoteMenuStart(data.name, "animals")
elseif data.table == "Shared" then
if data.table == "Shared" then
local target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), data.name)
TriggerServerEvent("rpemotes:server:requestEmote", GetPlayerServerId(target), data.name)
SimpleNotify(Translate('sentrequestto') .. GetPlayerName(target))
else
SimpleNotify(Translate('nobodyclose'))
end
else
EmoteMenuStart(data.name, data.data.category)
end
end
searchMenu.OnListSelect = function(menu, item, itemIndex, listIndex)
EmoteMenuStart(results[itemIndex].name, "props", item:IndexToItem(listIndex).Value)
searchMenu.OnListSelect = function(_, item, itemIndex, listIndex)
EmoteMenuStart(results[itemIndex].name, "PropEmotes", item:IndexToItem(listIndex).Value)
end
if Config.SharedEmotesEnabled then
if #sharedDanceMenu.Items > 0 then
table.insert(results, (favEnabled and 2 or 1), Translate('sharedanceemotes'))
sharedDanceMenu.OnItemSelect = function(sender, item, index)
table.insert(results, 1, Translate('sharedanceemotes'))
sharedDanceMenu.OnItemSelect = function(_, _, index)
if not LocalPlayer.state.canEmote then return end
local data = results[index]
local target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), data.name, 'Dances')
TriggerServerEvent("rpemotes:server:requestEmote", GetPlayerServerId(target), data.name, 'Dances')
SimpleNotify(Translate('sentrequestto') .. GetPlayerName(target))
else
SimpleNotify(Translate('nobodyclose'))
@ -407,7 +305,7 @@ if Config.Search then
end
else
sharedDanceMenu:Clear()
searchMenu:RemoveItemAt((favEnabled and 2 or 1))
searchMenu:RemoveItemAt(1)
end
end
@ -439,8 +337,8 @@ function AddCancelEmote(menu)
end
ShowPedPreview = function(menu)
menu.OnItemSelect = function(sender, item, index)
if (index == 1) then
menu.OnItemSelect = function(_, _, index)
if index == 1 then
isSearching = false
ShowPedMenu()
elseif index == 4 then
@ -458,20 +356,19 @@ function AddWalkMenu(menu)
local sortedWalks = {}
for a, b in PairsByKeys(RP.Walks) do
local x, label = table.unpack(b)
if x == "move_m@injured" then
table.insert(sortedWalks, 1, {label = label or a, anim = x})
if b[1] == "move_m@injured" then
table.insert(sortedWalks, 1, {label = a, anim = b[1]})
else
table.insert(sortedWalks, {label = label or a, anim = x})
table.insert(sortedWalks, {label = a, anim = b[1]})
end
end
for _, walk in ipairs(sortedWalks) do
submenu:AddItem(NativeUI.CreateItem(walk.label, "/walk (" .. string.lower(walk.label) .. ")"))
table.insert(WalkTable, walk.anim)
table.insert(WalkTable, walk.label)
end
submenu.OnItemSelect = function(sender, item, index)
submenu.OnItemSelect = function(_, item, index)
if item == walkreset then
ResetWalk()
DeleteResourceKvp("walkstyle")
@ -495,26 +392,26 @@ function AddFaceMenu(menu)
end
submenu.OnMenuClosed = function(menu)
ClosePedMenu()
submenu.OnIndexChange = function(_, newindex)
EmoteMenuStartClone(FaceTable[newindex], "Expressions")
end
submenu.OnIndexChange = function(menu, newindex)
EmoteMenuStartClone(FaceTable[newindex], "expression")
end
submenu.OnItemSelect = function(sender, item, index)
if item ~= facereset then
EmoteMenuStart(FaceTable[index], "expression")
else
DeleteResourceKvp("expression")
submenu.OnItemSelect = function(_, item, index)
if item == facereset then
DeleteResourceKvp("Expressions")
ClearFacialIdleAnimOverride(PlayerPedId())
else
EmoteMenuStart(FaceTable[index], "Expressions")
end
end
submenu.OnMenuClosed = function()
ClosePedMenu()
end
end
function AddInfoMenu(menu)
infomenu = _menuPool:AddSubMenu(menu, Translate('infoupdate'), "~h~~y~The RPEmotes Team & Collaborators~h~~y~", true, true)
infomenu = _menuPool:AddSubMenu(menu, Translate('infoupdate'), "~h~~y~The RPEmotes Developers~h~~y~", true, true)
for _,v in ipairs(Config.Credits) do
local item = NativeUI.CreateItem(v.title,v.subtitle or "")
@ -549,21 +446,51 @@ function OpenEmoteMenu()
end
end
LoadAddonEmotes()
AddEmoteMenu(mainMenu)
AddCancelEmote(mainMenu)
if Config.PreviewPed then
ShowPedPreview(mainMenu)
end
if Config.WalkingStylesEnabled then
AddWalkMenu(mainMenu)
end
if Config.ExpressionsEnabled then
AddFaceMenu(mainMenu)
end
AddInfoMenu(mainMenu)
CreateThread(function()
LoadAddonEmotes()
AddEmoteMenu(mainMenu)
AddCancelEmote(mainMenu)
if Config.PreviewPed then
ShowPedPreview(mainMenu)
end
if Config.WalkingStylesEnabled then
AddWalkMenu(mainMenu)
end
if Config.ExpressionsEnabled then
AddFaceMenu(mainMenu)
end
AddInfoMenu(mainMenu)
_menuPool:RefreshIndex()
_menuPool:RefreshIndex()
local newRP = {}
for emoteType, content in pairs(RP) do
for emoteName, emoteData in pairs(content) do
local shouldRemove = false
if Config.AdultEmotesDisabled and emoteData.AdultAnimation then
shouldRemove = true
end
if newRP[emoteName] then
print('WARNING - Duplicate emote name found: ' .. emoteName .. ' in ' .. emoteType .. ' and ' .. newRP[emoteName].category)
end
if shouldRemove then
elseif type(emoteData) == "table" then
newRP[emoteName] = {}
for k, v in pairs(emoteData) do
newRP[emoteName][k] = v
end
newRP[emoteName].category = emoteType
else
newRP[emoteName] = { emoteData }
newRP[emoteName].category = emoteType
end
end
newRP[emoteType] = nil
end
RP = newRP
CONVERTED = true
end)
local isMenuProcessing = false
function ProcessMenu()
@ -576,17 +503,6 @@ function ProcessMenu()
isMenuProcessing = false
end
RegisterNetEvent("rp:Update", function(state)
UpdateAvailable = state
AddInfoMenu(mainMenu)
_menuPool:RefreshIndex()
end)
RegisterNetEvent("rp:RecieveMenu", function()
OpenEmoteMenu()
end)
-- While ped is dead, don't show menus
CreateThread(function()
while true do

View file

@ -1,46 +1,37 @@
function SetPlayerPedExpression(expression, saveToKvp)
SetFacialIdleAnimOverride(PlayerPedId(), expression, 0)
if Config.PersistentExpression and saveToKvp then SetResourceKvp("expression", expression) end
end
local function DisplayExpressions()
local moodsString = ""
for name, _ in pairs(RP.Expressions) do
moodsString = moodsString .. string.lower(name) .. ", "
local emote = RP[expression]
if emote and emote.category == "Expressions" then
SetFacialIdleAnimOverride(PlayerPedId(), emote[1], 0)
if Config.PersistentExpression and saveToKvp then SetResourceKvp("expression", emote[1]) end
else
ClearFacialIdleAnimOverride(PlayerPedId())
DeleteResourceKvp("expression")
end
EmoteChatMessage(moodsString)
EmoteChatMessage("To reset do /mood reset")
end
if Config.ExpressionsEnabled then
RegisterCommand('mood', function(_source, args, _raw)
local expression = FirstToUpper(string.lower(args[1]))
if RP.Expressions[expression] ~= nil then
SetPlayerPedExpression(RP.Expressions[expression][1], true)
local emote = RP[expression]
if emote and emote.category == "Expressions" then
SetPlayerPedExpression(RP[expression][1], true)
elseif expression == "Reset" then
ClearFacialIdleAnimOverride(PlayerPedId())
DeleteResourceKvp("expression")
else
EmoteChatMessage("'" .. expression .. "' is not a valid mood, do /moods to see all moods.")
EmoteChatMessage("'" .. expression .. "' is not a valid mood")
end
end, false)
RegisterCommand('moods', function()
DisplayExpressions()
end, false)
-- Chat Suggestions
TriggerEvent('chat:addSuggestion', '/mood', 'Set your current mood/expression.',
{ { name = "expression", help = "/moods for a list of valid moods" } })
TriggerEvent('chat:addSuggestion', '/moods', 'List available walking moods/expressions.')
-- Load the expression once the player has spawned. Standalone, QBCore and ESX --
local function LoadPersistentExpression()
local expression = GetResourceKvpString("expression")
if expression then
Wait(2500) -- Delay, to ensure the player ped has loaded in
Wait(2500)
SetPlayerPedExpression(expression, false)
end
end
@ -50,4 +41,10 @@ if Config.ExpressionsEnabled then
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', LoadPersistentExpression)
RegisterNetEvent('esx:playerLoaded', LoadPersistentExpression)
end
AddEventHandler('onResourceStart', function(resource)
if resource == GetCurrentResourceName() then
LoadPersistentExpression()
end
end)
end

View file

@ -0,0 +1,86 @@
local function HandsUpLoop()
CreateThread(function()
while InHandsup do
if Config.DisabledHandsupControls then
for control, state in pairs(Config.DisabledHandsupControls) do
DisableControlAction(0, control, state)
end
end
if IsPlayerAiming(PlayerId()) then
ClearPedSecondaryTask(PlayerPedId())
CreateThread(function()
Wait(350)
InHandsup = false
end)
end
Wait(0)
end
end)
end
if Config.HandsupEnabled then
local function ToggleHandsUp(commandType)
RegisterCommand(commandType, function()
if IsPedInAnyVehicle(PlayerPedId(), false) and not Config.HandsupInCar and not InHandsup then
return
end
Handsup()
end, false)
end
if Config.HoldToHandsUp then
ToggleHandsUp('+handsup')
ToggleHandsUp('-handsup')
else
ToggleHandsUp('handsup')
end
function Handsup()
local playerPed = PlayerPedId()
if not IsPedHuman(playerPed) then
return
end
if IsInActionWithErrorMessage() then
return
end
InHandsup = not InHandsup
if InHandsup then
LocalPlayer.state:set('currentEmote', 'handsup', true)
DestroyAllProps()
local dict = "random@mugging3"
RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do
Wait(0)
end
TaskPlayAnim(PlayerPedId(), dict, "handsup_standing_base", 3.0, 3.0, -1, 49, 0, false,
IsThisModelABike(GetEntityModel(GetVehiclePedIsIn(PlayerPedId(), false))) and 4127 or false, false)
HandsUpLoop()
else
LocalPlayer.state:set('currentEmote', nil, true)
ClearPedSecondaryTask(PlayerPedId())
if Config.ReplayEmoteAfterHandsup and IsInAnimation then
local emote = RP[CurrentAnimationName]
if not emote then
return
end
Wait(400)
DestroyAllProps()
OnEmotePlay(CurrentAnimationName, CurrentTextureVariation)
end
end
end
TriggerEvent('chat:addSuggestion', '/handsup', Translate('handsup'))
if Config.HandsupKeybindEnabled then
RegisterKeyMapping("handsup", Translate('register_handsup'), "keyboard", Config.HandsupKeybind)
end
CreateExport('IsPlayerInHandsUp', function()
return InHandsup
end)
end

View file

@ -0,0 +1,96 @@
CreateThread(function()
TriggerEvent('chat:addSuggestion', '/e', Translate('play_emote'),
{ { name = "emotename", help = Translate('help_command') },
{ name = "texturevariation", help = Translate('help_variation') } })
TriggerEvent('chat:addSuggestion', '/emote', Translate('play_emote'),
{ { name = "emotename", help = Translate('help_command') },
{ name = "texturevariation", help = Translate('help_variation') } })
if Config.Keybinding then
TriggerEvent('chat:addSuggestion', '/emotebind', Translate('link_emote_keybind'),
{ { name = "key", help = "num4, num5, num6, num7. num8, num9. Numpad 4-9!" },
{ name = "emotename", help = Translate('help_command') } })
TriggerEvent('chat:addSuggestion', '/emotebinds', Translate('show_emote_keybind'))
TriggerEvent('chat:addSuggestion', '/emotedelete', Translate('remove_emote_keybind'),
{ { name = "key", help = "num4, num5, num6, num7. num8, num9. Numpad 4-9!" } })
end
TriggerEvent('chat:addSuggestion', '/emotemenu', Translate('open_menu_emote'))
TriggerEvent('chat:addSuggestion', '/emotes', Translate('show_list_emote'))
TriggerEvent('chat:addSuggestion', '/emotecancel', Translate('cancel_emote'))
end)
RegisterCommand('e', function(source, args, raw) EmoteCommandStart(args) end, false)
RegisterCommand('emote', function(source, args, raw) EmoteCommandStart(args) end, false)
RegisterCommand('emotecancel', function() EmoteCancel() end, false)
if Config.MenuKeybindEnabled then
RegisterCommand('emoteui', function() OpenEmoteMenu() end, false)
RegisterKeyMapping("emoteui", Translate('register_open_menu'), "keyboard", Config.MenuKeybind)
else
RegisterCommand('emotemenu', function() OpenEmoteMenu() end, false)
end
if Config.EnableCancelKeybind then
RegisterKeyMapping("emotecancel", Translate('register_cancel_emote'), "keyboard", Config.CancelEmoteKey)
end
-- BINDING EMOTES TO KEYS
if Config.Keybinding then
RegisterCommand('emotebind', function(source, args, raw) EmoteBindStart(source, args, raw) end, false)
RegisterCommand('emotebinds', function(source, args, raw) ListKeybinds() end, false)
RegisterCommand('emotedelete', function(source, args) DeleteEmote(args) end, false)
for i = 1, #Config.KeybindKeys do
local cmd = string.format('emoteSelect%s', i)
RegisterCommand(cmd, function()
local emote = GetResourceKvpString(string.format('%s_emob%s', Config.keybindKVP, i))
if emote and emote ~= "" then
EmoteCommandStart({ emote, 0 })
end
end, false)
RegisterKeyMapping(cmd, string.format('Emote bind %s', i), 'keyboard', Config.KeybindKeys[i])
end
function EmoteBindStart(source, args, raw)
if #args > 0 then
local numkey = tonumber(args[1])
local emote = string.lower(args[2])
if not (numkey and emote) then
DebugPrint('Invalid arguments to EmoteBindStart')
return
end
if type(numkey) == "number" then
if RP[emote] then
SetResourceKvp(string.format('%s_emob%s', Config.keybindKVP, numkey), emote)
else
EmoteChatMessage("'" .. emote .. "' " .. Translate('notvalidemote') .. "")
end
else
EmoteChatMessage("'" .. numkey .. "' " .. Translate('notvalidkey'))
end
else
DebugPrint('Invalid number of arguments to EmoteBindStart')
end
end
function ListKeybinds()
for i = 1, #Config.KeybindKeys do
local emote = GetResourceKvpString(string.format('%s_emob%s', Config.keybindKVP, i))
if emote then
EmoteChatMessage(string.format('Emote %s : %s',i, emote))
end
end
end
function DeleteEmote(args)
if #args > 0 then
local numkey = tonumber(args[1])
if type(numkey) == "number" then
DeleteResourceKvp(string.format('%s_emob%s', Config.keybindKVP, numkey))
else
EmoteChatMessage("'" .. numkey .. "' " .. Translate('notvalidkey'))
end
else
DebugPrint("invalid")
end
end
end

View file

@ -239,7 +239,7 @@ if Config.NewscamEnabled then
end
end)
exports('toggleNewscam', function()
CreateExport('toggleNewscam', function()
UseNewscam()
end)
end

View file

@ -1,4 +1,4 @@
if not Config.NoIdleCam then return end
if not Config.DisableIdleCam then return end
RegisterCommand('idlecamoff', function() -- help2 31, 167, 9
TriggerEvent('chat:addMessage', {

View file

@ -0,0 +1,65 @@
local PlayerParticles = {}
function PtfxThis(asset)
while not HasNamedPtfxAssetLoaded(asset) do
RequestNamedPtfxAsset(asset)
Wait(10)
end
UseParticleFxAsset(asset)
end
function PtfxStart()
LocalPlayer.state:set('ptfx', true, true)
end
function PtfxStop()
LocalPlayer.state:set('ptfx', nil, true)
end
AddStateBagChangeHandler('ptfx', '', function(bagName, key, value, _unused, replicated)
local plyId = tonumber(bagName:gsub('player:', ''), 10)
if (PlayerParticles[plyId] and value) or (not PlayerParticles[plyId] and not value) then return end
local ply = GetPlayerFromServerId(plyId)
if ply <= 0 then return end
local plyPed = GetPlayerPed(ply)
if not DoesEntityExist(plyPed) then return end
local stateBag = Player(plyId).state
if value then
local boneIndex = stateBag.ptfxBone and GetPedBoneIndex(plyPed, stateBag.ptfxBone) or GetEntityBoneIndexByName(stateBag.ptfxName, "VFX")
local entityTarget = plyPed
if stateBag.ptfxPropNet then
local propObj = NetToObj(stateBag.ptfxPropNet)
if DoesEntityExist(propObj) then
entityTarget = propObj
end
end
PtfxThis(stateBag.ptfxAsset)
local offset = stateBag.ptfxOffset
local rot = stateBag.ptfxRot
PlayerParticles[plyId] = StartNetworkedParticleFxLoopedOnEntityBone(stateBag.ptfxName, entityTarget, offset.x, offset.y, offset.z, rot.x, rot.y, rot.z, boneIndex, (stateBag.ptfxScale or 1) + 0.0, false, false, false)
local color = stateBag.ptfxColor
if color then
if color[1] and type(color[1]) == 'table' then
local randomIndex = math.random(1, #color)
color = color[randomIndex]
end
SetParticleFxLoopedAlpha(PlayerParticles[plyId], color.A)
SetParticleFxLoopedColour(PlayerParticles[plyId], color.R / 255, color.G / 255, color.B / 255, false)
end
DebugPrint("Started PTFX: " .. PlayerParticles[plyId])
else
DebugPrint("Stopped PTFX: " .. PlayerParticles[plyId])
StopParticleFxLooped(PlayerParticles[plyId], false)
RemoveNamedPtfxAsset(stateBag.ptfxAsset)
PlayerParticles[plyId] = nil
end
end)

View file

@ -23,15 +23,15 @@ local function PointingStopped()
ClearPedSecondaryTask(playerPed)
end
RemoveAnimDict("anim@mp_point")
if Config.PersistentEmoteAfterPointing and IsInAnimation then
local emote = RP.Emotes[CurrentAnimationName] or RP.PropEmotes[CurrentAnimationName] or RP.Dances[CurrentAnimationName] or RP.AnimalEmotes[CurrentAnimationName]
if Config.ReplayEmoteAfterPointing and IsInAnimation then
local emote = RP[CurrentAnimationName]
if not emote then
return
end
Wait(400)
DestroyAllProps()
OnEmotePlay(emote, CurrentAnimationName, CurrentTextureVariation)
OnEmotePlay(CurrentAnimationName, CurrentTextureVariation)
end
end
@ -103,7 +103,7 @@ end
-- Commands & KeyMapping --
if Config.PointingEnabled then
RegisterCommand('pointing', function()
if IsPedInAnyVehicle(PlayerPedId(), false) and not Config.PointingKeybindInCarEnabled then
if IsPedInAnyVehicle(PlayerPedId(), false) and not Config.PointingInCar then
return
end
StartPointing()
@ -117,11 +117,8 @@ if Config.PointingEnabled then
end
-- Exports --
---@return boolean
local function IsPlayerPointing()
return Pointing
end
exports('IsPlayerPointing', IsPlayerPointing)
CreateExport('IsPlayerPointing', IsPlayerPointing)

View file

@ -16,7 +16,7 @@ if Config.RagdollEnabled then
isRagdolling = true
end
while not isRagdolling do
while isRagdolling do
ped = PlayerPedId()
SetPedRagdollForceFall(ped)
ResetPedRagdollTimer(ped)

View file

@ -1,5 +1,4 @@
local isRequestAnim = false
local requestedemote = ''
local targetPlayerId
if Config.SharedEmotesEnabled then
@ -13,9 +12,9 @@ if Config.SharedEmotesEnabled then
local emotename = string.lower(args[1])
local target, distance = GetClosestPlayer()
if (distance ~= -1 and distance < 3) then
if RP.Shared[emotename] ~= nil then
local _, _, ename = table.unpack(RP.Shared[emotename])
TriggerServerEvent("ServerEmoteRequest", GetPlayerServerId(target), emotename)
if RP[emotename] ~= nil and RP[emotename].category == "Shared" then
local _, _, ename = table.unpack(RP[emotename])
TriggerServerEvent("rpemotes:server:requestEmote", GetPlayerServerId(target), emotename)
SimpleNotify(Translate('sentrequestto') ..
GetPlayerName(target) .. " ~w~(~g~" .. ename .. "~w~)")
else
@ -30,7 +29,7 @@ if Config.SharedEmotesEnabled then
end, false)
end
RegisterNetEvent("SyncPlayEmote", function(emote, player)
RegisterNetEvent("rpemotes:client:syncEmote", function(emote, player)
EmoteCancel()
Wait(300)
targetPlayerId = player
@ -40,12 +39,11 @@ RegisterNetEvent("SyncPlayEmote", function(emote, player)
return EmoteChatMessage(Translate('not_in_a_vehicle'))
end
-- wait a little to make sure animation shows up right on both clients after canceling any previous emote
if RP.Shared[emote] then
local options = RP.Shared[emote].AnimationOptions
if RP[emote] then
local options = RP[emote].AnimationOptions
if options and options.Attachto then
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 targetEmote = RP[emote][4]
if not targetEmote or not RP[targetEmote] or not RP[targetEmote].AnimationOptions or not RP[targetEmote].AnimationOptions.Attachto then
local ped = PlayerPedId()
local pedInFront = GetPlayerPed(plyServerId ~= 0 and plyServerId or GetClosestPlayer())
@ -69,17 +67,14 @@ RegisterNetEvent("SyncPlayEmote", function(emote, player)
end
end
OnEmotePlay(RP.Shared[emote], emote)
return
elseif RP.Dances[emote] then
OnEmotePlay(RP.Dances[emote], emote)
OnEmotePlay(emote)
return
else
DebugPrint("SyncPlayEmote : Emote not found")
DebugPrint("rpemotes:client:syncEmote : Emote not found")
end
end)
RegisterNetEvent("SyncPlayEmoteSource", function(emote, player)
RegisterNetEvent("rpemotes:client:syncEmoteSource", function(emote, player)
local ped = PlayerPedId()
local plyServerId = GetPlayerFromServerId(player)
local pedInFront = GetPlayerPed(plyServerId ~= 0 and plyServerId or GetClosestPlayer())
@ -88,9 +83,8 @@ RegisterNetEvent("SyncPlayEmoteSource", function(emote, player)
return EmoteChatMessage(Translate('not_in_a_vehicle'))
end
local options = RP.Shared[emote] and RP.Shared[emote].AnimationOptions or RP.Dances[emote] and RP.Dances[emote].AnimationOptions
local options = RP[emote] and RP[emote].AnimationOptions
if options then
if (options.Attachto) then
AttachEntityToEntity(
ped,
@ -112,24 +106,21 @@ RegisterNetEvent("SyncPlayEmoteSource", function(emote, player)
end
end
local coords = GetOffsetFromEntityInWorldCoords(pedInFront, (options?.SyncOffsetSide or 0) + 0.0, (options?.SyncOffsetFront or 1) + 0.0, (options?.SyncOffsetHeight or 0) + 0.0)
local coords = GetOffsetFromEntityInWorldCoords(pedInFront, (options and options.SyncOffsetSide or 0) + 0.0, (options and options.SyncOffsetFront or 1) + 0.0, (options and options.SyncOffsetHeight or 0) + 0.0)
local heading = GetEntityHeading(pedInFront)
SetEntityHeading(ped, heading - (options?.SyncOffsetHeading or 180) + 0.0)
SetEntityHeading(ped, heading - (options and options.SyncOffsetHeading or 180) + 0.0)
SetEntityCoordsNoOffset(ped, coords.x, coords.y, coords.z)
EmoteCancel()
Wait(300)
targetPlayerId = player
if RP.Shared[emote] ~= nil then
OnEmotePlay(RP.Shared[emote], emote)
return
elseif RP.Dances[emote] ~= nil then
OnEmotePlay(RP.Dances[emote], emote)
if RP[emote] ~= nil then
OnEmotePlay(emote)
return
end
end)
RegisterNetEvent("SyncCancelEmote", function(player)
RegisterNetEvent("rpemotes:client:cancelEmote", function(player)
if targetPlayerId and targetPlayerId == player then
targetPlayerId = nil
EmoteCancel()
@ -138,15 +129,15 @@ end)
function CancelSharedEmote()
if targetPlayerId then
TriggerServerEvent("ServerEmoteCancel", targetPlayerId)
TriggerServerEvent("rpemotes:server:cancelEmote", targetPlayerId)
targetPlayerId = nil
end
end
RegisterNetEvent("ClientEmoteRequestReceive", function(emotename, etype, target)
RegisterNetEvent("rpemotes:client:requestEmote", function(emotename, etype, target)
isRequestAnim = true
local displayed = (etype == 'Dances') and select(3, table.unpack(RP.Dances[emotename])) or select(3, table.unpack(RP.Shared[emotename]))
local displayed = RP[emotename] and select(3, table.unpack(RP[emotename]))
PlaySound(-1, "NAV", "HUD_AMMO_SHOP_SOUNDSET", false, 0, true)
SimpleNotify(Translate('doyouwanna') .. displayed .. "~w~)")
@ -163,8 +154,8 @@ RegisterNetEvent("ClientEmoteRequestReceive", function(emotename, etype, target)
if IsControlJustPressed(1, 246) then
isRequestAnim = false
local otheremote = RP.Shared[emotename] and RP.Shared[emotename][4] or RP.Dances[emotename] and RP.Dances[emotename][4] or emotename
TriggerServerEvent("ServerValidEmote", target, emotename, otheremote)
local otheremote = RP[emotename] and RP[emotename][4] or emotename
TriggerServerEvent("rpemotes:server:confirmEmote", target, emotename, otheremote)
elseif IsControlJustPressed(1, 182) then
isRequestAnim = false
SimpleNotify(Translate('refuseemote'))

View file

@ -1,5 +1,3 @@
LocalPlayer.state:set('canEmote', true, true) -- Allow emotes to be played by default
-- You can edit this function to add support for your favorite notification system
function SimpleNotify(message)
if Config.NotificationsAsChatMessage then
@ -11,6 +9,16 @@ function SimpleNotify(message)
end
end
-- Don't touch after this line if you don't know what you're doing
CreateExport = function(name, func)
AddEventHandler('__cfx_export_rpemotes_'..name, function(setCb)
setCb(function(...)
return func(...)
end)
end)
exports(name, func)
end
function DebugPrint(...)
if Config.DebugDisplay then
print(...)
@ -100,11 +108,10 @@ function LoadAnim(dict)
end
function LoadPropDict(model)
-- load the model if it's not loaded and wait until it's loaded or timeout
if not HasModelLoaded(joaat(model)) then
RequestModel(joaat(model))
if not HasModelLoaded(GetHashKey(model)) then
RequestModel(GetHashKey(model))
local timeout = 2000
while not HasModelLoaded(joaat(model)) and timeout > 0 do
while not HasModelLoaded(GetHashKey(model)) and timeout > 0 do
Wait(5)
timeout = timeout - 5
end
@ -140,8 +147,10 @@ end
function NearbysOnCommand(source, args, raw)
local NearbysCommand = ""
for a in PairsByKeys(RP.Shared) do
NearbysCommand = NearbysCommand .. "" .. a .. ", "
for a, b in PairsByKeys(RP) do
if type(b) == "table" and b.category == "Shared" then
NearbysCommand = NearbysCommand .. a .. ", "
end
end
EmoteChatMessage(NearbysCommand)
EmoteChatMessage(Translate('emotemenucmd'))
@ -185,7 +194,7 @@ end
---@param ignores? table | nil key string is the ignored value
function IsInActionWithErrorMessage(ignores)
DebugPrint(ignores)
if ignores then DebugPrint(ignores) end
DebugPrint('IsProne', IsProne)
DebugPrint('IsUsingNewscam', IsUsingNewscam)
DebugPrint('IsUsingBinoculars', IsUsingBinoculars)

View file

@ -11,11 +11,17 @@ function WalkMenuStart(name, force)
ResetWalk()
return
end
if not RP[name] or type(RP[name]) ~= "table" or RP[name].category ~= "Walks" then
EmoteChatMessage("'" .. tostring(name) .. "' is not a valid walk")
return
end
local walk = RP[name][1]
RequestWalking(walk)
SetPedMovementClipset(PlayerPedId(), walk, 0.2)
RemoveAnimSet(walk)
if Config.PersistentWalk then SetResourceKvp("walkstyle", name) end
RequestWalking(name)
SetPedMovementClipset(PlayerPedId(), name, 0.2)
RemoveAnimSet(name)
end
function ResetWalk()
@ -28,8 +34,10 @@ end
function WalksOnCommand()
local WalksCommand = ""
for a in PairsByKeys(RP.Walks) do
WalksCommand = WalksCommand .. "" .. string.lower(a) .. ", "
for name, data in PairsByKeys(RP) do
if type(data) == "table" and data.category == "Walks" then
WalksCommand = WalksCommand .. string.lower(name) .. ", "
end
end
EmoteChatMessage(WalksCommand)
EmoteChatMessage("To reset do /walk reset")
@ -48,23 +56,21 @@ function WalkCommandStart(name)
return
end
if TableHasKey(RP.Walks, name) then
local name2 = table.unpack(RP.Walks[name])
WalkMenuStart(name2)
else
EmoteChatMessage("'" .. name .. "' is not a valid walk")
end
WalkMenuStart(name, true)
end
-- Persistent Walkstyles are stored to KVP. Once the player has spawned, the walkstyle is applied.
if Config.WalkingStylesEnabled and Config.PersistentWalk then
-- Function to check if walkstyle is available to prevent exploiting
local function walkstyleExists(kvp)
for _, v in pairs(RP.Walks) do
if v[1] == kvp then
return true
end
while not CONVERTED do
Wait(0)
end
if not kvp or kvp == "" then
return false
end
local walkstyle = RP[kvp]
if walkstyle and type(walkstyle) == "table" and walkstyle.category == "Walks" then
return true
end
return false
end
@ -104,15 +110,15 @@ if Config.WalkingStylesEnabled then
TriggerEvent('chat:addSuggestion', '/walks', 'List available walking styles.')
end
exports('toggleWalkstyle', function(bool, message)
CreateExport('toggleWalkstyle', function(bool, message)
canChange = bool
if message then
unable_message = message
end
end)
exports('getWalkstyle', function()
CreateExport('getWalkstyle', function()
return GetResourceKvpString("walkstyle")
end)
exports('setWalkstyle', WalkMenuStart)
CreateExport('setWalkstyle', WalkMenuStart)

View file

@ -0,0 +1,164 @@
-- FOR ALL KEYBINDS, GET THE BUTTON STRING HERE: https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/
Config = {
MenuLanguage = 'de', -- Change the language of the menu here
EnableCancelKeybind = true,
CancelEmoteKey = 'X',
MenuKeybindEnabled = true,
MenuKeybind = 'F4',
Keybinding = false,
keybindKVP = "rpemotes",
NotificationsAsChatMessage = false,
Search = true, -- Used to enable or disable the search feature in the menu.
CancelPreviousEmote = false, -- If turned on, playing an emote will cancel the previous one.
DisableControlsInMenu = false,
MenuTitle = '',
TitleOutline = true,
TitleColour = { R = 255, G = 0, B = 255, A = 255 },
MenuPosition = 'right', -- 'left' / 'right'
CustomMenuEnabled = true, -- Change the header.png to your own image
-- Combat Car, and Player Movement
DisarmPlayerOnEmote = false,
AllowPunchingDuringEmote = false,
AllowEmoteInVehicle = true,
AllowInWater = false,
-- Ragdoll
RagdollEnabled = false,
RagdollKeybind = 'U',
RagdollAsToggle = true,
-- Expressions, Walks, and More
ExpressionsEnabled = true,
PersistentExpression = true,
WalkingStylesEnabled = true,
PersistentWalk = true,
SharedEmotesEnabled = true,
AdultEmotesDisabled = false,
AnimalEmotesEnabled = true,
-- Hands Up
HandsupEnabled = false,
HandsupKeybind = 'Y',
HandsupKeybindEnabled = false,
HandsupInCar = false,
ReplayEmoteAfterHandsup = true,
HoldToHandsUp = false,
-- Pointing
PointingEnabled = true,
PointingKeybindEnabled = true,
PointingKeybind = 'B',
PointingInCar = false,
ReplayEmoteAfterPointing = true,
-- Crouching
CrouchEnabled = true,
CrouchKeybindEnabled = true,
CrouchKeybind = 'LCONTROL',
CrouchOverrideStealthMode = false, -- If true, you won't enter stealth mode even if the crouch key and the 'duck' key are the same.
FpsMode = false, -- set this to true if you have first-person shooting to disable the ability to crouch and shoot in third-person
-- Crawling
CrawlEnabled = true,
CrawlKeybindEnabled = true,
CrawlKeybind = 'RCONTROL',
-- Binocular (/binoculars)
BinocularsEnabled = false,
AllowVisionsToggling = false,
-- News Camera (/newscam)
NewscamEnabled = true,
DisableIdleCam = true,
-- Preview Ped : Shows a preview of the emote on the player's ped next to the emote menu. Note that resmon will increase when this when emotes are being previewed.
PreviewPed = false,
CheckForUpdates = true,
DebugDisplay = false,
}
Config.KeybindKeys = {
'NUMPAD1',
'NUMPAD2',
'NUMPAD3',
'NUMPAD4',
'NUMPAD5',
'NUMPAD6',
'NUMPAD7',
'NUMPAD8',
'NUMPAD9'
}
Config.DisabledHandsupControls = {
[36] = true, -- INPUT_DUCK
[44] = true, -- INPUT_COVER
[53] = true, -- INPUT_WEAPON_SPECIAL
[54] = true, -- INPUT_WEAPON_SPECIAL_TWO
[59] = true, -- INPUT_VEH_MOVE_LR
[60] = true, -- INPUT_VEH_MOVE_UD
[61] = true, -- INPUT_VEH_MOVE_UP_ONLY
[62] = true, -- INPUT_VEH_MOVE_DOWN_ONLY
[63] = true, -- INPUT_VEH_MOVE_LEFT_ONLY
[64] = true, -- INPUT_VEH_MOVE_RIGHT_ONLY
[65] = true, -- INPUT_VEH_SPECIAL
[66] = true, -- INPUT_VEH_GUN_LR
[67] = true, -- INPUT_VEH_GUN_UD
[69] = true, -- INPUT_VEH_ATTACK
[70] = true, -- INPUT_VEH_ATTACK2
[71] = true, -- INPUT_VEH_ACCELERATE
[72] = true, -- INPUT_VEH_BRAKE
[73] = true, -- INPUT_VEH_DUCK
[74] = true, -- INPUT_VEH_HEADLIGHT
[77] = true, -- INPUT_VEH_HOTWIRE_LEFT
[78] = true, -- INPUT_VEH_HOTWIRE_RIGHT
[80] = true, -- INPUT_VEH_CIN_CAM
[86] = true, -- INPUT_VEH_HORN
[91] = true, -- INPUT_VEH_PASSENGER_AIM
[102] = true, -- INPUT_VEH_JUMP
[104] = true, -- INPUT_VEH_SHUFFLE
[105] = true, -- INPUT_VEH_DROP_PROJECTILE
[136] = true, -- INPUT_VEH_PUSHBIKE_PEDAL
[137] = true, -- INPUT_VEH_PUSHBIKE_SPRINT
[139] = true, -- INPUT_VEH_PUSHBIKE_REAR_BRAKE
[140] = true, -- INPUT_MELEE_ATTACK_LIGHT
[141] = true, -- INPUT_MELEE_ATTACK_HEAVY
[142] = true, -- INPUT_MELEE_ATTACK_ALTERNATE
[143] = true, -- INPUT_MELEE_BLOCK
[337] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_TOGGLE
[338] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_LEFT
[339] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_RIGHT
[340] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_UP
[341] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_DOWN
[342] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_UD
[343] = true, -- INPUT_VEH_HYDRAULICS_CONTROL_LR
[351] = true, -- INPUT_VEH_ROCKET_BOOST
[354] = true, -- INPUT_VEH_BIKE_WINGS
[357] = true, -- INPUT_VEH_TRANSFORM
[345] = true, -- INPUT_VEH_MELEE_HOLD
[346] = true, -- INPUT_VEH_MELEE_LEFT
[347] = true, -- INPUT_VEH_MELEE_RIGHT
}
Config.Credits = {
{ title = "<b>Thanks to the community<b>", subtitle = "For supporting and using RP Emotes!" },
{ title = "Thanks ~o~DullPear 🍐~s~", subtitle = "~o~DullPear~s~ for the original dpemotes ❤️" },
{ title = "Thanks <font color=\"#ff451d\">Mathu_lmn 🇫🇷 </font>", subtitle = "<font color=\"#ff451d\">Mathu_lmn 🇫🇷</font> Maintainer, additional features and fixes 🛠️" },
{ title = "Thanks <font color=\"#ff451d\">Enzo2991 🇧🇪 </font>", subtitle = "<font color=\"#ff451d\">Enzo2991 🇧🇪 </font> for creating the ped preview functionality, keybind with kvp" },
{ title = "Thanks <b>Kibook 🐩</b>", subtitle = "<b>Kibook</b> for the addition of Animal Emotes 🐩 submenu." },
{ title = "Thanks ~y~AvaN0x 🇫🇷~s~", subtitle = "~y~AvaN0x~s~ 🇫🇷 for reformatting and assisting with code and additional features 🙏" },
{ title = "Thanks <font color=\"#40E0D0\">iSentrie </font>", subtitle = "<font color=\"#40E0D0\">iSentrie</font> for assisting with code 🛠️" },
{ title = "Thanks <font color=\"#0e64ed\">Mads 🤖</font>", subtitle = "<font color=\"#0e64ed\">Mads 🤖</font> for the addition of Exit Emotes, Crouch & Crawl ⚙️" },
{ title = "Thanks <font color=\"#ff00c3\">Tigerle 🐯</font>", subtitle = "<font color=\"#ff00c3\">Tigerle</font> for assisting with attached Shared Emotes ⚙️." },
{ title = "Thanks <font color=\"#1C9369\">northsqrd ⚙️</font>", subtitle = "<font color=\"#1C9369\">northsqrd</font> for assisting with search feature and phone colours 🔎" },
{ title = "Thanks <font color=\"#15BCEC\">GeekGarage 🤓</font>", subtitle = "<font color=\"#15BCEC\">GeekGarage</font> for assisting with code and features" },
}

View file

@ -1,7 +1,7 @@
fx_version 'cerulean'
game 'gta5'
description 'rpemotes-reborn'
version '1.8.5'
version '1.9.0'
lua54 'yes'
use_experimental_fxv2_oal 'yes'
@ -9,7 +9,6 @@ use_experimental_fxv2_oal 'yes'
provide "rpemotes"
dependencies {
-- '/server:7290',
'/server:6683',
'/onesync'
}
@ -31,12 +30,12 @@ shared_scripts {
server_scripts {
'server/Server.lua',
'server/Updates.lua',
'server/frameworks/*.lua'
}
client_scripts {
'NativeUI.lua',
'client/Utils.lua',
'client/Bridge.lua',
'client/AnimationList.lua',
'client/AnimationListCustom.lua',
'client/Binoculars.lua',
@ -44,14 +43,15 @@ client_scripts {
'client/Emote.lua',
'client/EmoteMenu.lua',
'client/Expressions.lua',
'client/Handsup.lua',
'client/Keybinds.lua',
'client/NewsCam.lua',
'client/NoIdleCam.lua',
'client/Pointing.lua',
'client/PTFX.lua',
'client/Ragdoll.lua',
'client/Syncing.lua',
'client/Walk.lua',
'client/frameworks/*.lua'
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

View file

@ -1,9 +1,9 @@
Locales = {}
function Translate(str, ...) -- Translate string
function Translate(str, ...)
if not str then
print(("[^1ERROR^7] Resource ^5%s^7 You did not specify a parameter for the Translate function or the value is nil!"):format(GetInvokingResource() or GetCurrentResourceName()))
return "Given translate function parameter is nil!"
return "Unknown"
end
if Locales[Config.MenuLanguage] then
if Locales[Config.MenuLanguage][str] then
@ -20,10 +20,9 @@ function Translate(str, ...) -- Translate string
end
end
function TranslateCap(str, ...) -- Translate string first char uppercase
function TranslateCap(str, ...)
return _(str, ...):gsub("^%l", string.upper)
end
_ = Translate
-- luacheck: ignore _U
_U = TranslateCap

View file

@ -4,12 +4,8 @@ Locales['ar'] = {
['danceemotes'] = "~h~~p~ 🕺 حركات الرقص",
['animalemotes'] = "~h~~p~ 🐩 حركات الحيوانات",
['propemotes'] = "~h~~p~ 📦 حركات الاوبجكتات",
['favoriteemotes'] = "~h~~y~ 🌟 المفضلة",
['favoriteinfo'] = "اختر حركة من هنا لوضعها على خانة المفضلة",
['rfavorite'] = "اعادة ضبط المفضلة",
['prop2info'] = "❓ حركات الاوبجكتات تكون محددة في النهاية",
['set'] = "وضع (",
['setboundemote'] = ") لتكون حركة مربوطة ؟",
['newsetemote'] = "~w~ هي حركتك المربوطة , اضغط على ~g~CapsLock~w~ لإستخدامها",
['cancelemote'] = "~h~~r~ الغاء الحركة 🚷",
['cancelemoteinfo'] = "لالغاء لعب الحركة الحالية ~r~X~w~",
@ -54,8 +50,6 @@ Locales['ar'] = {
['searchinputtitle'] = "بحث:",
['searchmenudesc'] = " نتيجة لـ ",
['searchnoresult'] = "لا يوجد نتيجة للبحث ",
['searchshifttofav'] = "اضغط ضغطة مطولة على L-Shift لوضعها في المفضلة",
['searchcantsetfav'] = "الحركات المشتركة لا تستطيع وضعها في المفضلة",
['invalidvariation'] = "تكستشر غير صالح, الاختيارات الصحيحة هي : %s",
['firework'] = "اضغط ~y~G~w~ لاستخدام الالعاب النارية",
['poop'] = "اضغط ~y~G~w~ لقضاء الحاجة 2",

View file

@ -4,12 +4,8 @@ Locales['cs'] = {
['danceemotes'] = "~h~~p~ 🕺 Taneční Animace",
['animalemotes'] = "~h~~p~ 🐩 Zvířecí Animace",
['propemotes'] = "~h~~p~ 📦 Animace s předměty",
['favoriteemotes'] = "~h~~y~ 🌟 Oblíbené",
['favoriteinfo'] = "Vyberte si animaci a nastavte ji jako svou oblíbenou.",
['rfavorite'] = "Obnovit oblíbené",
['prop2info'] = "❓ Pomůcky se mohou nacházet na konci",
['set'] = "Nastavit",
['setboundemote'] = "Nastavit jako vaši animaci?",
['newsetemote'] = "~w~ je nyní vaší novou nastavenou animací. Chcete-li jej použít, stiskněte ~g~CapsLock~w~.",
['cancelemote'] = "~h~~r~ Zrušit animaci 🚷",
['cancelemoteinfo'] = "~r~X~w~ Zruší aktuálně přehrávanou animaci",
@ -54,8 +50,6 @@ Locales['cs'] = {
['searchinputtitle'] = "Vyhledáno:",
['searchmenudesc'] = "výsledek pro",
['searchnoresult'] = "Žádna animace nebyla nalezena",
['searchshifttofav'] = "Podrž L-Shift a stiskni enter pro nastavení animace do oblíbeních.",
['searchcantsetfav'] = "Sdílené animace nelze nastavit jako oblíbené.",
['invalidvariation'] = "Neplatná variace textury. Platné výběry jsou: %s",
['firework'] = "Stiskni ~y~G~w~ pro použití ohňostroje",
['poop'] = "Stisknutím ~y~G~w~ se vykakáte",

View file

@ -4,12 +4,8 @@ Locales['da'] = {
['danceemotes'] = "~h~~p~ 🕺 Danse Animationer",
['animalemotes'] = "~h~~p~ 🐩 Dyr Animationer",
['propemotes'] = "~h~~p~ 📦 Rekvisit Animationer",
['favoriteemotes'] = "~h~~y~ 🌟 Favorit",
['favoriteinfo'] = "Vælg en animation her for at sætte den som din favorit.",
['rfavorite'] = "Nulstil Favorit",
['prop2info'] = "❓ Rekvisit animationer findes i slutningen",
['set'] = "Sæt (",
['setboundemote'] = ") til din favorit animation?",
['newsetemote'] = "~w~ er nu din favorit animation, tryk ~g~CapsLock~w~ for at bruge den.",
['cancelemote'] = "~h~~r~ Afbryd animation",
['cancelemoteinfo'] = "~r~X~w~ annullerer din igangværende animation.",
@ -54,8 +50,6 @@ Locales['da'] = {
['searchinputtitle'] = "Søg:",
['searchmenudesc'] = "resultat(er) for",
['searchnoresult'] = "Ingen resultater fundet med",
['searchshifttofav'] = "Hold L-Shift og tryk enter for at sætte som favorit.",
['searchcantsetfav'] = "Delte animationer kan ikke være favoritter.",
['invalidvariation'] = "Ugyldig teksturvariation. Gyldige valg er: %s",
['firework'] = "Tryk på ~y~G~w~ for at bruge fyrværkeri",
['poop'] = "Tryk på ~y~G~w~ for at skide",

View file

@ -4,12 +4,8 @@ Locales['de'] = {
['danceemotes'] = "~h~~p~ 🕺 Tanz-Emotes",
['animalemotes'] = "~h~~p~ 🐩 Tier Emotes",
['propemotes'] = "~h~~p~ 📦 Prop-Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 Favoriten",
['favoriteinfo'] = "Wähle hier ein Emote, um es als Favorit festzulegen.",
['rfavorite'] = "Favorit zurücksetzen",
['prop2info'] = "❓ Prop-Emotes können am Ende platziert werden",
['set'] = "Setze (",
['setboundemote'] = ") soll dein gebundenes Emote sein?",
['newsetemote'] = "~w~ ist jetzt ein gebundenes Emote, drücke ~g~CapsLock~w~, um es zu verwenden.",
['cancelemote'] = "~h~~r~ Emote abbrechen 🚷",
['cancelemoteinfo'] = "~r~ X ~w~ Bricht das aktuell wiedergegebene Emote ab",
@ -63,8 +59,6 @@ Locales['de'] = {
['searchinputtitle'] = "Suche:",
['searchmenudesc'] = "Ergebnis(se) für ",
['searchnoresult'] = "Es wurden keine Ergebnisse gefunden für",
['searchshifttofav'] = "Halte L-Shift und drücke Enter, um das Emote als Favorit festzulegen.",
['searchcantsetfav'] = "Geteilte Emotes können nicht als Favorit gesetzt werden.",
['invalidvariation'] = "Ungültige Texturvariante. Gültige Auswahlen sind: %s",
['firework'] = "Drücke ~y~G~w~, um das Feuerwerk zu zünden",
['poop'] = "Drücke ~y~G~w~, um zu kacken",
@ -91,7 +85,6 @@ Locales['de'] = {
-- Key maps
['register_cancel_emote'] = "Aktuellen Emote abbrechen",
['register_open_menu'] = "Animationsmenü öffnen",
['register_fav_anim'] = "Deinen Favoriten-Emote abspielen",
['register_handsup'] = "Hände hoch",
['register_crouch'] = "Hocken",
['register_crawl'] = "Kriechen",

View file

@ -4,12 +4,8 @@ Locales['el'] = {
['danceemotes'] = "~h~~p~ 🕺 Χοροί",
['animalemotes'] = "~h~~p~ 🐩 Ζώα",
['propemotes'] = "~h~~p~ 📦 Αντικείμενα",
['favoriteemotes'] = "~h~~y~ 🌟 Αγαπημένα",
['favoriteinfo'] = "Διάλεξε κίνηση για να τη βάλεις στα αγαπημένα.",
['rfavorite'] = "Διαγραφή αγαπημένων",
['prop2info'] = "Τα αντικείμενα βρίσκοντε στο τέλος",
['set'] = "Set (",
['setboundemote'] = ") να προστεθεί στα αγαπημένα?",
['newsetemote'] = "~w~ είναι τώρα στα αγαπημένα σου, πάτησε ~g~CapsLock~w~ για να την χρησιμοποιήσεις.",
['cancelemote'] = "~h~~r~ Ακύρωση Κίνησης 🚷",
['cancelemoteinfo'] = "~r~X~w~ Ακυρώνει την κίνηση που κάνεις τώρα",
@ -54,8 +50,6 @@ Locales['el'] = {
['searchinputtitle'] = "Αναζήτηση:",
['searchmenudesc'] = "αποτέλεσμα(ατα) για",
['searchnoresult'] = "Κανένα απότέλεσμα για την αναζήτηση",
['searchshifttofav'] = "Κράτησε L-Shift και πάτησε enter για να το αποθηκεύσεις ως αγαπημένο.",
['searchcantsetfav'] = "Οι κινήσεις που μοιράζοντε με παίκτες δεν μπορούν να μπούν στα αγαπημένα.",
['invalidvariation'] = "Μη έγκυρη επιλογή. Σωστές επιλογές είναι: %s",
['firework'] = "Πάτησε ~y~G~w~ για να χρησιμοποιήσεις βεγγαλικό",
['poop'] = "Πάτησε ~y~G~w~ για χέσιμο",

View file

@ -4,12 +4,8 @@ Locales['en'] = {
['danceemotes'] = "🕺 Dance Emotes",
['animalemotes'] = "🐩 Animal Emotes",
['propemotes'] = "📦 Prop Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 Favorite",
['favoriteinfo'] = "Select an emote here to set it as your favorite.",
['rfavorite'] = "Reset favorite",
['prop2info'] = "❓ Prop Emotes can be located at the end",
['set'] = "Set (",
['setboundemote'] = ") to be your bound emote?",
['newsetemote'] = "~w~ is now your bound emote, press ~g~CapsLock~w~ to use it.",
['cancelemote'] = "Cancel Emote 🚷",
['cancelemoteinfo'] = "~r~X~w~ Cancels the currently playing emote",
@ -44,15 +40,16 @@ Locales['en'] = {
['doyouwanna'] = "~y~Y~w~ to accept, ~r~L~w~ to refuse (~g~",
['refuseemote'] = "Emote refused.",
['makenearby'] = "makes the nearby player play",
['useleafblower'] = "Press ~y~G~w~ to use the leaf blower.",
['camera'] = "Press ~y~G~w~ to use camera flash.",
['makeitrain'] = "Press ~y~G~w~ to make it rain.",
['pee'] = "Hold ~y~G~w~ to pee.",
['useleafblower'] = "Press ~y~G~w~ to use the leaf blower",
['camera'] = "Press ~y~G~w~ to use camera flash",
['makeitrain'] = "Press ~y~G~w~ to make it rain",
['pee'] = "Hold ~y~G~w~ to pee",
['spraychamp'] = "Hold ~y~G~w~ to spray champagne",
['stun'] = "Press ~y~G~w~ to 'use' stun gun.",
['smoke'] = "Press ~y~G~w~ to smoke.",
['vape'] = "Press ~y~G~w~ to vape.",
['candle'] = "press ~y~G~w~ to light candle.",
['stun'] = "Press ~y~G~w~ to 'use' stun gun",
['smoke'] = "Press ~y~G~w~ to smoke",
['vape'] = "Press ~y~G~w~ to vape",
['candle'] = "Press ~y~G~w~ to light candle",
['ptfxinfo'] = "Press ~y~G~w~ to activate the effects",
['boundto'] = "Bound (~y~%s~w~) to ~g~%s~w~",
['handsup'] = "Hands up",
['currentlyboundemotes'] = "Currently bound emotes:",
@ -63,8 +60,6 @@ Locales['en'] = {
['searchinputtitle'] = "Search:",
['searchmenudesc'] = "result(s) for",
['searchnoresult'] = "No results for search",
['searchshifttofav'] = "Hold L-Shift and press enter to set as favorite.",
['searchcantsetfav'] = "Shared emotes cannot be set as favorites.",
['invalidvariation'] = "Invalid texture variation. Valid selections are: %s",
['firework'] = "Press ~y~G~w~ to use the firework",
['poop'] = "Press ~y~G~w~ to poop",
@ -91,7 +86,6 @@ Locales['en'] = {
-- Key maps
['register_cancel_emote'] = "Cancel current emote",
['register_open_menu'] = "Open animation menu",
['register_fav_anim'] = "Play your favorite emote",
['register_handsup'] = "Raise hands up",
['register_crouch'] = "Crouch",
['register_crawl'] = "Crawl",

View file

@ -4,12 +4,8 @@ Locales['es'] = {
['danceemotes'] = "~h~~p~ 🕺 Bailes",
['animalemotes'] = "~h~~p~ 🐩 Emotes de animales",
['propemotes'] = "~h~~p~ 📦 Objetos",
['favoriteemotes'] = "~h~~y~ 🌟 Favoritos",
['favoriteinfo'] = "Seleccione una animación aquí para configurarlo como su favorito.",
['rfavorite'] = "Restablecer favoritos",
['prop2info'] = "❓ Los Prop Emotes se pueden encontrar al final",
['set'] = "Elegir (",
['setboundemote'] = ") como tu animación favorita?",
['newsetemote'] = "~w~ es ahora tu animación favorita, presiona ~g~[CapsLock]~w~ para usarla.",
['cancelemote'] = "~h~~r~ Cancelar animación 🚷",
['cancelemoteinfo'] = "~r~X~w~ Cancela la animación actual.",
@ -53,8 +49,6 @@ Locales['es'] = {
['searchinputtitle'] = "Buscar:",
['searchmenudesc'] = "resultado(s) para",
['searchnoresult'] = "No se encontró nada con",
['searchshifttofav'] = "Mantén L-Shift y presiona Enter para guardar como favorito.",
['searchcantsetfav'] = "Las animaciones compartidas no pueden ser guardadas como favoritas.",
['invalidvariation'] = "Variación de textura no válida. Las opciones válidas son: %s",
['firework'] = "Presione ~y~G~w~ para usar los fuegos artificiales",
['poop'] = "Presione ~y~G~w~ para hacer caca",

View file

@ -4,12 +4,8 @@ Locales['fa'] = {
['danceemotes'] = "~h~~p~ 🕺 raghs Emotes",
['animalemotes'] = "~h~~p~ 🐩 hevanat Emotes",
['propemotes'] = "~h~~p~ 📦 tekye dadan Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 alaghemandiha",
['favoriteinfo'] = "yek emote ra baray ezafe kardan be alaghe mandi ha entekhab konid.",
['rfavorite'] = "bazneshani alaghe mandi ha",
['prop2info'] = "❓ bad az tekye dadan be yek ja motavaghef mishavad",
['set'] = "Set (",
['setboundemote'] = ") che kelid baray dastressi sari entekhab shavad?",
['newsetemote'] = "~w~ baray dastresi sari, press ~g~CapsLock~w~ baray ejra",
['cancelemote'] = "~h~~r~ laghv emote🚷",
['cancelemoteinfo'] = "~r~X~w~ baray laghv emote ",
@ -54,8 +50,6 @@ Locales['fa'] = {
['searchinputtitle'] = "jostojo:",
['searchmenudesc'] = "result(s) for",
['searchnoresult'] = "No results for search",
['searchshifttofav'] = "Hold L-Shift and press enter to set as favorite.",
['searchcantsetfav'] = "Shared emotes cannot be set as favorites.",
['invalidvariation'] = "Invalid texture variation. Valid selections are: %s",
['firework'] = "Press ~y~G~w~ to use the firework",
['poop'] = "Press ~y~G~w~ to poop",

View file

@ -4,12 +4,8 @@ Locales['fi'] = {
['danceemotes'] = "~h~~p~ 🕺 Tanssi Animaatiot",
['animalemotes'] = "~h~~p~ 🐩 Eläin Animaatiot",
['propemotes'] = "~h~~p~ 📦 Esine Animaatiot",
['favoriteemotes'] = "~h~~p~ 🌟 Suosikit",
['favoriteinfo'] = "Valitse animaatio asettaaksesi sen suosikiksi.",
['rfavorite'] = "Resetoi suosikit.",
['prop2info'] = "❓ Esine animaatiot voivat sijaita lopussa",
['set'] = "Aseta (",
['setboundemote'] = ") bindatuksi animaatioksi?",
['newsetemote'] = "~w~ on nyt bindattu animaatio, paina ~g~CapsLock~w~ käyttääksesi",
['cancelemote'] = "~h~~r~ Peru animaatio 🚷",
['cancelemoteinfo'] = "~r~X~w~ Peruu tämän hetkisen animaation",
@ -54,8 +50,6 @@ Locales['fi'] = {
['searchinputtitle'] = "Etsi:",
['searchmenudesc'] = "tulokset",
['searchnoresult'] = "Ei tuloksia haulle",
['searchshifttofav'] = "Pidä L-Shift painettuna ja aseta suosikiksi painamalla Enter.",
['searchcantsetfav'] = "Jaettuja emoteja ei voi asettaa suosikeiksi.",
['invalidvariation'] = "Virheellinen tekstuurimuunnelma. Kelvollisia valintoja ovat: %s",
['firework'] = "Käytä ilotulitteita painamalla ~y~G~w~",
['poop'] = "Paina ~y~G~w~ kakataksesi.",

View file

@ -4,12 +4,8 @@ Locales['fr'] = {
['danceemotes'] = "~p~ 🕺 Danses",
['animalemotes'] = "~p~ 🐩 Emotes d'animaux",
['propemotes'] = "~p~ 📦 Emotes objet",
['favoriteemotes'] = "~h~~y~ 🌟 Favori",
['favoriteinfo'] = "Définir une emote comme favori.",
['rfavorite'] = "Réinitialiser le favori.",
['prop2info'] = "❓ Les emotes d'objet peuvent être à la fin",
['set'] = "Mettre (",
['setboundemote'] = ") en emote favorite?",
['newsetemote'] = "~w~ est maintenant votre emote favorite, appuyez sur ~g~CapsLock~w~ pour l'utiliser.",
['cancelemote'] = "~r~ Annuler l'émote 🚷",
['cancelemoteinfo'] = "~r~X~w~ Annule l'emote en cours",
@ -53,8 +49,6 @@ Locales['fr'] = {
['searchinputtitle'] = "Recherche:",
['searchmenudesc'] = "resultat(s) pour",
['searchnoresult'] = "Aucun résultat pour la recherche : ",
['searchshifttofav'] = "Maintenir L-Shift et appuyer sur entrer pour marquer comme favorie.",
['searchcantsetfav'] = "Les emotes partagées ne peuvent pas être mise en favorie.",
['invalidvariation'] = "Variation de texture invalide. Les sélections valides sont : %s",
['firework'] = "Appuyez sur <b>G</b> pour utiliser les feux d'artifice",
['poop'] = "Appuyez sur <b>G</b> pour faire caca.",

View file

@ -4,12 +4,8 @@ Locales['hu'] = {
['danceemotes'] = "~h~~p~ 🕺 Tánc Animációk",
['animalemotes'] = "~h~~p~ 🐩 Állatos Animációk",
['propemotes'] = "~h~~p~ 📦 Tárgyas Animációk",
['favoriteemotes'] = "~h~~y~ 🌟 Kedvenc",
['favoriteinfo'] = "Válassz ki itt egy animációt, hogy kedvenceddé tedd.",
['rfavorite'] = "Kedvenc alaphelyzetbe állítása",
['prop2info'] = "❓ A Prop Emote-ok a végén találhatók",
['set'] = "Kiválasztod (",
['setboundemote'] = ") hogy ez legyen a kedvenc animációd?",
['newsetemote'] = "~w~ lett a kedvenc animációd, nyomj egy ~g~CapsLock~w~-ot a használatához.",
['cancelemote'] = "~h~~r~ Animáció Befejezése 🚷",
['cancelemoteinfo'] = "~r~X~w~ Megszünteti az aktuálisan lejátszott animációt",
@ -54,8 +50,6 @@ Locales['hu'] = {
['searchinputtitle'] = "Keresés:",
['searchmenudesc'] = "eredmény erre: ",
['searchnoresult'] = "Nincs eredmény erre:",
['searchshifttofav'] = "Tartsd lenyomva az L-Shift billentyűt, és nyomd meg az enter billentyűt a kedvencek beállításához.",
['searchcantsetfav'] = "A megosztott animációkat nem lehet kedvencekként beállítani.",
['invalidvariation'] = "Érvénytelen textúra variáció. Érvényes választások a következők: %s",
['firework'] = "Nyomj ~y~G~w~ gombot a tűzijáték használatához",
['poop'] = "Nyomj ~y~G~w~ gombot a kakiláshoz",

View file

@ -4,12 +4,8 @@ Locales['id'] = {
['danceemotes'] = "~h~~p~ 🕺 Emote Menari",
['animalemotes'] = "~h~~p~ 🐩 Emote Hewan",
['propemotes'] = "~h~~p~ 📦 Prop Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 Favorit",
['favoriteinfo'] = "Pilih emote di sini untuk menetapkannya sebagai favorit Anda.",
['rfavorite'] = "Setel ulang favorit",
['prop2info'] = "❓ Prop Emotes can be located at the end",
['set'] = "Tetapkan (",
['setboundemote'] = ") untuk menjadi emote terikat Anda?",
['newsetemote'] = "~w~ sekarang menjadi emote terikat Anda, tekan ~g~CapsLock~w~ untuk menggunakannya.",
['cancelemote'] = "~h~~r~ Batalkan Emote 🚷",
['cancelemoteinfo'] = "~r~X~w~ Batalkan emote yang sedang dimainkan",
@ -54,8 +50,6 @@ Locales['id'] = {
['searchinputtitle'] = "Cari:",
['searchmenudesc'] = "hasil untuk",
['searchnoresult'] = "Tidak ada hasil untuk pencarian",
['searchshifttofav'] = "Tahan L-Shift dan tekan enter untuk menetapkan sebagai favorit.",
['searchcantsetfav'] = "Emote yang dibagikan tidak dapat ditetapkan sebagai favorit.",
['invalidvariation'] = "Variasi tekstur tidak valid. Pilihan yang valid adalah: %s",
['firework'] = "Tekan ~y~G~w~ untuk menggunakan kembang api",
['poop'] = "Tekan ~y~G~w~ untuk buang air besar",

View file

@ -4,12 +4,8 @@ Locales['it'] = {
['danceemotes'] = "~h~~p~ 🕺 Animazioni Di Danza",
['animalemotes'] = "~h~~p~ 🐩 Animazioni Di Animali",
['propemotes'] = "~h~~p~ 📦 Animazioni Prop",
['favoriteemotes'] = "~h~~y~ 🌟 Emote preferite",
['favoriteinfo'] = "Seleziona un'animazione per metterla nei preferiti.",
['rfavorite'] = "Rimuovi preferito",
['prop2info'] = "❓ Le animazioni Prop possono essere trovate in fondo.",
['set'] = "Imposta (",
['setboundemote'] = ") come tua animazione corrente?",
['newsetemote'] = "~w~ è ora la tua animazione corrente, premi ~g~CapsLock~w~ per usarla.",
['cancelemote'] = "~h~~r~ Annulla animazione 🚷",
['cancelemoteinfo'] = "~r~X~w~ Cancella l'animazione in corso.",
@ -54,8 +50,6 @@ Locales['it'] = {
['searchinputtitle'] = "Search:",
['searchmenudesc'] = "result(s) for",
['searchnoresult'] = "No results for search",
['searchshifttofav'] = "Hold L-Shift and press enter to set as favorite.",
['searchcantsetfav'] = "Shared emotes cannot be set as favorites.",
['invalidvariation'] = "Opzioni colore non valide. scelte valide sono: %s",
['firework'] = "Premere ~y~G~w~ per utilizzare il fuoco d'artificio",
['poop'] = "Premere ~y~G w~ per fare la cacca",

View file

@ -4,12 +4,8 @@ Locales['lk'] = {
['danceemotes'] = "~h~~p~ 🕺 Natana Emotes",
['animalemotes'] = "~h~~p~ 🐩 Sattunge Emotes",
['propemotes'] = "~h~~p~ 📦 Prop Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 Favorite Emotes",
['favoriteinfo'] = "Methanin oyage favorite emote eka thoraganna.",
['rfavorite'] = "Favorite emote eka reset karanna",
['prop2info'] = "❓ Prop emotes tiyenne anthimata",
['set'] = "Set karanna (",
['setboundemote'] = ") favorite emote eka widiyata?",
['newsetemote'] = "~w~ thamai oyage favorite emote eka, ~g~CapsLock~w~ eken use karanna.",
['cancelemote'] = "~h~~r~ Emote Eka Nawattanna 🚷",
['cancelemoteinfo'] = "~r~X~w~ Wetila thiyana emote eka nawattanawa",
@ -54,8 +50,6 @@ Locales['lk'] = {
['searchinputtitle'] = "Search karanna:",
['searchmenudesc'] = "result(s) for",
['searchnoresult'] = "Mukut hambune na",
['searchshifttofav'] = "L-Shift obagena Enter press karala, favorite karaganna.",
['searchcantsetfav'] = "Shared emotes favorite karanna ba.",
['invalidvariation'] = "Weradi texture variation ekak. Hari ewa thamai: %s",
['firework'] = "Firework ekata ~y~G~w~ press karanna",
['poop'] = "Kakki danna ~y~G~w~ press karanna",

View file

@ -4,12 +4,8 @@ Locales['lt'] = {
['danceemotes'] = "~h~~p~ 🕺 Sokiu animacijos",
['animalemotes'] = "~h~~p~ 🐩 Gyvunu animacijos",
['propemotes'] = "~h~~p~ 📦 Daiktu animacijos",
['favoriteemotes'] = "~h~~y~ 🌟 Megstamiausi",
['favoriteinfo'] = "Cia pasirinkite jaustuka, kad nustatytumete ji kaip megstamiausia.",
['rfavorite'] = "Atstatyti megstamiausia",
['prop2info'] = "❓ Daiktu animacijos gali buti pabaigoje",
['set'] = "Rinkinys (",
['setboundemote'] = ") buti tavo surista emocija?",
['newsetemote'] = "~w~ dabar yra jusu susietas jaustukas, paspauskite ~g~CapsLock~w~, kad ji naudotumete.",
['cancelemote'] = "~h~~r~ Atsaukti animacija 🚷",
['cancelemoteinfo'] = "~r~X~w~ Atsaukti dabar naudojama animacija",
@ -63,8 +59,6 @@ Locales['lt'] = {
['searchinputtitle'] = "Ieskoti:",
['searchmenudesc'] = "rezultatas (-ai), skirtas",
['searchnoresult'] = "Paieskos rezultatu nera",
['searchshifttofav'] = "Laikykite nuspaude L-Shift ir paspauskite Enter, kad nustatytumete kaip megstamiausia.",
['searchcantsetfav'] = "Bendrinamos animacijos negali buti nustatytos kaip megstamiausios.",
['invalidvariation'] = "Netinkamas teksturos variantas. Galiojantys pasirinkimai yra: %s",
['firework'] = "Paspauskite ~y~G~w~, kad galetumete naudoti fejerverka",
['poop'] = "Paspauskite ~y~G~w~, kad istustumete",
@ -93,7 +87,6 @@ Locales['lt'] = {
['register_cancel_emote'] = "Atšaukti animaciją",
['register_handsup'] = "Pakelti rankas",
['register_open_menu'] = "Animacijų meniu",
['register_fav_anim'] = "Paleisti mėgstamiausia animaciją",
['register_crouch'] = "Pritūpti",
['register_crawl'] = "Šliaužti",
['register_pointing'] = "Rodyti pirštu",

View file

@ -4,12 +4,8 @@ Locales['nl'] = {
['danceemotes'] = "🕺 Dans Animaties",
['animalemotes'] = "🐩 Dier Animaties",
['propemotes'] = "📦 Voorwerp Animaties",
['favoriteemotes'] = "~h~~y~ 🌟 Favoriete",
['favoriteinfo'] = "Selecteer hier een animatie om deze als favoriete in te stellen.",
['rfavorite'] = "Favoriete wissen",
['prop2info'] = "❓ Voorwerp animaties aan het einde",
['set'] = "Maak (",
['setboundemote'] = ") je toegewezen animatie.",
['newsetemote'] = "~w~ is nu je toegewezen animatie, druk op ~g~CapsLock~w~ om het te gebruiken.",
['cancelemote'] = "Animatie Stoppen 🚷",
['cancelemoteinfo'] = "~r~X~w~ Stopt je huidige animatie.",
@ -63,8 +59,6 @@ Locales['nl'] = {
['searchinputtitle'] = "Zoeken:",
['searchmenudesc'] = "resultaten voor",
['searchnoresult'] = "Geen resultaten voor zoekopdracht",
['searchshifttofav'] = "Houd ~y~L-Shift~w~ ingedrukt en druk op enter om als favoriet op te slaan.",
['searchcantsetfav'] = "Gedeelde animaties kunnen niet als favoriet worden ingesteld",
['invalidvariation'] = "Ongeldige texture variatie. Geldige selecties zijn: %s",
['firework'] = "Druk op ~y~G~w~ om het vuurwerk te gebruiken",
['poop'] = "Druk op ~y~G~w~ om te poepen",
@ -91,7 +85,6 @@ Locales['nl'] = {
-- Key maps
['register_cancel_emote'] = "Huidige animatie stoppen",
['register_open_menu'] = "Animatiemenu openen",
['register_fav_anim'] = "Start je favoriete animatie",
['register_handsup'] = "Handen omhoog",
['register_crouch'] = "Hurken",
['register_crawl'] = "Kruipen",

View file

@ -4,12 +4,8 @@ Locales['no'] = {
['danceemotes'] = "~h~~p~ 🕺 Danse Animasjoner",
['animalemotes'] = "~h~~p~ 🐩 Dyreanimasjoner",
['propemotes'] = "~h~~p~ 📦 Rekvisitt Animasjoner",
['favoriteemotes'] = "~h~~y~ 🌟 Favoritt",
['favoriteinfo'] = "Her kan du velge en favoritt animasjon.",
['rfavorite'] = "Reset favoritt",
['prop2info'] = "❓ Rekvisitt Animasjoner er på bunnen",
['set'] = "Vil du sette (",
['setboundemote'] = ") som din favoritt?",
['newsetemote'] = "~w~ er nå lagret som din favoritt, trykk ~g~CapsLock~w~ for å bruke den.",
['cancelemote'] = "~h~~r~ Avbryt Animasjonen 🚷",
['cancelemoteinfo'] = "~r~X~w~ Avbryt den nåværende animasjonen",
@ -54,8 +50,6 @@ Locales['no'] = {
['searchinputtitle'] = "Søk:",
['searchmenudesc'] = "resultat(er) for",
['searchnoresult'] = "Ingen resultater for søk",
['searchshifttofav'] = "Hold L-Shift og trykk Enter for å sette som favoritt.",
['searchcantsetfav'] = "Du kan ikke sitte en Felles Animasjon som favoritt.",
['invalidvariation'] = "Ugyldig tekstur variant. Gyldige varianter: %s",
['firework'] = "Trykk ~y~G~w~ for å avfyre fyrverkeriet",
['poop'] = "Hold ~y~G~w~ for å bæsje",

View file

@ -4,12 +4,8 @@ Locales['pl'] = {
['danceemotes'] = "~h~~p~ 🕺 Tańce",
['animalemotes'] = "~h~~p~ 🐩 Animacje zwierząt",
['propemotes'] = "~h~~p~ 📦 Animacje z propami",
['favoriteemotes'] = "~h~~y~ 🌟 Ulubione",
['favoriteinfo'] = "Wybierz animację i ustaw ją jako ulubioną.",
['rfavorite'] = "Zresetuj ulubione animacje",
['prop2info'] = "❓ Animacje z propami są zlokalizowane na samym końcu listy",
['set'] = "Ustaw (",
['setboundemote'] = ") jako Twoją przypisaną animację?",
['newsetemote'] = "~w~ jest teraz Twoją przypisaną animacją, wciśnij ~g~CapsLock~w~ by jej użyć.",
['cancelemote'] = "~h~~r~ Anuluj animację 🚷",
['cancelemoteinfo'] = "~r~X~w~ Anuluje aktualnie graną animację",
@ -54,8 +50,6 @@ Locales['pl'] = {
['searchinputtitle'] = "Szukaj:",
['searchmenudesc'] = "wyników dla frazy",
['searchnoresult'] = "Brak wyników dla frazy",
['searchshifttofav'] = "Przytrzymaj L-Shift i naciśnij Enter by dodać do ulubionych.",
['searchcantsetfav'] = "Współdzielona animacja nie może być dodana do ulubionych.",
['invalidvariation'] = "Niepoprawny wariant tekstury. Dostępne tekstury to: %s",
['firework'] = "Naciśnij ~y~G~w~ aby odpalić fajerwerki",
['poop'] = "Naciśnij ~y~G~w~ by zrobić kupę",

View file

@ -4,12 +4,8 @@ Locales['pt'] = {
['danceemotes'] = "~h~~p~ 🕺 Emotes de Danças",
['animalemotes'] = "~h~~p~ 🐩 Emotes de Animais",
['propemotes'] = "~h~~p~ 📦 Emotes com Props",
['favoriteemotes'] = "~h~~y~ 🌟 Favoritos",
['favoriteinfo'] = "Selecione um emote para colocá-lo nos seus favoritos",
['rfavorite'] = "Limpar favoritos",
['prop2info'] = "❓ Emotes de props podem ser localizados no fim",
['set'] = "Set (",
['setboundemote'] = ") para ser seu emote vinculado?",
['newsetemote'] = "~w~ é o seu emote vinculado, pressione ~g~CapsLock~w~ para usá-lo",
['cancelemote'] = "~h~~r~ Cancelar emote 🚷",
['cancelemoteinfo'] = "~r~X~w~ Cancela os emotes rodando atualmente",
@ -54,8 +50,6 @@ Locales['pt'] = {
['searchinputtitle'] = "Procurar:",
['searchmenudesc'] = "resultado(s) para",
['searchnoresult'] = "Nenhum resultado para a pesquisa",
['searchshifttofav'] = "Segure Shift Esquerdo e pressione enter para setar como favorito.",
['searchcantsetfav'] = "Emotes compartilhados não podem ser setados como favorito.",
['invalidvariation'] = "Variação de textura inválida. As opções válidas são: %s",
['firework'] = "Pressione ~y~G~w~ para usar o fogo de artifício",
['poop'] = "Pressione ~y~G~w~ para fazer cocô", -- Translated using smodin.io

View file

@ -4,12 +4,8 @@ Locales['ro'] = {
['danceemotes'] = "~h~~p~ 🕺 Dansuri",
['animalemotes'] = "~h~~p~ 🐩 Emote-uri pentru animale",
['propemotes'] = "~h~~p~ 📦 Prop Emote-uri",
['favoriteemotes'] = "~h~~y~ 🌟 Favorite",
['favoriteinfo'] = "Selecteaza un emote aici pentru a îl alege ca favorit.",
['rfavorite'] = "Reseteaza emote-uri favorite",
['prop2info'] = "❓ Prop Emote-urile pot fi gasite la final",
['set'] = "Seteaza (",
['setboundemote'] = ") sa fie emote-ul binduit?",
['newsetemote'] = "~w~ este acum emote-ul tau binduit, apasa ~g~CapsLock~w~ pentru a folosi.",
['cancelemote'] = "~h~~r~ Anuleaza animatia 🚷",
['cancelemoteinfo'] = "~r~X~w~ Anuleaza animatia curenta",
@ -54,8 +50,6 @@ Locales['ro'] = {
['searchinputtitle'] = "Cautare:",
['searchmenudesc'] = "rezultat(e) pentru",
['searchnoresult'] = "Fara rezultate pentru cautarea",
['searchshifttofav'] = "Tine apasat L-Shift si apasa enter pentru a seta ca favorit.",
['searchcantsetfav'] = "Emote-urile Shared nu pot fi setate ca favorite.",
['invalidvariation'] = "Variație nevalidă a texturii. Selectările valide sunt: %s",
['firework'] = "Apasa ~y~G~w~ pentru a folosi artificiile",
['poop'] = "Apăsați pe ~y~G~w~ pentru a face caca", --Trannslated using smodin.io

View file

@ -4,12 +4,8 @@ Locales['ru'] = {
['danceemotes'] = "~h~~p~ 🕺 Танцевальные эмоции",
['animalemotes'] = "~h~~p~ 🐩 Эмоции животных",
['propemotes'] = "~h~~p~ 📦 Эмоции с пропом",
['favoriteemotes'] = "~h~~y~ 🌟 Избранные",
['favoriteinfo'] = "Выберите здесь эмоцию, чтобы сделать ее избранной.",
['rfavorite'] = "Сбросить избранное",
['prop2info'] = "❓ Эмоции с пропом могут быть расположены в конце",
['set'] = "Установить (",
['setboundemote'] = ") как привязанную эмоцию?",
['newsetemote'] = "~w~ теперь привязанная эмоция, нажмите ~g~CapsLock~w~ для использования.",
['cancelemote'] = "~h~~r~ Остановить эмоцию 🚷",
['cancelemoteinfo'] = "~r~X~w~ Отменяет воспроизводимую эмоцию",
@ -62,8 +58,6 @@ Locales['ru'] = {
['searchinputtitle'] = "Поиск:",
['searchmenudesc'] = "результат(ы) для",
['searchnoresult'] = "Нет результатов по поиску",
['searchshifttofav'] = "Удерживайте L-Shift и нажмите Enter, чтобы установить в избранное.",
['searchcantsetfav'] = "Парные эмоции не могут быть добавлены в избранное.",
['invalidvariation'] = "Недопустимая вариация текстуры. Допустимые варианты: %s",
['firework'] = "Нажмите ~y~G~w~, чтобы запустить фейерверк.",
['poop'] = "Нажмите ~y~G~w~, чтобы какать",
@ -91,7 +85,6 @@ Locales['ru'] = {
-- Key maps
['register_cancel_emote'] = "Отменить текущую эмоцию",
['register_open_menu'] = "Открыть меню анимации",
['register_fav_anim'] = "Воспроизведите свою любимую эмоцию",
['register_handsup'] = "Поднимите руки вверх",
['register_crouch'] = "В приседи",
['register_crawl'] = "Ползти",

View file

@ -4,12 +4,8 @@ Locales['sl'] = {
['danceemotes'] = "~h~~p~ 🕺 Plesi",
['animalemotes'] = "~h~~p~ 🐩 Emote živali",
['propemotes'] = "~h~~p~ 📦 Emote pripomočkov",
['favoriteemotes'] = "~h~~y~ 🌟 Priljubljeni",
['favoriteinfo'] = "Izberite emote tukaj, da ga nastavite kot priljubljenega.",
['rfavorite'] = "Ponastavi priljubljenega",
['prop2info'] = "❓ Emote pripomočki se nahajajo na koncu",
['set'] = "Nastavi (",
['setboundemote'] = ") kot vaš vezan emote?",
['newsetemote'] = "~w~ je sedaj vaš vezan emote, pritisnite ~g~CapsLock~w~, da ga uporabite.",
['cancelemote'] = "~h~~r~ Prekliči Emote 🚷",
['cancelemoteinfo'] = "~r~X~w~ Prekliče trenutno predvajani emote",
@ -54,8 +50,6 @@ Locales['sl'] = {
['searchinputtitle'] = "Iskanje:",
['searchmenudesc'] = "rezultat(ov) za",
['searchnoresult'] = "Ni rezultatov za iskanje",
['searchshifttofav'] = "Pritisnite in pridržite levi Shift ter pritisnite Enter, da ga nastavite kot priljubljenega.",
['searchcantsetfav'] = "Deljeni emotes ni mogoče nastaviti kot priljubljene.",
['invalidvariation'] = "Neveljavna teksturna variacija. Veljavne izbire so: %s",
['firework'] = "Pritisnite ~y~G~w~, da uporabite ognjemet",
['poop'] = "Pritisnite ~y~G~w~, da opravite veliko potrebo",

View file

@ -4,12 +4,8 @@ Locales['sq'] = {
['danceemotes'] = "~h~~p~ 🕺 Emotet e Kërcimit",
['animalemotes'] = "~h~~p~ 🐩 Emotet e Kafshëve",
['propemotes'] = "~h~~p~ 📦 Emotet e Përparave",
['favoriteemotes'] = "~h~~y~ 🌟 Të preferuar",
['favoriteinfo'] = "Zgjidh një emote këtu për ta caktuar si të preferuarin tënd.",
['rfavorite'] = "Rivendos të preferuarin",
['prop2info'] = "❓ Emotet e Përparave mund të gjenden në fund",
['set'] = "Vendos (",
['setboundemote'] = ") të jetë emote e lidhur?",
['newsetemote'] = "~w~ është tani emota e lidhur, shtyp ~g~CapsLock~w~ për ta përdorur.",
['cancelemote'] = "~h~~r~ Anulo Emoten 🚷",
['cancelemoteinfo'] = "~r~X~w~ Anulon emoten që është duke u luajtur momentalisht",
@ -54,8 +50,6 @@ Locales['sq'] = {
['searchinputtitle'] = "Kërko:",
['searchmenudesc'] = "rezultat(e) për",
['searchnoresult'] = "Asnjë rezultat për kërkimin",
['searchshifttofav'] = "Mbaj Shift të majtë dhe shtyp enter për ta caktuar si të preferuar.",
['searchcantsetfav'] = "Emotet e ndara nuk mund të caktohen si të preferuara.",
['invalidvariation'] = "Variacioni i teksturës i pavlefshëm. Zgjedhjet e vlefshme janë: %s",
['firework'] = "Shtyp ~y~G~w~ për të përdorur fenerin",
['poop'] = "Shtyp ~y~G~w~ për të bërë që të defekosh",

View file

@ -4,12 +4,8 @@ Locales['sr'] = {
['danceemotes'] = "🕺 Plesovi",
['animalemotes'] = "🐩 Životinjske Animacije",
['propemotes'] = "📦 Animacije Sa Predmetima",
['favoriteemotes'] = "🌟 Omiljeno",
['favoriteinfo'] = "Izaberite animaciju ovdje da je stavite kao omiljenu",
['rfavorite'] = "Resetuj omiljeno",
['prop2info'] = "❓ Animacije sa predmetima se mogu naći na kraju",
['set'] = "Postavi (",
['setboundemote'] = ") da bude tvoji bound-ana animacija?",
['newsetemote'] = "~w~ je sada tvoja bound-ana animacija, pritisni ~g~CapsLock~w~ da je uradiš.",
['cancelemote'] = "Prekini Animaciju 🚷",
['cancelemoteinfo'] = "~r~X~w~ Prekine animaciju koju trenutno radiš",
@ -53,8 +49,6 @@ Locales['sr'] = {
['searchinputtitle'] = "Pretraži:",
['searchmenudesc'] = "rezultat(a) za",
['searchnoresult'] = "Nema rezultata za pretraživanje",
['searchshifttofav'] = "Drži L-Shift i pritisni Enter da staviš kao tvoje omiljeno.",
['searchcantsetfav'] = "Društvene Animacije ne mogu biti omiljene.",
['invalidvariation'] = "Nevažeća varijacija teksture. Važeće selekcije su: %s",
['firework'] = "Pritisni ~y~G~w~ da koristiš vatromet",
['poop'] = "Pritisni ~y~G~w~ da kakiš",

View file

@ -4,12 +4,8 @@ Locales['sv'] = {
['danceemotes'] = "~h~~p~ 🕺 Dans Emotes",
['animalemotes'] = "~h~~p~ 🐩 Djur Emotes",
['propemotes'] = "~h~~p~ 📦 Objekt Emotes",
['favoriteemotes'] = "~h~~y~ 🌟 Favorit",
['favoriteinfo'] = "Välj en emote för att ställa in den som din favorit.",
['rfavorite'] = "Återställ favorit.",
['prop2info'] = "❓ Objekt Emotes finns längst ner i listan.",
['set'] = "Sätt (",
['setboundemote'] = ") till din favorit emote?",
['newsetemote'] = "~w~ är nu din favorit emote, tryck ~g~CapsLock~w~ för att använda den.",
['cancelemote'] = "~h~~r~ Avbryt Emote 🚷",
['cancelemoteinfo'] = "~r~X~w~ avbryter nuvarande spelande emote.",
@ -54,8 +50,6 @@ Locales['sv'] = {
['searchinputtitle'] = "Sök:",
['searchmenudesc'] = "resultat på",
['searchnoresult'] = "Inga resultat hittades på",
['searchshifttofav'] = "Håll ned L-Shift och tryck på enter för att ställa in som favorit.",
['searchcantsetfav'] = "Delade Emotes kan inte ställas in som favoriter.",
['invalidvariation'] = "Ogiltig texturvariation. Giltiga val är: %s",
['firework'] = "Tryck ~y~G~w~ för att avfyra dina fyrverkerier",
['poop'] = "Tryck ~y~G~w~ för att bajsa", -- Translated using smodin.io

View file

@ -4,12 +4,8 @@ Locales['tr'] = {
['danceemotes'] = "🕺 Dans Animasyonları",
['animalemotes'] = "🐩 Hayvan Animasyonları",
['propemotes'] = "📦 Eşyaları Animasyonlar",
['favoriteemotes'] = "~h~~y~ 🌟 Favoriler",
['favoriteinfo'] = "Favori olarak seçmek için buradan bir animasyon seçin",
['rfavorite'] = "Favorileri sıfırla",
['prop2info'] = "❓ Eşyalı animasyonlar sonda bulunur",
['set'] = "Set (",
['setboundemote'] = ") animasyonu bağlansın mı?",
['newsetemote'] = "~w~ animasyonu bağlandı, kullanmak için ~g~CapsLock~w~ tuşuna basın",
['cancelemote'] = "Animasyonu iptal et 🚷",
['cancelemoteinfo'] = "~r~X~w~ Şu anki animasyonu iptal eder",
@ -63,8 +59,6 @@ Locales['tr'] = {
['searchinputtitle'] = "Ara:",
['searchmenudesc'] = "sonuçlar:",
['searchnoresult'] = "Animasyon bulunamadı",
['searchshifttofav'] = "Animasyonu favori eklemek için LShift + Enter tuşlarına basın",
['searchcantsetfav'] = "Ortak animasyonlar favori olarak eklenemez",
['invalidvariation'] = "Geçersiz doku. Geçerli dokular: %s",
['firework'] = "Havai fişeği kullanmak için ~y~G~w~ tuşuna basın",
['poop'] = "Kaka yapmak için ~y~G~w~ tuşuna basın",
@ -91,7 +85,6 @@ Locales['tr'] = {
-- Key maps
['register_cancel_emote'] = "Şu anki animasyonu iptal et",
['register_open_menu'] = "Animasyon menüsünü aç",
['register_fav_anim'] = "Favori animasyonuna gir",
['register_handsup'] = "Ellerini kaldır",
['register_crouch'] = "Eğil",
['register_crawl'] = "Sürün",

View file

@ -4,12 +4,8 @@ Locales['vi'] = {
['danceemotes'] = "~h~~p~ 🕺 Nhảy nhót",
['animalemotes'] = "~h~~p~ 🐩 Thú cưng",
['propemotes'] = "~h~~p~ 📦 Đồ vật",
['favoriteemotes'] = "~h~~y~ 🌟 Ưa thích",
['favoriteinfo'] = "Hãy chọn 1 hành động và đưa vào mục ưa thích.",
['rfavorite'] = "Xóa toàn bộ Ưa thích",
['prop2info'] = "❓ Hành động liên quan đến đồ vật sẽ ở cuối.",
['set'] = "Đặt (",
['setboundemote'] = ") Làm hành động ưa thích?",
['newsetemote'] = "~w~ đã được đặt, Bấm ~g~CapsLock~w~ để sử dụng.",
['cancelemote'] = "~h~~r~ Hủy hành động 🚷",
['cancelemoteinfo'] = "~r~X~w~ để hủy hành động",
@ -54,8 +50,6 @@ Locales['vi'] = {
['searchinputtitle'] = "Tìm kiếm:",
['searchmenudesc'] = "Kết quả cho",
['searchnoresult'] = "Không có kết quả",
['searchshifttofav'] = "Giữ l-shift và nhấn enter để đặt làm hành động yêu thích.",
['searchcantsetfav'] = "ác biểu tượng được chia sẻ không thể được đặt làm mục yêu thích.",
['invalidvariation'] = "Biến thể kết cấu không hợp lệ.Các lựa chọn hợp lệ là: %s",
['firework'] = "Nhấn ~y~G~w~ Để sử dụng pháo hoa",
['poop'] = "Nhấn ~y~G~w~ để ị", -- Translated using smodin.io

View file

@ -4,12 +4,8 @@ Locales['zhcn'] = {
['danceemotes'] = "🕺 舞蹈动作",
['animalemotes'] = "🐩 动物动作",
['propemotes'] = "📦 道具动作",
['favoriteemotes'] = "~h~~y~ 🌟 收藏",
['favoriteinfo'] = "在这里选择一个动作作为收藏。",
['rfavorite'] = "重置收藏",
['prop2info'] = "❓ 道具动作位于末尾",
['set'] = "设置 (",
['setboundemote'] = ") 为你的绑定动作?",
['newsetemote'] = "~w~ 现在是你的绑定动作,按 ~g~CapsLock~w~ 使用它。",
['cancelemote'] = "取消动作 🚷",
['cancelemoteinfo'] = "~r~X~w~ 取消当前的动作",
@ -63,8 +59,6 @@ Locales['zhcn'] = {
['searchinputtitle'] = "搜索:",
['searchmenudesc'] = "搜索结果",
['searchnoresult'] = "没有搜索结果",
['searchshifttofav'] = "按住 L-Shift 并按回车键设置为收藏。",
['searchcantsetfav'] = "共享动作不能设置为收藏。",
['invalidvariation'] = "无效的纹理变体。有效选择为: %s",
['firework'] = "按 ~y~G~w~ 使用烟花",
['poop'] = "按 ~y~G~w~ 大便",
@ -91,7 +85,6 @@ Locales['zhcn'] = {
-- 按键映射
['register_cancel_emote'] = "取消当前动作",
['register_open_menu'] = "打开动作菜单",
['register_fav_anim'] = "使用你最喜欢的动作",
['register_handsup'] = "举手",
['register_crouch'] = "蹲下",
['register_crawl'] = "爬行",

View file

@ -4,12 +4,8 @@ Locales['zhtw'] = {
['danceemotes'] = "~h~~p~ 🕺 舞蹈動作",
['animalemotes'] = "~h~~p~ 🐩 動物動作",
['propemotes'] = "~h~~p~ 📦 物品動作",
['favoriteemotes'] = "~h~~y~ 🌟 收藏",
['favoriteinfo'] = "在此處選擇壹個動作並將其設為收藏。",
['rfavorite'] = "重置收藏",
['prop2info'] = "❓ 物品動作在最後面",
['set'] = "設置 (",
['setboundemote'] = ") 為綁定動作?",
['newsetemote'] = "~w~ 已設置為妳的綁定動作,按 ~g~CapsLock~w~ 使用。",
['cancelemote'] = "~h~~r~ 取消動作 🚷",
['cancelemoteinfo'] = "~r~X~w~ 取消當前動作",
@ -54,8 +50,6 @@ Locales['zhtw'] = {
['searchinputtitle'] = "搜索:",
['searchmenudesc'] = " 有 %s 個結果:",
['searchnoresult'] = " 沒有搜索結果。",
['searchshifttofav'] = "按住 L-Shift 並按回車鍵設置為收藏。",
['searchcantsetfav'] = "共享動作無法設置為收藏。",
['invalidvariation'] = "紋理顏色無效。有效選擇為: %s",
['firework'] = "按 ~y~G~w~ 放煙花",
['poop'] = "按 ~y~G~w~ 排便",

View file

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 4.1 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.2 MiB

After

Width:  |  Height:  |  Size: 4.2 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4 MiB

After

Width:  |  Height:  |  Size: 4 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 267 KiB

After

Width:  |  Height:  |  Size: 267 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.1 MiB

After

Width:  |  Height:  |  Size: 3.1 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 2.8 MiB

After

Width:  |  Height:  |  Size: 2.8 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.4 MiB

After

Width:  |  Height:  |  Size: 3.4 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.1 MiB

After

Width:  |  Height:  |  Size: 4.1 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.3 MiB

After

Width:  |  Height:  |  Size: 3.3 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4.2 MiB

After

Width:  |  Height:  |  Size: 4.2 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 4 MiB

After

Width:  |  Height:  |  Size: 4 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 3.7 MiB

After

Width:  |  Height:  |  Size: 3.7 MiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 183 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Before After
Before After

View file

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Before After
Before After

View file

@ -0,0 +1,164 @@
RegisterNetEvent("rpemotes:server:requestEmote", function(target, emotename, etype)
local source = source
if not Player(source).state.canEmote then return end
if target == -1 then
return
end
local distance = #(GetEntityCoords(GetPlayerPed(source)) - GetEntityCoords(GetPlayerPed(target)))
if distance > 3 then
return
end
TriggerClientEvent("rpemotes:client:requestEmote", target, emotename, etype, source)
end)
RegisterNetEvent("rpemotes:server:confirmEmote", function(target, requestedemote, otheremote)
local source = source
if target == -1 then
return
end
local distance = #(GetEntityCoords(GetPlayerPed(source)) - GetEntityCoords(GetPlayerPed(target)))
if distance > 3 then
return
end
TriggerClientEvent("rpemotes:client:syncEmote", source, otheremote, target)
TriggerClientEvent("rpemotes:client:syncEmoteSource", target, requestedemote, source)
end)
RegisterNetEvent("rpemotes:server:cancelEmote", function(target)
TriggerClientEvent("rpemotes:client:cancelEmote", target, source)
end)
RegisterNetEvent("rpemotes:ptfx:sync", function(asset, name, offset, rot, bone, scale, color)
assert(type(asset) == "string", "[rpemotes] ptfx:sync: invalid asset for source: " .. tostring(source))
assert(type(name) == "string", "[rpemotes] ptfx:sync: invalid name for source: " .. tostring(source))
assert(type(offset) == "vector3", "[rpemotes] ptfx:sync: invalid offset for source: " .. tostring(source))
assert(type(rot) == "vector3", "[rpemotes] ptfx:sync: invalid rot for source: " .. tostring(source))
local state = Player(source).state
state:set("ptfxAsset", asset, true)
state:set("ptfxName", name, true)
state:set("ptfxOffset", offset, true)
state:set("ptfxRot", rot, true)
state:set("ptfxBone", bone, true)
state:set("ptfxScale", scale, true)
state:set("ptfxColor", color, true)
state:set("ptfxPropNet", nil, true)
state:set("ptfx", nil, true)
end)
RegisterNetEvent("rpemotes:ptfx:syncProp", function(propNet)
local state = Player(source).state
if propNet then
local entity
local maxAttempts = 100
local attempt = 0
repeat
entity = NetworkGetEntityFromNetworkId(propNet)
if entity and DoesEntityExist(entity) then
state:set("ptfxPropNet", propNet, true)
return
end
attempt = attempt + 1
Wait(10)
until attempt >= maxAttempts
print(("[rpemotes] Warning: Failed to find entity for propNet %s after %d attempts (source: %s)"):format(tostring(propNet), maxAttempts, tostring(source)))
end
state:set("ptfxPropNet", nil, true)
end)
local function ExtractEmoteProps(format)
format = tonumber(format)
local xt, c, total = '', '', 0
if format == 1 then
print("Selected format: ^2'prop_name',")
xt = "'"; c = ","
elseif format == 2 then
print("Selected format: ^2\"prop_name\",")
xt = "\""; c = ","
elseif format == 3 then
print("Selected format: ^2prop_name,")
elseif format == 4 then
print("Selected to calculate ^2total amount of emotes^0.")
else
print(
"\n### RPEmotes - Props Extractor ###\n\n^3Select output format^0\nAvailable formats:\n^11^0 - ^2'prop_name',\n^12^0 - ^2\"prop_name\",\n^13^0 - ^2prop_name\n^14^0 - ^2calculate total emotes\n\n^0Command usage example: ^5emoteextract 1^0\n")
return
end
local animationFile = LoadResourceFile(GetCurrentResourceName(), "client/AnimationList.lua")
if not animationFile then return nil end
local f, err = load(animationFile .. " return RP")
if err then return nil end
local success, res = pcall(f)
if not success then return nil end
if format == 4 then
local emoteTypes = { "Shared", "Dances", "AnimalEmotes", "Emotes", "PropEmotes", "Expressions", "Walks" }
local expressionAndWalkCount = 0
local otherEmotesCount = 0
for _, emoteType in ipairs(emoteTypes) do
local count = 0
for _ in pairs(res[emoteType]) do
count = count + 1
end
if emoteType == "Expressions" or emoteType == "Walks" then
expressionAndWalkCount = expressionAndWalkCount + count
else
otherEmotesCount = otherEmotesCount + count
end
end
local totalEmotes = expressionAndWalkCount + otherEmotesCount
print("Total Expressions and Walks: ^3" .. expressionAndWalkCount .. "^0")
print("Total Emotes without Expressions and Walks: ^3" .. otherEmotesCount .. "^0")
print("Total Emotes: ^3" .. totalEmotes .. "^0")
else
local file = io.open(GetResourcePath(GetCurrentResourceName()) .. "/prop_list.lua", "w+")
if not file then
print("Failed to open file for writing.")
return
end
local uniqueProps = {}
for _, value in pairs(res.PropEmotes) do
if type(value) == "table" and value.AnimationOptions then
local prop = value.AnimationOptions.Prop
local secondProp = value.AnimationOptions.SecondProp
if prop then uniqueProps[prop] = true end
if secondProp then uniqueProps[secondProp] = true end
end
end
-- Write all unique props to file
for propName in pairs(uniqueProps) do
file:write(xt .. propName .. xt .. c .. "\n")
total = total + 1
end
file:close()
print("Exported " .. total .. " props to ^2prop_list.lua^0")
end
end
RegisterCommand("emoteextract", function(source, args)
if source > 0 then return end
ExtractEmoteProps(args[1])
end, true)

Some files were not shown because too many files have changed in this diff Show more