feat: add hunt/monster domain entities and pure danger-rating helper

Adds Task 1 of Playable Slice 0.2: pure entity/enum/helper definitions
for the Hunt/Encounter system (MonsterDefinition, LocationMonster,
Hunt, HuntEncounter, EncounterType, HuntStatus, RandomSource,
DangerRating). No DB migration, module wiring, or seed data yet.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Bastian Wagner
2026-08-19 11:41:09 +02:00
parent 5b662aad4c
commit 0c2f079a6e
9 changed files with 305 additions and 0 deletions

View File

@@ -0,0 +1,6 @@
export enum EncounterType {
NORMAL = 'NORMAL',
RARE = 'RARE',
ELITE = 'ELITE',
BOSS = 'BOSS',
}

View File

@@ -0,0 +1,45 @@
import {
Column,
Entity,
JoinColumn,
ManyToOne,
PrimaryGeneratedColumn,
} from 'typeorm';
import { LocationDefinition } from '../../world/entities/location-definition.entity';
import { EncounterType } from './encounter-type.enum';
import { MonsterDefinition } from './monster-definition.entity';
@Entity({ name: 'location_monsters' })
export class LocationMonster {
@PrimaryGeneratedColumn('uuid', { name: 'id' })
id!: string;
@Column({ name: 'location_id', type: 'uuid' })
locationId!: string;
@Column({ name: 'monster_id', type: 'uuid' })
monsterId!: string;
@Column({ name: 'weight', type: 'integer' })
weight!: number;
@Column({
name: 'encounter_type',
type: 'enum',
enum: EncounterType,
enumName: 'location_monster_encounter_type_enum',
default: EncounterType.NORMAL,
})
encounterType!: EncounterType;
@Column({ name: 'enabled', type: 'boolean', default: true })
enabled!: boolean;
@ManyToOne(() => LocationDefinition, { onDelete: 'RESTRICT' })
@JoinColumn({ name: 'location_id' })
location!: LocationDefinition;
@ManyToOne(() => MonsterDefinition, { onDelete: 'RESTRICT' })
@JoinColumn({ name: 'monster_id' })
monster!: MonsterDefinition;
}

View File

@@ -0,0 +1,51 @@
import {
Column,
CreateDateColumn,
Entity,
Index,
PrimaryGeneratedColumn,
UpdateDateColumn,
} from 'typeorm';
@Entity({ name: 'monster_definitions' })
@Index('IDX_monster_definitions_key', ['key'], { unique: true })
export class MonsterDefinition {
@PrimaryGeneratedColumn('uuid', { name: 'id' })
id!: string;
@Column({ name: 'key', type: 'varchar', length: 100 })
key!: string;
@Column({ name: 'name', type: 'varchar', length: 150 })
name!: string;
@Column({ name: 'level', type: 'integer' })
level!: number;
@Column({ name: 'max_hp', type: 'integer' })
maxHp!: number;
@Column({ name: 'attack', type: 'integer' })
attack!: number;
@Column({ name: 'armor', type: 'integer' })
armor!: number;
@Column({ name: 'experience_reward', type: 'integer' })
experienceReward!: number;
@Column({ name: 'silver_min', type: 'integer' })
silverMin!: number;
@Column({ name: 'silver_max', type: 'integer' })
silverMax!: number;
@Column({ name: 'artwork_path', type: 'varchar', length: 255 })
artworkPath!: string;
@CreateDateColumn({ name: 'created_at', type: 'timestamptz' })
createdAt!: Date;
@UpdateDateColumn({ name: 'updated_at', type: 'timestamptz' })
updatedAt!: Date;
}