# Projeto Novo Jogo — project rules

> Co-op PvE medieval fantasy game, 5–10 players, Unreal Engine 5.8, Windows client,
> dedicated Linux server in São Paulo. Living documentation:
> gamedesign.liztem.com (design) · gameengine.liztem.com (tech) · gameserver.liztem.com (infra).
> Those sites are in Brazilian Portuguese because the group reads them; work with the human in English.
> Full background: see HANDOFF.md (archive it once the project is running).

## Locked decisions — do not reopen without the human
- Engine: **Unreal Engine 5.8**, C++ first. Blueprints only as near-empty leaf subclasses.
- Art: **stylized low-poly painterly** (Synty POLYGON base), optional toon dial. Substrate stays
  **disabled** in `DefaultEngine.ini` by default; the cel look must work as a post-process fallback.
- Networking: **dedicated server** only, never a listen server. 5–10 players, drop-in/drop-out.
- Classes: 10 fixed, distinct classes — one per friend — that specialise over time.
- Session: guild-hall hub + 20–40 min expeditions with a Blessing and 1–2 Curses per contract.
- Persistence: **SQLite on the server**, server-authoritative. The client never writes a save.
- PvE only. Voice is Discord, external — no in-game voice or chat needed.

## Where art assets live — NOT in git
Decided 2026-08-03 on the Windows side, ratified here. Supersedes any earlier "commit assets through
LFS" wording in this file or in HANDOFF.md.

Vendored art packs (Synty and anything like them) are **never committed**. GitHub's free Git LFS
allowance is 1 GiB of storage and 1 GiB of bandwidth per month; the first Synty batch alone is 5.1 GB,
every clone re-spends the bandwidth, and data packs cost US$5/month per 50 GB — real money on a project
that runs at ~US$8/month with budget alarms at $20.

- **Masters** stay where they were downloaded on the Windows machine — currently
  `C:\Users\willy\Downloads\SyntyMedievalFantasy`. The only rule that matters is *outside the repo*;
  the exact folder is not worth a migration.
- **Mirror:** `s3://gameserver-liztem-assets` — private, versioned, non-current versions expire after
  90 days. Uploading needs credentials that only exist once Willy provisions the scoped IAM user
  (policy published at gameserver.liztem.com/iam-policy-windows.json).
- `.gitignore` blocks the usual import paths (`Content/Synty/`, `Content/POLYGON*/`, …). The LFS rules
  in `.gitattributes` remain as a safety net for the occasional one-off asset, not as the storage plan.
- What *is* committed: C++, config, GameplayTags, DataAssets, CSV/JSON. Text, as below.

## The golden rule
Everything that matters lives in **text an agent can read**:
- Gameplay logic in **C++** (`Source/`), never in a Blueprint graph.
- GameplayTags in `Config/DefaultGameplayTags.ini`.
- Class/ability/monster data in **DataAssets + committed CSV/JSON**.
- Blueprints only to wire mesh/montage/VFX in a leaf subclass, named `BP_` + the C++ class name.

Why: printing "hello" is ~8,000 characters of Blueprint clipboard versus 14 of C++, and `.uasset` is
binary — it cannot be diffed, reviewed, or refactored by an agent.

## Gameplay architecture
- **GAS** is the backbone: abilities, cooldowns, attributes, buffs.
- ASC on the **PlayerState** (Lyra pattern — survives respawns mid-expedition).
- **One DataAsset per class** (10 files), each carrying its AbilitySet.
- **Blessings and Curses are GameplayEffects** — GAS's native feature, no plugin needed.
- Lyra is a **pattern quarry, never a fork**: copy the idea, not the files.
- AI: Behavior Trees for grunts, StateTree for boss phases. Cap ~40–60 concurrent enemies with
  significance-based tick throttling. Do not adopt Mass/MassAI.
- Use `CharacterMovementComponent`, not the experimental Mover plugin.

## Difficulty scaling (5–10 players)
Tune encounters for 5. Scale spawn counts roughly linearly per extra player. Reserve HP scaling
(+20–30%/player) for bosses and elites only. Keep enemy damage growth near +4%/player. Re-scale live with
30–60 s hysteresis when headcount changes mid-mission.

## Build targets
Three `.Target.cs` files, distinct from modules — the server one is what feeds São Paulo, and the
dedicated-server package cannot build without it:
`NewGame.Target.cs` (Game) · `NewGameEditor.Target.cs` (Editor) · `NewGameServer.Target.cs` (Server,
`Type = TargetType.Server`, `ExtraModuleNames.Add("NewGame")`).

Toolchain: UE 5.8 installed **with the Linux target platform ticked** (Epic's matching clang
cross-toolchain), plus Visual Studio 2022 with the *Game development with C++* and *.NET desktop
development* workloads.

## Commands
```bash
# Editor build (from the project folder)
"C:/Program Files/Epic Games/UE_5.8/Engine/Build/BatchFiles/Build.bat" NewGameEditor Win64 Development \
  -Project="$PWD/NewGame.uproject" -WaitMutex

# Automated tests
UnrealEditor-Cmd.exe NewGame.uproject -ExecCmds="Automation RunTests Projeto; Quit" -unattended -nullrhi -log

# Package the Linux dedicated server (needs Epic's Linux cross-compile toolchain)
RunUAT.bat BuildCookRun -project="$PWD/NewGame.uproject" -platform=Linux -server \
  -serverconfig=Development -cook -stage -pak -archive -archivedirectory="$PWD/Builds"

# Publish to the São Paulo server
aws s3 cp servidor.tar.gz s3://gameserver-liztem-builds/server/latest.tar.gz --region sa-east-1
# then, on the server via SSM: /srv/game/bin/deploy-server.sh
```

## Infrastructure that already exists — do not rebuild
- `game.liztem.com` — EC2 m6a.large in sa-east-1, UDP 7777 only, SSM-only admin, no SSH.
- Auto-shutdown after 30 idle minutes, 8-hour hard cap. Panel: gamepanel.liztem.com.
- `/srv/game/bin/deploy-server.sh` pulls builds from S3, keeps the previous version, restarts the service.
- Buckets: `gameserver-liztem-builds` (private, versioned), `gameserver-liztem-saves` (private, versioned).
- Budget alarms at $20/$35/$40/$50; a traffic-anomaly alarm auto-stops the instance.

## Ratified decisions (asked for, and granted — do not re-litigate)
- **Editor plugins go into `.uproject` only after the editor opens once.** `ModelContextProtocol` and
  `AllToolsets` are NOT added blind. Rationale, and it is correct: the first clean UBT run is T1's
  acceptance test, and naming plugins the installed engine may not carry turns a compile result into a
  dialog box. Verify the real plugin list in the editor, then add both (both — `AllToolsets` is off by
  default and without it the MCP server exposes zero tools).
- **The MCP server is unauthenticated arbitrary editor control on 127.0.0.1:8000.** Never bind it to
  anything else, never port-forward it, never expose it through a tunnel.

## Progress reporting
Keep `PROGRESS.md` at the project root updated (one line per finished task, with dates and any decision
forced along the way) and commit it — the AWS dev machine reads the repo. Then tell the human, so the
board at https://gameengine.liztem.com/tasks gets updated from that machine (the websites live there,
not here). If something in the docs turns out to be wrong, say so — stale plans get corrected, not defended.

## What NOT to do
- Do not put logic in Blueprints "just to test quickly" — it never comes back out.
- Do not commit `Binaries/`, `Intermediate/`, `Saved/`, `DerivedDataCache/`.
- Do not mix asset packs from different visual schools without the palette/LUT pass.
- Do not let the client write saves or report its own progression.
- Do not open ports on the game server; do not serve project files anonymously anywhere.
- Do not commit secrets — they belong in AWS SSM SecureString.
