Files
tft/frontend/src/store.js
2026-09-07 07:44:09 +02:00

68 lines
2.0 KiB
JavaScript

import { reactive } from 'vue'
import { newGame, doAction, fetchReplay } from './api.js'
export const store = reactive({
gameId: null,
state: null,
error: null,
selectedItem: null,
dragging: null,
// Kampf-Protokoll der letzten Runde, nur wenn es angefragt wurde.
replay: null,
async start() {
this.error = null
this.selectedItem = null
try {
const data = await newGame()
this.gameId = data.game_id
this.state = data
} catch (e) {
this.error = e.message
}
},
async act(action) {
this.error = null
// Jede Aktion ändert das Board — ein alter Kampf gehört dann weg.
// Sonst verdeckt das Protokoll das Hex-Feld und man kann nichts
// mehr aufstellen.
if (action.action !== 'lock') this.replay = null
try {
this.state = await doAction(this.gameId, action)
// Item-Indizes verschieben sich bei jeder Aktion — Auswahl verfällt.
this.selectedItem = null
} catch (e) {
this.error = e.message
setTimeout(() => { if (this.error === e.message) this.error = null }, 2500)
}
},
buy(slot) { return this.act({ action: 'buy', slot }) },
sell(where, idx) { return this.act({ action: 'sell', where, idx }) },
reroll() { return this.act({ action: 'reroll' }) },
buyXp() { return this.act({ action: 'buy_xp' }) },
move(where, idx) { return this.act({ action: 'move', where, idx }) },
place(where, idx, hex) { return this.act({ action: 'place', where, idx, hex }) },
async next() {
return this.act({ action: 'next' })
},
async loadReplay() {
try {
this.replay = await fetchReplay(this.gameId)
} catch {
// Kein Gegner oder leeres Board: dann gibt es nichts zu zeigen.
this.replay = null
}
},
pickAugment(choice) { return this.act({ action: 'pick_augment', choice }) },
equip(boardIdx) {
if (this.selectedItem === null) return
const itemIdx = this.selectedItem
this.selectedItem = null
return this.act({ action: 'equip', item_idx: itemIdx, board_idx: boardIdx })
},
})