Files
NightSpire/web-next/lib/change-faction.ts
T
Inna eaae16e33a web-next: change-race/faction/level-up/gold por SumUp + rastreador de misiones
- /change-race-character (3€), /change-faction-character (5€, valida condiciones:
  sin hermandad/correo/subastas/capitán-arena y oro <= cap por nivel),
  /level-up-character (10€), /gold-character (oro por correo SOAP). Cada uno borra
  su ruta antigua y actualiza el link del panel.
- SumUp: hook precheck en PaidServiceConfig (condiciones cambio de facción);
  columna home_stripelog.metadata para campos extra (gold_amount).
- /quest-character: rastreador de estado de misiones/cadenas (clase, Hijos de
  Hodir, misión por ID) en personaje offline; cooldowns por categoría, Turnstile,
  IDs de misión verificados en wotlkdb 3.3.5a. Tabla home_questsearchhistory.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-14 12:39:28 +00:00

56 lines
2.1 KiB
TypeScript

import type { RowDataPacket } from 'mysql2'
import { db, DB } from './db'
/**
* Condiciones para cambiar de facción (AzerothCore). El personaje NO puede:
* tener subastas activas, correos en el buzón, ser capitán de un equipo de arena,
* ser miembro de una hermandad, ni superar el máximo de oro según su nivel.
*/
/** Máximo de oro (en oro) permitido según el nivel. */
export function factionGoldCap(level: number): number {
if (level <= 30) return 300
if (level <= 50) return 1000
if (level <= 70) return 5000
return 20000
}
export interface FactionEligibility {
ok: boolean
reasons: string[]
}
export async function checkFactionChangeEligibility(accountId: number, character: string): Promise<FactionEligibility> {
const [chars] = await db(DB.characters).query<RowDataPacket[]>(
'SELECT guid, level, money FROM characters WHERE name = ? AND account = ? LIMIT 1',
[character, accountId],
)
const ch = chars[0]
if (!ch) return { ok: false, reasons: ['El personaje no pertenece a tu cuenta.'] }
const guid = Number(ch.guid)
const level = Number(ch.level)
const money = Number(ch.money)
const reasons: string[] = []
const cap = factionGoldCap(level)
if (money > cap * 10000) reasons.push(`tiene demasiado oro (máximo ${cap} para su nivel)`)
// Cada condición en su try/catch: alguna tabla puede no existir en esta BD.
const exists = async (sql: string): Promise<boolean> => {
try {
const [rows] = await db(DB.characters).query<RowDataPacket[]>(sql, [guid])
return Boolean(rows[0])
} catch {
return false // tabla ausente => no bloquea (el core lo valida al aplicar)
}
}
if (await exists('SELECT 1 FROM guild_member WHERE guid = ? LIMIT 1')) reasons.push('es miembro de una hermandad')
if (await exists('SELECT 1 FROM mail WHERE receiver = ? LIMIT 1')) reasons.push('tiene correos en el buzón')
if (await exists('SELECT 1 FROM auctionhouse WHERE owner = ? LIMIT 1')) reasons.push('tiene subastas activas')
if (await exists('SELECT 1 FROM arena_team WHERE captainGuid = ? LIMIT 1')) reasons.push('es capitán de un equipo de arena')
return { ok: reasons.length === 0, reasons }
}