Skip to content

Character

Responsibility

Character is the shared native model for human-like actors. It layers stats, body state, traits, skills, needs, equipment, inventory access, crafting knowledge, and activities on top of Creature; avatar and NPC implementations supply the concrete save boundary.

Entry points

Start at class Character in src/character.h, then follow the focused character_*.cpp translation unit for the behavior being changed. initialize, turn processing, inventory visits, effect handling, and the pure virtual serialize / deserialize boundary are the main integration points.

Data ownership

The instance owns character-specific mutable state and durable identifiers. It visits rather than globally owns map and vehicle objects; item ownership is mediated by worn, wielded, and inventory containers. Static definitions such as traits and professions are ID-backed data.

Dependencies

Character depends on Creature, item and pocket traversal, effects, activities, recipes, mutations, map coordinates, and save JSON. Callers must not bypass those owners' invariants.

Lifecycle

Construction establishes an uninitialized actor, initialize fills defaults, the game loop updates derived state and activities, and a concrete subclass saves or loads the actor. Actor conversion and NPC control require identity and ownership to remain coherent.

Invariants

Character IDs become stable once assigned; base stats and body parts must agree with derived caches; inventory mutation must invalidate the relevant caches; and position-dependent work must use the correct coordinate space and current map.

Extension points

Add narrowly scoped behavior in the matching character_*.cpp, reuse ID registries for new data, and add virtual behavior only when both avatar and NPC semantics are defined. Prefer JSON, EOC, or a supported Lua surface for content-only extensions.

Serialization

Character declares the contract but concrete subclasses serialize it. Durable field changes must be traced through src/savegame_json.cpp, legacy/default handling, and save compatibility; ephemeral caches should remain explicitly non-serialized.

Tests

Use focused character, crafting, effect, inventory, mutation, and save/world tests. A change to derived values needs assertions before and after cache invalidation, not only construction.

Performance

Turn processing is hot. Avoid repeated whole-inventory visits, registry lookups, and broad cache rebuilds; preserve the existing invalidation boundaries and measure large inventories.

CCB divergence

This page asserts no blanket equivalence with an upstream Character. CCB retains legacy EOC and mod-facing state such as kill_xp; every upstream port must be checked against CCB's current save, activity, and Lua boundaries.

Technical debt

The header records an ongoing, piecewise migration of player logic into Character, leaving many getters, setters, and wide dependencies. New work should reduce coupling locally without combining that cleanup with behavior changes.