---
name: author-base-chunk
description: Use when authoring, editing, or validating a base chunk Lua file for the fa-joe-ai mod (files under lua/Shared/BaseChunks/<Faction>/). Covers the file format, coordinate convention, footprint lookup, tier-progression rule, validation, and loader registration. Faction-agnostic — pair with the matching author-<faction>-chunk skill for placement philosophy.
---

# Authoring a base chunk (mechanics)

A base chunk is a hand-authored, faction-tagged blueprint for a small piece of a base. The planner tiles flat regions of the map with chunks. This skill captures how to write a chunk file correctly. Faction-specific *style* lives in the `author-<faction>-chunk` skill — invoke that one alongside this one.

If you have not already, read [lua/Shared/BaseChunks/CLAUDE.md](../../../lua/Shared/BaseChunks/CLAUDE.md) for the system overview. This skill assumes that context and gives the procedural rules.

## Required reading before placing any building

[lua/Shared/BaseChunks/units.md](../../../lua/Shared/BaseChunks/units.md) — the auto-generated, per-faction footprint export. **Every placement decision must consult this file.** The `SkirtSizeX` / `SkirtSizeZ` columns are the rectangles the engine reserves around each structure on the build grid; no two skirts may overlap. `FootprintX` / `FootprintZ` are smaller and informational only.

When skirt sizes diverge across factions for the same identifier, author against the *faction whose chunk you are writing*. The chunk is faction-tagged in `Faction = "..."` and the planner will only build it with that faction's engineers.

## File format

Chunks live at `lua/Shared/BaseChunks/<Faction>/<role>_<size>x<size>_<NN>.lua`. Naming:
- `<Faction>` is one of `UEF`, `Aeon`, `Cybran`, `Seraphim`.
- `<role>` is lowercase: `power`, `land`, `air`, `naval`, `defense`, `special`, `random`, etc. Pick the role that best describes what the chunk is *for*.
- `<size>` is the chunk side length, zero-padded to two digits: `04`, `08`, `16`, `32`, `64`, `128`.
- `<NN>` is the index for that role+size combination, also zero-padded: `01`, `02`, ...

The file exports a global `Template`:

```lua
-- This code is generated by the Average Joe AI mod. For more information, visit:
-- - https://github.com/Garanas/fa-joe-ai

---@type JoeBaseChunk
Template = {
    Name = "Land factory - 03",
    Faction = "UEF",
    Size = 16,
    Units = { "ueb0101", "ueb1101", "ueb5101" },
    Locations = {
        T1LandFactory = {
            { 4, 4, 0 },
        },
        T1EnergyProduction = {
            { 9, 3, 0 },
            { 9, 5, 0 },
            { 11, 3, 0 },
            { 11, 5, 0 },
        },
        Wall = {
            { 1, 14, 0 },
            { 2, 14, 0 },
        },
    },
}
```

- `Name` — short, role-descriptive, ends with ` - NN` matching the file index.
- `Faction` — `"UEF"`, `"Aeon"`, `"Cybran"`, or `"Seraphim"`. Must match the parent folder.
- `Size` — must be one of `4`, `8`, `16`, `32`, `64`, `128`. The planner does not handle any other size.
- `Units` — flat list of every unique faction-specific unit ID that appears in the chunk. Used by the loader for entity-category interactions; informational, not authoritative.
- `Locations` — keyed by `JoeBuildingIdentifier` (see [lua/Shared/BaseChunks/JoeBuildingIdentifiers.lua](../../../lua/Shared/BaseChunks/JoeBuildingIdentifiers.lua) for the full alias list). Each value is an array of `{ X, Z, orientation }` triples.

## Coordinate rules

- **In-chunk offsets, not world coordinates.** All `X`, `Z` values must satisfy `0 ≤ value < Size`.
- **Top-left of the skirt rectangle is what you author.** A T1 PGen (2×2 skirt) at `{ 5, 3, 0 }` occupies cells `(5,3)`, `(6,3)`, `(5,4)`, `(6,4)`.
- **Half-cell offset for odd-footprint buildings.** Buildings whose `Footprint.SizeX` (or `Z`) is odd are saved at `x.5` instead of `x`. The capture hotkey handles this automatically; when authoring by hand, check units.md and add `.5` to both axes if either footprint dimension is odd. The 5×5-footprint T3 SMD in `special_16x16_01.lua` is the canonical example: `{ 12.5, 4.5, 0 }`.
- **Orientation is reserved but currently always `0`.** When orientation lands it will be 90° increments only — never 60°. **Do not place anything at non-90° orientations**, and for the time being do not rotate buildings at all (always `0`).

## Tier progression (faction-agnostic)

- **Every chunk should contain at least one T1 building.** This anchors the chunk and makes future expansion to higher tiers feel natural.
- **Chunks of `Size = 32` or larger should also contain T2 buildings** — at minimum one T2 power, shield, missile defense, or factory.
- **Chunks of `Size = 64` or larger should also contain T3 buildings** — T3 power, T3 factory, T3 artillery, etc.

This rule is independent of role. A `power_64x64` should include T1 PGens *and* T2 PGens *and* a T3 power source. A `defense_32x32` should include T1 walls/AA *and* T2 shield/missile defense.

## Validation checklist

Before saving a chunk, verify:

1. **No skirt overlaps.** For every pair of placed buildings, look up both skirt sizes in units.md and confirm their rectangles do not intersect. Two T1 PGens (2×2) at `(5,3)` and `(7,3)` are exactly skirt-touching — this is allowed and is the adjacency-bonus formation. They cannot be at `(5,3)` and `(6,3)` (that overlaps).
2. **All identifiers exist.** Every key in `Locations` must be a valid `JoeBuildingIdentifier`. Check against [JoeBuildingIdentifiers.lua](../../../lua/Shared/BaseChunks/JoeBuildingIdentifiers.lua).
3. **All coordinates are in range.** Every `X` and `Z` is in `[0, Size)`. The skirt rectangle must also fit — a 6×6 skirt at `(11, 11)` in a 16×16 chunk fits; at `(12, 12)` it would extend past the edge and is invalid.
4. **`Units` covers every placed building.** For each identifier used, look up the faction-specific unit ID via the entity category and add it to the `Units` list. Duplicates not allowed.
5. **The faction folder matches `Faction`.** A file in `UEF/` must have `Faction = "UEF"`.
6. **Tier rule satisfied.** T1 present; T2 present at `Size >= 32`; T3 present at `Size >= 64`.

## Registration

Every new chunk file must be added to the loader. Open [lua/Shared/BaseChunks/JoeBaseChunkLoader.lua](../../../lua/Shared/BaseChunks/JoeBaseChunkLoader.lua), find `CreateDefaultJoeBaseChunkLoader`, and add a `LoadTemplate` call for the new file. Files not registered there are not discovered by the AI.

## Verification

After saving and registering, the user can verify visually in-game:
1. Bind the `average_joe_ai_create_chunk_template_<size>` hotkey for the chunk's size.
2. Use `JoeLoadedBaseChunk.PreviewTemplate(template)` (e.g. via the dialog wired up by [lua/ui/Actions/ToggleBaseChunkDialog.lua](../../../lua/ui/Actions/ToggleBaseChunkDialog.lua)) to drop the chunk on the map and confirm the layout matches the intent.

If anything overlaps, leaves a wrong gap, or extends past the chunk edge, fix the source file and re-preview. Do not ship a chunk you have not visually confirmed.

## Adjacency-bonus reality (engine fact, not style)

The FA engine awards adjacency bonuses for specific structure pairs only. When deciding where to place T1 PGens and storage, do not invent bonuses that the engine does not give:

- **T1 PGen adjacent to T2 PGen — NO bonus.** Packing T1 PGens around T2/T3 power generators is decorative only. Place T1 PGens around factories or mass extractors instead.
- **Energy storage adjacent to T2/T3 PGen — yes, big PGen output bonus.** Storage units are volatile (they explode on death and damage neighbours), so use **at most one or two per T2 PGen**, never a ring.
- **Mass storage adjacent to mass extractor — yes, big extractor output bonus.** Same volatility caveat.
- **Power adjacent to factory — yes, factory build-rate bonus.** Pack T1 PGens around factory sides where walls aren't placed.
- **Power adjacent to mass extractor — yes, small extractor energy-cost bonus.** Less impactful than mass-storage adjacency.

When in doubt about a pairing, leave it out. Decorative-only adjacencies waste cells that could be defenses or walls.

## Common pitfalls

- **Forgetting the half-cell offset for odd-footprint buildings.** Buildings will then sit half-a-cell off-grid and may overlap their neighbours. Always check `FootprintX` / `FootprintZ` parity in units.md.
- **Using a placeholder `SizeX`/`SizeZ` from `JoeBuildingIdentifiers.lua` instead of the real per-faction skirt from units.md.** The metadata `SizeX`/`SizeZ` in that file are role-level approximations; units.md has the authoritative numbers.
- **Writing T4 / experimental identifiers into chunks.** Experimentals are mobile units, not structures placed by chunks. Do not include `T4LandExperimental*`, `T4AirExperimental*`, etc. in `Locations`.
- **Walls or other buildings touching the chunk edge.** When two chunks abut, edge-aligned walls will produce a doubled wall on the seam. Leave at least a 1-cell buffer between walls and the chunk edge — see the faction skill for the exact convention.
