Expand beyond vertical slice with two new biomes and massive chemistry expansion: Chemistry: +20 real elements (Li→U), +39 compounds (acids/salts/oxides/organics), +85 reactions (Haber process, thermite variants, smelting, fermentation, etc.) Biomes: Kinetic Mountains (physics/mechanics themed) and Verdant Forests (biology/ecology themed), each with 8 tile types and unique generation rules. Creatures: 6 new species — Pendulums/Mechanoids/Resonators (mountains), Symbiotes/Mimics/Spore-bearers (forests). Species filtered by biome. Infrastructure: CradleScene biome selector UI, generic world generator (tile lookup by property instead of hardcoded names), actinide element category. 487 tests passing (32 new). Co-authored-by: Cursor <cursoragent@cursor.com>
133 lines
3.5 KiB
TypeScript
133 lines
3.5 KiB
TypeScript
/**
|
|
* Creature Types — data definitions for the creature/ecology system
|
|
*
|
|
* Catalytic Wastes: Crystallids, Acidophiles, Reagents
|
|
* Kinetic Mountains: Pendulums, Mechanoids, Resonators
|
|
* Verdant Forests: Symbiotes, Mimics, Spore-bearers
|
|
*/
|
|
|
|
/** Species identifier (stored as numeric ID in ECS components) */
|
|
export enum SpeciesId {
|
|
Crystallid = 0,
|
|
Acidophile = 1,
|
|
Reagent = 2,
|
|
Pendulum = 3,
|
|
Mechanoid = 4,
|
|
Resonator = 5,
|
|
Symbiote = 6,
|
|
Mimic = 7,
|
|
SporeBearer = 8,
|
|
}
|
|
|
|
/** AI behavior state (FSM) */
|
|
export enum AIState {
|
|
Idle = 0,
|
|
Wander = 1,
|
|
Feed = 2,
|
|
Flee = 3,
|
|
Attack = 4,
|
|
}
|
|
|
|
/** Life cycle stage */
|
|
export enum LifeStage {
|
|
Egg = 0,
|
|
Youth = 1,
|
|
Mature = 2,
|
|
Aging = 3,
|
|
}
|
|
|
|
/** Diet type — what a creature can feed on */
|
|
export type DietType = 'mineral' | 'acid' | 'creature';
|
|
|
|
/** Species definition loaded from creatures.json */
|
|
export interface SpeciesData {
|
|
id: string;
|
|
name: string;
|
|
nameRu: string;
|
|
speciesId: SpeciesId;
|
|
biome: string; // biome id this species belongs to
|
|
description: string;
|
|
descriptionRu: string;
|
|
|
|
/** Visual */
|
|
color: string; // hex color string
|
|
radius: number; // base radius in pixels
|
|
radiusYouth: number; // smaller when young
|
|
|
|
/** Stats */
|
|
health: number;
|
|
speed: number; // pixels per second
|
|
damage: number; // damage per attack
|
|
armor: number; // damage reduction (0-1)
|
|
|
|
/** Metabolism */
|
|
diet: DietType;
|
|
dietTiles: string[]; // tile names this species feeds on
|
|
excretionElement: number; // atomic number of excreted element (0 = none)
|
|
energyMax: number; // max energy capacity
|
|
energyPerFeed: number; // energy gained per feeding
|
|
energyDrainPerSecond: number; // passive energy loss rate
|
|
hungerThreshold: number; // below this → seek food (0-1 fraction of max)
|
|
|
|
/** Behavior */
|
|
aggressionRadius: number; // distance to detect threats
|
|
fleeRadius: number; // distance to start fleeing
|
|
wanderRadius: number; // max wander distance from home
|
|
attackRange: number; // melee attack range
|
|
attackCooldown: number; // ms between attacks
|
|
|
|
/** Life cycle durations (ms) */
|
|
eggDuration: number;
|
|
youthDuration: number;
|
|
matureDuration: number;
|
|
agingDuration: number;
|
|
|
|
/** Reproduction */
|
|
reproductionEnergy: number; // energy cost to reproduce
|
|
offspringCount: number; // eggs per reproduction event
|
|
|
|
/** Population */
|
|
maxPopulation: number; // per-species cap
|
|
spawnWeight: number; // relative spawn density (0-1)
|
|
preferredTiles: string[]; // tiles where this species spawns
|
|
}
|
|
|
|
/** Runtime creature state (non-ECS, for string data lookup) */
|
|
export interface CreatureInfo {
|
|
speciesId: SpeciesId;
|
|
speciesDataId: string; // key into species registry
|
|
}
|
|
|
|
/** Creature species registry */
|
|
export class SpeciesRegistry {
|
|
private byId = new Map<string, SpeciesData>();
|
|
private byNumericId = new Map<SpeciesId, SpeciesData>();
|
|
|
|
constructor(data: SpeciesData[]) {
|
|
for (const species of data) {
|
|
this.byId.set(species.id, species);
|
|
this.byNumericId.set(species.speciesId, species);
|
|
}
|
|
}
|
|
|
|
/** Get species by string ID */
|
|
get(id: string): SpeciesData | undefined {
|
|
return this.byId.get(id);
|
|
}
|
|
|
|
/** Get species by numeric ID (from ECS component) */
|
|
getByNumericId(id: SpeciesId): SpeciesData | undefined {
|
|
return this.byNumericId.get(id);
|
|
}
|
|
|
|
/** Get all species */
|
|
getAll(): SpeciesData[] {
|
|
return [...this.byId.values()];
|
|
}
|
|
|
|
/** Get species count */
|
|
get count(): number {
|
|
return this.byId.size;
|
|
}
|
|
}
|