tg-bot-ts/src/systems/characters.ts
Nuno Duque Nunes 1446cd10fc initial commit
2026-06-01 13:36:51 +01:00

111 lines
4.1 KiB
TypeScript

import fs from "fs";
import path from "path";
import { CharacterMap, Character, ClassKey, Nation, AccountMap, AccountData } from "../types";
const CHARS_PATH = path.join(__dirname, "../../data/characters.json");
const ACCOUNTS_PATH = path.join(__dirname, "../../data/accounts.json");
let _chars: CharacterMap = {};
let _accounts: AccountMap = {};
export function loadCharacters(): void {
try { _chars = JSON.parse(fs.readFileSync(CHARS_PATH, "utf8")); }
catch { _chars = {}; }
try { _accounts = JSON.parse(fs.readFileSync(ACCOUNTS_PATH, "utf8")); }
catch { _accounts = {}; }
}
function saveCharacters(): void {
fs.writeFileSync(CHARS_PATH, JSON.stringify(_chars, null, 2));
}
function saveAccounts(): void {
fs.writeFileSync(ACCOUNTS_PATH, JSON.stringify(_accounts, null, 2));
}
export function getCharacters(usermapKey: string): Character[] {
return _chars[usermapKey]?.characters ?? [];
}
export function getActiveCharacter(usermapKey: string): Character | null {
return getCharacters(usermapKey).find((c) => c.active) ?? null;
}
export function getCharacterByName(usermapKey: string, name: string): Character | null {
return getCharacters(usermapKey).find((c) => c.name.toLowerCase() === name.toLowerCase()) ?? null;
}
export function getCharacterByClass(usermapKey: string, cls: ClassKey): Character | null {
// Returns the active character of that class, or first found
const chars = getCharacters(usermapKey).filter((c) => c.class === cls);
return chars.find((c) => c.active) ?? chars[0] ?? null;
}
export function addCharacter(usermapKey: string, char: Omit<Character, "active">): boolean {
if (!_chars[usermapKey]) _chars[usermapKey] = { characters: [] };
const exists = _chars[usermapKey].characters.some((c) => c.name.toLowerCase() === char.name.toLowerCase());
if (exists) return false;
// If no active character, set this one as active
const hasActive = _chars[usermapKey].characters.some((c) => c.active);
_chars[usermapKey].characters.push({ ...char, active: !hasActive });
saveCharacters();
return true;
}
export function removeCharacter(usermapKey: string, name: string): boolean {
if (!_chars[usermapKey]) return false;
const before = _chars[usermapKey].characters.length;
_chars[usermapKey].characters = _chars[usermapKey].characters.filter(
(c) => c.name.toLowerCase() !== name.toLowerCase()
);
if (_chars[usermapKey].characters.length === before) return false;
// If we removed the active one, set the first remaining as active
if (!_chars[usermapKey].characters.some((c) => c.active) && _chars[usermapKey].characters.length > 0) {
_chars[usermapKey].characters[0].active = true;
}
saveCharacters();
return true;
}
export function setActiveCharacter(usermapKey: string, name: string): boolean {
const chars = _chars[usermapKey]?.characters;
if (!chars) return false;
const target = chars.find((c) => c.name.toLowerCase() === name.toLowerCase());
if (!target) return false;
chars.forEach((c) => (c.active = false));
target.active = true;
saveCharacters();
return true;
}
export function setCharacterNation(usermapKey: string, name: string, nation: Nation): boolean {
const char = getCharacterByName(usermapKey, name);
if (!char) return false;
char.nation = nation;
saveCharacters();
return true;
}
export function setCharacterStats(
usermapKey: string,
name: string,
stats: { atk?: number; def?: number; heal?: number }
): boolean {
const char = getCharacterByName(usermapKey, name);
if (!char) return false;
if (!char.stats) char.stats = {};
Object.assign(char.stats, stats);
saveCharacters();
return true;
}
// ─── Account data ─────────────────────────────────────────────────────────────
export function getAccountData(usermapKey: string): AccountData {
return _accounts[usermapKey] ?? {};
}
export function setAccountData(usermapKey: string, data: Partial<AccountData>): void {
if (!_accounts[usermapKey]) _accounts[usermapKey] = {};
Object.assign(_accounts[usermapKey], data);
saveAccounts();
}