experimental: remove Tekton Doors entirely
- Delete portal_mode_manager.gd, portal_door.gd, portal_door.tscn - Strip all Tekton Doors logic from main.gd, player.gd, lobby.gd, lobby_room.gd, lobby_manager.gd, camera_context_manager.gd, music_manager.gd, tekton.gd, enhanced_gridmap.gd, playerboard_manager.gd, special_tiles_manager.gd - Remove TK enum (TEKTON_DOORS=2), mode_config schema, arena area - Update tests: 3 modes instead of 4 - Strip HowToPlay tab from main.tscn
This commit is contained in:
@@ -0,0 +1,257 @@
|
||||
# Skin Creation Workflow
|
||||
|
||||
<a id="top"></a>
|
||||
|
||||
How to author a new character skin, register it in the game's shop/gacha catalog, and ship it to players.
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Each skin is defined in two places that must stay in sync:
|
||||
|
||||
| Layer | File | What it stores |
|
||||
|---|---|---|
|
||||
| **Client (visual)** | `scripts/managers/skin_manager.gd` | Mesh slots, material paths, override/overlay mode |
|
||||
| **Server (shop)** | `server/nakama/lua/economy.lua` | Item ID, name, category, price (gold/star) |
|
||||
|
||||
The item `id` in `economy.lua` must match the dictionary key in `skin_manager.gd` `SKIN_CATALOG` exactly -- the Godot client looks up the item ID from the wallet/inventory and applies the matching skin data.
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Step 1: Create the Skin Material
|
||||
|
||||
Open the **Skin Shader Generator** at `res://scenes/tools/skin_shader_generator.tscn`.
|
||||
|
||||
1. Run the scene (F6).
|
||||
2. Import your base albedo and mask textures (PNG with color/alpha channels).
|
||||
3. Use the UI to visualize UV overlays and adjust color channels (Red, Green, Blue, Alpha).
|
||||
4. Export the configured material as a `.tres` file into `assets/materials/skins/` or a subfolder:
|
||||
- `assets/characters/skins/hat/`
|
||||
- `assets/characters/skins/clothing/`
|
||||
- `assets/characters/skins/gloves/`
|
||||
|
||||
**Material path conventions (Oldpop character):**
|
||||
|
||||
| Category | Example path |
|
||||
|---|---|
|
||||
| hat | `res://assets/characters/skins/hat/oldpop_mat_hat_blue.tres` |
|
||||
| costume/clothing | `res://assets/characters/skins/clothing/oldpop_mat_cloth_red_pant.tres` |
|
||||
| glove | `res://assets/characters/skins/gloves/oldpop_mat_gloves_blue.tres` |
|
||||
| accessory | `res://assets/characters/skins/accessory/` |
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Step 2: Register the Skin in SkinManager (Client)
|
||||
|
||||
Open `res://scripts/managers/skin_manager.gd` and add a new entry inside `SKIN_CATALOG` (between `[BEGIN_SKIN_CATALOG]` and `[END_SKIN_CATALOG]` markers).
|
||||
|
||||
### Entry format
|
||||
|
||||
```gdscript
|
||||
"item_id": {
|
||||
"category": "head", # head | costume | glove | accessory
|
||||
"character": "Oldpop", # node name under CharacterRoot
|
||||
"slots": [
|
||||
{
|
||||
"mesh": "oldpop-hat1", # MeshInstance3D child name
|
||||
"mode": "override", # "override" | "overlay"
|
||||
"material": "res://path/to/material.tres"
|
||||
},
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Slot modes
|
||||
|
||||
- **`override`** -- `set_surface_override_material(0, mat)`. Replaces the base material entirely. Preserves the outline shader (`next_pass`) automatically.
|
||||
- **`overlay`** -- `material_overlay = mat`. Transparent layer on top of the base material. Good for costume/pant patterns.
|
||||
|
||||
### Multi-slot skins (costume example)
|
||||
|
||||
Costumes typically touch 3 meshes:
|
||||
|
||||
```gdscript
|
||||
"oldpop-grey-pant": {
|
||||
"category": "costume",
|
||||
"character": "Oldpop",
|
||||
"slots": [
|
||||
{ "mesh": "oldpop-body", "mode": "overlay", "material": "res://assets/characters/skins/clothing/oldpop_mat_cloth_grey_pant.tres" },
|
||||
{ "mesh": "oldpop-bottom1", "mode": "override", "material": "res://assets/characters/skins/clothing/oldpop_mat_cloth_grey_pant.tres" },
|
||||
{ "mesh": "oldpop-bottom2", "mode": "override", "material": "res://assets/characters/skins/clothing/oldpop_mat_cloth_grey_pant.tres" },
|
||||
]
|
||||
},
|
||||
```
|
||||
|
||||
### Tips
|
||||
|
||||
- Leave `"material"` as `""` if the `.tres` file is not ready yet. The slot is skipped gracefully.
|
||||
- Use the **Skin Catalog Editor** (`res://scenes/tools/skin_catalog_editor.tscn`) to avoid manual edits. Click **Save & Generate** to rewrite both `skin_manager.gd` and `economy.lua`.
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Step 3: Register the Skin in Economy (Server)
|
||||
|
||||
Open `server/nakama/lua/economy.lua` and add a new entry to `SHOP_CATALOG_DEFS`.
|
||||
|
||||
### Catalog entry format
|
||||
|
||||
```lua
|
||||
{ id = "oldpop-blue-hat", name = "Oldpop Blue Hat", category = "head", gold = 100, star = 0, rarity = "Common", character = "Oldpop" },
|
||||
```
|
||||
|
||||
| Field | Type | Description |
|
||||
|---|---|---|
|
||||
| `id` | string | Must match the `SKIN_CATALOG` key in `skin_manager.gd` exactly |
|
||||
| `name` | string | Display name shown in shop |
|
||||
| `category` | string | `head` / `costume` / `glove` / `accessory` |
|
||||
| `gold` | number | Gold coin price (0 = not sold for gold) |
|
||||
| `star` | number | Star gem price (0 = not sold for stars) |
|
||||
| `rarity` | string | `"Common"` / `"Uncommon"` / `"Rare"` -- cosmetic label only |
|
||||
| `character` | string | Character this skin belongs to (e.g. `"Oldpop"`) |
|
||||
|
||||
### Existing catalog (12 items)
|
||||
|
||||
```
|
||||
oldpop-blue-hat head 100 gold Common Oldpop
|
||||
oldpop-green-hat head 100 gold Common Oldpop
|
||||
oldpop-red-hat head 100 gold Common Oldpop
|
||||
oldpop-yellow-hat head 100 gold Common Oldpop
|
||||
oldpop-og-pant costume 0 gold Common Oldpop (free)
|
||||
oldpop-grey-pant costume 150 gold Common Oldpop
|
||||
oldpop-red-pant costume 150 gold Common Oldpop
|
||||
oldpop-yellow-pant costume 150 gold Common Oldpop
|
||||
oldpop-blue-gloves glove 75 gold Common Oldpop
|
||||
oldpop-green-gloves glove 75 gold Common Oldpop
|
||||
oldpop-red-gloves glove 75 gold Common Oldpop
|
||||
oldpop-yellow-gloves glove 75 gold Common Oldpop
|
||||
```
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Step 4 (Optional): Add Skin as Gacha Prize
|
||||
|
||||
Gacha-only skins are registered in `server/nakama/lua/gacha.lua` inside `GACHA_DATA.real_prize_catalog`.
|
||||
|
||||
### Existing gacha skins (4 items)
|
||||
|
||||
```lua
|
||||
skin_gacha_rainbow_suit = { name = "Rainbow Suit", category = "costume", rarity = "real_prize", character = "" }
|
||||
skin_gacha_dragon_hat = { name = "Dragon Hat", category = "head", rarity = "real_prize", character = "" }
|
||||
skin_gacha_phantom_gloves = { name = "Phantom Gloves", category = "glove", rarity = "real_prize", character = "" }
|
||||
skin_gacha_neon_acc = { name = "Neon Accessory", category = "accessory", rarity = "real_prize", character = "" }
|
||||
```
|
||||
|
||||
Gacha skins also need a `skin_manager.gd` entry (same step 2 format) and a `skin_catalog_editor` entry so `SkinManager.apply_loadout()` can render them. The server catalog is optional -- gacha skins are not sold in the shop directly.
|
||||
|
||||
The gacha pulls these IDs from `GACHA_DATA.pools.real_prize`, so add your item_id there too.
|
||||
|
||||
```lua
|
||||
pools = {
|
||||
common = {"frag_common"},
|
||||
uncommon = {"frag_uncommon"},
|
||||
rare = {"frag_rare"},
|
||||
real_prize = {
|
||||
"skin_gacha_rainbow_suit",
|
||||
"skin_gacha_dragon_hat",
|
||||
"skin_gacha_phantom_gloves",
|
||||
"skin_gacha_neon_acc",
|
||||
-- add new skin here
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Step 5: Deploy
|
||||
|
||||
### Hot patch (content only) -- recommended for skins
|
||||
|
||||
1. Commit changes to `experimental` branch:
|
||||
- `scripts/managers/skin_manager.gd`
|
||||
- `server/nakama/lua/economy.lua` (if shop item)
|
||||
- `server/nakama/lua/gacha.lua` (if gacha prize)
|
||||
- Material `.tres` files
|
||||
|
||||
2. Push to `experimental`.
|
||||
|
||||
3. Trigger `deploy_patch.yml` via Gitea UI workflow dispatch.
|
||||
- CI runs `--export-pack` to build `patch.pck`.
|
||||
- CI force-pushes `patch.pck` + `version.json` to `patches` branch.
|
||||
- Existing players auto-download on next boot via `GameUpdateManager`.
|
||||
|
||||
### Full binary release (if engine/templates changed)
|
||||
|
||||
Tag a version (e.g. `v2.5.0`) and push. CI builds all platform binaries and uploads to the release.
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Full Flow Diagram
|
||||
|
||||
```
|
||||
┌──────────────────────┐
|
||||
│ 1. Create Material │
|
||||
│ skin_shader_generator │
|
||||
│ ────────────────── │
|
||||
│ Export .tres file │
|
||||
└────────┬─────────────┘
|
||||
v
|
||||
┌──────────────────────────────┐
|
||||
│ 2. Register in SkinManager │
|
||||
│ skin_manager.gd │
|
||||
│ ────────────────── │
|
||||
│ Add SKIN_CATALOG entry │
|
||||
│ (mesh slots + material) │
|
||||
└────────┬─────────────────────┘
|
||||
v
|
||||
┌──────────────────────────────┐
|
||||
│ 3. Register in Economy │
|
||||
│ economy.lua │
|
||||
│ ────────────────── │
|
||||
│ Add SHOP_CATALOG_DEFS │
|
||||
│ (price, name, category) │
|
||||
└────────┬─────────────────────┘
|
||||
v (optional)
|
||||
┌──────────────────────────────┐
|
||||
│ 4. Gacha Prize │
|
||||
│ gacha.lua │
|
||||
│ ────────────────── │
|
||||
│ real_prize_catalog + pools │
|
||||
└────────┬─────────────────────┘
|
||||
v
|
||||
┌──────────────────────┐
|
||||
│ 5. Git Push & CI │
|
||||
│ deploy_patch.yml │
|
||||
│ ────────────────── │
|
||||
│ patch.pck → players │
|
||||
└──────────────────────┘
|
||||
```
|
||||
|
||||
[Back to top](#top)
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Cause | Fix |
|
||||
|---|---|---|
|
||||
| Skin visible in editor but not in-game | Material path wrong or `.tres` not exported | Verify `res://` path in SKIN_CATALOG, run `--export-pack` |
|
||||
| Skin purchase fails: "NotEnoughFunds" | Wallet balance insufficient | Check gold/star prices in economy.lua |
|
||||
| Skin visible on all characters | `character` field wrong | Set correct character node name |
|
||||
| Skin purchase fails: "ItemNotFound" | Item ID not in SHOP_CATALOG_DEFS | Add entry matching SKIN_CATALOG key |
|
||||
| Player downloads patch but skin missing | econmy.lua change didn't reach server | Nakama hot-reload: restart Nakama container or wait for next restart |
|
||||
| Outline shader lost on skin | next_pass not preserved | SkinManager preserves it automatically -- verify with latest `skin_manager.gd` |
|
||||
|
||||
[Back to top](#top)
|
||||
Reference in New Issue
Block a user