6ca94c2803
- CharacterSelect: componente reutilizable que colorea las opciones por clase (class="priest big-font"…) y el <select> con la clase seleccionada. Usado en unstuck, revive, gold, transfer, trade-points, servicios de pago y recruit. getGameCharacters ahora devuelve classCss. - /unstuck (+revive): diseño del original (info + NOTA, prompt, opciones coloreadas, botón "Desbloqueado"/"Revivido" con refresh). - /vote-points: seed de los 4 sitios con logos y URLs (sql/seed_votesites.sql); botón voted-button para sitios en cooldown; etiqueta "Nota:" separada. - account-info.png (imagen nueva) y CSS de los paneles de cuenta: se añade background-blend-mode: saturation y background-size en #account-settings y .account-fieldset para que la imagen salga como el original. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
45 lines
1.5 KiB
TypeScript
45 lines
1.5 KiB
TypeScript
import type { RowDataPacket } from 'mysql2'
|
|
import { db, DB } from './db'
|
|
import { getClassCss } from './character-info'
|
|
|
|
export interface GameCharacter {
|
|
name: string
|
|
online: boolean
|
|
classCss: string // clase CSS de color por clase (priest, warrior…), para el <select>
|
|
}
|
|
|
|
/** Personajes de una cuenta de juego (acore_characters). Vacío si no está poblada. */
|
|
export async function getGameCharacters(accountId: number): Promise<GameCharacter[]> {
|
|
try {
|
|
const [rows] = await db(DB.characters).query<RowDataPacket[]>(
|
|
'SELECT name, online, class FROM characters WHERE account = ?',
|
|
[accountId],
|
|
)
|
|
return rows.map((r) => ({ name: r.name, online: r.online === 1, classCss: getClassCss(r.class) }))
|
|
} catch {
|
|
return []
|
|
}
|
|
}
|
|
|
|
/** Id de la cuenta dueña de un personaje por su nombre (único), o null. */
|
|
export async function getAccountIdByCharacterName(name: string): Promise<number | null> {
|
|
const trimmed = name.trim()
|
|
if (!trimmed) return null
|
|
try {
|
|
const [rows] = await db(DB.characters).query<RowDataPacket[]>(
|
|
'SELECT account FROM characters WHERE name = ? LIMIT 1',
|
|
[trimmed],
|
|
)
|
|
return rows[0] ? Number(rows[0].account) : null
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|
|
|
|
/** True si el personaje pertenece a la cuenta y está desconectado. */
|
|
export async function characterIsOfflineAndOwned(accountId: number, name: string): Promise<boolean> {
|
|
const chars = await getGameCharacters(accountId)
|
|
const c = chars.find((ch) => ch.name === name)
|
|
return Boolean(c && !c.online)
|
|
}
|