İçeriğe geç
Porting from FiveM

Porting a FiveM resource to RedM

What changes when a FiveM resource moves to RedM, in the order you hit it: the game key, natives by hash, controls, peds and outfits, prompts, blips and game data.

Bu dokümanlar şimdilik İngilizce.

Last updated

The platform is shared, the game is not. Server code usually moves over untouched; client code that calls natives is rewritten. This is the order people run into the changes.

1. The game key

A resource declares the games it runs on, and one with only game 'gta5' does not start on an rdr3 server. Change the manifest:

fxmanifest.lua
fx_version 'cerulean'
game 'rdr3'
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'

Use games { 'gta5', 'rdr3' } instead if the same code is meant to run on both. The rdr3_warning line has to be word for word, see The fxmanifest.

2. Natives: a different set, often called by hash

GTA V and RDR2 natives do not match by name or by hash. A GTA V native that RDR2 does not have fails the first time that line runs. Many RDR2 natives have no settled name yet, so RedM scripts call them as Citizen.InvokeNative with the hash, and write the name in a comment:

client.lua
-- SET_BLIP_SCALE (0xD38744167B2FA257)
Citizen.InvokeNative(0xD38744167B2FA257, blip, 0.2)

When a native returns something, tell InvokeNative what to read back, the same way the Prompt Builder output does it:

client.lua
local N = Citizen.InvokeNative
local p = N(0x04F97DE45A519419, Citizen.ResultAsInteger()) -- _UI_PROMPT_REGISTER_BEGIN

Go through the client files native by native. Some common ones keep their name on RedM (PlayerPedId, GetEntityCoords, RequestModel, IsControlJustPressed, all used in the code our RedM tools write); everything else needs its RDR2 equivalent looked up, not guessed.

3. Controls are hashes

On GTA V IsControlJustPressed(0, 38) is the pickup key. On RDR2 a control is the joaat hash of its INPUT_ name:

Control Hash
INPUT_JUMP 0xD9D0E1C0
INPUT_ENTER 0xCEFD9220
client.lua
if IsControlJustPressed(0, 0xCEFD9220) then -- INPUT_ENTER
end

Every input action of the game is listed on RedM Assets under Controls, and the Hash Calculator turns any INPUT_ name into its hash.

4. Peds need an outfit

A ped spawned from a model with nothing else done to it is invisible on RDR2. Every ped spawn in a port needs an outfit call after it:

client.lua
local model = joaat("a_c_horse_arabian_white")
RequestModel(model)
while not HasModelLoaded(model) do Wait(0) end
local ped = CreatePed(model, x, y, z, heading, true, false, false, false)
-- _SET_RANDOM_OUTFIT_VARIATION: a RedM ped with no outfit is invisible
Citizen.InvokeNative(0x283978A15512B2FE, ped, true)
SetModelAsNoLongerNeeded(model)

CreatePed has no ped type argument first, unlike GTA V. A horse is a ped model, so this is also how a horse is spawned.

5. “Press E” becomes a prompt

FiveM scripts usually show a help text box (“Press INPUT_CONTEXT to open”) and check a key every frame. RDR2’s own way is a prompt: the key and label in the corner of the screen, with press, release, hold and mash modes and the game’s own hold timings, grouped under a title.

A prompt is created once, shown with _UI_PROMPT_SET_ACTIVE_GROUP_THIS_FRAME every frame while the player is near, and checked with the _UI_PROMPT_HAS_..._COMPLETED natives. Every one of those is a call by hash, so there is no reason to write it by hand: the Prompt Builder writes the whole resource for you, with a zone check around a point.

6. Blips are created from a style

A GTA V blip is a sprite number and a colour number. An RDR2 blip is created from a blip style, a hash that decides the icon, colour and label, and the icon can then be swapped for a sprite, also by hash:

client.lua
-- BLIP_ADD_FOR_COORDS (0x554D9D53F696D002): the style decides the icon, colour and label
local blip = Citizen.InvokeNative(0x554D9D53F696D002, joaat("BLIP_STYLE_PICKUP_WEAPON"), x, y, z)
-- SET_BLIP_SPRITE (0x74F74D3207ED525C): another icon than the style's own
Citizen.InvokeNative(0x74F74D3207ED525C, blip, joaat("blip_shop_store"), true)
-- _SET_BLIP_NAME (0x9CB1A1623062F402)
Citizen.InvokeNative(0x9CB1A1623062F402, blip, "General Store")

The GTA V sprite and colour numbers mean nothing here. Pick styles on Blip Styles and place blips with the Blip Placer, which writes this code for a whole list of points.

7. Game data is new

Ped, horse, weapon, vehicle and prop names, scenarios, timecycles, weathers, zones, interiors and text labels all come from RDR2. None of the GTA V lists apply. Replace every model name, weapon name, coordinate and text label in the port:

What carries over unchanged

Server side code, NUI pages, events, state bags, convars, exports, ACE and database code work the same, because that part is the Cfx.re platform, not the game. A server file that only handles events and talks to the database often needs no change at all.

A porting checklist

  1. Manifest: game 'rdr3' (or games), the warning line, fx_version cerulean.
  2. Every client native: find its RDR2 equivalent, call it by hash where it has no name, comment the name.
  3. Every control number: replace with the INPUT_ hash.
  4. Every CreatePed: new argument list, plus an outfit call.
  5. Every help text interaction: a prompt.
  6. Every blip: a style hash and a sprite hash.
  7. Every model, weapon, coordinate and label: an RDR2 one.
  8. Drop the resource on the Resource Conflict Checker with the rest of your server to catch manifest mistakes before you restart.