Files
Code_of_Conquest/api/docs/DATA_MODELS.md

39 KiB
Raw Blame History

Data Models

All data models use Python dataclasses serialized to JSON for storage in Appwrite.


Type System (Enums)

All enum types are defined in /app/models/enums.py for type safety throughout the application.

EffectType

Value Description
BUFF Temporarily increase stats
DEBUFF Temporarily decrease stats
DOT Damage over time (poison, bleed, burn)
HOT Heal over time (regeneration)
STUN Prevent actions (skip turn)
SHIELD Absorb damage before HP loss

DamageType

Value Description
PHYSICAL Standard weapon damage
FIRE Fire-based magic damage
ICE Ice-based magic damage
LIGHTNING Lightning-based magic damage
HOLY Holy/divine damage
SHADOW Dark/shadow magic damage
POISON Poison damage (usually DoT)

ItemType

Value Description
WEAPON Adds damage, may have special effects
ARMOR Adds defense/resistance
CONSUMABLE One-time use (potions, scrolls)
QUEST_ITEM Story-related, non-tradeable

StatType

Value Description
STRENGTH Physical power
DEXTERITY Agility and precision
CONSTITUTION Endurance and health
INTELLIGENCE Magical power
WISDOM Perception and insight
CHARISMA Social influence

AbilityType

Value Description
ATTACK Basic physical attack
SPELL Magical spell
SKILL Special class ability
ITEM_USE Using a consumable item
DEFEND Defensive action

CombatStatus

Value Description
ACTIVE Combat is ongoing
VICTORY Player(s) won
DEFEAT Player(s) lost
FLED Player(s) escaped

SessionStatus

Value Description
ACTIVE Session is ongoing
COMPLETED Session ended normally
TIMEOUT Session ended due to inactivity

ListingType & ListingStatus

ListingType:

  • AUCTION - Bidding system
  • FIXED_PRICE - Immediate purchase at set price

ListingStatus:

  • ACTIVE - Listing is live
  • SOLD - Item has been sold
  • EXPIRED - Listing time ran out
  • REMOVED - Seller cancelled listing

LocationType

Types of locations in the game world (defined in both enums.py and action_prompt.py).

Value Description
TOWN Populated settlements
TAVERN Taverns and inns
WILDERNESS Outdoor areas, forests, fields
DUNGEON Dungeons and caves
RUINS Ancient ruins
LIBRARY Libraries and archives
SAFE_AREA Protected zones, temples

Location System

Locations define the game world structure. They are loaded from YAML files at runtime via LocationLoader.

Location

Represents a defined location in the game world.

Field Type Description
location_id str Unique identifier (e.g., "crossville_tavern")
name str Display name (e.g., "The Rusty Anchor Tavern")
location_type LocationType Type (town, tavern, wilderness, dungeon, etc.)
region_id str Parent region this location belongs to
description str Full description for AI narrative context
lore Optional[str] Historical/background information
ambient_description Optional[str] Atmospheric details for AI narration
available_quests List[str] Quest IDs discoverable at this location
npc_ids List[str] NPC IDs present at this location
discoverable_locations List[str] Location IDs that can be revealed from here
is_starting_location bool Whether valid for new character spawn
tags List[str] Metadata tags for filtering/categorization

Methods:

  • to_dict() - Serialize for JSON responses
  • to_story_dict() - Trimmed version for AI prompts (reduces token usage)
  • from_dict(data) - Deserialize from YAML/JSON

YAML Format:

location_id: "crossville_tavern"
name: "The Rusty Anchor Tavern"
location_type: "tavern"
region_id: "crossville"
description: "A cozy tavern known for its hearty stew and warm atmosphere."
lore: "Built fifty years ago by a retired sailor."
ambient_description: "The smell of roasting meat and spilled ale fills the air."
available_quests:
  - "quest_rats_tavern"
npc_ids:
  - "npc_grom_001"
  - "npc_elara_001"
discoverable_locations:
  - "crossville_market"
  - "crossville_forest_path"
is_starting_location: false
tags:
  - "social"
  - "rest"

Region

Represents a geographical region containing multiple locations.

Field Type Description
region_id str Unique identifier (e.g., "crossville")
name str Display name (e.g., "Crossville Province")
description str Region overview and atmosphere
location_ids List[str] All location IDs in this region

YAML Format:

region_id: "crossville"
name: "Crossville Province"
description: "A peaceful farming region on the edge of the kingdom."
location_ids:
  - "crossville_village"
  - "crossville_tavern"
  - "crossville_market"

LocationLoader Service

Singleton service that loads and caches location/region data from YAML files.

Location: /app/services/location_loader.py

Usage:

from app.services.location_loader import get_location_loader

loader = get_location_loader()

# Get specific location
location = loader.get_location("crossville_tavern")

# Get all locations in a region
locations = loader.get_locations_by_region("crossville")

# Get starting locations for new characters
starting_locations = loader.get_starting_locations()

# Get connected locations for travel
available = loader.get_discoverable_from("crossville_village")

Data Files:

  • /app/data/regions/crossville.yaml - Region definition with locations

NPC System

NPCs are persistent non-player characters with rich personality, knowledge, and interaction tracking. They are loaded from YAML files via NPCLoader.

NPC

Main NPC definition with personality and dialogue data for AI generation.

Field Type Description
npc_id str Unique identifier (e.g., "npc_grom_001")
name str Display name (e.g., "Grom Ironbeard")
role str NPC's job/title (e.g., "bartender", "blacksmith")
location_id str ID of location where NPC resides
personality NPCPersonality Personality traits and speech patterns
appearance NPCAppearance Physical description
image_url Optional[str] URL path to NPC portrait image (e.g., "/static/images/npcs/crossville/grom_ironbeard.png")
knowledge Optional[NPCKnowledge] What the NPC knows (public and secret)
relationships List[NPCRelationship] How NPC feels about other NPCs
inventory_for_sale List[NPCInventoryItem] Items NPC sells (if merchant)
dialogue_hooks Optional[NPCDialogueHooks] Pre-defined dialogue snippets
quest_giver_for List[str] Quest IDs this NPC can give
reveals_locations List[str] Location IDs this NPC can unlock
tags List[str] Metadata tags (e.g., "merchant", "quest_giver")

Methods:

  • to_dict() - Serialize for JSON responses
  • to_story_dict() - Trimmed version for AI dialogue prompts
  • from_dict(data) - Deserialize from YAML/JSON

NPCPersonality

Personality traits for AI dialogue generation.

Field Type Description
traits List[str] Personality descriptors (e.g., "gruff", "kind", "suspicious")
speech_style str How the NPC speaks (accent, vocabulary, patterns)
quirks List[str] Distinctive behaviors or habits

NPCAppearance

Physical description for AI narration.

Field Type Description
brief str Short one-line description for lists
detailed Optional[str] Longer description for detailed encounters

NPCKnowledge

Knowledge an NPC possesses - public and conditionally revealed.

Field Type Description
public List[str] Knowledge NPC freely shares with anyone
secret List[str] Hidden knowledge (for AI reference only)
will_share_if List[NPCKnowledgeCondition] Conditional reveals based on interaction

NPCKnowledgeCondition

Condition for revealing secret knowledge.

Field Type Description
condition str Expression (e.g., "interaction_count >= 3")
reveals str Information revealed when condition is met

NPCDialogueHooks

Pre-defined dialogue snippets for consistent NPC voice.

Field Type Description
greeting Optional[str] What NPC says when first addressed
farewell Optional[str] What NPC says when conversation ends
busy Optional[str] What NPC says when occupied
quest_complete Optional[str] What NPC says when player completes their quest

NPCRelationship

NPC-to-NPC relationship for dialogue context.

Field Type Description
npc_id str The other NPC's identifier
attitude str Feeling (e.g., "friendly", "distrustful")
reason Optional[str] Explanation for the attitude

NPCInventoryItem

Item available for purchase from merchant NPCs.

Field Type Description
item_id str Reference to item definition
price int Cost in gold
quantity Optional[int] Stock count (None = unlimited)

NPCInteractionState

Tracks a character's interaction history with an NPC. Stored on Character record.

Field Type Description
npc_id str The NPC this state tracks
first_met str ISO timestamp of first interaction
last_interaction str ISO timestamp of most recent interaction
interaction_count int Total number of conversations
revealed_secrets List[int] Indices of secrets revealed
relationship_level int 0-100 scale (50 is neutral)
custom_flags Dict[str, Any] Arbitrary flags for special conditions
dialogue_history List[Dict] Recent conversation exchanges (max 10 per NPC)

Dialogue History Entry Format:

{
  "player_line": "What have you heard about the old mines?",
  "npc_response": "Aye, strange noises coming from there lately...",
  "timestamp": "2025-11-24T10:30:00Z"
}

The dialogue history enables bidirectional NPC conversations - players can respond to NPC dialogue and continue conversations with context. The system maintains the last 10 exchanges per NPC to provide conversation context without excessive storage.

Relationship Levels:

  • 0-20: Hostile
  • 21-40: Unfriendly
  • 41-60: Neutral
  • 61-80: Friendly
  • 81-100: Trusted

Example NPC YAML:

npc_id: "npc_grom_001"
name: "Grom Ironbeard"
role: "bartender"
location_id: "crossville_tavern"
personality:
  traits:
    - "gruff"
    - "honest"
    - "protective of locals"
  speech_style: "Short sentences, occasional dwarven expressions"
  quirks:
    - "Polishes same glass repeatedly when nervous"
    - "Refuses to serve anyone who insults his stew"
appearance:
  brief: "A stocky dwarf with a magnificent iron-grey beard"
  detailed: "A weathered dwarf standing about four feet tall..."
knowledge:
  public:
    - "The tavern was built by his grandfather"
    - "Knows most travelers who pass through"
  secret:
    - "Saw strange lights in the forest last week"
  will_share_if:
    - condition: "relationship_level >= 70"
      reveals: "Has heard rumors of goblins gathering in the old mines"
dialogue_hooks:
  greeting: "Welcome to the Rusty Anchor! What'll it be?"
  farewell: "Safe travels, friend."
  busy: "Can't talk now, got orders to fill."
inventory_for_sale:
  - item: "ale"
    price: 2
  - item: "hearty_stew"
    price: 5
quest_giver_for:
  - "quest_rats_tavern"
reveals_locations:
  - "crossville_old_mines"
tags:
  - "merchant"
  - "quest_giver"
  - "information"

NPCLoader Service

Singleton service that loads and caches NPC data from YAML files.

Location: /app/services/npc_loader.py

Usage:

from app.services.npc_loader import get_npc_loader

loader = get_npc_loader()

# Get specific NPC
npc = loader.get_npc("npc_grom_001")

# Get all NPCs at a location
npcs = loader.get_npcs_at_location("crossville_tavern")

# Get NPCs by tag
merchants = loader.get_npcs_by_tag("merchant")

Data Files:

  • /app/data/npcs/crossville_npcs.yaml - NPCs for Crossville region

Character System

Stats

Field Type Description
strength int Physical power
dexterity int Agility and precision
constitution int Endurance and health
intelligence int Magical power
wisdom int Perception and insight
charisma int Social influence

Derived Properties (Computed):

  • hit_points = 10 + (constitution × 2)
  • mana_points = 10 + (intelligence × 2)
  • defense = constitution // 2 (physical damage reduction)
  • resistance = wisdom // 2 (magical damage reduction)

Note: Defense and resistance are computed properties, not stored values. They are calculated on-the-fly from constitution and wisdom.

SkillNode

Field Type Description
skill_id str Unique identifier
name str Display name
description str What the skill does
tier int 1-5 (1=basic, 5=master)
prerequisites List[str] Required skill_ids
effects Dict Stat bonuses, abilities unlocked
unlocked bool Current unlock status

Effect Types:

  • Passive bonuses (permanent stat increases)
  • Active abilities (new spells/skills to use)
  • Unlocks (access to equipment types or features)

SkillTree

Field Type Description
tree_id str Unique identifier
name str Tree name
description str Tree theme
nodes List[SkillNode] All nodes in tree

Methods:

  • can_unlock(skill_id, unlocked_skills) - Check if prerequisites met

Progression Rules:

  • Must unlock tier 1 before accessing tier 2
  • Some nodes have prerequisites within same tier
  • 1 skill point earned per level
  • Respec available (costs gold, scales with level)

PlayerClass

Field Type Description
class_id str Unique identifier
name str Class name
description str Class theme
base_stats Stats Starting stats
skill_trees List[SkillTree] 2+ skill trees
starting_equipment List[str] Starting item IDs

Initial 8 Player Classes

Class Theme Skill Tree 1 Skill Tree 2
Vanguard Tank/melee Defensive (shields, armor, taunts) Offensive (weapon mastery, heavy strikes)
Assassin Stealth/critical Assassination (critical hits, poisons) Shadow (stealth, evasion)
Arcanist Elemental spells Pyromancy (fire spells, DoT) Cryomancy (ice spells, crowd control)
Luminary Healing/support Holy (healing, buffs) Divine Wrath (smite, undead damage)
Wildstrider Ranged/nature Marksmanship (bow skills, critical shots) Beast Master (pet companion, nature magic)
Oathkeeper Hybrid tank/healer Protection (defensive auras, healing) Retribution (holy damage, smites)
Necromancer Death magic/summon Dark Arts (curses, life drain) Summoning (undead minions)
Lorekeeper Support/control Performance (buffs, debuffs via music) Trickery (illusions, charm)

Extensibility: Class system designed to easily add more classes in future updates.

Item

Field Type Description
item_id str Unique identifier
name str Item name
item_type str weapon, armor, consumable, quest_item
stats Dict[str, int] {"damage": 10, "defense": 5}
effects List[Effect] Buffs/debuffs on use/equip
value int Gold value
description str Item lore/description
is_tradeable bool Can be sold on marketplace

Item Types:

  • Weapon: Adds damage, may have special effects
  • Armor: Adds defense/resistance
  • Consumable: One-time use (potions, scrolls)
  • Quest Item: Story-related, non-tradeable

Ability

Abilities represent actions that can be taken in combat (attacks, spells, skills, item uses).

Field Type Description
ability_id str Unique identifier
name str Display name
description str What the ability does
ability_type AbilityType ATTACK, SPELL, SKILL, ITEM_USE, DEFEND
base_power int Base damage or healing value
damage_type DamageType Type of damage dealt (if applicable)
scaling_stat StatType Which stat scales this ability's power
scaling_factor float Multiplier for scaling stat (default 0.5)
mana_cost int MP required to use this ability
cooldown int Turns before ability can be used again
effects_applied List[Effect] Effects applied to target(s) on hit
is_aoe bool Whether this affects multiple targets
target_count int Number of targets if AoE (0 = all)

Damage/Healing Calculation:

Final Power = base_power + (scaling_stat × scaling_factor)
Minimum power is always 1

Example:

  • Fireball: base_power=30, scaling_stat=INTELLIGENCE, scaling_factor=0.5
  • If caster has 16 intelligence: 30 + (16 × 0.5) = 38 power

Methods:

  • calculate_power(caster_stats) - Calculate final power based on caster's stats
  • get_effects_to_apply() - Get copies of effects to apply to targets

AbilityLoader

Abilities are loaded from YAML configuration files in /app/data/abilities/ for data-driven game design.

YAML Format:

ability_id: "fireball"
name: "Fireball"
description: "Hurl a ball of fire at enemies"
ability_type: "spell"
base_power: 30
damage_type: "fire"
scaling_stat: "intelligence"
scaling_factor: 0.5
mana_cost: 15
cooldown: 0
is_aoe: false
target_count: 1
effects_applied:
  - effect_id: "burn"
    name: "Burning"
    effect_type: "dot"
    duration: 3
    power: 5
    max_stacks: 3

Usage:

from app.models.abilities import AbilityLoader

loader = AbilityLoader()
fireball = loader.load_ability("fireball")
power = fireball.calculate_power(caster_stats)

Benefits:

  • Game designers can add/modify abilities without code changes
  • Easy balancing and iteration
  • Version control friendly (text files)
  • Hot-reloading capable

Character

Field Type Description
character_id str Unique identifier
user_id str Owner user ID
name str Character name
player_class PlayerClass Character class
level int Current level
experience int XP points
stats Stats Current stats
unlocked_skills List[str] Unlocked skill_ids
inventory List[Item] All items
equipped Dict[str, Item] {"weapon": Item, "armor": Item}
gold int Currency
active_quests List[str] Quest IDs
discovered_locations List[str] Location IDs

Methods:

  • to_dict() - Serialize to dictionary for JSON storage
  • from_dict(data) - Deserialize from dictionary
  • get_effective_stats(active_effects) - THE CRITICAL METHOD - Calculate final stats

get_effective_stats() Details:

This is the single source of truth for all stat calculations in the game. It combines modifiers from all sources in this order:

def get_effective_stats(self, active_effects: Optional[List[Effect]] = None) -> Stats:
    """
    Calculate final effective stats from all sources:
    1. Base stats (from character)
    2. Equipment bonuses (from equipped items)
    3. Skill tree bonuses (from unlocked skills)
    4. Active effect modifiers (buffs/debuffs from combat)

    Returns fully typed Stats object with all modifiers applied.
    Debuffs are clamped to minimum stat value of 1.
    """

Example Calculation:

  • Base strength: 12
  • Equipped weapon bonus: +5 strength
  • Unlocked skill bonus: +5 strength
  • Active buff effect: +3 strength
  • Final effective strength: 25

Important Notes:

  • Defense and resistance are calculated from final constitution/wisdom
  • Debuffs cannot reduce stats below 1 (minimum clamping)
  • Equipment stat_bonuses dictionary: {"strength": 5, "constitution": 3}
  • Skill effects dictionary: {"strength": 5} extracted from unlocked skills

Story Progression System

ActionPrompt

Represents a button-based action prompt available to players during story progression turns.

Field Type Description
prompt_id str Unique identifier (e.g., "ask_surroundings")
category str Action category: "ask", "travel", "gather"
display_text str Button text shown to player
description str Tooltip/help text
tier_required str Minimum tier: "free", "basic", "premium", "elite"
context_filter Optional[str] Where action is available: "town", "wilderness", "any"
dm_prompt_template str Jinja2 template for AI prompt generation

Methods:

  • is_available(user_tier, location_type) -> bool - Check if action available to user

YAML Format:

prompt_id: "ask_surroundings"
category: "ask"
display_text: "What do I see around me?"
description: "Get a description of your current surroundings"
tier_required: "free"
context_filter: "any"
dm_prompt_template: |
  The player is currently in {{ location_name }}.
  Describe what they see, hear, and sense around them.

Tier-Based Availability:

  • Free tier: 4 basic actions (ask surroundings, check dangers, travel, explore)
  • Premium tier: +3 actions (recall memory, ask around, visit tavern)
  • Elite tier: +3 actions (search secrets, seek elder, chart course)
  • Premium/Elite: Custom free-form input (250/500 char limits)

Loading: Actions are loaded from /app/data/action_prompts.yaml via ActionPromptLoader service.

AI Response Parser

Data structures for parsing structured game actions from AI narrative responses.

ParsedAIResponse

Complete parsed AI response with narrative and game state changes.

Field Type Description
narrative str The narrative text to display to player
game_changes GameStateChanges Structured game state changes
raw_response str Original unparsed response
parse_success bool Whether parsing succeeded
parse_errors List[str] Any errors encountered

GameStateChanges

Structured game state changes extracted from AI response.

Field Type Description
items_given List[ItemGrant] Items to add to player inventory
items_taken List[str] Item IDs to remove
gold_given int Gold to add to player
gold_taken int Gold to remove from player
experience_given int XP to award player
quest_offered Optional[str] Quest ID to offer
quest_completed Optional[str] Quest ID completed
location_change Optional[str] New location ID

ItemGrant

Represents an item granted by the AI during gameplay.

Field Type Description
item_id Optional[str] ID for existing items from registry
name Optional[str] Name for generic items
item_type Optional[str] Type: weapon, armor, consumable, quest_item
description Optional[str] Description for generic items
value int Gold value (default 0)
quantity int Number of items (default 1)

Methods:

  • is_existing_item() -> bool - Check if references existing item
  • is_generic_item() -> bool - Check if AI-generated generic item

Files:

  • Parser: /app/ai/response_parser.py
  • Validator: /app/services/item_validator.py
  • Templates: /app/data/generic_items.yaml

Quest System

Quest

Represents a quest with objectives and rewards.

Field Type Description
quest_id str Unique identifier (e.g., "quest_rats_tavern")
name str Display name (e.g., "Rat Problem")
description str Full quest description
quest_giver str NPC or source name
difficulty str "easy", "medium", "hard", "epic"
objectives List[QuestObjective] List of objectives to complete
rewards QuestReward Rewards for completion
offering_triggers QuestTriggers When/where quest can be offered
narrative_hooks List[str] Story snippets for AI to use
status str "available", "active", "completed", "failed"
progress Dict[str, Any] Objective progress tracking

Methods:

  • is_complete() -> bool - Check if all objectives completed
  • get_next_objective() -> Optional[QuestObjective] - Get next incomplete objective
  • update_progress(objective_id, progress_value) -> None - Update objective progress
  • to_dict() / from_dict() - Serialization for JSON storage

YAML Format:

quest_id: "quest_rats_tavern"
name: "Rat Problem"
description: "Clear giant rats from the tavern basement"
quest_giver: "Tavern Keeper"
difficulty: "easy"
objectives:
  - objective_id: "kill_rats"
    description: "Kill 10 giant rats"
    objective_type: "kill"
    required_progress: 10
rewards:
  gold: 50
  experience: 100
  items: []
offering_triggers:
  location_types: ["town"]
  min_character_level: 1
  max_character_level: 3
  probability_weights:
    town: 0.30
    wilderness: 0.0
narrative_hooks:
  - "The tavern keeper waves you over, mentioning strange noises from the basement."

QuestObjective

Represents a single objective within a quest.

Field Type Description
objective_id str Unique ID (e.g., "kill_rats")
description str Player-facing description
objective_type str "kill", "collect", "travel", "interact", "discover"
required_progress int Target value (e.g., 10 rats)
current_progress int Current value (e.g., 5 rats killed)
completed bool Objective completion status

Objective Types:

  • kill: Defeat X enemies
  • collect: Gather X items
  • travel: Reach a specific location
  • interact: Talk to NPCs or interact with objects
  • discover: Find new locations or secrets

QuestReward

Rewards granted upon quest completion.

Field Type Description
gold int Gold reward
experience int XP reward (may trigger level up)
items List[str] Item IDs to grant
reputation Optional[str] Reputation faction (future feature)

QuestTriggers

Defines when and where a quest can be offered.

Field Type Description
location_types List[str] ["town", "wilderness", "dungeon"] or ["any"]
specific_locations List[str] Specific location IDs or empty for any
min_character_level int Minimum level required
max_character_level int Maximum level (for scaling)
required_quests_completed List[str] Quest prerequisites
probability_weights Dict[str, float] Location-specific offering chances

Methods:

  • get_offer_probability(location_type) -> float - Get probability for location type
  • can_offer(character_level, location, location_type, completed_quests) -> bool - Check if quest can be offered

Quest Offering Logic:

  1. Location-based roll: Towns (30%), Taverns (35%), Wilderness (5%), Dungeons (10%)
  2. Filter eligible quests: Level requirements, location match, prerequisites met
  3. Context-aware selection: AI analyzes narrative context to select fitting quest
  4. Max 2 active quests: Limit enforced to prevent player overwhelm

Quest Storage: Quests are defined in YAML files in /app/data/quests/ organized by difficulty:

  • /app/data/quests/easy/ - Levels 1-3
  • /app/data/quests/medium/ - Levels 3-7
  • /app/data/quests/hard/ - Levels 10+
  • /app/data/quests/epic/ - End-game content

Combat System

Effect

Effects are temporary status modifiers applied to combatants during combat.

Field Type Description
effect_id str Unique identifier
name str Effect name
effect_type EffectType BUFF, DEBUFF, DOT, HOT, STUN, SHIELD
duration int Turns remaining before expiration
power int Damage/healing per turn or stat modifier
stat_affected StatType Which stat is modified (for BUFF/DEBUFF only)
stacks int Current number of stacks (default 1)
max_stacks int Maximum stacks allowed (default 5)
source str Who/what applied it (ability_id or character_id)

Effect Types:

Type Description Power Usage
BUFF Increase stats temporarily Stat modifier (×stacks)
DEBUFF Decrease stats temporarily Stat modifier (×stacks)
DOT Damage over time (poison, bleed, burn) Damage per turn (×stacks)
HOT Heal over time (regeneration) Healing per turn (×stacks)
STUN Skip turn (cannot act) Not used
SHIELD Absorb damage before HP loss Shield strength (×stacks)

Methods:

tick() -> Dict[str, Any]

Process one turn of this effect. Called at the start of each combatant's turn.

Returns dictionary with:

  • effect_name: Name of the effect
  • effect_type: Type of effect
  • value: Damage dealt (DOT) or healing done (HOT) = power × stacks
  • shield_remaining: Current shield strength (SHIELD only)
  • stunned: True if this is a stun effect
  • stat_modifier: Amount stats are modified (BUFF/DEBUFF) = power × stacks
  • expired: True if duration reached 0
  • message: Human-readable description

Duration is decremented by 1 each tick. Effect is marked expired when duration reaches 0.

apply_stack(additional_duration) -> None

Apply an additional stack of this effect (stacking mechanic).

Behavior:

  • Increases stacks by 1 (up to max_stacks)
  • Refreshes duration to maximum
  • If already at max_stacks, only refreshes duration

Example: Poison with 2 stacks gets re-applied → becomes 3 stacks, duration refreshes

reduce_shield(damage) -> int

Reduce shield strength by damage amount (SHIELD effects only).

Returns remaining damage after shield absorption.

Examples:

  • Shield power=50, damage=30 → power becomes 20, returns 0 (all absorbed)
  • Shield power=20, damage=30 → power becomes 0, duration=0, returns 10 (partial)

Effect Stacking Rules:

  • Same effect applied multiple times increases stacks
  • Stacks are capped at max_stacks (default 5, configurable per effect)
  • Power scales linearly: 3 stacks of 5 power poison = 15 damage per turn
  • Duration refreshes on re-application (does not stack cumulatively)
  • Different effects (even same name) don't stack with each other

Combatant

Wrapper for a Character or Enemy in combat. Tracks combat-specific state.

Field Type Description
combatant_id str Character or enemy ID
name str Display name
is_player bool True for player characters, False for NPCs
current_hp int Current health points
max_hp int Maximum health points
current_mp int Current mana points
max_mp int Maximum mana points
stats Stats Combat stats (use Character.get_effective_stats())
active_effects List[Effect] Currently active effects on this combatant
abilities List[str] Available ability IDs (not full Ability objects)
cooldowns Dict[str, int] {ability_id: turns_remaining} for abilities on cooldown
initiative int Turn order value (rolled at combat start)

Methods:

  • is_alive() -> bool - Check if combatant has HP > 0
  • is_dead() -> bool - Check if combatant has HP <= 0
  • is_stunned() -> bool - Check if any active STUN effect
  • take_damage(damage) -> int - Apply damage with shield absorption, returns actual HP damage dealt
  • heal(amount) -> int - Restore HP (capped at max_hp), returns actual amount healed
  • restore_mana(amount) -> int - Restore MP (capped at max_mp)
  • can_use_ability(ability_id, ability) -> bool - Check if ability can be used (mana, cooldown)
  • use_ability_cost(ability, ability_id) -> None - Consume mana and set cooldown
  • tick_effects() -> List[Dict] - Process all active effects for this turn, remove expired
  • tick_cooldowns() -> None - Reduce all cooldowns by 1 turn
  • add_effect(effect) -> None - Add effect, stacks if same effect exists

Important Notes:

  • abilities stores ability IDs, not full Ability objects (for serialization)
  • stats should be set to Character.get_effective_stats() for players
  • Shield effects are processed automatically in take_damage()
  • Effects tick at start of turn via tick_effects()

CombatEncounter

Field Type Description
encounter_id str Unique identifier
combatants List[Combatant] All fighters
turn_order List[str] Combatant IDs in order
current_turn_index int Index in turn_order
round_number int Current round
combat_log List[Dict] Action history
status str active, victory, defeat

Methods:

  • initialize_combat() -> None - Roll initiative for all combatants, set turn order
  • get_current_combatant() -> Combatant - Get the combatant whose turn it is
  • get_combatant(combatant_id) -> Combatant - Get combatant by ID
  • advance_turn() -> None - Move to next combatant's turn, increment round if needed
  • start_turn() -> List[Dict] - Process effects and cooldowns at turn start
  • check_end_condition() -> CombatStatus - Check for victory/defeat, update status
  • log_action(action_type, combatant_id, message, details) -> None - Add entry to combat log

Combat Flow:

  1. initialize_combat() - Roll initiative, sort turn order
  2. Loop while status == ACTIVE:
    • start_turn() - Tick effects, check for stun
    • Execute action (if not stunned)
    • check_end_condition() - Check if combat should end
    • advance_turn() - Move to next combatant
  3. End when status becomes VICTORY, DEFEAT, or FLED

Session System

SessionConfig

Field Type Description
min_players int Session ends if below this
timeout_minutes int Inactivity timeout
auto_save_interval int Turns between auto-saves

GameSession

Field Type Description
session_id str Unique identifier
party_member_ids List[str] Character IDs in party
config SessionConfig Session settings
combat_encounter CombatEncounter Current combat or null
conversation_history List[Dict] Turn-by-turn log
game_state GameState Current world state
turn_order List[str] Character turn order
current_turn int Index in turn_order
turn_number int Global turn counter
created_at ISO Timestamp Session start
last_activity ISO Timestamp Last action time
status str active, completed, timeout

GameState

Field Type Description
current_location str Location name/ID
discovered_locations List[str] Location IDs
active_quests List[str] Quest IDs
world_events List[Dict] Server-wide events

Conversation History Entry

Field Type Description
turn int Turn number
character_id str Acting character
character_name str Character name
action str Player action text
dm_response str AI-generated response
combat_log List[Dict] Combat actions (if any)

Marketplace System

MarketplaceListing

Field Type Description
listing_id str Unique identifier
seller_id str User ID
character_id str Character ID
item_data Item Full item details
listing_type str "auction" or "fixed_price"
price int For fixed_price
starting_bid int For auction
current_bid int For auction
buyout_price int Optional instant buy
bids List[Bid] Bid history
auction_end ISO Timestamp For auction
status str active, sold, expired, removed
created_at ISO Timestamp Listing creation

Bid

Field Type Description
bidder_id str User ID
bidder_name str Character name
amount int Bid amount
timestamp ISO Timestamp Bid time

Transaction

Field Type Description
transaction_id str Unique identifier
buyer_id str User ID
seller_id str User ID
listing_id str Listing ID
item_data Item Item details
price int Final price
timestamp ISO Timestamp Transaction time
transaction_type str marketplace_sale, shop_purchase, etc.

NPC Shop System

ShopItem

Field Type Description
item_id str Item identifier
item Item Item details
stock int Available quantity (-1 = unlimited)
price int Fixed gold price

Shop Categories:

  • Consumables (health potions, mana potions)
  • Basic weapons (tier 1-2)
  • Basic armor (tier 1-2)
  • Crafting materials (future feature)

Purpose:

  • Provides gold sink to prevent inflation
  • Always available (not affected by marketplace access)
  • Sells basic items at fixed prices

Skill Tree Design

Each skill tree has 5 tiers with 3-5 nodes per tier.

Example: Vanguard - Shield Bearer Tree

Tier Node Type Prerequisites Effects
1 Shield Bash Active None Unlock shield_bash ability, 5 damage, 1 turn stun
1 Fortify Passive None +5 Defense
2 Shield Wall Active Shield Bash Unlock shield_wall ability, block all damage 1 turn, 3 turn cooldown
2 Iron Skin Passive Fortify +10 Defense, +5 HP
3 Guardian's Resolve Passive Shield Wall Immune to stun
3 Riposte Active Shield Bash Unlock riposte ability, counter attack on block
4 Bulwark Passive Iron Skin +15 Defense, +10 HP, damage reduction 10%
5 Unbreakable Ultimate Bulwark Unlock unbreakable ability, 5 turn buff: 50% damage reduction

Data Serialization

JSON Storage in Appwrite

All complex dataclasses are serialized to JSON strings for storage:

Storage:

Character dataclass → JSON string → Appwrite document field

Retrieval:

Appwrite document field → JSON string → Character dataclass

Benefits

  • Schema flexibility (easy to add fields)
  • No database migrations needed
  • Type safety in application code
  • Easy to serialize/deserialize

Future Data Models (Backlog)

Planned Additions

  • Guild: Player organizations
  • WorldEvent: Server-wide quests
  • Achievement: Badge system
  • CraftingRecipe: Item creation
  • PetCompanion: Beast Master pets
  • LeaderboardEntry: Rankings

Additional Player Classes (Backlog)

  • Monk (martial arts, chi energy)
  • Druid (shapeshifting, nature magic)
  • Warlock (pact magic, debuffs)
  • Artificer (gadgets, constructs)