feat: add hunt API client and models for Playable Slice 0.2

Add to game-api.models.ts:
- DangerRating type for hunt encounter danger levels
- MonsterSummary interface with key, name, level, artworkPath
- HuntEncounter interface for individual hunt encounters
- HuntResult interface for hunt completion results, reusing LocationSummary

Extend CurrentLocationResponse with possibleMonsters: string[] field.

Add to game-api.service.ts:
- startHunt(): Observable<HuntResult> method posting to /api/hunts

Update test fixtures to include possibleMonsters field in mock locations.

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
Bastian Wagner
2026-08-19 13:14:07 +02:00
parent bb307da0ff
commit ed03726931
4 changed files with 30 additions and 1 deletions

View File

@@ -34,6 +34,7 @@ export interface CurrentLocationResponse {
huntingEnabled: boolean;
artworkPath: string;
connections: CurrentLocationConnection[];
possibleMonsters: string[];
}
export type CurrentTravel =
@@ -46,3 +47,24 @@ export type CurrentTravel =
arrivesAt: string;
}
| { status: 'COMPLETED'; targetLocation: LocationSummary };
export type DangerRating = 'WEAK' | 'MATCH' | 'STRONG' | 'VERY_DANGEROUS' | 'DEADLY';
export interface MonsterSummary {
key: string;
name: string;
level: number;
artworkPath: string;
}
export interface HuntEncounter {
id: string;
monster: MonsterSummary;
dangerRating: DangerRating;
}
export interface HuntResult {
id: string;
location: LocationSummary;
encounters: HuntEncounter[];
}

View File

@@ -1,7 +1,7 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { CharacterResponse, CurrentLocationResponse, CurrentTravel } from './game-api.models';
import { CharacterResponse, CurrentLocationResponse, CurrentTravel, HuntResult } from './game-api.models';
@Injectable({ providedIn: 'root' })
export class GameApiService {
@@ -22,4 +22,8 @@ export class GameApiService {
getCurrentTravel(): Observable<CurrentTravel> {
return this.http.get<CurrentTravel>('/api/travel/current');
}
startHunt(): Observable<HuntResult> {
return this.http.post<HuntResult>('/api/hunts', {});
}
}

View File

@@ -32,6 +32,7 @@ const southGate: CurrentLocationResponse = {
huntingEnabled: false,
artworkPath: '/images/backgrounds/Suedtor.png',
connections: [burnedRoadConnection],
possibleMonsters: [],
};
const burnedRoad: CurrentLocationResponse = {
@@ -43,6 +44,7 @@ const burnedRoad: CurrentLocationResponse = {
isSafe: false,
huntingEnabled: true,
artworkPath: '/images/backgrounds/Aschestrasse.png',
possibleMonsters: ['goblin', 'skeleton'],
connections: [
{
targetLocation: { id: 'south-gate-id', key: 'south-gate', name: 'Südtor von Graufurt' },

View File

@@ -33,6 +33,7 @@ const currentLocation: CurrentLocationResponse = {
isSafe: true,
huntingEnabled: false,
artworkPath: '/images/backgrounds/Suedtor.png',
possibleMonsters: [],
connections: [
{
targetLocation: {