# Unreal routers (Fusion's Unreal kit)

The Unreal kit is a UE4SS mod (a Rust DLL, a little C++, Lua) that Fusion's one-click setup puts
in the game. It works on Unreal 4.12 to 5.x, Direct3D 11 and 12. From Unreal's conventions it
already does, with no router code:
- the player is player controller 0's pawn; it opens `bind.map` from the main menu and waits for
  the world (and World Partition) to load; picks Fusion's origin on open ground;
- draws the world from Fusion's camera with depth (scene captures), and hides the game's own view;
- traces collision around Fusion's camera (if a block gives `collision`);
- lists characters near Fusion's camera (if a block gives `entities`), spawns, removes, sets
  health, moves and stops NPCs; teleports the player;
- plays as the game's own character (a `character` block that needs `input`): Fusion's keys and
  mouse go through Unreal's own movement, and Fusion's camera follows its eyes;
- keeps the game running when it isn't the window in front.

Don't redo any of that in Lua. A router lists only what's particular to the game.

## Data: `[block.bind]` on the world block

```toml
[block.bind]
map = "/Game/Maps/Town"          # opened from the main menu; the name alone also matches
player = "BP_Hero_C"             # the game is in its world once the player is one
player_follows_camera = true     # World Partition games load around the player
```

## Data: NPCs, on a block that gives `entities`

One rule per kind; other characters are listed as "character".

```toml
[[block.bind.entity]]
class = "BP_Zombie_C"            # exact class; or is_a = "/Script/Game.BaseEnemy" for subclasses
kind = "zombie"
name = "Zombie"
health = "Health.Health"         # field paths from the actor
max_health = "Health.MaxHealth"
team = 2
spawn = "/Game/Zombies/BP_Zombie"  # what Fusion's Spawn makes for this kind
```

Find names by asking the running game (Fusion closed): `fusion-cli game find zombie --game-id <id>`
gives classes and objects; `fusion-cli game inspect <object> --game-id <id>` lists its fields. An
`Object` field's value is another object: inspect it to build a path such as `Health.Health`.
Router Studio does the same with clicks (F4 in Fusion).

## Playing as the game's character

```toml
[[block]]
id = "mygame.player"
name = "My Game's Hero"
kind = "character"
needs = ["input"]
gives = ["pose"]
```

No bind data needed: the kit drives player controller 0's pawn.

## Lua: `router.lua`, only when data isn't enough

It runs in a sandbox (`Router`, `Game`, Lua 5.4's safe libraries; no files, OS or `require`):

```lua
Router.block "mygame.world" {
    enter = function()                       -- twice a second until in the world
        local menu = Game.widget("WBP_TitleScreen_C")
        if menu then Game.call(menu, "OnStartClicked") end
    end,
}
```

- World blocks: `enter`, `ready`, `anchor`, `hidden`. Entity blocks: `describe(object, class,
  is_character)` → `{ kind, name, health, max_health, team }` / `false` / `nil`, and
  `spawn = { kind = function(at, rotation) ... end }`.
- `Game.*`: `find`, `find_all`, `object`, `class`, `class_name`, `full_name`, `is_a`, `get`/`set`
  (field paths), `call`, `player`, `controller`, `world`, `map`, `widget`, `console`, `trace`,
  `spawn`, `loaded`, `time`, `log`.
- A wrong field name fails when the script runs, with the line and what's allowed. `router check`
  checks every `Game.x`/`Router.x` name before that.
- `fusion-cli router reload routers/<id> [--watch]` sends router.toml and router.lua to the
  running game without restarting it.

## Setup (one click for players)

`router new --kit unreal` writes it; the project folder is the one holding `Binaries/Win64`:

```toml
[router.setup]
installed_when = "{game}/MyGame/Binaries/Win64/ue4ss/Mods/FusionKit/dlls/main.dll"

[[router.setup.require]]
name = "UE4SS"
check = "{game}/MyGame/Binaries/Win64/ue4ss/UE4SS.dll"
guide = "Download UE4SS and unzip it into the game's MyGame/Binaries/Win64 folder."
url = "https://github.com/UE4SS-RE/RE-UE4SS/releases"

[[router.setup.step]]
copy = "{tools}/fusion_unreal.dll"
to = "{game}/MyGame/Binaries/Win64/ue4ss/Mods/FusionKit/dlls/main.dll"

[[router.setup.step]]
copy = "{fusion}/kits/unreal/lua"
to = "{game}/MyGame/Binaries/Win64/ue4ss/Mods/FusionKit/Scripts"
```

(plus copies of `{router}/router.toml` and `{router}/router.lua` into `Scripts`, and
`add_line = "FusionKit : 1"` to `mods.txt`; see `example-unreal.router.toml`).

## Gotchas

- Content in `.pak` files: read it from the running game. Never unlock encrypted paks.
- Unreal before 4.13 can't capture depth: the world is drawn behind Fusion's own objects
  (conformance says so); everything else works.
- After changing the kit itself, set the router up again (My Games → Set up): an old kit in the
  game gives confusing failures.
- Example: `example-unreal.router.toml` and `example-unreal.router.lua` (a made-up game in the
  shape of a real router: about 20 lines of data, Lua only for two menus and one NPC rule).
