FiveM Emote ve Animasyon Menüleri: Rol Yapmaya Hazır Scriptler
FiveM sunucunuza zengin animasyonlar ve emotelar ekleyin. RPEmotes, Dpemotes, özel yürüyüş stilleri ve roleplay derinliği için en iyi emote menüleri.
Agency Scripts
Agency Scripts Kurucusu ve Baş Geliştiricisi
GTA V Animasyon Sözlüklerini Anlamak
GTA V içerisindeki animasyonlar, birbiriyle ilişkili animasyon kliplerinin koleksiyonu olan animasyon sözlükleri (animation dictionaries) halinde düzenlenmiştir. Her animasyon iki dize ile tanımlanır: sözlük adı ve bu sözlük içindeki animasyon adı. Örneğin sözlük amb@world_human_hang_out_street@female_hold_arm@idle_a kadın pedler için bekleme duruşu animasyonlarını içerir. Herhangi bir animasyonu oynatmadan önce, sözlüğü şu fonksiyonla istemelisiniz: RequestAnimDict ve şununla yüklenmesi tamamlanana kadar bekleyin: HasAnimDictLoaded. Öncesinde dictionary istememek, yeni geliştiricilerin en sık yaptığı hatalardan biridir ve animasyonların sessizce oynatılamamasına neden olur. GTA V, dövüş duruşlarından yoga pozlarına kadar her şeyi kapsayan binlerce animasyon dictionary'si ile birlikte gelir ve kullanışlı olanları keşfetmek, kapsamlı bir emote menüsü oluşturma sürecinin yarısını oluşturur.
Animasyonları Oynatma ve Yönetme
Animasyonları oynatmak için kullanılan temel fonksiyon şudur: TaskPlayAnim, oyuncu ped'i, dictionary, animasyon adı, blend-in hızı, blend-out hızı, süre, flag'ler ve oynatma hızını kabul eder. Animasyon flag'leri kritik davranışları kontrol eder: flag 1 animasyonu döngüye alır, flag 2 animasyonu son karede durdurur, flag 16 oyuncunun yürümesine izin vererek yalnızca üst gövdeyi oynatır ve flag 32 animasyon sırasında dönmeye izin verir. Flag'leri bit düzeyinde OR ile birleştirmek ayrıntılı davranışlar oluşturmanızı sağlar. Oturma emote'u döngü için flag 1 ve kesintiye uğrarsa son kareyi tutmak için flag 2 gerektirir. El sallama emote'u en iyi, yalnızca üst gövdeyi döngü ve dönme ile birleştiren ve oyuncunun dolaşırken el sallamasına olanak tanıyan flag 49 ile çalışır.
-- Core animation helper functions
local function LoadAnimDict(dict)
if HasAnimDictLoaded(dict) then return true end
RequestAnimDict(dict)
local timeout = GetGameTimer() + 5000
while not HasAnimDictLoaded(dict) do
Wait(10)
if GetGameTimer() > timeout then
return false
end
end
return true
end
local function PlayEmote(dict, anim, flags, duration)
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then return end
if not LoadAnimDict(dict) then return end
flags = flags or 1 -- default: loop
duration = duration or -1 -- -1 = indefinite
TaskPlayAnim(ped, dict, anim, 2.0, 2.0, duration, flags, 0, false, false, false)
end
local function StopCurrentEmote()
local ped = PlayerPedId()
ClearPedTasks(ped)
-- Also remove any attached props
ClearPedSecondaryTask(ped)
end
-- Export for other resources
exports('PlayEmote', PlayEmote)
exports('StopEmote', StopCurrentEmote)
Animasyonları Kategorilere Ayırma
İyi organize edilmiş bir emote menüsü, animasyonları oyuncuların hızla göz atabileceği sezgisel kategorilere ayırır. Yaygın kategoriler şunları içerir: Danslar, Selamlar, Tepkiler, Pozlar, Spor, Senaryolar (oturma, yaslanma veya uzanma gibi), Prop Emote'ları (sigara veya telefon gibi nesneleri içeren), Yürüyüş Stilleri, ve Yüz İfadeleri. Her emote girişi dictionary, animasyon adı, flag'ler, prop kullanıp kullanmadığı, varsa prop model hash'i, prop takma için bone index'i ve doğru prop yerleşimi için offset ve rotation değerlerini saklamalıdır. Tüm bunların yapılandırılmış bir yapılandırma tablosunda saklanması, oynatma mantığını değiştirmeden yeni emote'lar eklemeyi kolaylaştırır.
-- Emote configuration (config.lua)
Config = {}
Config.Emotes = {
dances = {
{label = 'Dance 1', dict = 'anim@amb@nightclub@dancers@club_dance_bar_1', anim = 'high_center', flags = 1},
{label = 'Dance 2', dict = 'anim@amb@nightclub@mini@dance@dance_solo@female@var_a@', anim = 'high_center', flags = 1},
{label = 'Dance 3', dict = 'anim@amb@nightclub@dancers@crowddance_facedj@', anim = 'hi_dance_facedj_09_v2_female^1', flags = 1},
{label = 'Flamenco', dict = 'special_ped@jessie@idle_latina', anim = 'idle_latina', flags = 1},
},
greetings = {
{label = 'Wave', dict = 'friends@frj@ig_1', anim = 'wave_A', flags = 49, duration = 3000},
{label = 'Salute', dict = 'anim@mp_player_intuppersalute', anim = 'idle_a', flags = 49, duration = 3000},
{label = 'Handshake', dict = 'mp_ped_interaction', anim = 'handshake_guy_a', flags = 49, duration = 4000},
{label = 'Fist Bump', dict = 'mp_ped_interaction', anim = 'fist_bump', flags = 49, duration = 3000},
},
props = {
{label = 'Cigarette', dict = 'amb@world_human_smoking@male@male_a@idle_a', anim = 'idle_c', flags = 49,
prop = 'prop_cs_ciggy_01', bone = 28422, pos = {0.0, 0.0, 0.0}, rot = {0.0, 0.0, 0.0}},
{label = 'Coffee', dict = 'amb@world_human_drinking@coffee@male@idle_a', anim = 'idle_c', flags = 49,
prop = 'p_amb_coffeecup_01', bone = 28422, pos = {0.0, 0.0, 0.0}, rot = {0.0, 0.0, 0.0}},
{label = 'Clipboard', dict = 'amb@world_human_clipboard@male@idle_a', anim = 'idle_c', flags = 49,
prop = 'p_amb_clipboard_01', bone = 36029, pos = {0.16, 0.08, 0.03}, rot = {-100.0, 0.0, 0.0}},
},
scenarios = {
{label = 'Sit Chair', scenario = 'PROP_HUMAN_SEAT_CHAIR', isScenario = true},
{label = 'Lean Wall', scenario = 'WORLD_HUMAN_LEANING', isScenario = true},
{label = 'Guard', scenario = 'WORLD_HUMAN_GUARD_STAND', isScenario = true},
{label = 'Jog', scenario = 'WORLD_HUMAN_JOG_STANDING', isScenario = true},
},
}
Prop Emote'ları ve Nesne Bağlama
Prop emote'ları, bir oyun nesnesi oluşturmayı ve bunu oyuncunun ped'i üzerindeki belirli bir kemiğe bağlamayı içerir. GTA V, her kemiğin benzersiz bir dizine sahip olduğu bir iskelet kemik sistemine sahiptir. Yaygın bağlantı kemikleri şunları içerir: 57005 sağ el için, 18905 sol el için, 28422 sağ parmak bölgesi için (sigaralar için ideal) ve 31086 kafa için. Prop'u şununla oluşturduktan sonra: CreateObject, şunu kullanarak bağlayın: AttachEntityToEntity bu da prop entity, ped entity, bone index, pozisyon ofsetleri, rotasyon ofsetleri ile çarpışma ve fizik davranışı için birkaç boolean flag gerektirir. Pozisyon ve rotasyon ofsetlerini doğru ayarlamak deneme yanılma gerektirir ve farklı ped modelleri küçük ayarlamalar gerektirebilir. Emote iptal edildiğinde oluşturulan entity handle değerini takip edip silerek propları her zaman temizleyin.
-- Prop emote system
local currentProp = nil
local function PlayPropEmote(emoteData)
local ped = PlayerPedId()
if IsPedInAnyVehicle(ped, false) then return end
-- Clean up any existing prop
if currentProp and DoesEntityExist(currentProp) then
DeleteEntity(currentProp)
currentProp = nil
end
if not LoadAnimDict(emoteData.dict) then return end
-- Spawn and attach prop
local model = GetHashKey(emoteData.prop)
RequestModel(model)
while not HasModelLoaded(model) do Wait(10) end
local pos = GetEntityCoords(ped)
currentProp = CreateObject(model, pos.x, pos.y, pos.z, true, true, false)
SetModelAsNoLongerNeeded(model)
local boneIndex = GetPedBoneIndex(ped, emoteData.bone)
AttachEntityToEntity(
currentProp, ped, boneIndex,
emoteData.pos[1], emoteData.pos[2], emoteData.pos[3],
emoteData.rot[1], emoteData.rot[2], emoteData.rot[3],
true, true, false, true, 1, true
)
-- Play animation
TaskPlayAnim(ped, emoteData.dict, emoteData.anim,
2.0, 2.0, -1, emoteData.flags or 49, 0, false, false, false)
end
-- Cleanup on emote cancel
local function CleanupProps()
if currentProp and DoesEntityExist(currentProp) then
DeleteEntity(currentProp)
currentProp = nil
end
end
Yürüyüş Stilleri ve Hareket Klipleri
Yürüyüş stilleri oyuncu karakterinin nasıl hareket ettiğini değiştirir ve şu kullanılarak uygulanır: SetPedMovementClipset. Eylemleri geçersiz kılan normal animasyonların aksine, hareket clipset'leri yürüme, koşma ve depar atma dahil tüm hareket durumlarında kalıcıdır. GTA V, şunlar gibi onlarca yerleşik hareket clipset'i içerir: MOVE_M@DRUNK@MODERATEDRUNK sarhoş sendelemesi için, MOVE_M@GANGSTER@NG gangster yürüyüşü için, MOVE_M@CONFIDENT kendinden emin bir yürüyüş için ve MOVE_F@HEELS@C yüksek topuklu ayakkabılarla yürümek için. Animasyon sözlükleri gibi, clipset'ler de uygulanmadan önce talep edilmeli ve yüklenmelidir. Oyuncuların varsayılan yürüyüşe dönebilmesi için bir sıfırlama seçeneği sunun. Oyuncunun tercih ettiği yürüyüş stilini oturumlar arasında korunması için karakter verilerinde saklayın ve giriş yaptıklarında otomatik olarak yeniden uygulayın.
-- Walking style system
local currentWalkStyle = nil
Config.WalkStyles = {
{label = 'Default', clipset = nil},
{label = 'Drunk', clipset = 'MOVE_M@DRUNK@MODERATEDRUNK'},
{label = 'Gangster', clipset = 'MOVE_M@GANGSTER@NG'},
{label = 'Confident', clipset = 'MOVE_M@CONFIDENT'},
{label = 'Tough', clipset = 'MOVE_M@TOUGH_GUY@'},
{label = 'Femme', clipset = 'MOVE_F@FEMME@'},
{label = 'Heels', clipset = 'MOVE_F@HEELS@C'},
{label = 'Injured', clipset = 'move_m@injured'},
{label = 'Hobo', clipset = 'MOVE_M@HOBO@A'},
{label = 'Brave', clipset = 'MOVE_M@BRAVE@A'},
}
local function SetWalkStyle(clipset)
local ped = PlayerPedId()
ResetPedMovementClipset(ped, 0.2)
if not clipset then
currentWalkStyle = nil
return
end
RequestClipSet(clipset)
local timeout = GetGameTimer() + 3000
while not HasClipSetLoaded(clipset) do
Wait(10)
if GetGameTimer() > timeout then return end
end
SetPedMovementClipset(ped, clipset, 0.2)
currentWalkStyle = clipset
end
exports('SetWalkStyle', SetWalkStyle)
exports('GetWalkStyle', function() return currentWalkStyle end)
Yüz İfadeleri
Yüz ifadeleri, roleplay etkileşimlerine ince bir duygusal derinlik katar. GTA V, yüz animasyonlarını şu yolla destekler: SetFacialIdleAnimOverride, ped'in dinlenme anındaki yüz ifadesini değiştirir. Kullanılabilir ifadeler şunları içerir: mood_normal_1, mood_happy_1, mood_angry_1, mood_injured_1, mood_stressed_1, mood_smug_1, ve mood_sulk_1 ve diğerleri. Bu ifadeler şununla temizlenene kadar geçerliliğini korur: ClearFacialIdleAnimOverride. Bir yüz ifadesini vücut animasyonu ve yürüme tarzıyla birleştirmek, oyunculara karakterlerinin kendilerini nasıl sunduğu konusunda tam kontrol sağlar. Kendini beğenmiş bir ifade ve kendinden emin bir yürüyüşle duvara yaslanan bir karakter, yaralı şekilde topallayan ve stresli bir yüze sahip olan bir karaktere kıyasla tamamen farklı bir hikaye anlatır. Bu küçük detaylar, roleplay deneyimini basit etkileşimlerden zengin bir karakter tasvirine yükseltir.
-- Facial expression system
local currentExpression = nil
Config.Expressions = {
{label = 'Normal', expression = 'mood_Normal_1'},
{label = 'Happy', expression = 'mood_Happy_1'},
{label = 'Angry', expression = 'mood_Angry_1'},
{label = 'Injured', expression = 'mood_Injured_1'},
{label = 'Stressed', expression = 'mood_Stressed_1'},
{label = 'Smug', expression = 'mood_smug_1'},
{label = 'Sulking', expression = 'mood_sulk_1'},
{label = 'Sleeping', expression = 'pose_injured_1'},
{label = 'Scared', expression = 'mood_scared_1'},
}
local function SetExpression(expression)
local ped = PlayerPedId()
ClearFacialIdleAnimOverride(ped)
if expression then
SetFacialIdleAnimOverride(ped, expression, nil)
currentExpression = expression
else
currentExpression = nil
end
end
exports('SetExpression', SetExpression)
-- Shared emotes: sync with nearby players
RegisterNetEvent('emote:syncShared', function(senderId, dict, anim)
local senderPed = GetPlayerPed(GetPlayerFromServerId(senderId))
if not DoesEntityExist(senderPed) then return end
local myPed = PlayerPedId()
local dist = #(GetEntityCoords(myPed) - GetEntityCoords(senderPed))
if dist > 3.0 then return end
if not LoadAnimDict(dict) then return end
TaskPlayAnim(myPed, dict, anim, 2.0, 2.0, -1, 1, 0, false, false, false)
end)
Emote Menüsü Arayüzünü Geliştirme
Emote menüsü, NUI tabanlı bir radial menü veya ox_lib ya da qb-menu gibi bir kütüphane kullanan oyun içi bir menü olarak uygulanabilir. Radial menü animasyonlar için doğal hissettirir, çünkü oyuncular uzun metin listelerini okumak zorunda kalmadan kategoriler arasında hızla gezinebilir ve bir animasyon seçebilir. Menüyü şu şekilde bir tuşa atayın: F4 veya yapılandırılabilir bir tuş ataması ve şu şekilde bir komut yedeği sağlayın: /emote [name] doğrudan erişim içindir. Menü, emote adını, isteğe bağlı bir önizleme küçük resmini göstermeli ve hangi emote'ların prop kullandığını belirtmelidir. Oyuncuların en sık kullandıkları emote'ları hızlı erişim çarkına sabitlemelerine olanak tanıyan bir favoriler sistemi ekleyin; böylece yaygın bir eylemi gerçekleştirmek istedikleri her seferinde kategorilere göz atmak zorunda kalmazlar. Favorileri oyuncunun KVP depolamasında şununla kalıcı hale getirin: SetResourceKvp böylece veritabanı yazma işlemlerine gerek kalmadan sunucu yeniden başlatmalarından sonra da korunurlar. İyi yapılandırılmış bir emote menüsü, herhangi bir roleplay sunucusunda en çok kullanılan özelliklerden biri haline gelir; bu nedenle arayüze zaman ayırmak oyuncu memnuniyeti olarak geri döner.