combat
This commit is contained in:
BIN
apps/web/public/assets/hud-elements/x.png
Normal file
BIN
apps/web/public/assets/hud-elements/x.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 MiB |
@@ -1,6 +1,6 @@
|
|||||||
<section class="combat" aria-label="Kampf">
|
<section class="combat" aria-label="Kampf">
|
||||||
@if (combat(); as combat) {
|
@if (combat(); as combat) {
|
||||||
<div class="combat__stage" [class.combat__stage--shaken]="phase() === 'hit'">
|
<div class="combat__stage" [class.combat__stage--shaken]="stageShake()">
|
||||||
<header class="combat__status">
|
<header class="combat__status">
|
||||||
<div class="fighter fighter--player">
|
<div class="fighter fighter--player">
|
||||||
<img class="fighter__icon" [src]="playerIcon" alt="" />
|
<img class="fighter__icon" [src]="playerIcon" alt="" />
|
||||||
|
|||||||
@@ -20,7 +20,12 @@
|
|||||||
container-type: inline-size;
|
container-type: inline-size;
|
||||||
grid-template-rows: auto minmax(0, 1fr) auto;
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
||||||
gap: var(--ar-space-4);
|
gap: var(--ar-space-4);
|
||||||
min-block-size: 26rem;
|
// The sprites are sized as a share of the stage, so the stage has to carry a
|
||||||
|
// height of its own. With only a min-block-size the tallest cut-out -- the
|
||||||
|
// road bandit -- sized the battlefield row from its intrinsic height and
|
||||||
|
// pushed the page into a scrollbar. The subtracted 12.5rem is the shell
|
||||||
|
// chrome around the main column: top bar, footer and its own padding.
|
||||||
|
block-size: max(24rem, calc(100dvh - 12.5rem));
|
||||||
padding: var(--ar-space-4);
|
padding: var(--ar-space-4);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
border: 1px solid var(--ar-border);
|
border: 1px solid var(--ar-border);
|
||||||
@@ -182,7 +187,11 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
display: grid;
|
display: grid;
|
||||||
|
// The single row is spelled out rather than left implicit: only then is it a
|
||||||
|
// definite height, and only then do the sprites' percentage heights resolve
|
||||||
|
// against the battlefield instead of against their own artwork.
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
|
grid-template-rows: minmax(0, 1fr);
|
||||||
align-items: end;
|
align-items: end;
|
||||||
min-block-size: 0;
|
min-block-size: 0;
|
||||||
}
|
}
|
||||||
@@ -602,7 +611,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.combat__stage {
|
.combat__stage {
|
||||||
min-block-size: clamp(24rem, 55vh, 34rem);
|
block-size: clamp(20rem, 55dvh, 34rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.combat__log {
|
.combat__log {
|
||||||
|
|||||||
@@ -162,7 +162,8 @@ describe('CombatPageComponent', () => {
|
|||||||
expect(sprite?.classList.contains('sprite--hit')).toBe(true);
|
expect(sprite?.classList.contains('sprite--hit')).toBe(true);
|
||||||
expect(monster?.classList.contains('sprite--lunge')).toBe(true);
|
expect(monster?.classList.contains('sprite--lunge')).toBe(true);
|
||||||
expect(monster?.classList.contains('sprite--flinch')).toBe(false);
|
expect(monster?.classList.contains('sprite--flinch')).toBe(false);
|
||||||
expect(stage?.classList.contains('combat__stage--shaken')).toBe(true);
|
// The stage jolt is wired up but no longer fires on an ordinary hit.
|
||||||
|
expect(stage?.classList.contains('combat__stage--shaken')).toBe(false);
|
||||||
expect(element.textContent).toContain('90 / 100');
|
expect(element.textContent).toContain('90 / 100');
|
||||||
expect(countOccurrences(element.textContent, monsterHitLine)).toBe(2);
|
expect(countOccurrences(element.textContent, monsterHitLine)).toBe(2);
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ const SWING_MS = 540;
|
|||||||
const RECOIL_MS = 540;
|
const RECOIL_MS = 540;
|
||||||
// Beat between the player's blow landing and the monster striking back.
|
// Beat between the player's blow landing and the monster striking back.
|
||||||
const RIPOSTE_DELAY_MS = 260;
|
const RIPOSTE_DELAY_MS = 260;
|
||||||
|
// Length of the stage jolt keyframes, see `stage-shake` in the stylesheet.
|
||||||
|
const STAGE_SHAKE_MS = 200;
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-combat-page',
|
selector: 'app-combat-page',
|
||||||
@@ -47,9 +49,15 @@ export class CombatPageComponent implements OnInit {
|
|||||||
private readonly displayed = signal<Combat | null>(null);
|
private readonly displayed = signal<Combat | null>(null);
|
||||||
private readonly replaying = signal(false);
|
private readonly replaying = signal(false);
|
||||||
|
|
||||||
|
// The stage jolt stays wired up but is no longer fired by an ordinary hit --
|
||||||
|
// it was too much for every single round. Call `shakeStage()` to bring it
|
||||||
|
// back for a specific ability.
|
||||||
|
private readonly stageShaking = signal(false);
|
||||||
|
|
||||||
protected readonly combat = this.displayed.asReadonly();
|
protected readonly combat = this.displayed.asReadonly();
|
||||||
protected readonly phase = signal<CombatPhase>('idle');
|
protected readonly phase = signal<CombatPhase>('idle');
|
||||||
protected readonly monsterPhase = signal<MonsterPhase>('idle');
|
protected readonly monsterPhase = signal<MonsterPhase>('idle');
|
||||||
|
protected readonly stageShake = this.stageShaking.asReadonly();
|
||||||
protected readonly busy = computed(() => this.replaying() || this.combatStore.actionPending());
|
protected readonly busy = computed(() => this.replaying() || this.combatStore.actionPending());
|
||||||
protected readonly playerIcon = PLAYER_ICON;
|
protected readonly playerIcon = PLAYER_ICON;
|
||||||
|
|
||||||
@@ -125,6 +133,16 @@ export class CombatPageComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Jolts the whole stage once. Reserved for abilities; no attack triggers it. */
|
||||||
|
protected shakeStage(): void {
|
||||||
|
this.stageShaking.set(true);
|
||||||
|
setTimeout(() => {
|
||||||
|
if (!this.destroyed) {
|
||||||
|
this.stageShaking.set(false);
|
||||||
|
}
|
||||||
|
}, STAGE_SHAKE_MS);
|
||||||
|
}
|
||||||
|
|
||||||
protected retry(): void {
|
protected retry(): void {
|
||||||
void this.loadFromRoute();
|
void this.loadFromRoute();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<div class="app-shell">
|
<div class="app-shell">
|
||||||
<app-top-bar [character]="worldStore.character()" />
|
<app-top-bar [character]="worldStore.character()" />
|
||||||
|
|
||||||
<div class="app-shell__content">
|
<div class="app-shell__content" [class.app-shell__content--no-context]="inCombat()">
|
||||||
<app-side-navigation />
|
<app-side-navigation />
|
||||||
<main class="app-shell__main" aria-label="Spielinhalt">
|
<main class="app-shell__main" aria-label="Spielinhalt">
|
||||||
<router-outlet />
|
<router-outlet />
|
||||||
</main>
|
</main>
|
||||||
|
@if (!inCombat()) {
|
||||||
<app-context-panel />
|
<app-context-panel />
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<app-game-footer />
|
<app-game-footer />
|
||||||
|
|||||||
@@ -16,6 +16,12 @@
|
|||||||
min-block-size: 0;
|
min-block-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Without the context rail the main column takes its place. The narrow layouts
|
||||||
|
// below re-declare the template, so they keep working either way.
|
||||||
|
.app-shell__content--no-context {
|
||||||
|
grid-template-columns: minmax(11rem, 13rem) minmax(0, 1fr);
|
||||||
|
}
|
||||||
|
|
||||||
.app-shell__main {
|
.app-shell__main {
|
||||||
min-inline-size: 0;
|
min-inline-size: 0;
|
||||||
min-block-size: 0;
|
min-block-size: 0;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Component, inject } from '@angular/core';
|
import { Component, inject } from '@angular/core';
|
||||||
import { RouterOutlet } from '@angular/router';
|
import { Router, RouterOutlet, isActive } from '@angular/router';
|
||||||
import { WorldStore } from '../../features/world/world.store';
|
import { WorldStore } from '../../features/world/world.store';
|
||||||
import { ContextPanelComponent } from '../context-panel/context-panel.component';
|
import { ContextPanelComponent } from '../context-panel/context-panel.component';
|
||||||
import { GameFooterComponent } from '../game-footer/game-footer.component';
|
import { GameFooterComponent } from '../game-footer/game-footer.component';
|
||||||
@@ -20,4 +20,8 @@ import { TopBarComponent } from '../top-bar/top-bar.component';
|
|||||||
})
|
})
|
||||||
export class AppShellComponent {
|
export class AppShellComponent {
|
||||||
protected readonly worldStore = inject(WorldStore);
|
protected readonly worldStore = inject(WorldStore);
|
||||||
|
|
||||||
|
// The fight has its own log rail and wants the width, and the area info
|
||||||
|
// belongs to the world view anyway, so the rail is dropped during combat.
|
||||||
|
protected readonly inCombat = isActive('/combat', inject(Router));
|
||||||
}
|
}
|
||||||
|
|||||||
1916
docs/Ashen_Realms_Story_Narrative_Implementation_V1.md
Normal file
1916
docs/Ashen_Realms_Story_Narrative_Implementation_V1.md
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/references/verbrannte_strasse_in_den_aschenfeldern.png
Normal file
BIN
docs/references/verbrannte_strasse_in_den_aschenfeldern.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.3 MiB |
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,921 @@
|
|||||||
|
# Ashen Realms – Local Location View Design Specification V1
|
||||||
|
|
||||||
|
## Zweck
|
||||||
|
|
||||||
|
Dieses Dokument definiert die dauerhaften Design- und Content-Regeln für die **lokale Ortsansicht** von Ashen Realms.
|
||||||
|
|
||||||
|
Die Ortsansicht bildet die fehlende Weltebene zwischen der globalen Karte und spezialisierten Aktivitäten wie Jagd, Kampf, Händler, Quests, Dungeons oder Bossen.
|
||||||
|
|
||||||
|
Sie beantwortet dem Spieler unmittelbar vier Fragen:
|
||||||
|
|
||||||
|
1. **Wo bin ich?**
|
||||||
|
2. **Wie sieht dieser Ort aus und wie fühlt er sich an?**
|
||||||
|
3. **Wer oder was befindet sich hier?**
|
||||||
|
4. **Was kann ich hier tun?**
|
||||||
|
|
||||||
|
Diese Spezifikation soll auch für zukünftige Gebiete und Orte gültig bleiben. Einzelne Orte dürfen sich visuell und spielerisch deutlich unterscheiden, verwenden aber dieselbe grundlegende Struktur und dasselbe Interaktionsmodell.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 1. Rolle im Kernloop
|
||||||
|
|
||||||
|
Die lokale Ortsansicht wird zum normalen Ankunfts- und Ausgangsscreen, solange sich der Charakter physisch an einem Ort befindet.
|
||||||
|
|
||||||
|
Empfohlener Ablauf:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Karte
|
||||||
|
→ Reise
|
||||||
|
→ Ortsansicht
|
||||||
|
→ Aktivität
|
||||||
|
→ Jagd
|
||||||
|
→ NPC
|
||||||
|
→ Untersuchung
|
||||||
|
→ Händler
|
||||||
|
→ Quest
|
||||||
|
→ Boss / Dungeon
|
||||||
|
→ zurück zur Ortsansicht
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Karte beantwortet:
|
||||||
|
|
||||||
|
**Wohin kann ich reisen?**
|
||||||
|
|
||||||
|
Die Ortsansicht beantwortet:
|
||||||
|
|
||||||
|
**Was gibt es hier?**
|
||||||
|
|
||||||
|
Die Jagd beantwortet:
|
||||||
|
|
||||||
|
**Was kann ich hier bekämpfen?**
|
||||||
|
|
||||||
|
Der Kampf beantwortet:
|
||||||
|
|
||||||
|
**Wie besiege ich diesen Gegner?**
|
||||||
|
|
||||||
|
Diese Verantwortlichkeiten sollen getrennt bleiben.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 2. Position in der Navigation
|
||||||
|
|
||||||
|
Die persistente linke Navigation erhält einen eigenen Eintrag:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ort
|
||||||
|
Karte
|
||||||
|
Jagd
|
||||||
|
Quests
|
||||||
|
Inventar
|
||||||
|
Charakter
|
||||||
|
Shop
|
||||||
|
```
|
||||||
|
|
||||||
|
`Ort` ist aktiv hervorgehoben, solange der Spieler die lokale Ortsansicht betrachtet.
|
||||||
|
|
||||||
|
Der Spieler soll grundsätzlich jederzeit zu dieser Ansicht zurückkehren können, sofern kein blockierender Gameplay-Zustand aktiv ist, beispielsweise ein noch nicht abgeschlossener Kampf.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 3. Ziel des Spielerlebnisses
|
||||||
|
|
||||||
|
Ein Ort muss sich wie ein **Ort** anfühlen und nicht wie ein Datensatz oder Menüpunkt.
|
||||||
|
|
||||||
|
Der Screen soll beim Spieler das Gefühl erzeugen:
|
||||||
|
|
||||||
|
> Ich befinde mich gerade hier. Das ist meine Umgebung. Diese Personen und interessanten Punkte befinden sich hier. Von hier aus entscheide ich, was ich als Nächstes tue.
|
||||||
|
|
||||||
|
Die Ortsansicht ist deshalb kein Dashboard aus vielen kleinen Karten.
|
||||||
|
|
||||||
|
Das zentrale Artwork ist die wichtigste Präsentationsebene.
|
||||||
|
|
||||||
|
UI liegt darum herum oder gezielt darüber.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 4. Grundaufbau des Screens
|
||||||
|
|
||||||
|
Jede Ortsansicht verwendet den bestehenden Ashen-Realms-App-Shell:
|
||||||
|
|
||||||
|
- persistente Topbar
|
||||||
|
- persistente linke Navigation
|
||||||
|
- große zentrale Artwork-Fläche
|
||||||
|
- kontextuelle rechte Sidebar
|
||||||
|
- persistenter Footer / Weltstatus
|
||||||
|
|
||||||
|
Der eigentliche Ortsinhalt besteht aus fünf funktionalen Ebenen.
|
||||||
|
|
||||||
|
## 4.1 Ortskopf
|
||||||
|
|
||||||
|
Zeigt:
|
||||||
|
|
||||||
|
- Ortsname
|
||||||
|
- Gebiet / Region als Breadcrumb
|
||||||
|
- kurze atmosphärische Beschreibung
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Verbrannte Straße
|
||||||
|
Gebiet 1 > Aschenfelder
|
||||||
|
|
||||||
|
Ein alter Handelsweg, der durch Feuer und Krieg in Asche gelegt wurde.
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Beschreibung sollte meist in 1–3 kurzen Zeilen auskommen.
|
||||||
|
|
||||||
|
Längere Lore gehört in Dialoge, Quests, Bücher oder eigene Lore-Inhalte.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4.2 Großes Orts-Artwork
|
||||||
|
|
||||||
|
Das Orts-Artwork ist das visuelle Zentrum des Screens.
|
||||||
|
|
||||||
|
Es soll vermitteln:
|
||||||
|
|
||||||
|
- Biom
|
||||||
|
- lokale Gefahr
|
||||||
|
- Wetter / Atmosphäre
|
||||||
|
- Architektur
|
||||||
|
- Spuren vergangener Ereignisse
|
||||||
|
- wichtige Landmarken
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
### Aschenfelder
|
||||||
|
- verbrannte Straßen
|
||||||
|
- Asche
|
||||||
|
- Glut
|
||||||
|
- tote Bäume
|
||||||
|
- zerstörte Wagen
|
||||||
|
- Rauch
|
||||||
|
|
||||||
|
### Dämmerwald
|
||||||
|
- dichte Vegetation
|
||||||
|
- Nebel
|
||||||
|
- dunkles Blätterdach
|
||||||
|
- überwucherte Ruinen
|
||||||
|
- Spuren verdorbener Tiere
|
||||||
|
|
||||||
|
### Vergessene Ruinen
|
||||||
|
- alter Stein
|
||||||
|
- Gräber
|
||||||
|
- eingestürzte Mauern
|
||||||
|
- Banner
|
||||||
|
- Krypteneingänge
|
||||||
|
- kaltes magisches Licht
|
||||||
|
|
||||||
|
Interaktionsbeschriftungen dürfen **nicht fest in das Artwork eingebrannt** sein.
|
||||||
|
|
||||||
|
Marker und Labels werden durch die UI gerendert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 5. Points of Interest und Hotspots
|
||||||
|
|
||||||
|
Ein Ort kann direkt auf dem Artwork interaktive **Points of Interest (POIs)** besitzen.
|
||||||
|
|
||||||
|
Ein POI besteht aus:
|
||||||
|
|
||||||
|
- Icon
|
||||||
|
- Titel
|
||||||
|
- optionalem kurzen Aktionslabel
|
||||||
|
- normalisierter X-/Y-Position im Artwork
|
||||||
|
- Interaktionstyp
|
||||||
|
- optionalem Verfügbarkeitszustand
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Truhen-Icon]
|
||||||
|
Verlassener Wagen
|
||||||
|
Durchsuchen
|
||||||
|
```
|
||||||
|
|
||||||
|
POIs sollen sich optisch in die Szene integrieren.
|
||||||
|
|
||||||
|
Der Screen darf dadurch nicht zu einem Hidden-Object-Spiel werden.
|
||||||
|
|
||||||
|
Empfohlene sichtbare Anzahl:
|
||||||
|
|
||||||
|
- einfacher Übergangsort: 1–3
|
||||||
|
- normaler Ort: 2–5
|
||||||
|
- großer Hub: 3–7
|
||||||
|
|
||||||
|
Wenn deutlich mehr Aktionen notwendig sind, müssen sie gruppiert oder in eigene Panels/Screens ausgelagert werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 6. Wiederverwendbare Interaktionstypen
|
||||||
|
|
||||||
|
Die erste gemeinsame Interaktionssprache lautet:
|
||||||
|
|
||||||
|
```text
|
||||||
|
HUNT
|
||||||
|
INVESTIGATE
|
||||||
|
SEARCH
|
||||||
|
NPC
|
||||||
|
MAP
|
||||||
|
TRAVEL
|
||||||
|
SHOP
|
||||||
|
QUEST
|
||||||
|
BOSS
|
||||||
|
DUNGEON
|
||||||
|
```
|
||||||
|
|
||||||
|
Nicht jeder Typ muss bereits im ersten Slice vollständig umgesetzt sein.
|
||||||
|
|
||||||
|
Wichtig ist, dass neue Orte aus wiederverwendbaren Interaktionstypen aufgebaut werden und nicht jeweils eigene Angular-Spezialkomponenten erhalten.
|
||||||
|
|
||||||
|
## 6.1 HUNT
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
|
||||||
|
Startet die normale Jagd-/Encounter-Schleife des aktuellen Ortes.
|
||||||
|
|
||||||
|
Ablauf:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ortsansicht
|
||||||
|
→ Jagd
|
||||||
|
```
|
||||||
|
|
||||||
|
Die Ortsansicht würfelt oder rendert selbst keine Encounter-Auswahl.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.2 INVESTIGATE
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
|
||||||
|
Untersucht Spuren, Ruinen, Symbole, Leichen, Zeichen oder andere Hinweise in der Umgebung.
|
||||||
|
|
||||||
|
Mögliche Ergebnisse:
|
||||||
|
|
||||||
|
- atmosphärischer Text
|
||||||
|
- Lore-Hinweis
|
||||||
|
- Hinweis auf einen Ort
|
||||||
|
- später Questfortschritt
|
||||||
|
- später versteckte Verbindung
|
||||||
|
|
||||||
|
Für die erste Umsetzung reicht ein serverseitig geliefertes Ergebnis-Panel.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.3 SEARCH
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
|
||||||
|
Durchsucht ein konkretes Objekt oder einen kleinen Bereich.
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
- verlassener Wagen
|
||||||
|
- alte Vorratskiste
|
||||||
|
- Lagerreste
|
||||||
|
- Kryptennische
|
||||||
|
|
||||||
|
Später mögliche Ergebnisse:
|
||||||
|
|
||||||
|
- Item
|
||||||
|
- Währung
|
||||||
|
- Verbrauchsgegenstand
|
||||||
|
- Hinweis
|
||||||
|
- nichts
|
||||||
|
|
||||||
|
Sobald eine Interaktion echte Belohnungen vergibt, muss sie serverautoritativ sein.
|
||||||
|
|
||||||
|
Die erste Version darf reine Text-/Informationsresultate verwenden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.4 NPC
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
|
||||||
|
Interaktion mit einem sichtbar am Ort vorhandenen NPC.
|
||||||
|
|
||||||
|
Für V1 reicht ein einfaches Dialogpanel.
|
||||||
|
|
||||||
|
Spätere Erweiterungen können sein:
|
||||||
|
|
||||||
|
- Quests
|
||||||
|
- Händler
|
||||||
|
- Ruf-/Tauschsystem
|
||||||
|
- Dienstleistungen
|
||||||
|
- Fraktionsinteraktionen
|
||||||
|
|
||||||
|
NPCs sollen möglichst im Kontext der Szene sichtbar sein und nicht ausschließlich als Textliste in einem Panel erscheinen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.5 MAP
|
||||||
|
|
||||||
|
Zweck:
|
||||||
|
|
||||||
|
Öffnet die bestehende Karten-/Reiseansicht.
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ortsansicht
|
||||||
|
→ Karte
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.6 TRAVEL
|
||||||
|
|
||||||
|
Reisen bleibt Bestandteil des bestehenden Karten-/Reisesystems.
|
||||||
|
|
||||||
|
Die Ortsansicht darf visuell Ausgänge oder Ziele zeigen, soll aber im Normalfall in den vorhandenen Reiseflow weiterleiten statt eine zweite Reiselogik zu bauen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6.7 SHOP, QUEST, BOSS, DUNGEON
|
||||||
|
|
||||||
|
Diese Typen sind Erweiterungspunkte für späteren Content.
|
||||||
|
|
||||||
|
Sie verwenden dieselben POI- und Aktionsregeln, öffnen aber jeweils einen eigenen Screen, ein Panel oder einen spezialisierten Flow.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 7. Primäre Aktionsleiste
|
||||||
|
|
||||||
|
Die wichtigsten lokalen Aktionen werden zusätzlich in einer großen Aktionsleiste unterhalb des Artworks dargestellt.
|
||||||
|
|
||||||
|
Diese Dopplung ist beabsichtigt.
|
||||||
|
|
||||||
|
POIs erzeugen Atmosphäre und räumlichen Kontext.
|
||||||
|
|
||||||
|
Die Aktionsleiste sorgt für klare Bedienbarkeit.
|
||||||
|
|
||||||
|
Empfohlenes Maximum:
|
||||||
|
|
||||||
|
**4 primäre Ortsaktionen**
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Jagd beginnen]
|
||||||
|
[Spuren untersuchen]
|
||||||
|
[Umgebung durchsuchen]
|
||||||
|
[Zur Karte]
|
||||||
|
```
|
||||||
|
|
||||||
|
Sekundäre Aktionen dürfen ausschließlich als POI oder in der rechten Sidebar erscheinen.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 8. Rechte Kontext-Sidebar
|
||||||
|
|
||||||
|
Die rechte Sidebar fasst die spielerische Bedeutung des aktuellen Ortes zusammen.
|
||||||
|
|
||||||
|
Empfohlene Bereiche:
|
||||||
|
|
||||||
|
## Ortsidentität
|
||||||
|
|
||||||
|
- Gebiet / Region
|
||||||
|
- Ortsname
|
||||||
|
- Ortstyp
|
||||||
|
|
||||||
|
## Progressionskontext
|
||||||
|
|
||||||
|
- empfohlener Fortschrittsbereich oder Empfehlung
|
||||||
|
- relative Gefahr
|
||||||
|
|
||||||
|
Diese Information darf keine harte Zugangssperre sein.
|
||||||
|
|
||||||
|
Der bestehende Ashen-Realms-Grundsatz bleibt:
|
||||||
|
|
||||||
|
> Die Welt kommuniziert Gefahr, ohne Experimente künstlich zu verbieten.
|
||||||
|
|
||||||
|
## Mögliche Begegnungen
|
||||||
|
|
||||||
|
Zeigt repräsentative Gegner oder Encounter-Kategorien.
|
||||||
|
|
||||||
|
Das ist nur Vorschauinformation.
|
||||||
|
|
||||||
|
Der tatsächliche Encounter-Wurf erfolgt weiterhin im Jagdsystem.
|
||||||
|
|
||||||
|
## Verfügbare Interaktionen
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
- Jagd
|
||||||
|
- Untersuchen
|
||||||
|
- Durchsuchen
|
||||||
|
- Sprechen
|
||||||
|
|
||||||
|
## Mögliche Belohnungen
|
||||||
|
|
||||||
|
Optionale Vorschau-Icons für:
|
||||||
|
|
||||||
|
- Ausrüstung
|
||||||
|
- Materialien
|
||||||
|
- Verbrauchsgegenstände
|
||||||
|
- Handelswaren
|
||||||
|
- regionsspezifische Belohnungen
|
||||||
|
|
||||||
|
Es dürfen keine exakten Belohnungen versprochen werden, wenn der zugrunde liegende Content diese nicht garantiert.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 9. Ortstypen
|
||||||
|
|
||||||
|
Orte können über wiederverwendbare Typen ihre grundlegende Rolle ausdrücken.
|
||||||
|
|
||||||
|
Empfohlene Startwerte:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SAFE_HUB
|
||||||
|
TRANSITION
|
||||||
|
HUNTING_GROUND
|
||||||
|
QUEST_LOCATION
|
||||||
|
OUTPOST
|
||||||
|
ELITE_ZONE
|
||||||
|
BOSS_LOCATION
|
||||||
|
DUNGEON_ENTRANCE
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Typ beeinflusst Präsentation und verfügbare Aktionen, benötigt aber keine eigene Page-Implementierung.
|
||||||
|
|
||||||
|
Beispiele:
|
||||||
|
|
||||||
|
### Südtor von Graufurt
|
||||||
|
|
||||||
|
```text
|
||||||
|
TRANSITION
|
||||||
|
```
|
||||||
|
|
||||||
|
Fokus:
|
||||||
|
|
||||||
|
- Wachposten
|
||||||
|
- Reise
|
||||||
|
- Gebietsinformation
|
||||||
|
- wenig oder keine reguläre Jagd
|
||||||
|
|
||||||
|
### Verbrannte Straße
|
||||||
|
|
||||||
|
```text
|
||||||
|
HUNTING_GROUND
|
||||||
|
```
|
||||||
|
|
||||||
|
Fokus:
|
||||||
|
|
||||||
|
- Jagd
|
||||||
|
- Umgebungsinformationen
|
||||||
|
- Spuren
|
||||||
|
- erste NPC-Begegnung
|
||||||
|
|
||||||
|
### Verlassener Wachtposten
|
||||||
|
|
||||||
|
```text
|
||||||
|
OUTPOST / QUEST_LOCATION
|
||||||
|
```
|
||||||
|
|
||||||
|
Fokus:
|
||||||
|
|
||||||
|
- NPC
|
||||||
|
- stärkere Jagd
|
||||||
|
- Untersuchung
|
||||||
|
- Storyfortschritt
|
||||||
|
|
||||||
|
### Aschengrube
|
||||||
|
|
||||||
|
```text
|
||||||
|
ELITE_ZONE / BOSS_LOCATION
|
||||||
|
```
|
||||||
|
|
||||||
|
Fokus:
|
||||||
|
|
||||||
|
- Gefahr
|
||||||
|
- Elite-/Bosszugang
|
||||||
|
- kaum zivile Interaktionen
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 10. Wiederverwendbares Content-Modell
|
||||||
|
|
||||||
|
Die Ortsansicht soll datengetrieben sein.
|
||||||
|
|
||||||
|
Ein konzeptionelles View-Model sollte mindestens enthalten:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface LocalLocationView {
|
||||||
|
locationId: string;
|
||||||
|
locationKey: string;
|
||||||
|
name: string;
|
||||||
|
regionName: string;
|
||||||
|
description: string;
|
||||||
|
locationType: LocationType;
|
||||||
|
artworkPath: string;
|
||||||
|
dangerRating: DangerRating;
|
||||||
|
recommendationLabel?: string;
|
||||||
|
huntingEnabled: boolean;
|
||||||
|
pointsOfInterest: LocationPointOfInterest[];
|
||||||
|
primaryActions: LocationAction[];
|
||||||
|
encounterPreview: EncounterPreview[];
|
||||||
|
rewardPreview: RewardPreview[];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Konzeptionelles POI-Modell:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface LocationPointOfInterest {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
actionLabel?: string;
|
||||||
|
type: LocationInteractionType;
|
||||||
|
iconKey: string;
|
||||||
|
xPercent: number;
|
||||||
|
yPercent: number;
|
||||||
|
enabled: boolean;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Koordinaten werden als Prozentwerte gespeichert, damit Hotspots beim Skalieren des Artworks an derselben Stelle bleiben.
|
||||||
|
|
||||||
|
Beispiel:
|
||||||
|
|
||||||
|
```text
|
||||||
|
xPercent: 42.5
|
||||||
|
yPercent: 66.0
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 11. Interaktionsergebnisse
|
||||||
|
|
||||||
|
Lokale Interaktionen sollen ein vorhersehbares Ergebnisformat zurückgeben.
|
||||||
|
|
||||||
|
Konzeptionell:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
interface LocationInteractionResult {
|
||||||
|
interactionKey: string;
|
||||||
|
title: string;
|
||||||
|
text: string;
|
||||||
|
nextAction?: {
|
||||||
|
type: string;
|
||||||
|
target?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Die erste Version bleibt bewusst klein.
|
||||||
|
|
||||||
|
Nicht nur für diesen Screen bauen:
|
||||||
|
|
||||||
|
- generische Visual-Novel-Engine
|
||||||
|
- verzweigte Dialogengine
|
||||||
|
- Event-Skriptsprache
|
||||||
|
- komplexen Questgraph
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 12. Navigationsregeln
|
||||||
|
|
||||||
|
## Nach abgeschlossener Reise
|
||||||
|
|
||||||
|
Der Spieler landet in der lokalen Ortsansicht des neuen aktuellen Ortes.
|
||||||
|
|
||||||
|
```text
|
||||||
|
Reise abgeschlossen
|
||||||
|
→ current location aktualisiert
|
||||||
|
→ Ortsansicht
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nach normalem Kampf
|
||||||
|
|
||||||
|
Empfohlener Standard:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Kampfergebnis / Loot
|
||||||
|
→ Ortsansicht
|
||||||
|
```
|
||||||
|
|
||||||
|
Von dort kann der Spieler erneut jagen.
|
||||||
|
|
||||||
|
## Beim Verlassen der Jagd
|
||||||
|
|
||||||
|
`Zurück` führt zur Ortsansicht.
|
||||||
|
|
||||||
|
## Karte
|
||||||
|
|
||||||
|
`Zur Karte` öffnet die Karte, verändert aber nicht den aktuellen Ort.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 13. Screen-Zustände
|
||||||
|
|
||||||
|
Die Ortsansicht muss mindestens folgende Zustände definieren.
|
||||||
|
|
||||||
|
## Loading
|
||||||
|
|
||||||
|
- App-Shell bleibt sichtbar
|
||||||
|
- zurückhaltender Ladezustand im Hauptbereich
|
||||||
|
|
||||||
|
## Loaded
|
||||||
|
|
||||||
|
- Artwork
|
||||||
|
- POIs
|
||||||
|
- Aktionen
|
||||||
|
- Kontext-Sidebar
|
||||||
|
|
||||||
|
## Interaktion geöffnet
|
||||||
|
|
||||||
|
- Ort bleibt im Hintergrund sichtbar
|
||||||
|
- kurze Untersuchungen und einfache NPC-Dialoge öffnen kein komplett neues Seitenlayout
|
||||||
|
|
||||||
|
## Aktion nicht verfügbar
|
||||||
|
|
||||||
|
- sichtbar deaktiviert
|
||||||
|
- optional kurze Erklärung / Tooltip
|
||||||
|
|
||||||
|
## API-Fehler
|
||||||
|
|
||||||
|
- Navigation bleibt benutzbar
|
||||||
|
- kompakter Retry-Zustand
|
||||||
|
|
||||||
|
## Aktiver Kampf
|
||||||
|
|
||||||
|
Wenn der Server einen noch nicht abgeschlossenen Kampf meldet, darf die Ortsansicht nicht zum Umgehen dieses Kampfes genutzt werden.
|
||||||
|
|
||||||
|
Der bestehende Combat-Resume-Flow hat Vorrang.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 14. Visuelle Regeln
|
||||||
|
|
||||||
|
Die Ortsansicht folgt vollständig der bestehenden Ashen-Realms-UI-Spezifikation.
|
||||||
|
|
||||||
|
Wichtig:
|
||||||
|
|
||||||
|
- Artwork zuerst
|
||||||
|
- dunkles Metall / Stein / Leder
|
||||||
|
- dezente Goldverzierungen
|
||||||
|
- keine weißen SaaS-Cards
|
||||||
|
- kein Glassmorphism
|
||||||
|
- keine Neon-Dashboard-Optik
|
||||||
|
- Fantasy-Serif für große Überschriften
|
||||||
|
- sehr gut lesbare UI-Schrift für normalen Text
|
||||||
|
- zurückhaltender Glow
|
||||||
|
- eindeutige Interaktionszustände
|
||||||
|
- konsistente Icon-Sprache
|
||||||
|
|
||||||
|
POI-Marker müssen erkennbar sein, dürfen aber das Artwork nicht dominieren.
|
||||||
|
|
||||||
|
Bevorzugt werden kleine runde oder schildartige Fantasy-Marker statt moderner Map-Pins.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 15. Responsive Verhalten
|
||||||
|
|
||||||
|
Desktop bleibt das primäre Ziel.
|
||||||
|
|
||||||
|
## Desktop
|
||||||
|
|
||||||
|
- volle linke Navigation
|
||||||
|
- Artwork mit positionierten POIs
|
||||||
|
- rechte Sidebar sichtbar
|
||||||
|
- primäre Aktionsleiste sichtbar
|
||||||
|
|
||||||
|
## Tablet
|
||||||
|
|
||||||
|
- rechte Sidebar darf einklappbar werden
|
||||||
|
- Hauptaktionen bleiben sichtbar
|
||||||
|
- POIs bleiben durch Prozentkoordinaten korrekt verankert
|
||||||
|
|
||||||
|
## Mobile – später
|
||||||
|
|
||||||
|
Nicht V1-Priorität.
|
||||||
|
|
||||||
|
Mögliche spätere Anpassung:
|
||||||
|
|
||||||
|
- Artwork oben
|
||||||
|
- POI-Liste unterhalb des Artworks
|
||||||
|
- rechte Sidebar wird einklappbare Ortsinfo
|
||||||
|
- Aktionen als zweispaltiges Grid
|
||||||
|
|
||||||
|
Das Desktop-Design soll jetzt nicht zugunsten von Mobile kompromittiert werden.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 16. Content-Regeln für zukünftige Orte
|
||||||
|
|
||||||
|
Bei jedem neuen Ort werden in dieser Reihenfolge definiert:
|
||||||
|
|
||||||
|
1. **Zweck des Ortes**
|
||||||
|
2. **Visuelle Szene**
|
||||||
|
3. **Wichtigste Spielerentscheidung**
|
||||||
|
4. **2–5 sinnvolle POIs**
|
||||||
|
5. **Bis zu 4 primäre Aktionen**
|
||||||
|
6. **Encounter-Vorschau, falls relevant**
|
||||||
|
7. **Informationen für die rechte Sidebar**
|
||||||
|
8. **Rückkehr- und Weiterreise-Flow**
|
||||||
|
|
||||||
|
Für jeden relevanten Ort muss beantwortet werden:
|
||||||
|
|
||||||
|
> Warum soll sich der Spieler an diesen Ort erinnern und ihn nicht nur als weiteren Menüpunkt wahrnehmen?
|
||||||
|
|
||||||
|
Mindestens ein identitätsstiftendes Element sollte vorhanden sein:
|
||||||
|
|
||||||
|
- markanter NPC
|
||||||
|
- besondere Landmarke
|
||||||
|
- Untersuchung
|
||||||
|
- spezieller Service
|
||||||
|
- Elitezugang
|
||||||
|
- Bosszugang
|
||||||
|
- ungewöhnlicher Encounter-Pool
|
||||||
|
- Story-Hinweis
|
||||||
|
- visuelles Ereignis
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 17. Was ausdrücklich nicht gebaut werden soll
|
||||||
|
|
||||||
|
Die Ortsansicht ist kein:
|
||||||
|
|
||||||
|
- frei begehbarer Screen
|
||||||
|
- WASD-Bewegungssystem
|
||||||
|
- Point-and-Click-Adventure
|
||||||
|
- Hidden-Object-Spiel
|
||||||
|
- zweiter Kartenscreen
|
||||||
|
- Ersatz für die Jagd
|
||||||
|
- Ersatz für Quests
|
||||||
|
- universelles Modal für alle Spielsysteme
|
||||||
|
|
||||||
|
Vermeiden:
|
||||||
|
|
||||||
|
- dutzende Hotspots
|
||||||
|
- individuelle Komponenten pro Ort
|
||||||
|
- Kampflogik im Orts-Screen
|
||||||
|
- clientseitige Loot-Rolls
|
||||||
|
- clientseitiger Reiseabschluss
|
||||||
|
- duplizierte Jagdlogik
|
||||||
|
- lange Lore-Textwände direkt auf der Szene
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 18. V1-Referenzort – Verbrannte Straße
|
||||||
|
|
||||||
|
Die erste Referenzimplementierung ist die **Verbrannte Straße** in den **Aschenfeldern**.
|
||||||
|
|
||||||
|
## Zweck
|
||||||
|
|
||||||
|
Beweisen, dass die Ortsansicht Weltgefühl, Jagd, einfache Exploration und NPC-Präsenz verbinden kann, ohne ein neues komplexes Subsystem zu werden.
|
||||||
|
|
||||||
|
## Visuelle Identität
|
||||||
|
|
||||||
|
- verbrannte Handelsstraße
|
||||||
|
- zerstörter Wagen
|
||||||
|
- aschebedeckter Boden
|
||||||
|
- glühende Risse / Glut
|
||||||
|
- tote Bäume
|
||||||
|
- Wachtstrukturen in der Ferne
|
||||||
|
- Rauch
|
||||||
|
- Spuren früherer Kämpfe
|
||||||
|
|
||||||
|
## POIs
|
||||||
|
|
||||||
|
### Jagdgebiet
|
||||||
|
|
||||||
|
Typ:
|
||||||
|
|
||||||
|
```text
|
||||||
|
HUNT
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktion:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Jagd beginnen
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verdächtige Spuren
|
||||||
|
|
||||||
|
Typ:
|
||||||
|
|
||||||
|
```text
|
||||||
|
INVESTIGATE
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktion:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Untersuchen
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispielresultat:
|
||||||
|
|
||||||
|
> Zwischen Asche und zerbrochenen Steinen erkennst du mehrere frische Stiefelabdrücke. Sie führen nach Osten, in Richtung des verlassenen Wachtpostens.
|
||||||
|
|
||||||
|
### Verlassener Wagen
|
||||||
|
|
||||||
|
Typ:
|
||||||
|
|
||||||
|
```text
|
||||||
|
SEARCH
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktion:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Durchsuchen
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispielresultat für die erste Umsetzung:
|
||||||
|
|
||||||
|
> Der Wagen wurde gründlich geplündert. Zwischen verbrannten Brettern findest du nur leere Kisten und Spuren eines hastigen Aufbruchs.
|
||||||
|
|
||||||
|
In der ersten Implementierung muss diese Aktion noch keine Belohnung vergeben.
|
||||||
|
|
||||||
|
### Verwundeter Kundschafter
|
||||||
|
|
||||||
|
Typ:
|
||||||
|
|
||||||
|
```text
|
||||||
|
NPC
|
||||||
|
```
|
||||||
|
|
||||||
|
Aktion:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Sprechen
|
||||||
|
```
|
||||||
|
|
||||||
|
Beispieldialog:
|
||||||
|
|
||||||
|
> „Die Straße ist nicht mehr sicher. Die Plünderer kommen aus Richtung des alten Wachtpostens. Wenn du weitergehst, halte die Augen offen.“
|
||||||
|
|
||||||
|
Für diese erste NPC-Interaktion ist noch kein Quest-System notwendig.
|
||||||
|
|
||||||
|
## Primäre Aktionen
|
||||||
|
|
||||||
|
```text
|
||||||
|
Jagd beginnen
|
||||||
|
Spuren untersuchen
|
||||||
|
Umgebung durchsuchen
|
||||||
|
Zur Karte
|
||||||
|
```
|
||||||
|
|
||||||
|
## Encounter-Vorschau
|
||||||
|
|
||||||
|
Repräsentative Gegner:
|
||||||
|
|
||||||
|
- Aschenratte
|
||||||
|
- Verwilderter Straßenhund
|
||||||
|
- Straßenräuber
|
||||||
|
- Verkohlter Plünderer
|
||||||
|
|
||||||
|
Die Vorschau ist rein informativ.
|
||||||
|
|
||||||
|
Sie ersetzt nicht den gewichteten Encounter-Pool der Jagd.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 19. Visuelle Referenz
|
||||||
|
|
||||||
|
Für dieses Konzept wurde folgender Referenzscreen erzeugt:
|
||||||
|
|
||||||
|
```text
|
||||||
|
verbrannte_strasse_in_den_aschenfeldern.png
|
||||||
|
```
|
||||||
|
|
||||||
|
Der Screenshot definiert Komposition und Zielgefühl, aber keine pixelgenauen Maße.
|
||||||
|
|
||||||
|
Zukünftige Ortsansichten sollen insbesondere beibehalten:
|
||||||
|
|
||||||
|
- denselben App-Shell
|
||||||
|
- dominantes Orts-Artwork
|
||||||
|
- dieselbe POI-Markersprache
|
||||||
|
- primäre Aktionsleiste unten
|
||||||
|
- kontextuelle rechte Sidebar
|
||||||
|
- klare Trennung zwischen Ort, Karte, Jagd und Kampf
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 20. Definition of Done für zukünftige Orte
|
||||||
|
|
||||||
|
Eine Ortsansicht ist fertig, wenn:
|
||||||
|
|
||||||
|
- aktueller Ort und Region sofort erkennbar sind
|
||||||
|
- das Artwork den Ort eindeutig vermittelt
|
||||||
|
- verfügbare Aktionen klar sind
|
||||||
|
- wichtige NPCs / POIs im Kontext sichtbar sind
|
||||||
|
- POIs beim Skalieren korrekt positioniert bleiben
|
||||||
|
- Jagdaktionen den bestehenden Jagdflow verwenden
|
||||||
|
- Reisen den bestehenden Karten-/Reiseflow verwenden
|
||||||
|
- lokale Interaktionen keine fremden Systeme duplizieren
|
||||||
|
- serverautoritative Aktionen serverautoritativ bleiben
|
||||||
|
- derselbe Komponentenaufbau den nächsten Ort nur über andere Daten rendern kann
|
||||||
|
- der Screen wie ein Bestandteil desselben Ashen-Realms-UI-Systems wirkt
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 21. Leitprinzip
|
||||||
|
|
||||||
|
> **Die Karte zeigt dem Spieler, wohin er gehen kann. Die Ortsansicht lässt ihn spüren, wo er gerade ist.**
|
||||||
|
|
||||||
|
Jede zukünftige Ortsansicht soll genau diese Trennung stärken.
|
||||||
Reference in New Issue
Block a user