FAQ

Everything extracted as @bytes(...) — why?

No schema. Pass --game-root pointing at the game install, and make sure it actually contains the script packages (Core.u, Engine.u, the game's own .u files). Run schema-resolve on a known class to check the index:

ue3-tools --game-root /path/to/game schema-resolve engine "Class Engine.Actor"

package 'x' not in --game-root

The import graph reached a package your root doesn't cover. Point --game-root higher up, or check that DLC and patch directories are included. --verbose streams every miss as it happens.

Invalid file signature

Not a UE3 package, or it's encrypted/wrapped by the title. The tool requires the literal 0x9E2A83C1 tag at offset zero.

Corrupted pak

The header parsed but reported a non-positive name, export or import count. Usually a truncated file or a wrong offset — try upk-header to see how far it got.

Decompression fails or panics

Only LZO is implemented. Zlib and LZX packages are recognised but hit an unimplemented path and abort. A panic inside LZO decompression means the chunk data didn't match its declared size — the file is likely truncated.

Textures extract with no .dds

Three common causes:

  • Unmapped pixel format. Only PF_DXT1, PF_DXT3, PF_DXT5, PF_A8R8G8B8, PF_G8, PF_BC5, PF_FloatRGBA are handled; anything else warns and skips.
  • Mips live in a .tfc that isn't under --game-root. LZO-compressed TFC payloads are inflated; zlib or LZX compression in a TFC hits the same unimplemented path as packages do.
  • No resolvable mips at all, which the warning states explicitly.

My replacement .dds is rejected

Its top mip has to match one of the original mips' dimensions. To change resolution, also update SizeX and SizeY in the .uo to your DDS's top mip — that authorises replacing the whole mip list.

Can I replace audio?

Yes. SoundNodeWave has an injector. Put a replacement next to the .uo; the filename picks which payload slot it replaces:

Filename contains Slot
.raw. Raw PCM
.xbox360. Xbox 360
.ps3. PS3
none of the above PC compressed data (expects Ogg)

On pack the sound's properties (NumChannels, SampleRate, Duration, RawPCMDataSize, CompressionQuality) are synced from the new payload. A PC payload that doesn't start with OggS is injected anyway, with a warning.

Can I replace a mesh?

Not yet. StaticMesh and SkeletalMesh extract to .glb for viewing and conversion, but there is no injector.

Can I edit a class, add a function, or change UnrealScript?

No. Class, struct, enum and const .uo files are read-only reference material — pack-mod skips them. Bytecode is located and skipped during schema parsing, never decompiled or re-emitted.

type mismatch: original is Int but edit is string

By design. The packer won't coerce types, because a wrong guess produces a package the game will mis-deserialize. Match the original's form — quotes for strings, bare digits for numbers, 'name' for names, Enum::Value for enums, &Ref for object references.

struct has no field 'X' in the original export

That field held its default value, so the engine never serialized it. With --game-root the packer creates it from the schema; without one, it can't know the field's type and fails.

could not resolve object reference '&Foo'

The label was ambiguous or matched nothing. Use a fuller dotted path (Outer.Foo), or extern: for imports. If the target genuinely doesn't exist yet, the packer reserves a slot and records it in .newexports instead of failing.

Does pack-mod produce a modified .upk?

No. The output is per-export .bin blobs plus a .newnames file, intended for a runtime loader such as CU3ML. Repacking a whole package is out of scope — there is no pack command.

Do I have to ship the .newnames?

Yes. Property tags reference names by index, and almost any edit can append entries. Ship the .newnames from the same run as the .bin files. It lists only the appended names with their indices; it is not a full copy of the name table.

Can the GUI extract or build mods?

It can build mods. The mod workspace extracts the objects you select into a temporary directory, then packs them into <key>/mod.toml, main.lua and overrides/. It doesn't write extracted files out for hand-editing — use the CLI extract command for that.

Is it slow?

Yes, on large packages. Whole packages are held in memory, import resolution scans export tables linearly, and resolving one import can pull in and decompress another package. Running decompress once and working against the flattened file helps.

Will it work on my game?

Anything UE3-era with a package version inside the supported gate range should read. Console (byte-swapped) packages decompress, but console-cooked script layouts aren't handled, so their meta-objects will mis-parse. Expect to add version constants for anything far from the Dishonored-era target.