finished out skills per level, added skill trees to professions templates
This commit is contained in:
291
docs/char_gen.md
Normal file
291
docs/char_gen.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# 🧩 Code of Conquest — Character Generation (Flask API)
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes how **character generation** operates inside the Flask API.
|
||||
The goal is to produce a fully realized `Entity` (hero, enemy, or NPC) based on **race**, **profession**, **abilities**, and **level** using YAML-defined data and procedural logic.
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ Directory Overview
|
||||
|
||||
```
|
||||
app/
|
||||
├── blueprints/
|
||||
│ ├── main.py # Root routes
|
||||
│ └── char.py # Character creation and progression endpoints
|
||||
│
|
||||
├── game/
|
||||
│ ├── generators/ # Procedural content
|
||||
│ │ ├── abilities_factory.py # Generates abilities / skills
|
||||
│ │ ├── entity_factory.py # Builds complete entity objects
|
||||
│ │ ├── level_progression.py # XP and level curve logic
|
||||
│ │ └── ... (compiled files)
|
||||
│ │
|
||||
│ ├── loaders/ # YAML loaders for static templates
|
||||
│ │ ├── profession_loader.py
|
||||
│ │ ├── races_loader.py
|
||||
│ │ └── spells_loader.py # May be deprecated in favor of skills
|
||||
│ │
|
||||
│ ├── models/ # Dataclasses for core game objects
|
||||
│ │ ├── abilities.py
|
||||
│ │ ├── entities.py
|
||||
│ │ ├── professions.py
|
||||
│ │ ├── races.py
|
||||
│ │ └── enemies.py
|
||||
│ │
|
||||
│ ├── systems/
|
||||
│ │ └── leveling.py # Handles XP gain, set_level, and skill growth
|
||||
│ │
|
||||
│ ├── templates/
|
||||
│ │ ├── ability_paths.yaml # Defines thematic skill sets (paths)
|
||||
│ │ ├── professions/*.yaml # Defines all professions
|
||||
│ │ └── races/*.yaml # Defines all playable races
|
||||
│ │
|
||||
│ └── utils/
|
||||
│ └── common.py
|
||||
│
|
||||
├── models/ # Shared models for the Flask layer
|
||||
│ ├── hero.py
|
||||
│ ├── enums.py
|
||||
│ └── primitives.py
|
||||
│
|
||||
└── utils/
|
||||
├── catalogs/ # Compiled catalog data for fast lookups
|
||||
│ ├── race_catalog.py
|
||||
│ ├── hero_catalog.py
|
||||
│ └── skill_catalog.py
|
||||
├── api_response.py
|
||||
└── settings.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧬 Entity Generation Pipeline
|
||||
|
||||
### 1. `entity_factory.build_entity()`
|
||||
|
||||
Creates a base entity by combining **Race** and **Profession** definitions.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. Load race + profession data from YAML via loaders.
|
||||
2. Apply racial ability modifiers.
|
||||
3. Apply profession base stats and per-level growth rates.
|
||||
4. Initialize HP, MP, XP, and skill lists.
|
||||
|
||||
---
|
||||
|
||||
### 2. `leveling.set_level(entity, target_level)`
|
||||
|
||||
Handles level setting and skill gain.
|
||||
|
||||
* Calculates XP using `level_progression.py`.
|
||||
* Calls `calculate_skills_gained()` (randomized 30% chance per level).
|
||||
* Generates new skills via `abilities_factory`.
|
||||
|
||||
---
|
||||
|
||||
## 🧝 Races
|
||||
|
||||
Located in `app/game/templates/races/`.
|
||||
|
||||
Each race defines:
|
||||
|
||||
* Base ability modifiers (STR, DEX, CON, INT, WIS, CHA)
|
||||
* Optional descriptive text
|
||||
* Tags for gameplay classification
|
||||
|
||||
Example (`elf.yaml`):
|
||||
|
||||
```yaml
|
||||
name: Elf
|
||||
description: Graceful and attuned to magic.
|
||||
ability_mods:
|
||||
DEX: 2
|
||||
INT: 1
|
||||
CON: -1
|
||||
tags: ["playable"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ⚔️ Professions
|
||||
|
||||
Located in `app/game/templates/professions/`.
|
||||
|
||||
Each profession file defines:
|
||||
|
||||
* Base HP / MP
|
||||
* Scaling per level
|
||||
* Primary stat (INT, WIS, etc.)
|
||||
* Flavor / lore fields
|
||||
|
||||
Example (`warlock.yaml`):
|
||||
|
||||
```yaml
|
||||
id: warlock
|
||||
name: Warlock
|
||||
description: A wielder of forbidden demonic power.
|
||||
primary_stat: CHA
|
||||
base_hp: 40
|
||||
base_mp: 80
|
||||
physical_attack_per_level: 1.0
|
||||
physical_defense_per_level: 0.5
|
||||
magic_attack_per_level: 2.5
|
||||
magic_defense_per_level: 1.5
|
||||
tags: ["caster","dark"]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Ability / Skill Generation
|
||||
|
||||
### Path Themes
|
||||
|
||||
Defined in `templates/ability_paths.yaml`:
|
||||
|
||||
```yaml
|
||||
Hellknight:
|
||||
elements: ["fire", "shadow"]
|
||||
adjectives: ["Infernal", "Hellfire", "Brimstone", "Abyssal"]
|
||||
nouns: ["Edict", "Judgment", "Brand", "Smite"]
|
||||
of_things: ["Dominion", "Torment", "Cinders", "Night"]
|
||||
```
|
||||
|
||||
### Generator Function
|
||||
|
||||
Located in `abilities_factory.py`:
|
||||
|
||||
```python
|
||||
def generate_spells_direct_damage(
|
||||
class_name: str,
|
||||
path: str,
|
||||
level: int,
|
||||
per_tier: int = 2,
|
||||
content_version: int = 1,
|
||||
primary: str = "INT"
|
||||
) -> List[Spell]:
|
||||
...
|
||||
```
|
||||
|
||||
**Features:**
|
||||
|
||||
* Deterministic random seed based on `(class, path, level, version)`
|
||||
* Generates direct-damage only
|
||||
* Scales power and cost by level
|
||||
* Names and effects are thematically consistent
|
||||
|
||||
### Example Output
|
||||
|
||||
```
|
||||
Infernal Judgment — Deal fire damage (power 120, CHA+125%). MP 30, CD 1
|
||||
Brand of Cinders — Deal shadow damage (power 118, CHA+125%). MP 30, CD 0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📈 Level Progression
|
||||
|
||||
Handled in `level_progression.py`.
|
||||
|
||||
* Defines XP thresholds per level (exponential curve)
|
||||
* Provides helper: `get_xp_for_level(level)`
|
||||
* Ensures `entity.xp_to_next_level` is always accurate after XP updates.
|
||||
|
||||
---
|
||||
|
||||
## 🎲 Skill Gain Logic
|
||||
|
||||
Implemented in `systems/leveling.py`.
|
||||
|
||||
```python
|
||||
def calculate_skills_gained(current_level, target_level, chance_per_level=0.3):
|
||||
levels_gained = max(0, target_level - current_level)
|
||||
if levels_gained == 0:
|
||||
return 0
|
||||
|
||||
gained = sum(1 for _ in range(levels_gained) if random.random() < chance_per_level)
|
||||
if levels_gained < 3:
|
||||
gained = max(gained, 2)
|
||||
|
||||
cap = math.ceil(levels_gained * 0.4)
|
||||
return min(gained, cap)
|
||||
```
|
||||
|
||||
* **30% random chance** per level to gain a new skill
|
||||
* Guarantees **≥ 2** if leveling fewer than 3 levels
|
||||
* Caps maximum growth to **40%** of total levels gained
|
||||
|
||||
---
|
||||
|
||||
## 🧮 XP / Level Curve Example
|
||||
|
||||
| Level | XP Needed (example) | XP Delta | Notes |
|
||||
| ----- | ------------------- | -------- | ----------------- |
|
||||
| 1 | 0 | — | Starting level |
|
||||
| 2 | 100 | +100 | Fast early growth |
|
||||
| 5 | 625 | +175 | Moderate |
|
||||
| 10 | 2500 | +350 | Midgame plateau |
|
||||
| 20 | 10000 | +750 | Late-game scaling |
|
||||
|
||||
*(Values may differ depending on `level_progression.py` formula)*
|
||||
|
||||
---
|
||||
|
||||
## ⚙️ API Integration
|
||||
|
||||
### Blueprint: `char.py`
|
||||
|
||||
Handles player-facing endpoints such as:
|
||||
|
||||
* `POST /char/create` → build entity from race + profession
|
||||
* `POST /char/level` → level up existing entity and add new skills
|
||||
* `GET /char/:id` → return current character stats, XP, and skills
|
||||
|
||||
Example:
|
||||
|
||||
```python
|
||||
@char_bp.route("/create", methods=["POST"])
|
||||
def create_character():
|
||||
data = request.json
|
||||
entity = build_entity(data["race"], data["profession"])
|
||||
return jsonify(entity.to_dict())
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📁 Data Flow Summary
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[API Request] --> B[char.py Blueprint]
|
||||
B --> C[entity_factory.build_entity()]
|
||||
C --> D[races_loader / profession_loader]
|
||||
C --> E[level_progression]
|
||||
C --> F[abilities_factory]
|
||||
F --> G[ability_paths.yaml]
|
||||
C --> H[Entity Model]
|
||||
H --> I[API Response JSON]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧾 Design Notes
|
||||
|
||||
* All YAML templates are static assets — easy to edit without code changes.
|
||||
* Procedural factories (`abilities_factory`, `entity_factory`) ensure deterministic generation for the same input.
|
||||
* Systems (`leveling.py`) handle simulation and logic, isolated from API routes.
|
||||
* `utils/catalogs` may eventually cache or precompute available skills, professions, and races for faster response times.
|
||||
* The entire pipeline can operate **statelessly** inside Flask routes or **persisted** in a database later.
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Future Ideas
|
||||
|
||||
* Add **passive traits** per race or profession.
|
||||
* Implement **rarity** or **tiered skills** (common → legendary).
|
||||
* Generate **enemy entities** using the same system with difficulty scaling.
|
||||
* Add a **training system** or **skill mastery** mechanic tied to XP.
|
||||
* Create **hero_catalog.py** entries for pre-built templates used in story mode.
|
||||
|
||||
Reference in New Issue
Block a user