diff --git a/apps/keira/src/app/routes.ts b/apps/keira/src/app/routes.ts index af72c06ab1..001fa54f7c 100644 --- a/apps/keira/src/app/routes.ts +++ b/apps/keira/src/app/routes.ts @@ -19,7 +19,7 @@ import { CreatureTemplateResistanceComponent, CreatureTemplateSpellComponent, CreatureTextComponent, - NpcTrainerComponent, + CreatureDefaultTrainerComponent, NpcVendorComponent, PickpocketingLootTemplateComponent, SaiCreatureComponent, @@ -94,6 +94,7 @@ import { SelectAcoreStringComponent, } from 'texts'; import { GameTeleComponent, GameTeleHandlerService, SelectGameTeleComponent } from '@keira/features/game-tele'; +import { SelectTrainerComponent, TrainerComponent, TrainerHandlerService, TrainerSpellComponent } from '@keira/features/trainer'; import { UnusedGuidSearchComponent } from '@keira/features/unused-guid-search'; export const KEIRA_ROUTES: Routes = [ @@ -178,10 +179,11 @@ export const KEIRA_ROUTES: Routes = [ canActivate: [CreatureHandlerService], }, { - path: 'npc-trainer', - component: NpcTrainerComponent, + path: 'creature-default-trainer', + component: CreatureDefaultTrainerComponent, canActivate: [CreatureHandlerService], }, + { path: 'creature-spawn', component: CreatureSpawnComponent, @@ -506,6 +508,25 @@ export const KEIRA_ROUTES: Routes = [ }, ], }, + { + path: 'trainer', + children: [ + { + path: 'select', + component: SelectTrainerComponent, + }, + { + path: 'trainer', + component: TrainerComponent, + canActivate: [TrainerHandlerService], + }, + { + path: 'trainer-spell', + component: TrainerSpellComponent, + canActivate: [TrainerHandlerService], + }, + ], + }, { path: 'unused-guid-search', component: UnusedGuidSearchComponent, diff --git a/apps/keira/src/assets/i18n/de.json b/apps/keira/src/assets/i18n/de.json index ad6a80bacb..24e6986e85 100644 --- a/apps/keira/src/assets/i18n/de.json +++ b/apps/keira/src/assets/i18n/de.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Ruf bei Tötung", "EQUIP_TEMPLATE": "Ausrüstungsvorlage", "VENDOR": "Händler", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest-Gegenstand", "CREATURE_LOOT": "Kreaturenbeute", "PICKPOCKETING_LOOT": "Taschendiebstahl-Beute", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "Tötungsgutschriften", "MODELS": "Modelle", "MONEY_LOOT": "Geldbeute", - "TRAINER": "Trainer", "LOOTS": "Beute", "DIFFICULTY_ENTRIES": "Schwierigkeitsstufen", "DAMAGE": "Schaden", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/el.json b/apps/keira/src/assets/i18n/el.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/el.json +++ b/apps/keira/src/assets/i18n/el.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/en.json b/apps/keira/src/assets/i18n/en.json index a2ad6a758d..e87f2fabc2 100644 --- a/apps/keira/src/assets/i18n/en.json +++ b/apps/keira/src/assets/i18n/en.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -902,6 +905,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/es.json b/apps/keira/src/assets/i18n/es.json index 2575cd8d04..0fb4e5d92b 100644 --- a/apps/keira/src/assets/i18n/es.json +++ b/apps/keira/src/assets/i18n/es.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Reputación Al Matar", "EQUIP_TEMPLATE": "Plantilla de Equipamiento", "VENDOR": "Vendedor", - "TRAINER": "Entrenador", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Item de Misión", "CREATURE_LOOT": "Botín de Criatura", "PICKPOCKETING_LOOT": "Botín de Robo con ganzúa", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "Créditos de Muerte", "MODELS": "Modelos", "MONEY_LOOT": "Botín de Dinero", - "TRAINER": "Entrenador", "LOOTS": "Botines", "DIFFICULTY_ENTRIES": "Entradas de Dificultad", "DAMAGE": "Daño", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Valores permitidos: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "El coste a pagar para poder aprender el Hechizo, representado en monedas de cobre (1 de oro = 100 de plata = 10000 de cobre)", - "REQ_SKILL_LINE": "La Habilidad requerida que debe tener previamente el jugador para poder aprender el Hechizo.", - "REQ_SKILL_RANK": "La Aptitud en la Habilidad (La cantidad de Puntos de Habilidad) dentro de 'reqskill' que el jugador necesita tener previamente para poder aprender el Hechizo.", - "REQ_LEVEL": "El nivel mínimo que debe tener el jugador para poder aprender el Hechizo." - }, "NPC_VENDOR": { "SLOT": "Posición del Item dentro de la Ventana del Vendedor", "MAXCOUNT": "El número máximo de aquellos mismos Items cargados por el vendedor en cualquier momento. 0 para que el Item sea infinito.", "INCRTIME": "En combinación con 'maxcount', la frecuencia (en segundos) con la que se actualiza la lista de proveedores.", "EXTENDED_COST": "El valor que aquí se encuentre almacenado proviene del mismo archivo 'DBC' del cual se presta justamente el nombre de la casilla; un selector para esto se implementará en un futuro dentro de Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/fr.json b/apps/keira/src/assets/i18n/fr.json index 1c0c017206..809f79fec5 100644 --- a/apps/keira/src/assets/i18n/fr.json +++ b/apps/keira/src/assets/i18n/fr.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Réputation OnKill", "EQUIP_TEMPLATE": "Modèle d'équipement", "VENDOR": "Vendeur", - "TRAINER": "Entraineur", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Objet de quête", "CREATURE_LOOT": "Loot de créature", "PICKPOCKETING_LOOT": "Loot de pickpocketing", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/it.json b/apps/keira/src/assets/i18n/it.json index b0af53d990..bc8ed2badd 100644 --- a/apps/keira/src/assets/i18n/it.json +++ b/apps/keira/src/assets/i18n/it.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Reputazione alla morte", "EQUIP_TEMPLATE": "Equipaggia Template", "VENDOR": "Venditore", - "TRAINER": "Istruttore", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Oggetto Missione", "CREATURE_LOOT": "Loot Creatura", "PICKPOCKETING_LOOT": "Loot Scippo", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Cerca Teletrasporto", "SELECT_GAME_TELE": "Editor Tele Gioco" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "GUID non utilizzati" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "Crediti Uccisione", "MODELS": "Modelli", "MONEY_LOOT": "Loot Oro", - "TRAINER": "Istruttore", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Voci di Difficoltà", "DAMAGE": "Danno", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Valori consentiti: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "Il costo da pagare per apprendere l'incantesimo rappresentato in rame (1 oro = 100 argento = 10000 rame)", - "REQ_SKILL_LINE": "L'abilità richiesta che il giocatore deve avere per poter apprendere l'incantesimo", - "REQ_SKILL_RANK": "La competenza nell'abilità da reqskill che il giocatore deve raggiungere per apprendere l'incantesimo", - "REQ_LEVEL": "Il livello minimo che il giocatore deve avere per poter apprendere l'incantesimo." - }, "NPC_VENDOR": { "SLOT": "Posizione dell'oggetto nella finestra del venditore", "MAXCOUNT": "Il numero massimo di oggetti trasportati dal venditore in qualsiasi momento. 0 per infinito (se si sceglie un valore di 1 o superiore, è necessario anche il valore incrtime per funzionare)", "INCRTIME": "Combinato con maxcount, quanto spesso (in secondi) viene aggiornato l'elenco dei venditori", "EXTENDED_COST": "Il valore proviene da DBC e un selettore per questo sarà implementato in seguito in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "Se ci sono più di un'entrata (più di un testo che la creatura dice), questa colonna viene utilizzata per scegliere se si tratta di un dillo casuale o di un elenco ordinato. Se una creatura ha più di un testo da dire in un dato ordine, deve essere incrementato per ogni nuova entrata corrispondente (es. 0, 1, 2, 3...). Se c'è solo un'entrata o solo un gruppo, questo valore dovrebbe essere 0. Se ci sono più gruppi di testi, questo valore rimane lo stesso all'interno del gruppo mentre l'id viene incrementato all'interno dello stesso gruppo.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Editor Teletrasporto" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Tabella", "START_INDEX": "Indice Inizio", diff --git a/apps/keira/src/assets/i18n/ko.json b/apps/keira/src/assets/i18n/ko.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/ko.json +++ b/apps/keira/src/assets/i18n/ko.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/nl.json b/apps/keira/src/assets/i18n/nl.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/nl.json +++ b/apps/keira/src/assets/i18n/nl.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/pl.json b/apps/keira/src/assets/i18n/pl.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/pl.json +++ b/apps/keira/src/assets/i18n/pl.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/pt.json b/apps/keira/src/assets/i18n/pt.json index 5a5fa93064..436d802ccb 100644 --- a/apps/keira/src/assets/i18n/pt.json +++ b/apps/keira/src/assets/i18n/pt.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Valores permitidos: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "O preço para aprender o spell, representado em copper (1 gold = 100 silver = 10000 copper)", - "REQ_SKILL_LINE": "O skill necessário para o jogador aprender o spell", - "REQ_SKILL_RANK": "A proficiência na skill de reqskill necessária para o jogador aprender o spell", - "REQ_LEVEL": "O level mínimo necessário para o jogador aprender o spell." - }, "NPC_VENDOR": { "SLOT": "Posição do item na janela do vendedor", "MAXCOUNT": "O número máximo de items carregados pelo vendedor em qualquer momento. 0 para infinito.", "INCRTIME": "Combinado com maxcount, qual a frequência (em segundos) que a lista do vendedor é atualizada", "EXTENDED_COST": "Valor vem do DBC e um selecionador para isso será implementado futuramente no Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/ro.json b/apps/keira/src/assets/i18n/ro.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/ro.json +++ b/apps/keira/src/assets/i18n/ro.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/ru.json b/apps/keira/src/assets/i18n/ru.json index 88486b03bf..6454adb563 100644 --- a/apps/keira/src/assets/i18n/ru.json +++ b/apps/keira/src/assets/i18n/ru.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/sk.json b/apps/keira/src/assets/i18n/sk.json index 280e1d84b3..0c3248df95 100644 --- a/apps/keira/src/assets/i18n/sk.json +++ b/apps/keira/src/assets/i18n/sk.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "The cost to pay to learn the spell represented in copper (1 gold = 100 silver = 10000 cooper)", - "REQ_SKILL_LINE": "The required skill the player needs to have in order to be able to learn the spell", - "REQ_SKILL_RANK": "The proficiency in the skill from reqskill that the player needs to meet to learn the spell", - "REQ_LEVEL": "The minimum level the player needs to be in order to learn the spell." - }, "NPC_VENDOR": { "SLOT": "Position of the item in the vendor window", "MAXCOUNT": "The maximum number of items carried by the vendor at any time. 0 for infinite (if choosing a value of 1 or higher also requires incrtime value to work)", "INCRTIME": "Combined with maxcount, how often (in seconds) the vendor list is refreshed", "EXTENDED_COST": "Value comes from DBC and a selector for this will be implemented later in Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/sv.json b/apps/keira/src/assets/i18n/sv.json index 8012c8b856..4f49011f5f 100644 --- a/apps/keira/src/assets/i18n/sv.json +++ b/apps/keira/src/assets/i18n/sv.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "Onkill Reputation", "EQUIP_TEMPLATE": "Equip Template", "VENDOR": "Vendor", - "TRAINER": "Trainer", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "Quest Item", "CREATURE_LOOT": "Creature Loot", "PICKPOCKETING_LOOT": "Pickpocketing Loot", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "KillCredits", "MODELS": "Models", "MONEY_LOOT": "Money Loot", - "TRAINER": "Trainer", "LOOTS": "Loots", "DIFFICULTY_ENTRIES": "Difficulty Entries", "DAMAGE": "Damage", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "Allowed values: 0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "Vad det kommer att kosta att lära sig en Spell i coppar (1 gold = 100 silver = 10000 copper)", - "REQ_SKILL_LINE": "Vilken Spell som behövs för att spelaren ska kunna lära sig denna Spell", - "REQ_SKILL_RANK": "Den rank som behövs från ReqSkill som spelaren behöver ha för att kunna lära sig denna Spell", - "REQ_LEVEL": "Den minimala leveln som spelaren måste vara för att kunna lära sig denna Spell." - }, "NPC_VENDOR": { "SLOT": "Positionen för Item i Vendor Window", "MAXCOUNT": "Det maximala antalet denna Vendor kan ha utav ett Item. 0 för oändligt.", "INCRTIME": "Kombinerat med MaxCount, hur ofta (i sekunder) Vendor listan Refreshas", "EXTENDED_COST": "ID kommer från DBC och kommer att implementeras senare i Keira3" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/apps/keira/src/assets/i18n/zh.json b/apps/keira/src/assets/i18n/zh.json index 98386d4df1..4d06dbf9f7 100644 --- a/apps/keira/src/assets/i18n/zh.json +++ b/apps/keira/src/assets/i18n/zh.json @@ -86,7 +86,7 @@ "ONKILL_REPUTATION": "声望配置", "EQUIP_TEMPLATE": "装备模板", "VENDOR": "商贩", - "TRAINER": "训练师", + "DEFAULT_TRAINER": "Default Trainer", "QUEST_ITEM": "任务物品", "CREATURE_LOOT": "生物掉落", "PICKPOCKETING_LOOT": "扒窃掉落", @@ -182,6 +182,12 @@ "SEARCH_GAME_TELE": "Search Teleport", "SELECT_GAME_TELE": "Game Tele Editor" }, + "TRAINER": { + "TITLE": "Trainer", + "SEARCH_TRAINER": "Search Trainer", + "SELECT_TRAINER": "Trainer", + "TRAINER_SPELL": "Trainer Spell" + }, "UNUSED_GUID_SEARCH": "Unused GUIDs" }, "DASHBOARD": { @@ -216,7 +222,6 @@ "KILL_CREDITS": "荣誉击杀", "MODELS": "模组", "MONEY_LOOT": "金钱掉落", - "TRAINER": "训练师", "LOOTS": "掉落", "DIFFICULTY_ENTRIES": "副本难度", "DAMAGE": "伤害", @@ -299,18 +304,16 @@ "TEMPLATE_SPELL": { "INDEX": "范围值:0-7" }, - "NPC_TRAINER": { - "MONEY_COST": "学习该法术的金钱,用铜币表示(1金=100银=10000铜)", - "REQ_SKILL_LINE": "玩家学习技能所需的前置技能", - "REQ_SKILL_RANK": "玩家学习技能所需要的技能熟练度要求", - "REQ_LEVEL": "玩家学习技能锁需要的最低角色等级要求" - }, "NPC_VENDOR": { "SLOT": "物品在商贩售卖窗口中的显示位置", "MAXCOUNT": "供应商在销售物品的最大数量。0表示无限制。", "INCRTIME": "结合供应商销售物品的最大数量,如果设置了最大数量限制,则在此处设置物品在售卖窗口的刷新时间(单位:秒)", "EXTENDED_COST": "值来自DBC,稍后将在Keira3中实现该值的选择器" }, + "DEFAULT_TRAINER": { + "TITLE": "Default Trainer", + "TRAINER_ID_TOOLTIP": "ID of the trainer template (trainer.Id) assigned to this creature. Use 0 for no default trainer. Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list." + }, "TEXT": { "GROUP_ID": "If there is more than one of the same entry (more than one text the creature says), this column is used to choose if it is a random say or an ordered list. If a creature has got more than one say text to be shown in a given order, it must be incremented for each new matching entry (ex. 0, 1, 2, 3...). If there is only one entry or only one group, this value should be 0. If there are multiple groups of texts, this value stays the same within the group while the id increments within the same group.", "ID": "Entry for each group of texts. This is the unique identifier when entry (creature) is the same and groupid is unchanged, it must be incremented (ex. 0, 1, 2, 3...). A creature say will be randomly selected from this list based on the groupid it belongs to.", @@ -900,6 +903,27 @@ "GAME_TELE": { "EDITOR": "Teleport Editor" }, + "TRAINER": { + "EDITOR": "Trainer Editor", + "TRAINER_ID_TOOLTIP": "References trainer.id (trainer template). Examples: 1=Trainer Warrior, 3=Trainer Paladin, 7=Trainer Hunter, 9=Trainer Rogue, 11=Trainer Priest, 13=Trainer Death Knight, 14=Trainer Shaman, 16=Trainer Mage, 31=Trainer Warlock, 33=Trainer Druid, 36=Trainer Mount & Fly. See the trainer wiki for the full list.", + "REQUIREMENT_TOOLTIP": "Meaning depends on Type - use 0 for none. Types: 0-Class (ChrClass ID e.g. 1=Warrior, 2=Paladin, 3=Hunter, 4=Rogue, 5=Priest, 6=Death Knight, 7=Shaman, 8=Mage, 9=Warlock, 11=Druid), 1-Mount (ChrRace ID (e.g. 1=Human, 2=Orc, 3=Dwarf, 4=Night Elf, 5=Undead, 6=Tauren, 7=Gnome, 8=Troll, 10=Blood Elf, 11=Draenei), 2-Tradeskill Spell ID (player must know this spell to learn from this trainer), 3-Pet ChrClass ID (see above). ", + "GREETING_TOOLTIP": "Text shown at the top of the trainer window when opened (this is not gossip). For localized greetings add entries in the \"trainer_locale\" table (Greeting_lang).", + "SPELL": { + "TRAINER_ID": "References trainer.id (trainer template linked to this entry).", + "SPELL_ID": "Spell ID being taught.", + "MONEY_COST": "Cost in copper to learn this spell from the trainer (1 gold = 100 silver = 10000 copper).", + "REQ_SKILL_LINE": "SkillLine ID required to learn this spell (e.g., profession ID). Use 0 if none.", + "REQ_SKILL_RANK": "Minimum skill rank in ReqSkillLine required to learn the spell.", + "REQ_ABILITY_1": "Spell ID the player is required to already know (first required ability).", + "REQ_ABILITY_1_TOOLTIP": "Spell ID the player must already know to be taught this spell (first prerequisite). Use 0 if none.", + "REQ_ABILITY_2": "Spell ID the player is required to already know (second required ability).", + "REQ_ABILITY_2_TOOLTIP": "Spell ID the player must already know to be taught this spell (second prerequisite). Use 0 if none.", + "REQ_ABILITY_3": "Spell ID the player is required to already know (third required ability).", + "REQ_ABILITY_3_TOOLTIP": "Spell ID the player must already know to be taught this spell (third prerequisite). Use 0 if none.", + "REQ_LEVEL": "Minimum player level required to learn this spell.", + "VERIFIED_BUILD": "Used by AzerothCore to indicate whether this entry was verified against WDB files (0 = not parsed; >0 = parsed; -1 = placeholder; - = parsed with specific client build and manually edited)." + } + }, "UNUSED_GUID_SEARCH": { "TABLE": "Table", "START_INDEX": "Start Index", diff --git a/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.html b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.html new file mode 100644 index 0000000000..52e271ff1c --- /dev/null +++ b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.html @@ -0,0 +1,40 @@ + + +
+ @if (editorService.loading) { + + } + + @if (editorService.form && !!editorService.loadedEntityId && !editorService.loading) { +
+
+ +
+
+
+ +
+
+ + +
+
+ + + +
+
+
+
+
+ } +
diff --git a/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.ts b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.ts new file mode 100644 index 0000000000..c0df37741c --- /dev/null +++ b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.component.ts @@ -0,0 +1,20 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { CreatureDefaultTrainer } from '@keira/shared/acore-world-model'; +import { SingleRowEditorComponent } from '@keira/shared/base-abstract-classes'; +import { QueryOutputComponent, TopBarComponent } from '@keira/shared/base-editor-components'; +import { TranslateModule } from '@ngx-translate/core'; +import { TooltipModule } from 'ngx-bootstrap/tooltip'; +import { CreatureHandlerService } from '../creature-handler.service'; +import { CreatureDefaultTrainerService } from './creature-default-trainer.service'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'keira-creature-default-trainer', + templateUrl: './creature-default-trainer.component.html', + imports: [TopBarComponent, TranslateModule, QueryOutputComponent, FormsModule, ReactiveFormsModule, TooltipModule], +}) +export class CreatureDefaultTrainerComponent extends SingleRowEditorComponent { + protected override readonly editorService = inject(CreatureDefaultTrainerService); + readonly handlerService = inject(CreatureHandlerService); +} diff --git a/libs/features/creature/src/creature-default-trainer/creature-default-trainer.integration.spec.ts b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.integration.spec.ts new file mode 100644 index 0000000000..48ad6ea46b --- /dev/null +++ b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.integration.spec.ts @@ -0,0 +1,147 @@ +import { provideZonelessChangeDetection } from '@angular/core'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { CreatureDefaultTrainer } from '@keira/shared/acore-world-model'; +import { MysqlQueryService, SqliteService } from '@keira/shared/db-layer'; +import { EditorPageObject, TranslateTestingModule } from '@keira/shared/test-utils'; +import { ModalModule } from 'ngx-bootstrap/modal'; +import { ToastrModule } from 'ngx-toastr'; +import { of } from 'rxjs'; +import { instance, mock } from 'ts-mockito'; +import { CreatureHandlerService } from '../creature-handler.service'; +import { SaiCreatureHandlerService } from '../sai-creature-handler.service'; +import { CreatureDefaultTrainerComponent } from './creature-default-trainer.component'; +import Spy = jasmine.Spy; + +class CreatureDefaultTrainerPage extends EditorPageObject {} + +describe('CreatureDefaultTrainer integration tests', () => { + let fixture: ComponentFixture; + let queryService: MysqlQueryService; + let querySpy: Spy; + let handlerService: CreatureHandlerService; + let page: CreatureDefaultTrainerPage; + + const id = 1234; + const expectedFullCreateQuery = + 'DELETE FROM `creature_default_trainer` WHERE (`CreatureId` = 1234);\n' + + 'INSERT INTO `creature_default_trainer` (`CreatureId`, `TrainerId`) VALUES\n' + + '(1234, 0);'; + + const originalEntity = new CreatureDefaultTrainer(); + originalEntity.CreatureId = id; + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + ToastrModule.forRoot(), + ModalModule.forRoot(), + CreatureDefaultTrainerComponent, + RouterTestingModule, + TranslateTestingModule, + ], + providers: [ + provideZonelessChangeDetection(), + provideNoopAnimations(), + CreatureHandlerService, + SaiCreatureHandlerService, + { provide: SqliteService, useValue: instance(mock(SqliteService)) }, + ], + }).compileComponents(); + }); + + function setup(creatingNew: boolean) { + handlerService = TestBed.inject(CreatureHandlerService); + handlerService['_selected'] = `${id}`; + handlerService.isNew = creatingNew; + + queryService = TestBed.inject(MysqlQueryService); + querySpy = spyOn(queryService, 'query').and.returnValue(of([])); + spyOn(queryService, 'queryValue').and.returnValue(of()); + + spyOn(queryService, 'selectAll').and.returnValue(of(creatingNew ? [] : [originalEntity])); + + fixture = TestBed.createComponent(CreatureDefaultTrainerComponent); + page = new CreatureDefaultTrainerPage(fixture); + fixture.autoDetectChanges(true); + fixture.detectChanges(); + } + + describe('Creating new', () => { + beforeEach(() => setup(true)); + + it('should correctly initialise', () => { + page.expectQuerySwitchToBeHidden(); + page.expectFullQueryToBeShown(); + page.expectFullQueryToContain(expectedFullCreateQuery); + }); + + it('should correctly update the unsaved status', () => { + const field = 'TrainerId'; + expect(handlerService.isCreatureDefaultTrainerUnsaved()).toBe(false); + page.setInputValueById(field, 3); + expect(handlerService.isCreatureDefaultTrainerUnsaved()).toBe(true); + page.setInputValueById(field, 0); + expect(handlerService.isCreatureDefaultTrainerUnsaved()).toBe(false); + }); + + it('changing a property and executing the query should correctly work', () => { + const expectedQuery = + 'DELETE FROM `creature_default_trainer` WHERE (`CreatureId` = 1234);\n' + + 'INSERT INTO `creature_default_trainer` (`CreatureId`, `TrainerId`) VALUES\n' + + '(1234, 100);'; + querySpy.calls.reset(); + + page.setInputValueById('TrainerId', '100'); + page.expectFullQueryToContain(expectedQuery); + + page.clickExecuteQuery(); + + expect(querySpy).toHaveBeenCalledTimes(1); + expect(querySpy.calls.mostRecent().args[0]).toContain(expectedQuery); + }); + }); + + describe('Editing existing', () => { + beforeEach(() => setup(false)); + + it('should correctly initialise', () => { + page.expectDiffQueryToBeShown(); + page.expectDiffQueryToBeEmpty(); + page.expectFullQueryToContain(expectedFullCreateQuery); + }); + + it('changing all properties and executing the query should correctly work', () => { + const expectedQuery = 'UPDATE `creature_default_trainer` SET `TrainerId` = 1 WHERE (`CreatureId` = 1234);'; + querySpy.calls.reset(); + + page.setInputValueById('TrainerId', '1'); + + page.expectDiffQueryToContain(expectedQuery); + + page.clickExecuteQuery(); + + expect(querySpy).toHaveBeenCalledTimes(1); + expect(querySpy.calls.mostRecent().args[0]).toContain(expectedQuery); + }); + + it('changing values should correctly update the queries', () => { + page.setInputValueById('TrainerId', '50'); + page.expectDiffQueryToContain('UPDATE `creature_default_trainer` SET `TrainerId` = 50 WHERE (`CreatureId` = 1234);'); + page.expectFullQueryToContain( + 'DELETE FROM `creature_default_trainer` WHERE (`CreatureId` = 1234);\n' + + 'INSERT INTO `creature_default_trainer` (`CreatureId`, `TrainerId`) VALUES\n' + + '(1234, 50);', + ); + + page.setInputValueById('TrainerId', '75'); + page.expectDiffQueryToContain('UPDATE `creature_default_trainer` SET `TrainerId` = 75 WHERE (`CreatureId` = 1234);'); + page.expectFullQueryToContain( + 'DELETE FROM `creature_default_trainer` WHERE (`CreatureId` = 1234);\n' + + 'INSERT INTO `creature_default_trainer` (`CreatureId`, `TrainerId`) VALUES\n' + + '(1234, 75);', + ); + }); + }); +}); diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.service.spec.ts b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.spec.ts similarity index 81% rename from libs/features/creature/src/npc-trainer/npc-trainer.service.spec.ts rename to libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.spec.ts index 8ea7fcdbe7..47bce2de5b 100644 --- a/libs/features/creature/src/npc-trainer/npc-trainer.service.spec.ts +++ b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.spec.ts @@ -1,16 +1,15 @@ -import { TestBed } from '@angular/core/testing'; import { provideZonelessChangeDetection } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; import { provideNoopAnimations } from '@angular/platform-browser/animations'; import { RouterTestingModule } from '@angular/router/testing'; import { MysqlQueryService, SqliteService } from '@keira/shared/db-layer'; - import { ToastrService } from 'ngx-toastr'; import { instance, mock } from 'ts-mockito'; import { CreatureHandlerService } from '../creature-handler.service'; import { SaiCreatureHandlerService } from '../sai-creature-handler.service'; -import { NpcTrainerService } from './npc-trainer.service'; +import { CreatureDefaultTrainerService } from './creature-default-trainer.service'; -describe('NpcTrainerService', () => { +describe('CreatureDefaultTrainerService', () => { beforeEach(() => TestBed.configureTestingModule({ imports: [RouterTestingModule], @@ -22,13 +21,13 @@ describe('NpcTrainerService', () => { { provide: SqliteService, useValue: instance(mock(SqliteService)) }, CreatureHandlerService, SaiCreatureHandlerService, - NpcTrainerService, + CreatureDefaultTrainerService, ], }), ); it('should be created', () => { - const service: NpcTrainerService = TestBed.inject(NpcTrainerService); + const service: CreatureDefaultTrainerService = TestBed.inject(CreatureDefaultTrainerService); expect(service).toBeTruthy(); }); }); diff --git a/libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.ts b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.ts new file mode 100644 index 0000000000..170914319a --- /dev/null +++ b/libs/features/creature/src/creature-default-trainer/creature-default-trainer.service.ts @@ -0,0 +1,19 @@ +import { Injectable, inject } from '@angular/core'; +import { SingleRowEditorService } from '@keira/shared/base-abstract-classes'; +import { CREATURE_DEFAULT_TRAINER_ID, CREATURE_DEFAULT_TRAINER_TABLE, CreatureDefaultTrainer } from '@keira/shared/acore-world-model'; +import { CreatureHandlerService } from '../creature-handler.service'; + +@Injectable({ + providedIn: 'root', +}) +export class CreatureDefaultTrainerService extends SingleRowEditorService { + protected override readonly handlerService = inject(CreatureHandlerService); + protected override readonly _entityClass = CreatureDefaultTrainer; + protected override readonly _entityTable = CREATURE_DEFAULT_TRAINER_TABLE; + protected override readonly _entityIdField = CREATURE_DEFAULT_TRAINER_ID; + + constructor() { + super(); + this.init(); + } +} diff --git a/libs/features/creature/src/creature-handler.service.ts b/libs/features/creature/src/creature-handler.service.ts index 8d47d9be8c..69bb0332cf 100644 --- a/libs/features/creature/src/creature-handler.service.ts +++ b/libs/features/creature/src/creature-handler.service.ts @@ -15,7 +15,7 @@ import { CREATURE_TEMPLATE_TABLE, CREATURE_TEXT_TABLE, CreatureTemplate, - NPC_TRAINER_TABLE, + CREATURE_DEFAULT_TRAINER_TABLE, NPC_VENDOR_TABLE, PICKPOCKETING_LOOT_TEMPLATE_TABLE, SAI_TABLE, @@ -58,8 +58,8 @@ export class CreatureHandlerService extends HandlerService { get isNpcVendorUnsaved(): Signal { return this.statusMap[NPC_VENDOR_TABLE].asReadonly(); } - get isNpcTrainerUnsaved(): Signal { - return this.statusMap[NPC_TRAINER_TABLE].asReadonly(); + get isCreatureDefaultTrainerUnsaved(): Signal { + return this.statusMap[CREATURE_DEFAULT_TRAINER_TABLE].asReadonly(); } get isCreatureQuestitemUnsaved(): Signal { return this.statusMap[CREATURE_QUESTITEM_TABLE].asReadonly(); @@ -99,7 +99,7 @@ export class CreatureHandlerService extends HandlerService { [CREATURE_ONKLL_REPUTATION_TABLE]: signal(false), [CREATURE_EQUIP_TEMPLATE_TABLE]: signal(false), [NPC_VENDOR_TABLE]: signal(false), - [NPC_TRAINER_TABLE]: signal(false), + [CREATURE_DEFAULT_TRAINER_TABLE]: signal(false), [CREATURE_QUESTITEM_TABLE]: signal(false), [CREATURE_LOOT_TEMPLATE_TABLE]: signal(false), [PICKPOCKETING_LOOT_TEMPLATE_TABLE]: signal(false), diff --git a/libs/features/creature/src/creature-template/creature-template.component.html b/libs/features/creature/src/creature-template/creature-template.component.html index 6197883ac7..1b3f53aefd 100644 --- a/libs/features/creature/src/creature-template/creature-template.component.html +++ b/libs/features/creature/src/creature-template/creature-template.component.html @@ -219,46 +219,6 @@ -
- -
-
- - -
-
- - - - -
-
- - -
-
- - -
-
-
diff --git a/libs/features/creature/src/creature-template/creature-template.component.ts b/libs/features/creature/src/creature-template/creature-template.component.ts index 5b5035ffa2..9b61b4cc08 100644 --- a/libs/features/creature/src/creature-template/creature-template.component.ts +++ b/libs/features/creature/src/creature-template/creature-template.component.ts @@ -18,7 +18,6 @@ import { NPC_FLAGS, RANK, SPELL_SCHOOL_MASK, - TRAINER_TYPE, UNIT_CLASS, UNIT_FLAGS, UNIT_FLAGS_2, @@ -32,7 +31,6 @@ import { FlagsSelectorBtnComponent, GenericOptionSelectorComponent, SingleValueSelectorBtnComponent, - SpellSelectorBtnComponent, } from '@keira/shared/selectors'; import { TranslateModule } from '@ngx-translate/core'; import { TooltipModule } from 'ngx-bootstrap/tooltip'; @@ -53,7 +51,6 @@ import { CreatureTemplateService } from './creature-template.service'; SingleValueSelectorBtnComponent, FactionSelectorBtnComponent, FlagsSelectorBtnComponent, - SpellSelectorBtnComponent, CreatureSelectorBtnComponent, GenericOptionSelectorComponent, BooleanOptionSelectorComponent, @@ -62,7 +59,6 @@ import { CreatureTemplateService } from './creature-template.service'; export class CreatureTemplateComponent extends SingleRowEditorComponent { protected readonly UNIT_FLAGS = UNIT_FLAGS; protected readonly UNIT_FLAGS_2 = UNIT_FLAGS_2; - protected readonly TRAINER_TYPE = TRAINER_TYPE; protected readonly NPC_FLAGS = NPC_FLAGS; protected readonly CREATURE_FAMILY = CREATURE_FAMILY; protected readonly CREATURE_TYPE = CREATURE_TYPE; diff --git a/libs/features/creature/src/creature-template/creature-template.integration.spec.ts b/libs/features/creature/src/creature-template/creature-template.integration.spec.ts index e80a01a6d3..8496fddee9 100644 --- a/libs/features/creature/src/creature-template/creature-template.integration.spec.ts +++ b/libs/features/creature/src/creature-template/creature-template.integration.spec.ts @@ -33,13 +33,13 @@ describe('CreatureTemplate integration tests', () => { '`KillCredit1`, `KillCredit2`, `name`, `subname`, ' + '`IconName`, `gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `speed_swim`, `speed_flight`, `detection_range`, ' + '`scale`, `rank`, `dmgschool`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, `RangeVariance`, ' + - '`unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, `trainer_type`, `trainer_spell`, `trainer_class`, ' + - '`trainer_race`, `type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, ' + + '`unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, ' + + '`type`, `type_flags`, `lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, ' + '`maxgold`, `AIName`, `MovementType`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `ExperienceModifier`, ' + '`RacialLeader`, `movementId`, `RegenHealth`, `mechanic_immune_mask`, `spell_school_immune_mask`, ' + '`flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES\n' + "(1234, 0, 0, 0, 0, 0, '', '', '', 0, 1, 1, 0, 0, 0, 1, 1.14286, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, " + - "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 0);\n"; + "0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 0);\n"; const originalEntity = new CreatureTemplate(); originalEntity.entry = id; @@ -93,12 +93,12 @@ describe('CreatureTemplate integration tests', () => { '`gossip_menu_id`, `minlevel`, `maxlevel`, `exp`, `faction`, `npcflag`, `speed_walk`, `speed_run`, `speed_swim`, `speed_flight`, `detection_range`, ' + '`scale`, `rank`, `dmgschool`, `DamageModifier`, `BaseAttackTime`, `RangeAttackTime`, `BaseVariance`, ' + '`RangeVariance`, `unit_class`, `unit_flags`, `unit_flags2`, `dynamicflags`, `family`, ' + - '`trainer_type`, `trainer_spell`, `trainer_class`, `trainer_race`, `type`, `type_flags`, ' + + '`type`, `type_flags`, ' + '`lootid`, `pickpocketloot`, `skinloot`, `PetSpellDataId`, `VehicleId`, `mingold`, `maxgold`, ' + '`AIName`, `MovementType`, `HoverHeight`, `HealthModifier`, `ManaModifier`, `ArmorModifier`, `ExperienceModifier`, `RacialLeader`, ' + '`movementId`, `RegenHealth`, `mechanic_immune_mask`, `spell_school_immune_mask`, `flags_extra`, `ScriptName`, `VerifiedBuild`) VALUES\n' + "(1234, 0, 0, 0, 0, 0, 'Shin', '', '', 0, 1, 1, 0, 0, 0, 1, 1.14286, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0," + - " 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 0);"; + " 0, 0, 0, 0, 0, 0, 0, 0, '', 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, '', 0);"; querySpy.calls.reset(); @@ -143,13 +143,10 @@ describe('CreatureTemplate integration tests', () => { values[25] = 1; // dmgschool await page.setNgxSelectValueByIndex('unit_class', 1); values[35] = 1; // family - values[36] = 1; // trainer_type - values[38] = 1; // trainer_class - await page.setNgxSelectValueByIndex('trainer_race', 1); - values[40] = 1; // type - values[50] = 2; // MovementType - values[56] = 1; // RacialLeader - values[58] = 0; // RegenHealth + values[36] = 1; // type + values[46] = 2; // MovementType + values[52] = 1; // RacialLeader + values[54] = 0; // RegenHealth const expectedQuery = 'UPDATE `creature_template` ' + @@ -158,12 +155,12 @@ describe('CreatureTemplate integration tests', () => { '`faction` = 12, `npcflag` = 13, `speed_walk` = 14, `speed_run` = 15, `speed_swim` = 16, ' + '`speed_flight` = 17, `detection_range` = 18, `scale` = 19, `DamageModifier` = 22, ' + '`BaseAttackTime` = 23, `RangeAttackTime` = 24, `BaseVariance` = 25, `RangeVariance` = 26, `unit_class` = 2, ' + - '`unit_flags` = 28, `unit_flags2` = 29, `dynamicflags` = 30, `trainer_spell` = 33, ' + - '`trainer_race` = 1, `type_flags` = 37, `lootid` = 38, `pickpocketloot` = 39, `skinloot` = 40,' + - " `PetSpellDataId` = 41, `VehicleId` = 42, `mingold` = 43, `maxgold` = 44, `AIName` = '45', " + - '`HoverHeight` = 47, `HealthModifier` = 48, `ManaModifier` = 49, `ArmorModifier` = 50, ' + - '`ExperienceModifier` = 51, `movementId` = 53, `mechanic_immune_mask` = 55, ' + - "`spell_school_immune_mask` = 56, `flags_extra` = 57, `ScriptName` = '58' WHERE (`entry` = 1234);"; + '`unit_flags` = 28, `unit_flags2` = 29, `dynamicflags` = 30, ' + + '`type_flags` = 33, `lootid` = 34, `pickpocketloot` = 35, `skinloot` = 36,' + + " `PetSpellDataId` = 37, `VehicleId` = 38, `mingold` = 39, `maxgold` = 40, `AIName` = '41', " + + '`HoverHeight` = 43, `HealthModifier` = 44, `ManaModifier` = 45, `ArmorModifier` = 46, ' + + '`ExperienceModifier` = 47, `movementId` = 49, `mechanic_immune_mask` = 51, ' + + "`spell_school_immune_mask` = 52, `flags_extra` = 53, `ScriptName` = '54' WHERE (`entry` = 1234);"; querySpy.calls.reset(); diff --git a/libs/features/creature/src/index.ts b/libs/features/creature/src/index.ts index c18763f387..3a80fe56ee 100644 --- a/libs/features/creature/src/index.ts +++ b/libs/features/creature/src/index.ts @@ -12,7 +12,7 @@ export * from './creature-template-resistance/creature-template-resistance.compo export * from './creature-template-spell/creature-template-spell.component'; export * from './creature-template/creature-template.component'; export * from './creature-text/creature-text.component'; -export * from './npc-trainer/npc-trainer.component'; +export * from './creature-default-trainer/creature-default-trainer.component'; export * from './npc-vendor/npc-vendor.component'; export * from './pickpocketing-loot-template/pickpocketing-loot-template.component'; export * from './sai-creature-handler.service'; diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.component.html b/libs/features/creature/src/npc-trainer/npc-trainer.component.html deleted file mode 100644 index c9a9eec044..0000000000 --- a/libs/features/creature/src/npc-trainer/npc-trainer.component.html +++ /dev/null @@ -1,111 +0,0 @@ - - -
- @if (editorService.loading) { - - } - - @if (editorService.form && !!editorService.loadedEntityId && !editorService.loading) { -
-
- -
-
-
-
-
- - - -
-
- - - -
-
- - - - -
-
- - - -
-
- - - -
-
- - -
-
-
-
-
- - - - - - - - - - - - - - - {{ sqliteQueryService.getSpellNameById(row.SpellID) | async }} - - - - - - - -
-
-
-
- } -
diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.integration.spec.ts b/libs/features/creature/src/npc-trainer/npc-trainer.integration.spec.ts deleted file mode 100644 index e92acb7531..0000000000 --- a/libs/features/creature/src/npc-trainer/npc-trainer.integration.spec.ts +++ /dev/null @@ -1,313 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; -import { provideZonelessChangeDetection } from '@angular/core'; -import { provideNoopAnimations } from '@angular/platform-browser/animations'; -import { RouterTestingModule } from '@angular/router/testing'; -import { MysqlQueryService, SqliteQueryService } from '@keira/shared/db-layer'; -import { MultiRowEditorPageObject, TranslateTestingModule } from '@keira/shared/test-utils'; -import { NpcTrainer } from '@keira/shared/acore-world-model'; -import { ModalModule } from 'ngx-bootstrap/modal'; -import { ToastrModule } from 'ngx-toastr'; -import { of } from 'rxjs'; -import { CreatureHandlerService } from '../creature-handler.service'; -import { SaiCreatureHandlerService } from '../sai-creature-handler.service'; -import { NpcTrainerComponent } from './npc-trainer.component'; -import Spy = jasmine.Spy; -import { KEIRA_APP_CONFIG_TOKEN, KEIRA_MOCK_CONFIG } from '@keira/shared/config'; - -class NpcTrainerPage extends MultiRowEditorPageObject {} - -describe('NpcTrainer integration tests', () => { - let fixture: ComponentFixture; - let queryService: MysqlQueryService; - let querySpy: Spy; - let handlerService: CreatureHandlerService; - let page: NpcTrainerPage; - - const id = 1234; - - const originalRow0 = new NpcTrainer(); - const originalRow1 = new NpcTrainer(); - const originalRow2 = new NpcTrainer(); - originalRow0.ID = originalRow1.ID = originalRow2.ID = id; - originalRow0.SpellID = 0; - originalRow1.SpellID = 1; - originalRow2.SpellID = 2; - - beforeEach(() => { - TestBed.configureTestingModule({ - imports: [ToastrModule.forRoot(), ModalModule.forRoot(), NpcTrainerComponent, RouterTestingModule, TranslateTestingModule], - providers: [ - provideZonelessChangeDetection(), - provideNoopAnimations(), - CreatureHandlerService, - SaiCreatureHandlerService, - { provide: KEIRA_APP_CONFIG_TOKEN, useValue: KEIRA_MOCK_CONFIG }, - ], - }).compileComponents(); - }); - - function setup(creatingNew: boolean) { - handlerService = TestBed.inject(CreatureHandlerService); - handlerService['_selected'] = `${id}`; - handlerService.isNew = creatingNew; - - queryService = TestBed.inject(MysqlQueryService); - querySpy = spyOn(queryService, 'query').and.returnValue(of([])); - spyOn(queryService, 'queryValue').and.returnValue(of()); - - spyOn(queryService, 'selectAll').and.returnValue(of(creatingNew ? [] : [originalRow0, originalRow1, originalRow2])); - - fixture = TestBed.createComponent(NpcTrainerComponent); - page = new NpcTrainerPage(fixture); - fixture.autoDetectChanges(true); - fixture.detectChanges(); - } - - describe('Creating new', () => { - beforeEach(() => setup(true)); - - it('should correctly initialise', () => { - page.expectDiffQueryToBeEmpty(); - page.expectFullQueryToBeEmpty(); - expect(page.formError.hidden).toBe(true); - expect(page.addNewRowBtn.disabled).toBe(false); - expect(page.deleteSelectedRowBtn.disabled).toBe(true); - expect(page.getInputById('SpellID').disabled).toBe(true); - expect(page.getInputById('MoneyCost').disabled).toBe(true); - expect(page.getInputById('ReqSkillLine').disabled).toBe(true); - expect(page.getInputById('ReqSkillRank').disabled).toBe(true); - expect(page.getInputById('ReqLevel').disabled).toBe(true); - expect(page.getEditorTableRowsCount()).toBe(0); - }); - - it('should correctly update the unsaved status', () => { - expect(handlerService.isNpcTrainerUnsaved()).toBe(false); - page.addNewRow(); - expect(handlerService.isNpcTrainerUnsaved()).toBe(true); - page.deleteRow(); - expect(handlerService.isNpcTrainerUnsaved()).toBe(false); - }); - - it('adding new rows and executing the query should correctly work', () => { - const expectedQuery = - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (0, 1, 2));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0),\n' + - '(1234, 1, 0, 0, 0, 0),\n' + - '(1234, 2, 0, 0, 0, 0);'; - querySpy.calls.reset(); - - page.addNewRow(); - expect(page.getEditorTableRowsCount()).toBe(1); - page.addNewRow(); - expect(page.getEditorTableRowsCount()).toBe(2); - page.addNewRow(); - expect(page.getEditorTableRowsCount()).toBe(3); - page.expectDiffQueryToContain(expectedQuery); - - page.clickExecuteQuery(); - expect(querySpy).toHaveBeenCalledTimes(1); - expect(querySpy.calls.mostRecent().args[0]).toContain(expectedQuery); - }); - - it('adding a row and changing its values should correctly update the queries', () => { - page.addNewRow(); - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (0));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0);', - ); - - page.setInputValueById('MoneyCost', '1'); - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (0));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 1, 0, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 1, 0, 0, 0);', - ); - - page.setInputValueById('ReqSkillLine', '2'); - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (0));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 1, 2, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 1, 2, 0, 0);', - ); - - page.setInputValueById('SpellID', '123'); - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (123));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 123, 1, 2, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 123, 1, 2, 0, 0);', - ); - }); - - it('adding a row changing its values and duplicate it should correctly update the queries', () => { - page.addNewRow(); - page.setInputValueById('MoneyCost', '1'); - page.setInputValueById('ReqSkillLine', '2'); - page.setInputValueById('SpellID', '123'); - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (123));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 123, 1, 2, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 123, 1, 2, 0, 0);', - ); - }); - }); - - describe('Editing existing', () => { - beforeEach(() => setup(false)); - - it('should correctly initialise', () => { - expect(page.formError.hidden).toBe(true); - page.expectDiffQueryToBeShown(); - page.expectDiffQueryToBeEmpty(); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0),\n' + - '(1234, 1, 0, 0, 0, 0),\n' + - '(1234, 2, 0, 0, 0, 0);', - ); - expect(page.getEditorTableRowsCount()).toBe(3); - }); - - it('deleting rows should correctly work', () => { - page.deleteRow(1); - expect(page.getEditorTableRowsCount()).toBe(2); - page.expectDiffQueryToContain('DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (1));'); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0),\n' + - '(1234, 2, 0, 0, 0, 0);', - ); - - page.deleteRow(1); - expect(page.getEditorTableRowsCount()).toBe(1); - page.expectDiffQueryToContain('DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (1, 2));'); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0);', - ); - - page.deleteRow(0); - expect(page.getEditorTableRowsCount()).toBe(0); - page.expectDiffQueryToContain('DELETE FROM `npc_trainer` WHERE `ID` = 1234;'); - page.expectFullQueryToBeEmpty(); - }); - - it('editing existing rows should correctly work', () => { - page.clickRowOfDatatable(1); - page.setInputValueById('ReqSkillRank', 1); - - page.clickRowOfDatatable(2); - page.setInputValueById('ReqLevel', 2); - - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (1, 2));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 1, 0, 0, 1, 0),\n' + - '(1234, 2, 0, 0, 0, 2);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0),\n' + - '(1234, 1, 0, 0, 1, 0),\n' + - '(1234, 2, 0, 0, 0, 2);', - ); - }); - - it('combining add, edit and delete should correctly work', () => { - page.addNewRow(); - expect(page.getEditorTableRowsCount()).toBe(4); - - page.clickRowOfDatatable(1); - page.setInputValueById('MoneyCost', 10); - expect(page.getEditorTableRowsCount()).toBe(4); - - page.deleteRow(2); - expect(page.getEditorTableRowsCount()).toBe(3); - - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (1, 2, 3));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 1, 10, 0, 0, 0),\n' + - '(1234, 3, 0, 0, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 0, 0, 0),\n' + - '(1234, 1, 10, 0, 0, 0),\n' + - '(1234, 3, 0, 0, 0, 0);', - ); - }); - - it('using the same row id for multiple rows should correctly show an error', () => { - page.clickRowOfDatatable(2); - page.setInputValueById('SpellID', 0); - - page.expectUniqueError(); - }); - - xit('changing a value via SkillSelector should correctly work', async () => { - const field = 'ReqSkillLine'; - const sqliteQueryService = TestBed.inject(SqliteQueryService); - spyOn(sqliteQueryService, 'query').and.returnValue(of([{ id: 123, name: 'Mock Skill' }])); - - // because this is a multi-row editor - page.clickRowOfDatatable(0); - await page.whenReady(); - - page.clickElement(page.getSelectorBtn(field)); - await page.whenReady(); - page.expectModalDisplayed(); - - page.clickSearchBtn(); - await fixture.whenStable(); - page.clickRowOfDatatableInModal(0); - await page.whenReady(); - page.clickModalSelect(); - await page.whenReady(); - - page.expectDiffQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234) AND (`SpellID` IN (0));\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 123, 0, 0);', - ); - page.expectFullQueryToContain( - 'DELETE FROM `npc_trainer` WHERE (`ID` = 1234);\n' + - 'INSERT INTO `npc_trainer` (`ID`, `SpellID`, `MoneyCost`, `ReqSkillLine`, `ReqSkillRank`, `ReqLevel`) VALUES\n' + - '(1234, 0, 0, 123, 0, 0),\n' + - '(1234, 1, 0, 0, 0, 0),\n' + - '(1234, 2, 0, 0, 0, 0);', - ); - }); - }); -}); diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.service.ts b/libs/features/creature/src/npc-trainer/npc-trainer.service.ts deleted file mode 100644 index 498cff55d0..0000000000 --- a/libs/features/creature/src/npc-trainer/npc-trainer.service.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Injectable, inject } from '@angular/core'; -import { MultiRowEditorService } from '@keira/shared/base-abstract-classes'; -import { NPC_TRAINER_ID, NPC_TRAINER_ID_2, NPC_TRAINER_TABLE, NpcTrainer } from '@keira/shared/acore-world-model'; -import { CreatureHandlerService } from '../creature-handler.service'; - -@Injectable({ - providedIn: 'root', -}) -export class NpcTrainerService extends MultiRowEditorService { - protected override readonly handlerService = inject(CreatureHandlerService); - protected override readonly _entityClass = NpcTrainer; - protected override readonly _entityTable = NPC_TRAINER_TABLE; - protected override readonly _entityIdField = NPC_TRAINER_ID; - protected override readonly _entitySecondIdField = NPC_TRAINER_ID_2; - - constructor() { - super(); - this.init(); - } -} diff --git a/libs/features/trainer/.eslintrc.json b/libs/features/trainer/.eslintrc.json new file mode 100644 index 0000000000..a20cf65c22 --- /dev/null +++ b/libs/features/trainer/.eslintrc.json @@ -0,0 +1,33 @@ +{ + "extends": ["../../../.eslintrc.json"], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts"], + "extends": ["plugin:@nx/angular", "plugin:@angular-eslint/template/process-inline-templates"], + "rules": { + "@angular-eslint/directive-selector": [ + "error", + { + "type": "attribute", + "prefix": "keira", + "style": "camelCase" + } + ], + "@angular-eslint/component-selector": [ + "error", + { + "type": "element", + "prefix": "keira", + "style": "kebab-case" + } + ] + } + }, + { + "files": ["*.html"], + "extends": ["plugin:@nx/angular-template"], + "rules": {} + } + ] +} diff --git a/libs/features/trainer/karma.conf.js b/libs/features/trainer/karma.conf.js new file mode 100644 index 0000000000..eb946d5780 --- /dev/null +++ b/libs/features/trainer/karma.conf.js @@ -0,0 +1,15 @@ +const { join } = require('path'); +const getBaseKarmaConfig = require('../../../karma.conf'); + +module.exports = function (config) { + const baseConfig = getBaseKarmaConfig(config); + config.set({ + ...baseConfig, + frameworks: [...baseConfig.frameworks], + plugins: [...baseConfig.plugins], + coverageReporter: { + ...baseConfig.coverageReporter, + dir: join(__dirname, '../../../coverage/libs/features/trainer'), + }, + }); +}; diff --git a/libs/features/trainer/project.json b/libs/features/trainer/project.json new file mode 100644 index 0000000000..32081f6982 --- /dev/null +++ b/libs/features/trainer/project.json @@ -0,0 +1,24 @@ +{ + "name": "keira-features-trainer", + "$schema": "../../../node_modules/nx/schemas/project-schema.json", + "sourceRoot": "libs/features/trainer/src", + "prefix": "keira", + "tags": ["scope:features"], + "projectType": "library", + "targets": { + "test": { + "executor": "@angular-devkit/build-angular:karma", + "options": { + "tsConfig": "libs/features/trainer/tsconfig.spec.json", + "karmaConfig": "libs/features/trainer/karma.conf.js", + "sourceMap": true, + "codeCoverage": true, + "styles": ["apps/keira/src/app/scss/main-test.scss"], + "scripts": ["node_modules/squel/dist/squel.min.js"] + } + }, + "lint": { + "executor": "@nx/eslint:lint" + } + } +} diff --git a/libs/features/trainer/src/edit-trainer/trainer.component.html b/libs/features/trainer/src/edit-trainer/trainer.component.html new file mode 100644 index 0000000000..5cd16d5c15 --- /dev/null +++ b/libs/features/trainer/src/edit-trainer/trainer.component.html @@ -0,0 +1,51 @@ + + +
+ @if (editorService.loading) { + + } + + @if (editorService.form && !!editorService.loadedEntityId && !editorService.loading) { +
+
+ +
+
+
+ +
+
+ + +
+
+ + +
+
+ + + +
+
+
+
+ + + +
+
+
+
+
+ } +
diff --git a/libs/features/trainer/src/edit-trainer/trainer.component.spec.ts b/libs/features/trainer/src/edit-trainer/trainer.component.spec.ts new file mode 100644 index 0000000000..f2258483dd --- /dev/null +++ b/libs/features/trainer/src/edit-trainer/trainer.component.spec.ts @@ -0,0 +1,65 @@ +import { Component, provideZonelessChangeDetection, viewChild } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { MysqlQueryService } from '@keira/shared/db-layer'; +import { TranslateTestingModule } from '@keira/shared/test-utils'; +import { ModalModule } from 'ngx-bootstrap/modal'; +import { ToastrModule } from 'ngx-toastr'; +import { of } from 'rxjs'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { TrainerComponent } from './trainer.component'; +import { TrainerService } from './trainer.service'; + +describe('TrainerComponent', () => { + @Component({ + template: '', + imports: [TrainerComponent], + }) + class TestHostComponent { + readonly child = viewChild.required(TrainerComponent); + } + + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ + ModalModule.forRoot(), + ToastrModule.forRoot(), + TestHostComponent, + TrainerComponent, + RouterTestingModule, + TranslateTestingModule, + ], + providers: [provideZonelessChangeDetection(), provideNoopAnimations(), TrainerHandlerService], + }).compileComponents(); + }); + + const setup = () => { + const queryService = TestBed.inject(MysqlQueryService); + spyOn(queryService, 'query').and.returnValue(of()); + + const fixture = TestBed.createComponent(TestHostComponent); + const host = fixture.componentInstance; + const component = host.child(); + const trainerService = TestBed.inject(TrainerService); + fixture.detectChanges(); + + return { fixture, host, component, queryService, trainerService }; + }; + + it('should create', () => { + const { component } = setup(); + expect(component).toBeTruthy(); + }); + + it('should have editorService injected', () => { + const { component, trainerService } = setup(); + expect(component['editorService']).toBeTruthy(); + expect(component['editorService']).toEqual(trainerService); + }); + + it('should have TRAINER_TYPE constant available', () => { + const { component } = setup(); + expect(component['TRAINER_TYPE']).toBeDefined(); + }); +}); diff --git a/libs/features/trainer/src/edit-trainer/trainer.component.ts b/libs/features/trainer/src/edit-trainer/trainer.component.ts new file mode 100644 index 0000000000..7c3844d7bf --- /dev/null +++ b/libs/features/trainer/src/edit-trainer/trainer.component.ts @@ -0,0 +1,30 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TRAINER_TYPE, Trainer } from '@keira/shared/acore-world-model'; +import { SingleRowEditorComponent } from '@keira/shared/base-abstract-classes'; +import { TranslateModule } from '@ngx-translate/core'; +import { TooltipModule } from 'ngx-bootstrap/tooltip'; +import { TrainerService } from './trainer.service'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { QueryOutputComponent, TopBarComponent } from '@keira/shared/base-editor-components'; +import { GenericOptionSelectorComponent } from '@keira/shared/selectors'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + selector: 'keira-trainer', + templateUrl: './trainer.component.html', + imports: [ + TopBarComponent, + TranslateModule, + FormsModule, + ReactiveFormsModule, + TooltipModule, + QueryOutputComponent, + GenericOptionSelectorComponent, + ], +}) +export class TrainerComponent extends SingleRowEditorComponent { + protected override readonly editorService = inject(TrainerService); + protected readonly handlerService = inject(TrainerHandlerService); + protected readonly TRAINER_TYPE = TRAINER_TYPE; +} diff --git a/libs/features/trainer/src/edit-trainer/trainer.service.ts b/libs/features/trainer/src/edit-trainer/trainer.service.ts new file mode 100644 index 0000000000..aed43c705e --- /dev/null +++ b/libs/features/trainer/src/edit-trainer/trainer.service.ts @@ -0,0 +1,19 @@ +import { Injectable, inject } from '@angular/core'; +import { SingleRowEditorService } from '@keira/shared/base-abstract-classes'; +import { TRAINER_ID, TRAINER_TABLE, Trainer } from '@keira/shared/acore-world-model'; +import { TrainerHandlerService } from '../trainer-handler.service'; + +@Injectable({ + providedIn: 'root', +}) +export class TrainerService extends SingleRowEditorService { + protected override readonly handlerService = inject(TrainerHandlerService); + protected override readonly _entityClass = Trainer; + protected override readonly _entityTable = TRAINER_TABLE; + protected override readonly _entityIdField = TRAINER_ID; + + constructor() { + super(); + this.init(); + } +} diff --git a/libs/features/trainer/src/index.ts b/libs/features/trainer/src/index.ts new file mode 100644 index 0000000000..557168e9b8 --- /dev/null +++ b/libs/features/trainer/src/index.ts @@ -0,0 +1,7 @@ +export * from './trainer-handler.service'; +export * from './select-trainer/select-trainer.component'; +export * from './select-trainer/select-trainer.service'; +export * from './edit-trainer/trainer.component'; +export * from './edit-trainer/trainer.service'; +export * from './trainer-spell/trainer-spell.component'; +export * from './trainer-spell/trainer-spell.service'; diff --git a/libs/features/trainer/src/select-trainer/select-trainer.component.html b/libs/features/trainer/src/select-trainer/select-trainer.component.html new file mode 100644 index 0000000000..71bef3c253 --- /dev/null +++ b/libs/features/trainer/src/select-trainer/select-trainer.component.html @@ -0,0 +1,59 @@ + + +
+
+ +
+ +
+

+
+
+ +
+ +
+
+ +
+
+
+ +
+
+ +
+
+ + + + @if (selectService.rows) { +
+ + + + + + +
+ } +
+
diff --git a/libs/features/trainer/src/select-trainer/select-trainer.component.spec.ts b/libs/features/trainer/src/select-trainer/select-trainer.component.spec.ts new file mode 100644 index 0000000000..0921608fb8 --- /dev/null +++ b/libs/features/trainer/src/select-trainer/select-trainer.component.spec.ts @@ -0,0 +1,56 @@ +import { provideZonelessChangeDetection } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; +import { Router } from '@angular/router'; +import { RouterTestingModule } from '@angular/router/testing'; +import { MysqlQueryService } from '@keira/shared/db-layer'; +import { TranslateTestingModule } from '@keira/shared/test-utils'; +import { ModalModule } from 'ngx-bootstrap/modal'; +import { ToastrModule } from 'ngx-toastr'; +import { of } from 'rxjs'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { SelectTrainerComponent } from './select-trainer.component'; +import { SelectTrainerService } from './select-trainer.service'; + +describe('SelectTrainerComponent', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ModalModule.forRoot(), ToastrModule.forRoot(), SelectTrainerComponent, RouterTestingModule, TranslateTestingModule], + providers: [provideZonelessChangeDetection(), provideNoopAnimations(), TrainerHandlerService], + }).compileComponents(); + }); + + const setup = () => { + const queryService = TestBed.inject(MysqlQueryService); + spyOn(queryService, 'query').and.returnValue(of()); + + const fixture = TestBed.createComponent(SelectTrainerComponent); + const component = fixture.componentInstance; + const selectService = TestBed.inject(SelectTrainerService); + const handlerService = TestBed.inject(TrainerHandlerService); + const router = TestBed.inject(Router); + fixture.detectChanges(); + + return { fixture, component, queryService, selectService, handlerService, router }; + }; + + it('should create', () => { + const { component } = setup(); + expect(component).toBeTruthy(); + }); + + it('should have correct entity table', () => { + const { component } = setup(); + expect(component['entityTable']).toBe('trainer'); + }); + + it('should have correct entity id field', () => { + const { component } = setup(); + expect(component['entityIdField']).toBe('Id'); + }); + + it('should have customStartingId set to 1000000', () => { + const { component } = setup(); + expect(component['customStartingId']).toBe(1000000); + }); +}); diff --git a/libs/features/trainer/src/select-trainer/select-trainer.component.ts b/libs/features/trainer/src/select-trainer/select-trainer.component.ts new file mode 100644 index 0000000000..a76902a6cc --- /dev/null +++ b/libs/features/trainer/src/select-trainer/select-trainer.component.ts @@ -0,0 +1,32 @@ +import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; +import { SelectComponent } from '@keira/shared/base-abstract-classes'; +import { TRAINER_ID, TRAINER_TABLE, Trainer } from '@keira/shared/acore-world-model'; +import { NgxDatatableModule } from '@siemens/ngx-datatable'; +import { TranslateModule } from '@ngx-translate/core'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { SelectTrainerService } from './select-trainer.service'; +import { WIKI_BASE_URL } from '@keira/shared/constants'; +import { CreateComponent, HighlightjsWrapperComponent, TopBarComponent } from '@keira/shared/base-editor-components'; + +@Component({ + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './select-trainer.component.html', + imports: [ + FormsModule, + ReactiveFormsModule, + TranslateModule, + NgxDatatableModule, + CreateComponent, + HighlightjsWrapperComponent, + TopBarComponent, + ], +}) +export class SelectTrainerComponent extends SelectComponent { + protected override readonly entityTable = TRAINER_TABLE; + protected override readonly entityIdField = TRAINER_ID; + protected readonly customStartingId = 1000000; + protected readonly selectService = inject(SelectTrainerService); + readonly handlerService = inject(TrainerHandlerService); + protected readonly WIKI_BASE_URL = WIKI_BASE_URL; +} diff --git a/libs/features/trainer/src/select-trainer/select-trainer.service.ts b/libs/features/trainer/src/select-trainer/select-trainer.service.ts new file mode 100644 index 0000000000..44e83a48d1 --- /dev/null +++ b/libs/features/trainer/src/select-trainer/select-trainer.service.ts @@ -0,0 +1,20 @@ +import { Injectable, inject } from '@angular/core'; +import { SelectService } from '@keira/shared/base-abstract-classes'; +import { MysqlQueryService } from '@keira/shared/db-layer'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { TRAINER_ID, TRAINER_TABLE, Trainer } from '@keira/shared/acore-world-model'; + +@Injectable({ + providedIn: 'root', +}) +export class SelectTrainerService extends SelectService { + override readonly queryService = inject(MysqlQueryService); + override readonly handlerService = inject(TrainerHandlerService); + protected override readonly entityTable = TRAINER_TABLE; + protected override readonly entityIdField = TRAINER_ID; + protected override readonly fieldList = [TRAINER_ID, 'Type', 'Requirement']; + constructor() { + super(); + this.init(); + } +} diff --git a/libs/features/trainer/src/trainer-handler.service.spec.ts b/libs/features/trainer/src/trainer-handler.service.spec.ts new file mode 100644 index 0000000000..62e0813494 --- /dev/null +++ b/libs/features/trainer/src/trainer-handler.service.spec.ts @@ -0,0 +1,37 @@ +import { provideZonelessChangeDetection } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { TrainerHandlerService } from './trainer-handler.service'; + +describe('TrainerHandlerService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [RouterTestingModule], + providers: [provideZonelessChangeDetection(), provideNoopAnimations(), TrainerHandlerService], + }); + }); + + const setup = () => { + const service = TestBed.inject(TrainerHandlerService); + return { service }; + }; + + it('should update isTrainerUnsaved status', () => { + const { service } = setup(); + expect(service.isTrainerUnsaved()).toBe(false); + + service['_statusMap']['trainer'].set(true); + + expect(service.isTrainerUnsaved()).toBe(true); + }); + + it('should update isTrainerSpellUnsaved status', () => { + const { service } = setup(); + expect(service.isTrainerSpellUnsaved()).toBe(false); + + service['_statusMap']['trainer_spell'].set(true); + + expect(service.isTrainerSpellUnsaved()).toBe(true); + }); +}); diff --git a/libs/features/trainer/src/trainer-handler.service.ts b/libs/features/trainer/src/trainer-handler.service.ts new file mode 100644 index 0000000000..39e0f897c2 --- /dev/null +++ b/libs/features/trainer/src/trainer-handler.service.ts @@ -0,0 +1,23 @@ +import { Injectable, signal, Signal } from '@angular/core'; +import { HandlerService } from '@keira/shared/base-abstract-classes'; +import { TRAINER_TABLE, TRAINER_SPELL_TABLE, Trainer } from '@keira/shared/acore-world-model'; + +@Injectable({ + providedIn: 'root', +}) +export class TrainerHandlerService extends HandlerService { + protected readonly mainEditorRoutePath = 'trainer/trainer'; + + get isTrainerUnsaved(): Signal { + return this.statusMap[TRAINER_TABLE].asReadonly(); + } + + get isTrainerSpellUnsaved(): Signal { + return this.statusMap[TRAINER_SPELL_TABLE].asReadonly(); + } + + protected _statusMap = { + [TRAINER_TABLE]: signal(false), + [TRAINER_SPELL_TABLE]: signal(false), + }; +} diff --git a/libs/features/trainer/src/trainer-spell/trainer-spell.component.html b/libs/features/trainer/src/trainer-spell/trainer-spell.component.html new file mode 100644 index 0000000000..1659759acb --- /dev/null +++ b/libs/features/trainer/src/trainer-spell/trainer-spell.component.html @@ -0,0 +1,159 @@ + + +
+ @if (editorService.loading) { + + } + + @if (editorService.form && !!editorService.loadedEntityId && !editorService.loading) { +
+
+ +
+
+
+
+
+ + + +
+
+ + + +
+
+ + + + +
+
+ + + +
+
+ + + + +
+
+ + + + +
+
+
+
+ + + + +
+
+ + + +
+
+
+ + + + + + + + @if (sqliteQueryService.getSpellNameById(value) | async; as spellName) { +
{{ spellName }}
+ } +
+
+ + + + + + @if (value !== 0) { + @if (sqliteQueryService.getSpellNameById(value) | async; as spellName) { +
{{ value }}: {{ spellName }}
+ } + } +
+
+ + + @if (value !== 0) { + @if (sqliteQueryService.getSpellNameById(value) | async; as spellName) { +
{{ value }}: {{ spellName }}
+ } + } +
+
+ + + @if (value !== 0) { + @if (sqliteQueryService.getSpellNameById(value) | async; as spellName) { +
{{ value }}: {{ spellName }}
+ } + } +
+
+ +
+
+
+ } +
diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.component.scss b/libs/features/trainer/src/trainer-spell/trainer-spell.component.scss similarity index 100% rename from libs/features/creature/src/npc-trainer/npc-trainer.component.scss rename to libs/features/trainer/src/trainer-spell/trainer-spell.component.scss diff --git a/libs/features/creature/src/npc-trainer/npc-trainer.component.ts b/libs/features/trainer/src/trainer-spell/trainer-spell.component.ts similarity index 67% rename from libs/features/creature/src/npc-trainer/npc-trainer.component.ts rename to libs/features/trainer/src/trainer-spell/trainer-spell.component.ts index 806e0c74fe..a0fc324756 100644 --- a/libs/features/creature/src/npc-trainer/npc-trainer.component.ts +++ b/libs/features/trainer/src/trainer-spell/trainer-spell.component.ts @@ -1,7 +1,7 @@ import { AsyncPipe } from '@angular/common'; import { ChangeDetectionStrategy, Component, inject } from '@angular/core'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; -import { NpcTrainer } from '@keira/shared/acore-world-model'; +import { TrainerSpell } from '@keira/shared/acore-world-model'; import { MultiRowEditorComponent } from '@keira/shared/base-abstract-classes'; import { EditorButtonsComponent, IconComponent, QueryOutputComponent, TopBarComponent } from '@keira/shared/base-editor-components'; import { SqliteQueryService } from '@keira/shared/db-layer'; @@ -9,14 +9,14 @@ import { SkillSelectorBtnComponent, SpellSelectorBtnComponent } from '@keira/sha import { TranslateModule } from '@ngx-translate/core'; import { NgxDatatableModule } from '@siemens/ngx-datatable'; import { TooltipModule } from 'ngx-bootstrap/tooltip'; -import { CreatureHandlerService } from '../creature-handler.service'; -import { NpcTrainerService } from './npc-trainer.service'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { TrainerSpellService } from './trainer-spell.service'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, - selector: 'keira-npc-trainer', - templateUrl: './npc-trainer.component.html', - styleUrls: ['./npc-trainer.component.scss'], + selector: 'keira-trainer-spell', + templateUrl: './trainer-spell.component.html', + styleUrls: ['./trainer-spell.component.scss'], imports: [ TopBarComponent, TranslateModule, @@ -32,8 +32,8 @@ import { NpcTrainerService } from './npc-trainer.service'; IconComponent, ], }) -export class NpcTrainerComponent extends MultiRowEditorComponent { - protected override readonly editorService = inject(NpcTrainerService); - readonly handlerService = inject(CreatureHandlerService); +export class TrainerSpellComponent extends MultiRowEditorComponent { + protected override readonly editorService = inject(TrainerSpellService); + readonly handlerService = inject(TrainerHandlerService); readonly sqliteQueryService = inject(SqliteQueryService); } diff --git a/libs/features/trainer/src/trainer-spell/trainer-spell.service.spec.ts b/libs/features/trainer/src/trainer-spell/trainer-spell.service.spec.ts new file mode 100644 index 0000000000..e24c685394 --- /dev/null +++ b/libs/features/trainer/src/trainer-spell/trainer-spell.service.spec.ts @@ -0,0 +1,48 @@ +import { provideZonelessChangeDetection } from '@angular/core'; +import { TestBed } from '@angular/core/testing'; +import { provideNoopAnimations } from '@angular/platform-browser/animations'; +import { RouterTestingModule } from '@angular/router/testing'; +import { MysqlQueryService } from '@keira/shared/db-layer'; +import { ToastrModule } from 'ngx-toastr'; +import { instance, mock } from 'ts-mockito'; +import { TrainerHandlerService } from '../trainer-handler.service'; +import { TrainerSpellService } from './trainer-spell.service'; + +describe('TrainerSpellService', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + imports: [ToastrModule.forRoot(), RouterTestingModule], + providers: [ + provideZonelessChangeDetection(), + provideNoopAnimations(), + { provide: MysqlQueryService, useValue: instance(mock(MysqlQueryService)) }, + TrainerHandlerService, + ], + }); + }); + + const setup = () => { + const service = TestBed.inject(TrainerSpellService); + return { service }; + }; + + it('should be created', () => { + const { service } = setup(); + expect(service).toBeTruthy(); + }); + + it('should have correct entity table', () => { + const { service } = setup(); + expect(service['_entityTable']).toBe('trainer_spell'); + }); + + it('should have correct entity id field', () => { + const { service } = setup(); + expect(service['_entityIdField']).toBe('TrainerId'); + }); + + it('should have correct entity second id field', () => { + const { service } = setup(); + expect(service['_entitySecondIdField']).toBe('SpellId'); + }); +}); diff --git a/libs/features/trainer/src/trainer-spell/trainer-spell.service.ts b/libs/features/trainer/src/trainer-spell/trainer-spell.service.ts new file mode 100644 index 0000000000..8d0f65887c --- /dev/null +++ b/libs/features/trainer/src/trainer-spell/trainer-spell.service.ts @@ -0,0 +1,20 @@ +import { Injectable, inject } from '@angular/core'; +import { MultiRowEditorService } from '@keira/shared/base-abstract-classes'; +import { TRAINER_SPELL_ID, TRAINER_SPELL_ID_2, TRAINER_SPELL_TABLE, TrainerSpell } from '@keira/shared/acore-world-model'; +import { TrainerHandlerService } from '../trainer-handler.service'; + +@Injectable({ + providedIn: 'root', +}) +export class TrainerSpellService extends MultiRowEditorService { + protected override readonly handlerService = inject(TrainerHandlerService); + protected override readonly _entityClass = TrainerSpell; + protected override readonly _entityTable = TRAINER_SPELL_TABLE; + protected override readonly _entityIdField = TRAINER_SPELL_ID; + protected override readonly _entitySecondIdField = TRAINER_SPELL_ID_2; + + constructor() { + super(); + this.init(); + } +} diff --git a/libs/features/trainer/tsconfig.json b/libs/features/trainer/tsconfig.json new file mode 100644 index 0000000000..dc5452d1bc --- /dev/null +++ b/libs/features/trainer/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "target": "ES2022", + "useDefineForClassFields": false, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + }, + { + "path": "./tsconfig.spec.json" + } + ], + "extends": "../../../tsconfig.base.json", + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/libs/features/trainer/tsconfig.lib.json b/libs/features/trainer/tsconfig.lib.json new file mode 100644 index 0000000000..b70a86075b --- /dev/null +++ b/libs/features/trainer/tsconfig.lib.json @@ -0,0 +1,12 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../../../dist/out-tsc", + "declaration": true, + "declarationMap": true, + "inlineSources": true, + "types": [] + }, + "exclude": ["src/**/*.spec.ts", "src/test-setup.ts", "**/*.test.ts"], + "include": ["src/**/*.ts"] +} diff --git a/libs/features/trainer/tsconfig.spec.json b/libs/features/trainer/tsconfig.spec.json new file mode 100644 index 0000000000..b864ec66ae --- /dev/null +++ b/libs/features/trainer/tsconfig.spec.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "types": ["jasmine", "node"] + }, + "include": ["**/*.spec.ts", "**/*.d.ts"], + "exclude": ["dist", "release", "node_modules"] +} diff --git a/libs/main/main-window/src/sidebar/sidebar.component.html b/libs/main/main-window/src/sidebar/sidebar.component.html index e5ca20b382..aebc10deb6 100644 --- a/libs/main/main-window/src/sidebar/sidebar.component.html +++ b/libs/main/main-window/src/sidebar/sidebar.component.html @@ -146,13 +146,14 @@
  • - - {{ 'SIDEBAR.CREATURE.TRAINER' | translate }} - @if (creatureHandlerService.isNpcTrainerUnsaved()) { + + {{ 'SIDEBAR.CREATURE.DEFAULT_TRAINER' | translate }} + @if (creatureHandlerService.isCreatureDefaultTrainerUnsaved()) { }
  • +
  • {{ 'SIDEBAR.CREATURE.QUEST_ITEM' | translate }} @@ -763,6 +764,41 @@
  • + +
  • {{ 'SIDEBAR.UNUSED_GUID_SEARCH' | translate }} diff --git a/libs/main/main-window/src/sidebar/sidebar.component.ts b/libs/main/main-window/src/sidebar/sidebar.component.ts index 2034cb2ab2..9487b767fc 100644 --- a/libs/main/main-window/src/sidebar/sidebar.component.ts +++ b/libs/main/main-window/src/sidebar/sidebar.component.ts @@ -23,6 +23,7 @@ import { AcoreStringHandlerService, } from '@keira/features/texts'; import { GameTeleHandlerService } from '@keira/features/game-tele'; +import { TrainerHandlerService } from '@keira/features/trainer'; import { LocationService } from '@keira/shared/common-services'; import { MysqlService } from '@keira/shared/db-layer'; import { SaiHandlerService } from '@keira/shared/sai-editor'; @@ -47,6 +48,7 @@ interface MenuStats { gossip: ToggleType; spell: ToggleType; gameTele: ToggleType; + trainer: ToggleType; } @Component({ @@ -84,6 +86,7 @@ export class SidebarComponent { gossip: 'up', spell: 'up', gameTele: 'up', + trainer: 'up', }; private readonly IMAGES_COUNT = 7; private readonly RANDOM_IMAGE = Math.floor(Math.random() * this.IMAGES_COUNT) + 1; @@ -108,6 +111,7 @@ export class SidebarComponent { protected readonly npcTextHandlerService = inject(NpcTextHandlerService); protected readonly acoreStringHandlerService = inject(AcoreStringHandlerService); protected readonly gameTeleHandlerService = inject(GameTeleHandlerService); + protected readonly trainerHandlerService = inject(TrainerHandlerService); private readonly locationService = inject(LocationService); getSideBarState(): boolean { @@ -140,10 +144,11 @@ export class SidebarComponent { this.menuStates.otherLoot = 'up'; this.menuStates.smartAi = 'up'; this.menuStates.conditions = 'up'; - this.menuStates.texts = 'up'; this.menuStates.gossip = 'up'; this.menuStates.spell = 'up'; this.menuStates.gameTele = 'up'; + this.menuStates.trainer = 'up'; + this.menuStates.gameTele = 'up'; } logout(): void { diff --git a/libs/shared/acore-world-model/src/entities/creature-default-trainer.type.ts b/libs/shared/acore-world-model/src/entities/creature-default-trainer.type.ts new file mode 100644 index 0000000000..4a0f508ac8 --- /dev/null +++ b/libs/shared/acore-world-model/src/entities/creature-default-trainer.type.ts @@ -0,0 +1,9 @@ +import { TableRow } from '@keira/shared/constants'; + +export const CREATURE_DEFAULT_TRAINER_TABLE = 'creature_default_trainer'; +export const CREATURE_DEFAULT_TRAINER_ID = 'CreatureId'; + +export class CreatureDefaultTrainer extends TableRow { + CreatureId: number = 0; + TrainerId: number = 0; +} diff --git a/libs/shared/acore-world-model/src/entities/creature-template.type.ts b/libs/shared/acore-world-model/src/entities/creature-template.type.ts index c3160fb842..56da7b8cc3 100644 --- a/libs/shared/acore-world-model/src/entities/creature-template.type.ts +++ b/libs/shared/acore-world-model/src/entities/creature-template.type.ts @@ -44,10 +44,6 @@ export class CreatureTemplate extends TableRow { unit_flags2: number = 0; dynamicflags: number = 0; family: number = 0; - trainer_type: number = 0; - trainer_spell: number = 0; - trainer_class: number = 0; - trainer_race: number = 0; type: number = 0; type_flags: number = 0; lootid: number = 0; diff --git a/libs/shared/acore-world-model/src/entities/npc-trainer.type.ts b/libs/shared/acore-world-model/src/entities/npc-trainer.type.ts deleted file mode 100644 index 55b123c945..0000000000 --- a/libs/shared/acore-world-model/src/entities/npc-trainer.type.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { TableRow } from '@keira/shared/constants'; - -export const NPC_TRAINER_TABLE = 'npc_trainer'; -export const NPC_TRAINER_ID = 'ID'; -export const NPC_TRAINER_ID_2 = 'SpellID'; - -export class NpcTrainer extends TableRow { - ID: number = 0; - SpellID: number = 0; - MoneyCost: number = 0; - ReqSkillLine: number = 0; - ReqSkillRank: number = 0; - ReqLevel: number = 0; -} diff --git a/libs/shared/acore-world-model/src/entities/trainer-locale.type.ts b/libs/shared/acore-world-model/src/entities/trainer-locale.type.ts new file mode 100644 index 0000000000..b7281429bf --- /dev/null +++ b/libs/shared/acore-world-model/src/entities/trainer-locale.type.ts @@ -0,0 +1,12 @@ +import { TableRow } from '@keira/shared/constants'; + +export const TRAINER_LOCALE_TABLE = 'trainer_locale'; +export const TRAINER_LOCALE_ID = 'Id'; +export const TRAINER_LOCALE_ID_2 = 'locale'; + +export class TrainerLocale extends TableRow { + Id: number = 0; + locale: string = ''; + Greeting_lang: string = ''; + VerifiedBuild: number = 0; +} diff --git a/libs/shared/acore-world-model/src/entities/trainer-spell.type.ts b/libs/shared/acore-world-model/src/entities/trainer-spell.type.ts new file mode 100644 index 0000000000..67680df2fa --- /dev/null +++ b/libs/shared/acore-world-model/src/entities/trainer-spell.type.ts @@ -0,0 +1,18 @@ +import { TableRow } from '@keira/shared/constants'; + +export const TRAINER_SPELL_TABLE = 'trainer_spell'; +export const TRAINER_SPELL_ID = 'TrainerId'; +export const TRAINER_SPELL_ID_2 = 'SpellId'; + +export class TrainerSpell extends TableRow { + TrainerId: number = 0; + SpellId: number = 0; + MoneyCost: number = 0; + ReqSkillLine: number = 0; + ReqSkillRank: number = 0; + ReqAbility1: number = 0; + ReqAbility2: number = 0; + ReqAbility3: number = 0; + ReqLevel: number = 0; + VerifiedBuild: number = 0; +} diff --git a/libs/shared/acore-world-model/src/entities/trainer.type.ts b/libs/shared/acore-world-model/src/entities/trainer.type.ts new file mode 100644 index 0000000000..70753b0ce7 --- /dev/null +++ b/libs/shared/acore-world-model/src/entities/trainer.type.ts @@ -0,0 +1,12 @@ +import { TableRow } from '@keira/shared/constants'; + +export const TRAINER_TABLE = 'trainer'; +export const TRAINER_ID = 'Id'; + +export class Trainer extends TableRow { + Id: number = 0; + Type: number = 0; + Requirement: number = 0; + Greeting: string = ''; + VerifiedBuild: number = 0; +} diff --git a/libs/shared/acore-world-model/src/index.ts b/libs/shared/acore-world-model/src/index.ts index 3e2c651d64..fcb618fbdf 100644 --- a/libs/shared/acore-world-model/src/index.ts +++ b/libs/shared/acore-world-model/src/index.ts @@ -46,9 +46,12 @@ export * from './entities/mail-loot-template.type'; export * from './entities/map.type'; export * from './entities/milling-loot-template.type'; export * from './entities/npc-text.type'; -export * from './entities/npc-trainer.type'; export * from './entities/npc-vendor.type'; export * from './entities/page-text.type'; +export * from './entities/trainer.type'; +export * from './entities/trainer-locale.type'; +export * from './entities/trainer-spell.type'; +export * from './entities/creature-default-trainer.type'; export * from './entities/pickpocketing-loot-template.type'; export * from './entities/prospecting-loot-template.type'; export * from './entities/quest-offer-reward.type'; diff --git a/libs/shared/selectors/src/selectors/spell-selector/spell-selector-modal.component.html b/libs/shared/selectors/src/selectors/spell-selector/spell-selector-modal.component.html index 23deebe4ed..329388bb9a 100644 --- a/libs/shared/selectors/src/selectors/spell-selector/spell-selector-modal.component.html +++ b/libs/shared/selectors/src/selectors/spell-selector/spell-selector-modal.component.html @@ -43,7 +43,7 @@ - {{ row.spellName }} +
    {{ row.spellName }}
    diff --git a/package-lock.json b/package-lock.json index 6d4733e688..fedd01b76e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -28070,7 +28070,6 @@ "integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", diff --git a/tsconfig.base.json b/tsconfig.base.json index acf13cc877..b7c58cd715 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -37,6 +37,7 @@ "@keira/features/spell": ["libs/features/spell/src/index.ts"], "@keira/features/sql-editor": ["libs/features/sql-editor/src/index.ts"], "@keira/features/texts": ["libs/features/texts/src/index.ts"], + "@keira/features/trainer": ["libs/features/trainer/src/index.ts"], "@keira/features/unused-guid-search": ["libs/features/unused-guid-search/src/index.ts"], "@keira/main/connection-window": ["libs/main/connection-window/src/index.ts"], "@keira/main/main-window": ["libs/main/main-window/src/index.ts"],