Skip to content

The Partner Pose Editor ​

VORP

A duo pose is two separate animations played on two separate characters. RedM has no reliable synchronised scene natives on this build, so the second character is not bound to the first — it is placed, by a set of four numbers on the pose. Get those numbers slightly wrong and a couple dances a hand's width apart, or a bow lands behind someone's shoulder.

The pose editor is the tool for getting them right. It moves the partner on screen a step at a time, shows the four numbers as you change them, and writes them where every player will pick them up.

Commandpartneredit, from the F8 console
NeedsThe selection screen, on a character that has a partner
Editsattach = vector4(right, forward, up, heading) on one duo pose
Saves topartner_poses.json, in the resource folder
PermissionConfigSelector.Partner.editor — a VORP group or an ace

Opening it ​

  1. Open the character selection screen on a character that has a partner. The partner has to be visible beside them — the editor checks for the partner ped, not only the pairing.

  2. Open the F8 console and type partneredit.

  3. Close F8. The selection menu hides itself, keyboard focus leaves the page, and the editor's readout appears in the top left.

It opens on whichever duo pose that character is already showing, so you can cycle to the pose you want to fix with E before you start.

The command toggles

Typing partneredit again closes the editor, which is the way out if the keyboard will not cooperate. Backspace does the same thing.

The keys ​

They are read as controls and as raw Windows key codes, so they work whether or not a panel holds focus. While the editor is open every game control is disabled — nothing you press reaches the character, the menu or the game.

Moving the partner ​

KeyDoesStep
Arrow keysMove the partner, as seen on screen0.02 m
PgUp / PgDnRaise / lower the partner0.02 m
Q / ETurn the partner2.0 degrees
Shift (hold)Small steps0.005 m, 0.5 degrees

Hold a key for 350 ms and it starts repeating every 60 ms, which covers a long move without hammering the key. Tapping is how you place the last centimetre.

The arrows are screen-relative, not character-relative

Right means right as you are looking at it, worked out from the rendered camera every time you press. So swinging the camera with A / D changes what the arrows do — and a side-on view is much better than a head-on one for judging how far apart two people are standing.

Moving the camera ​

KeyDoesRate
A / DSwing the camera around the middle of the pair60 degrees a second
W / SCloser / further1.5 m a second
Shift (hold)A quarter speed on both

The camera orbits the midpoint between the two characters and keeps its tilt, so it stays aimed at the pair as it travels. Distance is clamped between 0.6 m and 12.0 m.

Poses, saving, closing ​

KeyDoes
Z / XPrevious / next pose in this character's list
EnterSave this pose
RUndo to the last save
BackspaceClose, dropping anything unsaved

Z and X walk the whole list for the pairing type — all 8 lover poses or all 12 friend ones, unfiltered, including any marked as needing a prop. The list wraps at both ends.

R reverts the pose on screen to its last save. For a pose that has never been saved with the editor, that means back to the numbers in animations.lua.

A key you were already holding is ignored until you let go

The editor records which of its keys are down at the moment it opens and refuses them until they are released. If you held Enter to close the F8 console, Enter does nothing until you lift it.

The readout ​

Five lines in the top left, above the key hints:

text
PARTNER POSE EDITOR
Pose 6 / 12:  Fancy bow   (friend)
Right -0.003    Forward 2.260    Up 0.000    Turn 180.0
NOT SAVED  -  press Enter to save

Right, Forward, Up and Turn are the four components of attach, in that order and in the same units you would write in animations.lua. The fourth line is either a green Saved or an orange NOT SAVED, compared against what is actually on disk rather than against what you last pressed.

The pose restarts itself as you nudge

Moving a ped in RedM cancels whatever task it is running, so every nudge would stop the animation. The editor replays the pose 400 ms after your last keypress instead of on every step, and holds the camera still while it does — otherwise each replay would re-frame the shot under you. Picking a different pose with Z / X lets the framing through once.

What a save does ​

Enter sends the pose's kind, its label and the four numbers to the server. The server re-checks your permission, confirms the label exists in ConfigSelector.Partner.animations, range-checks the numbers, rounds the three distances to three decimals and the heading to one, wraps the heading into 0–360, and then does four things:

  • Writes partner_poses.json in the resource folder. The file does not ship; the first save creates it.
  • Sends the new numbers to every connected player at once. No restart, no resource reload.
  • Takes precedence over the attach in animations.lua from that moment on. This is the part worth reading the next section about.
  • Prints the pasteable line in your F8 console, so you can move the value into animations.lua by hand if you would rather keep it in config:
text
[vorp_character:poseeditor] saved Fancy bow: attach = vector4(-0.003, 2.260, 0.000, 180.0)

The server console gets its own line naming who saved what, which is the audit trail if two people are tuning poses on the same server:

text
[vorp_character:poseeditor] Hosea saved friend / Fancy bow -> -0.003, 2.260, 0.000, 180.0

Each pose is saved separately. Z and X move you to the next pose without saving the one you were on, and the readout is the only thing telling you so.

When a save is refused ​

Console messageMeans
you are not allowed to use the pose editorYour group and ace both failed, re-checked on every save
unknown poseNo pose with that label in the list for that kind
bad numbersOne of the four values was not a number
numbers out of rangeOver 5 m right or forward, or 3 m up
could not write partner_poses.jsonThe resource folder is not writable

The range limits are a guard, not a working constraint — 0.02 m steps cannot reach 5 m in a session, so they only trip on a hand-edited file or a tampered client.

Precedence: partner_poses.json beats animations.lua ​

This is the single thing most likely to waste an afternoon. Once a duo pose has been saved with the editor, editing its attach in animations.lua changes nothing.

Here is why. One second after the resource starts, each client asks the server for the file and writes every saved value straight into the pose table in memory — setting attach and clearing sharedOrigin. From then on the pose behaves exactly as though those numbers had always been in animations.lua. Your edited file is still read at startup; it is overwritten a moment later for any pose the JSON names.

When at least one pose is replaced, your F8 console says so on connect:

text
[vorp_character:poseeditor] 3 duo pose(s) set with the pose editor

That line is how you tell whether the file is in play before you go looking for a bug in config.

The full order ​

Where the partner stands is resolved like this, highest first:

  1. A matching entry in partner_poses.json, found by pairing type and the pose's label.

  2. sharedOrigin = true on the pose, which puts both characters on the same point with the same heading, for clips that carry their own baked movement.

  3. attach on the pose entry in animations.lua.

  4. The flat form — offsetX, offsetY, deltaZ, headingOffset — accepted as an alternative to attach on the same entry.

  5. ConfigSelector.Partner.attach for that pairing type, the defaults being vector4(0.0, 0.60, 0.0, 180.0) for lover and vector4(0.0, 1.05, 0.0, 180.0) for friend.

A saved value also clears sharedOrigin, so the editor can pull a shared-origin pose apart. That is deliberate, and it is one-way — step 2 cannot win back.

The file ​

json
{
  "lover": {
    "Standing together": [-0.021, 0.767, 0.0, 168.0]
  },
  "friend": {
    "Fancy bow": [-0.003, 2.26, 0.0, 180.0],
    "Campfire": [1.0, 0.0, 0.0, 0.0]
  }
}

Two keys, lover and friend, each holding poses by label, each pose holding [right, forward, up, heading].

The label is the key, so renaming a pose orphans its saved numbers

Change label = "Fancy bow" to anything else in animations.lua and the saved entry no longer matches anything. It is skipped in silence — no warning, and the pose quietly falls back to whatever attach is written in config.

Going back to config ​

To hand a pose back to animations.lua, delete that pose's entry from partner_poses.json — or delete the whole file to hand back all of them — and restart the resource. Clients read the file once at startup, so a file change on its own does not reach anyone already connected.

The tidier route, if you want your poses in version control rather than in a JSON file the next update might not preserve, is the pasteable line each save prints: copy it into the pose's entry in animations.lua, then remove the pose from partner_poses.json. Same numbers, one source of truth.

Back the file up before an update

partner_poses.json lives inside the resource folder, which is the folder you replace when you update. It is on the same list as your config files — see Installation.

Height is sometimes the clip's fault, not the pose's ​

PgUp and PgDn write into that one pose's attach.z. That is the right fix when one pose sits a little low and everything else is fine.

It is the wrong fix when a particular clip floats everywhere it is used, because the clip was authored above its set's floor and brings that height with it. Those belong in ConfigSelector.Partner.clipOffsets, keyed by the exact clip name or by the dictionary, where a positive value lowers the ped:

lua
clipOffsets = {
    ["KIT_EMOTE_GREET_FANCY_BOW_1"] = 0.128,
    ["MP_LOBBY_SCENARIO_06"]        = 0.116,
}

Those two ship. To find the number for a third, set ConfigSelector.Debug = true, show the pose, and read the console — it prints how far off the ground the partner settled and tells you to add it to clipOffsets. The correction then applies wherever that clip appears, instead of once per pose.

Scenario poses cannot have this problem

The engine places and grounds a scenario itself. If a duo pose keeps fighting you on height, the quickest answer is often a scenario pose from the same list — the reasoning is on Emote library.

Permissions ​

lua
-- config_selector.lua
ConfigSelector.Partner.editor = {
    enabled = true,
    command = "partneredit",
    groups  = { "admin" },
    ace     = "command",
}
KeyDefaultDoes
enabledtruefalse and the command is never registered at all
command"partneredit"The console command
groups{ "admin" }VORP groups allowed to use it
ace"command"An ace that also passes. false for groups only

Either check is enough. The VORP group comes from the character the player is using, read through vorp_core, so a player's access can change with the character they have loaded. See VORP framework for how groups are set.

The default ace is "command" because that is the blanket command ace txAdmin grants its admins — convenient, and it means the editor works out of the box for anyone who already administers the server from txAdmin. It is also broad. If you want to hand the editor to a builder who should not hold every command ace, name your own:

lua
ace = "vorp_character.partneredit",
cfg
add_ace group.builder vorp_character.partneredit allow

Both ends are checked

Permission is verified on the server when the editor opens and again on every save, along with the pose name and the numbers. A client that skips the open check still cannot write anything.

Troubleshooting ​

It says you are not allowed ​

text
[vorp_character:poseeditor] you are not allowed to use the pose editor
  1. Is your character's group one of Partner.editor.groups? The default list is admin only.

  2. If you are relying on the ace, is there an add_principal putting you in the group that holds it? This is the usual answer.

  3. Does the ace name in server.cfg match Partner.editor.ace?

  4. Did you switch characters? The group is read from the character in use.

partneredit is an unknown command ​

The command is only registered when editor.enabled is true and editor.command is set. Check both, then check you are looking at the right name — command is yours to rename, and a renamed command means the old one genuinely does not exist.

If neither is it, the resource did not start. The server console on start will say why.

The editor will not open ​

Console messageMeans
open the character selector firstYou are in the world, not on the selection screen
the character on screen has no partnerThe pairing is missing, or the partner ped is not there
Partner.sync is off, so duo poses are not usedConfigSelector.Partner.sync = false
no duo poses for loverThat list in Partner.animations is empty
already openIt is already running; Backspace or the command closes it

The sync one catches people out. With sync = false the partner does not share a pose at all — it stands on its own mark from ConfigSelector.Partner.freeOffset and cycles its own solo poses, so there is no duo pose to line up. Set sync = true to use the editor. Pairing itself is covered on Partner system.

Nothing happens when I press a key ​

  1. Is F8 still open? The console eats the keyboard. Close it.

  2. Were you holding that key when the editor opened? It is blocked until you release it.

  3. Is the readout on screen at all? No readout means the editor is not open and the keys are going to the selection menu.

  4. Is the number on the readout changing but the partner not appearing to move? Swing the camera side-on with A / D. A head-on view hides forward and back almost completely.

My changes vanished when I closed ​

Expected. Backspace reverts every pose you touched back to its last saved numbers and tells you how many it threw away:

text
[vorp_character:poseeditor] closed, 2 unsaved change(s) dropped

Enter saves one pose — the one on screen. Tune four poses, press Enter once, and the other three are gone on close. The orange NOT SAVED line is the warning; it is accurate, and it is checked against the file rather than against your keystrokes.

The same revert runs if the character or the partner disappears while you are editing, in which case the console names that as the reason.

Saved numbers stopped applying ​

CauseFix
The pose's label was renamed in animations.luaRename it back, or re-save the pose
The pose was deleted from animations.luaThe saved entry has nothing to attach to
partner_poses.json is not valid JSONThe server prints is not valid JSON, ignoring it and ignores the whole file
The file was lost in an updateRestore it from your backup, or re-save

A hand-edited file is the usual reason for the third row, and because one bad character disables every pose in the file, the symptom is all of your poses reverting at once rather than one.

Changes do not show for a player already on the screen ​

The numbers arrive immediately — the pose picks them up the next time it is applied, which is the next time that player cycles poses, changes character, or reopens the screen. Nobody needs to reconnect and nothing needs restarting.


Related: Partner system · Poses · Configuration · Emote library · Troubleshooting

Still stuck? Ask in Discord with your F8 output, your ConfigSelector.Partner.editor block, and the contents of partner_poses.json.

Documentation for RedMorrow. Scripts are licensed per server — redistribution is not permitted.