3af7f5e804
La ficha de personaje pasa a mostrar el equipo sobre el paperdoll (con encantamientos y gemas en los tooltips de wowhead), el árbol de talentos y la actividad reciente del personaje. El proxy de /modelviewer/* deja de ser un rewrite de Next y pasa a un route handler que cachea en disco los assets de zamimg, para no repetir la descarga en cada visita.
165 lines
8.5 KiB
TypeScript
165 lines
8.5 KiB
TypeScript
// Mapas de datos estáticos de WoW (WotLK 3.4.3): razas, clases, slots de equipo.
|
|
// Nombres en ES/EN; el color de clase para la interfaz de la armería.
|
|
|
|
export const RACES: Record<number, { es: string; en: string; faction: 'alliance' | 'horde' }> = {
|
|
1: { es: 'Humano', en: 'Human', faction: 'alliance' },
|
|
2: { es: 'Orco', en: 'Orc', faction: 'horde' },
|
|
3: { es: 'Enano', en: 'Dwarf', faction: 'alliance' },
|
|
4: { es: 'Elfo de la noche', en: 'Night Elf', faction: 'alliance' },
|
|
5: { es: 'No-muerto', en: 'Undead', faction: 'horde' },
|
|
6: { es: 'Tauren', en: 'Tauren', faction: 'horde' },
|
|
7: { es: 'Gnomo', en: 'Gnome', faction: 'alliance' },
|
|
8: { es: 'Trol', en: 'Troll', faction: 'horde' },
|
|
10: { es: 'Elfo de sangre', en: 'Blood Elf', faction: 'horde' },
|
|
11: { es: 'Draenei', en: 'Draenei', faction: 'alliance' },
|
|
}
|
|
|
|
export const CLASSES: Record<number, { es: string; en: string; color: string }> = {
|
|
1: { es: 'Guerrero', en: 'Warrior', color: '#C79C6E' },
|
|
2: { es: 'Paladín', en: 'Paladin', color: '#F58CBA' },
|
|
3: { es: 'Cazador', en: 'Hunter', color: '#ABD473' },
|
|
4: { es: 'Pícaro', en: 'Rogue', color: '#FFF569' },
|
|
5: { es: 'Sacerdote', en: 'Priest', color: '#FFFFFF' },
|
|
6: { es: 'Caballero de la Muerte', en: 'Death Knight', color: '#C41F3B' },
|
|
7: { es: 'Chamán', en: 'Shaman', color: '#0070DE' },
|
|
8: { es: 'Mago', en: 'Mage', color: '#69CCF0' },
|
|
9: { es: 'Brujo', en: 'Warlock', color: '#9482C9' },
|
|
11: { es: 'Druida', en: 'Druid', color: '#FF7D0A' },
|
|
}
|
|
|
|
// Slots de equipo 0-18 (EQUIPMENT_SLOT_*). Los que no se muestran (camisa 3, tabardo 18)
|
|
// se dejan igual por completitud del modelo 3D.
|
|
export const EQUIP_SLOTS: { slot: number; es: string; en: string }[] = [
|
|
{ slot: 0, es: 'Cabeza', en: 'Head' },
|
|
{ slot: 1, es: 'Cuello', en: 'Neck' },
|
|
{ slot: 2, es: 'Hombros', en: 'Shoulders' },
|
|
{ slot: 14, es: 'Espalda', en: 'Back' },
|
|
{ slot: 4, es: 'Pecho', en: 'Chest' },
|
|
{ slot: 3, es: 'Camisa', en: 'Shirt' },
|
|
{ slot: 18, es: 'Tabardo', en: 'Tabard' },
|
|
{ slot: 8, es: 'Muñecas', en: 'Wrists' },
|
|
{ slot: 9, es: 'Manos', en: 'Hands' },
|
|
{ slot: 5, es: 'Cintura', en: 'Waist' },
|
|
{ slot: 6, es: 'Piernas', en: 'Legs' },
|
|
{ slot: 7, es: 'Pies', en: 'Feet' },
|
|
{ slot: 10, es: 'Anillo', en: 'Ring' },
|
|
{ slot: 11, es: 'Anillo', en: 'Ring' },
|
|
{ slot: 12, es: 'Abalorio', en: 'Trinket' },
|
|
{ slot: 13, es: 'Abalorio', en: 'Trinket' },
|
|
{ slot: 15, es: 'Mano derecha', en: 'Main Hand' },
|
|
{ slot: 16, es: 'Mano izquierda', en: 'Off Hand' },
|
|
{ slot: 17, es: 'A distancia', en: 'Ranged' },
|
|
]
|
|
|
|
export function raceName(id: number, locale: string): string {
|
|
const r = RACES[id]
|
|
return r ? (locale === 'en' ? r.en : r.es) : `#${id}`
|
|
}
|
|
export function className(id: number, locale: string): string {
|
|
const c = CLASSES[id]
|
|
return c ? (locale === 'en' ? c.en : c.es) : `#${id}`
|
|
}
|
|
export function classColor(id: number): string {
|
|
return CLASSES[id]?.color ?? '#ffffff'
|
|
}
|
|
export function factionOf(race: number): 'alliance' | 'horde' | null {
|
|
return RACES[race]?.faction ?? null
|
|
}
|
|
|
|
// Mapa slot -> etiqueta y layout tipo "paperdoll" de la ficha (columnas izq/der + armas).
|
|
const SLOT_LABELS = new Map(EQUIP_SLOTS.map((s) => [s.slot, s]))
|
|
export function slotLabel(slot: number, locale: string): string {
|
|
const s = SLOT_LABELS.get(slot)
|
|
return s ? (locale === 'en' ? s.en : s.es) : ''
|
|
}
|
|
export const PAPERDOLL_LEFT = [0, 1, 2, 14, 4, 3, 18, 8]
|
|
export const PAPERDOLL_RIGHT = [9, 5, 6, 7, 10, 11, 12, 13]
|
|
export const PAPERDOLL_WEAPONS = [15, 16, 17]
|
|
|
|
// Skill lines de profesiones (primarias + secundarias) de WotLK. IDs estándar.
|
|
export const PROFESSION_SKILLS: Record<number, { es: string; en: string }> = {
|
|
171: { es: 'Alquimia', en: 'Alchemy' },
|
|
164: { es: 'Herrería', en: 'Blacksmithing' },
|
|
333: { es: 'Encantamiento', en: 'Enchanting' },
|
|
202: { es: 'Ingeniería', en: 'Engineering' },
|
|
182: { es: 'Herboristería', en: 'Herbalism' },
|
|
773: { es: 'Inscripción', en: 'Inscription' },
|
|
755: { es: 'Joyería', en: 'Jewelcrafting' },
|
|
165: { es: 'Peletería', en: 'Leatherworking' },
|
|
186: { es: 'Minería', en: 'Mining' },
|
|
393: { es: 'Desuello', en: 'Skinning' },
|
|
197: { es: 'Sastrería', en: 'Tailoring' },
|
|
129: { es: 'Primeros auxilios', en: 'First Aid' },
|
|
185: { es: 'Cocina', en: 'Cooking' },
|
|
356: { es: 'Pesca', en: 'Fishing' },
|
|
762: { es: 'Equitación', en: 'Riding' },
|
|
}
|
|
|
|
// Pestañas de talento de WotLK: tabId -> { clase, índice de árbol 0/1/2, nombre }.
|
|
export const TALENT_TABS: Record<number, { classId: number; index: number; es: string; en: string }> = {
|
|
161: { classId: 1, index: 0, es: 'Armas', en: 'Arms' },
|
|
164: { classId: 1, index: 1, es: 'Furia', en: 'Fury' },
|
|
163: { classId: 1, index: 2, es: 'Protección', en: 'Protection' },
|
|
382: { classId: 2, index: 0, es: 'Sagrado', en: 'Holy' },
|
|
383: { classId: 2, index: 1, es: 'Protección', en: 'Protection' },
|
|
381: { classId: 2, index: 2, es: 'Reprensión', en: 'Retribution' },
|
|
361: { classId: 3, index: 0, es: 'Bestias', en: 'Beast Mastery' },
|
|
363: { classId: 3, index: 1, es: 'Puntería', en: 'Marksmanship' },
|
|
362: { classId: 3, index: 2, es: 'Supervivencia', en: 'Survival' },
|
|
182: { classId: 4, index: 0, es: 'Asesinato', en: 'Assassination' },
|
|
181: { classId: 4, index: 1, es: 'Combate', en: 'Combat' },
|
|
183: { classId: 4, index: 2, es: 'Sutileza', en: 'Subtlety' },
|
|
201: { classId: 5, index: 0, es: 'Disciplina', en: 'Discipline' },
|
|
202: { classId: 5, index: 1, es: 'Sagrado', en: 'Holy' },
|
|
203: { classId: 5, index: 2, es: 'Sombras', en: 'Shadow' },
|
|
398: { classId: 6, index: 0, es: 'Sangre', en: 'Blood' },
|
|
399: { classId: 6, index: 1, es: 'Escarcha', en: 'Frost' },
|
|
400: { classId: 6, index: 2, es: 'Profano', en: 'Unholy' },
|
|
261: { classId: 7, index: 0, es: 'Elemental', en: 'Elemental' },
|
|
263: { classId: 7, index: 1, es: 'Mejora', en: 'Enhancement' },
|
|
262: { classId: 7, index: 2, es: 'Restauración', en: 'Restoration' },
|
|
81: { classId: 8, index: 0, es: 'Arcano', en: 'Arcane' },
|
|
41: { classId: 8, index: 1, es: 'Fuego', en: 'Fire' },
|
|
61: { classId: 8, index: 2, es: 'Escarcha', en: 'Frost' },
|
|
302: { classId: 9, index: 0, es: 'Aflicción', en: 'Affliction' },
|
|
303: { classId: 9, index: 1, es: 'Demonología', en: 'Demonology' },
|
|
301: { classId: 9, index: 2, es: 'Destrucción', en: 'Destruction' },
|
|
283: { classId: 11, index: 0, es: 'Equilibrio', en: 'Balance' },
|
|
281: { classId: 11, index: 1, es: 'Feral', en: 'Feral Combat' },
|
|
282: { classId: 11, index: 2, es: 'Restauración', en: 'Restoration' },
|
|
}
|
|
|
|
// Recurso primario por clase (WotLK): etiqueta + color. Guerrero=Ira, Pícaro=Energía,
|
|
// Caballero de la Muerte=Poder rúnico, resto=Maná. El valor sale de characters.power1.
|
|
export const CLASS_POWER: Record<number, { es: string; en: string; color: string }> = {
|
|
1: { es: 'Ira', en: 'Rage', color: '#c8412b' },
|
|
2: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
3: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
4: { es: 'Energía', en: 'Energy', color: '#e6cc00' },
|
|
5: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
6: { es: 'Poder rúnico', en: 'Runic Power', color: '#00b0d8' },
|
|
7: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
8: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
9: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
11: { es: 'Maná', en: 'Mana', color: '#4a90d9' },
|
|
}
|
|
|
|
export function classPower(classId: number, locale: string): { label: string; color: string } {
|
|
const p = CLASS_POWER[classId] ?? CLASS_POWER[2]
|
|
return { label: locale === 'en' ? p.en : p.es, color: p.color }
|
|
}
|
|
|
|
// Icono representativo de cada pestaña de talento (spec) de WotLK, por tabId.
|
|
export const SPEC_ICONS: Record<number, string> = {
|
|
161: 'ability_warrior_savageblow', 164: 'ability_warrior_innerrage', 163: 'ability_warrior_defensivestance',
|
|
382: 'spell_holy_holybolt', 383: 'spell_holy_devotionaura', 381: 'spell_holy_auraoflight',
|
|
361: 'ability_hunter_beasttaming', 363: 'ability_marksmanship', 362: 'ability_hunter_swiftstrike',
|
|
182: 'ability_rogue_eviscerate', 181: 'ability_backstab', 183: 'ability_stealth',
|
|
201: 'spell_holy_wordfortitude', 202: 'spell_holy_guardianspirit', 203: 'spell_shadow_shadowwordpain',
|
|
398: 'spell_deathknight_bloodpresence', 399: 'spell_deathknight_frostpresence', 400: 'spell_deathknight_unholypresence',
|
|
261: 'spell_nature_lightning', 263: 'spell_nature_lightningshield', 262: 'spell_nature_magicimmunity',
|
|
81: 'spell_holy_magicalsentry', 41: 'spell_fire_firebolt02', 61: 'spell_frost_frostbolt02',
|
|
302: 'spell_shadow_deathcoil', 303: 'spell_shadow_metamorphosis', 301: 'spell_shadow_rainoffire',
|
|
283: 'spell_nature_starfall', 281: 'ability_druid_catform', 282: 'spell_nature_healingtouch',
|
|
}
|