FiveM-Emote- und Animationsmenüs: Skripte für Rollenspiel
Ergänze deinen FiveM-Server um vielfältige Emotes und Animationen. RPEmotes, Dpemotes, individuelle Gangarten und beliebte Menüs für ein intensives Rollenspiel.
Agency Scripts
Gründer und leitender Entwickler bei Agency Scripts
Animations-Dictionaries in GTA V verstehen
Animationen in GTA V sind in Animations-Dictionaries organisiert, also Sammlungen zusammengehöriger Animationsclips. Jede Animation wird durch zwei Zeichenfolgen identifiziert: den Namen des Dictionaries und den Animationsnamen innerhalb dieses Dictionaries. Das Dictionary amb@world_human_hang_out_street@female_hold_arm@idle_a enthält Stand-Animationen für weibliche Peds. Bevor du eine Animation abspielen kannst, musst du das Dictionary mit RequestAnimDict anfordern und warten, bis es mit HasAnimDictLoadedvollständig geladen wurde. Das Dictionary nicht zuerst anzufordern, ist einer der häufigsten Fehler neuer Entwickler und führt dazu, dass Animationen unbemerkt nicht abgespielt werden. GTA V enthält Tausende von Animations-Dictionaries für alles von Kampfhaltungen bis hin zu Yoga-Posen. Nützliche Dictionaries zu entdecken, ist bereits die halbe Arbeit beim Aufbau eines umfassenden Emote-Menüs.
Animationen abspielen und verwalten
Die zentrale Funktion zum Abspielen von Animationen ist TaskPlayAnim; sie benötigt das Player-Ped, das Dictionary, den Animationsnamen, die Einblendgeschwindigkeit, die Ausblendgeschwindigkeit, die Dauer, Flags und die Wiedergabegeschwindigkeit. Die Animations-Flags steuern wichtige Verhaltensweisen: Flag 1 lässt die Animation in einer Schleife ablaufen, Flag 2 stoppt sie beim letzten Frame, Flag 16 spielt nur den Oberkörper ab und ermöglicht dem Spieler, sich zu bewegen, und Flag 32 erlaubt Drehungen während der Animation. Durch die Kombination von Flags mit bitweisem OR lassen sich differenzierte Verhaltensweisen erstellen. Ein Sitz-Emote benötigt Flag 1 für die Schleife und zusätzlich Flag 2, damit beim Unterbrechen der letzte Frame gehalten wird. Für ein Winke-Emote eignet sich Flag 49 am besten. Es kombiniert die Wiedergabe nur mit dem Oberkörper mit Schleife und Drehungen, sodass der Spieler beim Herumlaufen winken kann.
-- 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)
Emotes in Kategorien organisieren
Ein übersichtlich organisiertes Emote-Menü gruppiert Animationen in intuitive Kategorien, die Spieler schnell durchsuchen können. Zu den gängigen Kategorien gehören Tänze, Begrüßungen, Reaktionen, Posen, Sport, Szenarien (wie Sitzen, Anlehnen oder Liegen), Prop-Emotes (mit Objekten wie Zigaretten oder Handys), Gehstile , und Gesichtsausdrücke. Jeder Emote-Eintrag sollte das Dictionary, den Animationsnamen, die Flags, die Angabe, ob ein Prop verwendet wird, den Prop-Modell-Hash, falls zutreffend, den Bone-Index für die Prop-Befestigung sowie die Positions- und Rotationswerte für die korrekte Platzierung des Props speichern. Wenn du all das in einer strukturierten Konfigurationstabelle speicherst, kannst du neue Emotes hinzufügen, ohne die Wiedergabelogik zu ändern.
-- 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-Emotes und Objektbefestigung
Bei Prop-Emotes wird ein Spielobjekt erstellt und an einem bestimmten Bone des Spieler-Peds befestigt. GTA V verfügt über ein Skelett-Bone-System, bei dem jeder Bone einen eindeutigen Index hat. Zu den gängigen Befestigungs-Bones gehören 57005 für die rechte Hand, 18905 für die linke Hand, 28422 für den rechten Fingerbereich (ideal für Zigaretten) und 31086 für den Kopf. Nachdem du das Prop mit CreateObjecterstellt hast, befestigst du es mit AttachEntityToEntity Dafür brauchst du die Prop-Entity, die Ped-Entity, den Bone-Index, Positions-Offsets, Rotations-Offsets und mehrere boolesche Flags für das Kollisions- und Physikverhalten. Die richtigen Positions- und Rotations-Offsets zu finden, erfordert Ausprobieren, und bei verschiedenen Ped-Modellen können leichte Anpassungen nötig sein. Räume Props immer auf, wenn ein Emote abgebrochen wird. Verfolge dazu den Handle der erstellten Entity und lösche sie.
-- 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
Gehstile und Bewegungs-Clipsets
Gehstile ändern, wie sich der Spielercharakter bewegt, und werden mit SetPedMovementClipsetangewendet. Im Gegensatz zu normalen Animationen, die Aktionen überschreiben, bleiben Bewegungs-Clipsets in allen Bewegungszuständen aktiv, einschließlich Gehen, Rennen und Sprinten. GTA V enthält Dutzende integrierte Bewegungs-Clipsets, zum Beispiel MOVE_M@DRUNK@MODERATEDRUNK für einen betrunkenen Taumelgang, MOVE_M@GANGSTER@NG für einen Gangster-Gang, MOVE_M@CONFIDENT für einen selbstbewussten Schritt und MOVE_F@HEELS@C für das Gehen in High Heels. Wie Animations-Dictionaries müssen Clipsets vor ihrer Anwendung angefordert und geladen werden. Biete eine Zurücksetzen-Option an, damit Spieler zum Standardgang zurückkehren können. Speichere den bevorzugten Gehstil des Spielers in den Charakterdaten, damit er sitzungsübergreifend erhalten bleibt, und wende ihn beim Einloggen automatisch erneut an.
-- 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)
Gesichtsausdrücke
Gesichtsausdrücke verleihen Roleplay-Interaktionen eine subtile emotionale Tiefe. GTA V unterstützt Gesichtsanimationen über SetFacialIdleAnimOverridewodurch sich der ruhende Gesichtsausdruck des Peds ändert. Zu den verfügbaren Ausdrücken gehören unter anderem mood_normal_1, mood_happy_1, mood_angry_1, mood_injured_1, mood_stressed_1, mood_smug_1 , und mood_sulk_1 . Diese Ausdrücke bleiben aktiv, bis sie mit ClearFacialIdleAnimOverridezurückgesetzt werden. Wenn du einen Gesichtsausdruck mit einer Körperanimation und einem Gehstil kombinierst, können Spieler vollständig kontrollieren, wie ihr Charakter wirkt. Ein Charakter, der sich mit einem selbstgefälligen Gesichtsausdruck an eine Wand lehnt und selbstbewusst geht, erzählt eine völlig andere Geschichte als einer mit einem verletzungsbedingten Hinken und einem gestressten Gesicht. Diese kleinen Details heben Roleplay von einfachen Interaktionen zu einer ausdrucksstarken Charakterdarstellung.
-- 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)
Das Emote-Menü-Interface erstellen
Das Emote-Menü lässt sich entweder als NUI-basiertes Radialmenü oder als In-Game-Menü mit einer Bibliothek wie ox_lib oder qb-menu implementieren. Ein Radialmenü eignet sich für Emotes besonders gut, weil Spieler schnell durch Kategorien navigieren und ein Emote auswählen können, ohne lange Textlisten durchzugehen. Weise dem Menü eine Taste wie F4 oder einen konfigurierbaren Keybind zu und biete als direkten Zugriff einen alternativen Befehl wie /emote [name] an. Das Menü sollte den Emote-Namen, optional ein Vorschaubild und einen Hinweis darauf anzeigen, welche Emotes Props verwenden. Mit einem Favoritensystem können Spieler ihre meistgenutzten Emotes in einem Schnellzugriffsring ablegen, sodass sie nicht jedes Mal Kategorien durchsuchen müssen, wenn sie eine häufige Aktion ausführen möchten. Speichere Favoriten im KVP-Speicher des Spielers mit SetResourceKvp damit sie Serverneustarts überstehen, ohne Datenbankabfragen zu benötigen. Ein gut gestaltetes Emote-Menü wird zu einer der meistgenutzten Funktionen auf jedem Roleplay-Server. Die Zeit, die du in das Interface investierst, zahlt sich daher durch höhere Spielerzufriedenheit aus.