You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tekstowa gra RPG na Discordzie napisana w TypeScript. Walka rundowa, ekspedycje, bossowie, dungeony, party, crafting, NPC z dialogami i sklepy w prywatnych wątkach. Slash commands z autocomplete + klasyczne komendy .message-style.
Quick start
# 1. Klonuj i zainstaluj zależności
git clone <repo>&&cd discord-bot
bun install # lub npm install# 2. Konfiguracja
cp .env.example .env # uzupełnij DISCORD_TOKEN itd.# 3. Uruchom
bun start # bun (zalecane)
npm run start:node # node (z dist/)
npm run dev # watch mode
Konfiguracja (.env)
DISCORD_TOKEN=<bot_token>DISCORD_GUILD_ID=<server_id># opcjonalnie — instant slash registration; bez tego: globalnie (~1h propagacji)OLLAMA_MODEL=qwen2.5:7b# model dla .ask (jeśli używasz Ollama)TMDB_API_KEY=<key># opcjonalnie — dla .ask-movie / movie-of-the-dayTHREAD_TTL_MIN=60# auto-cleanup nieaktywnych wątkówAMBUSH_CHECK_INTERVAL_MS=300000# 5 min — częstotliwość losowania ambushAMBUSH_CHANCE=0.25# 25% szansy na ambush per check
Bot invite
Bot wymaga scope bot ORAZ applications.commands żeby slash commands działały. W Discord Developer Portal → twoja aplikacja → OAuth2 → URL Generator:
Każdy NPC ma dialog: Dialog z opcjami {label, goto} ('end' kończy)
Pliki w src/modules/game/npcs/{cityId}/{npc}.npc.ts
Architektura
src/
├── commands/ Komendy chat (Ollama-based: ask, movie, etc.)
├── managers/ CommandManager (dispatch, slash registration)
├── modules/game/
│ ├── cities/ Miasta + handlarze (Port Cikada, Oakhaven, Krasnoludzka Twierdza, Czarna Cytadela)
│ ├── classes/ Klasy + subklasy (tier-1 i tier-2)
│ ├── races/ Rasy
│ ├── mobs/ Boss-moby (8) + ambush-moby (10) z tier-multiplier
│ ├── npcs/ NPC z dialogami (grouped per cityId)
│ ├── skills/ Skille klas (35+) z apply/cooldown
│ ├── engine/ Combat-battle, AI, buffy, ambush loop
│ ├── ui/ Builder buttonów (battle, shop, menu, expedition, craft, boss, city, dialog)
│ ├── services/ Stan + logika: stats, party, expedition, boss, dungeon, duel, city, craft, inventory, dialog, menu
│ ├── commands/ Cienkie access-pointy (parsują args, delegują do services)
│ └── index.ts registerGameCommands — DI wiring
├── types/ ICommand + ISlashCommand interfejsy
├── ollama.ts Streaming Ollama API
├── tools.ts Function-calling tools (TMDB, etc.)
└── index.ts Bot bootstrap, slash registration on ready
Konwencje (utrwalone w pamięci między sesjami):
Komendy = cienkie access-pointy — logika w *.service.ts, komendy tylko parsują args
No as casts — proper typing / type guards / generics zamiast
Effective stats SoT — PlayerStatsService.effective*() jako single source of truth dla UI i buildPlayerCombatant
Development
npm run typecheck # tsc --noEmit
npm run lint # ESLint
npm run lint:fix # auto-fix
npm test# Jest (260+ testów)
npm run format # Prettier
npm run build # tsc → dist/
Tests: unit (test/unit/) i feature (test/feature/) — kombinują real PlayerStatsService z fake interaction objects, sprawdzają cały flow buttonów i slash commands.