diff --git a/CHANGELOG.md b/CHANGELOG.md index 47192f0..2bb0ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ ## Release/Patch Notes +### Version 1.4.0 - TBD + +- Feature [Github #70] - Added ability to track and roll Special Training. +- Enhancement - Slight restyle of Skill section of sheet, saving space. + ### Version 1.3.5 - 2023-11-20 - Working on improving the process for packing a new build, but some things have gone wrong. So no actual changes here, just iterating forward on the build to avoid some issues that cropped up. diff --git a/css/deltagreen.css b/css/deltagreen.css index 735e38f..785be1a 100644 --- a/css/deltagreen.css +++ b/css/deltagreen.css @@ -129,7 +129,7 @@ form.program-style { color: #999999; } -input.breaking-point-hit{ +input.breaking-point-hit { color: rgb(117, 0, 0); font-weight: bold; } @@ -224,6 +224,14 @@ input.breaking-point-hit{ .flex-thin-border { border: 1px solid #999; border-radius: 2px; + border-left-color: darkslategray; + border-left-width: 4px; +} + +/* Make sure Special Training boxes are the same height + as all other skill boxes */ +.flex-thin-border.special-training-box { + min-height: 27px; } .flex-mid-border { @@ -440,6 +448,18 @@ input.breaking-point-hit{ text-align: right; } +.deltagreen .skill-and-training-controls { + flex: 0 0 80px; +} + +.deltagreen .action-pill { + padding: 2px; + border-radius: 2.5px; + font-size: 0.8rem; + font-weight: bold; + background-color: rgba(0, 0, 0, 0.185); +} + a.btn-tiny { height: 26px; margin-left: 5px; @@ -495,6 +515,7 @@ input.percentile-skill-input { flex: 0 0 40px; margin-right: 5px; margin-left: 5px; + height: unset; } input.checkbox-skill-input { diff --git a/lang/en.json b/lang/en.json index d614a78..0813eab 100644 --- a/lang/en.json +++ b/lang/en.json @@ -44,7 +44,7 @@ "DG.Skills.unarmed_combat": "Unarmed Combat", "DG.Skills.unnatural": "Unnatural", - "DG.Skills.AddTypedOrCustomSkill": "Add Typed or Custom Skill", + "DG.Skills.AddTypedOrCustomSkill": "Add Typed/Custom Skill", "DG.Skills.AddSkill": "Add Skill", "DG.Skills.Apply": "Apply", "DG.Skills.ApplySkillImprovements": "Apply Skill Improvements", @@ -65,6 +65,15 @@ "DG.TypeSkills.Science": "Science", "DG.TypeSkills.Other": "Other", + "DG.SpecialTraining.Dialog.CreateSpecialTraining": "Add Special Training", + "DG.SpecialTraining.Dialog.DropDown.CustomSkills": "Custom/Typed Skills", + "DG.SpecialTraining.Dialog.DropDown.Skills": "Skills", + "DG.SpecialTraining.Dialog.DropDown.Statistics": "Statistics", + "DG.SpecialTraining.Dialog.EditSpecialTraining": "Edit Special Training", + "DG.SpecialTraining.Dialog.NameLabel": "Name", + "DG.SpecialTraining.Dialog.SkillLabel": "Skill or Stat", + "DG.SpecialTraining.Dialog.Title": "Create/Edit Special Training", + "DG.Attributes.HP": "HP", "DG.Attributes.WP": "WP", "DG.Attributes.SAN": "SAN", diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index a0c7b16..c00e470 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -1,5 +1,6 @@ -/* globals $ game Roll ChatMessage AudioHelper ActorSheet mergeObject Dialog TextEditor ActiveEffect ui duplicate fromUuidSync */ +/* globals $ game Roll ChatMessage AudioHelper ActorSheet mergeObject Dialog TextEditor ActiveEffect ui duplicate fromUuidSync renderTemplate randomID */ +import DG from "../config.js"; import { DGPercentileRoll, DGLethalityRoll, @@ -17,7 +18,7 @@ export default class DeltaGreenActorSheet extends ActorSheet { classes: ["deltagreen", "sheet", "actor"], template: "systems/deltagreen/templates/actor/actor-sheet.html", width: 700, - height: 800, + height: 770, tabs: [ { navSelector: ".sheet-tabs", @@ -66,6 +67,44 @@ export default class DeltaGreenActorSheet extends ActorSheet { this._prepareCharacterItems(data); } + // Prepare a simplified version of the special training for display on sheet. + if (this.actor.type !== "vehicle") { + const specialTraining = this.actor.system.specialTraining.map( + (training) => { + const simplifiedTraining = { + name: training.name, + id: training.id, + key: training.attribute, + }; + // Convert the machine-readable name to a human-readable one. + switch (true) { + // Stats + case DG.statistics.includes(training.attribute): + simplifiedTraining.attribute = training.attribute.toUpperCase(); + simplifiedTraining.targetNumber = + this.actor.system.statistics[training.attribute].value; + break; + // Skills + case DG.skills.includes(training.attribute): + simplifiedTraining.attribute = + this.actor.system.skills[training.attribute].label; + simplifiedTraining.targetNumber = + this.actor.system.skills[training.attribute].proficiency; + break; + // Typed Skills + default: + simplifiedTraining.attribute = + this.actor.system.typedSkills[training.attribute].label; + simplifiedTraining.targetNumber = + this.actor.system.typedSkills[training.attribute].proficiency; + break; + } + return simplifiedTraining; + }, + ); + data.specialTraining = specialTraining; + } + switch (this.actor.type) { case "agent": data.enrichedDescription = await TextEditor.enrichHTML( @@ -237,8 +276,8 @@ export default class DeltaGreenActorSheet extends ActorSheet { // Rollable abilities - bind to everything with the 'Rollable' class html.find(".rollable").click(this._onRoll.bind(this)); - html.find('.rollable').contextmenu(this._onRoll.bind(this)); // this is for right-click, which triggers the roll modifier dialogue for most rolls - + html.find(".rollable").contextmenu(this._onRoll.bind(this)); // this is for right-click, which triggers the roll modifier dialogue for most rolls + html.find(".toggle-untrained").click(() => this.actor.update({ "system.showUntrainedSkills": !this.actor.system.showUntrainedSkills, @@ -304,6 +343,27 @@ export default class DeltaGreenActorSheet extends ActorSheet { this.actor.update({ [`system.typedSkills.-=${targetskill}`]: null }); }); + html.find(".special-training-action").click((event) => { + event.preventDefault(); + const action = event.currentTarget.getAttribute("data-action"); + const targetID = event.currentTarget.getAttribute("data-id"); + this._showSpecialTrainingDialog(action, targetID); + }); + + // Handle deletion of Special Training + html.find(".special-training-delete").click((event) => { + event.preventDefault(); + const targetID = event.target.getAttribute("data-id"); + const specialTrainingArray = duplicate(this.actor.system.specialTraining); + // Get the index of the training to be deleted + const index = specialTrainingArray.findIndex( + (training) => training.id === targetID, + ); + + specialTrainingArray.splice(index, 1); + this.actor.update({ "system.specialTraining": specialTrainingArray }); + }); + html.find(".apply-skill-improvements").click((event) => { event.preventDefault(); @@ -686,6 +746,107 @@ export default class DeltaGreenActorSheet extends ActorSheet { } } + async _showSpecialTrainingDialog(action, targetID) { + const specialTraining = this.actor.system.specialTraining.find( + (training) => training.id === targetID, + ); + + // Prepare simplified stat list + const statList = Object.entries(this.actor.system.statistics).map( + ([key, stat]) => ({ + key, + label: game.i18n.localize(`DG.Attributes.${key}`), + targetNumber: stat.value * 5, + }), + ); + + // Prepare simplified skill list + const skillList = Object.entries(this.actor.system.skills).map( + ([key, skill]) => ({ + key, + label: skill.label, + targetNumber: skill.proficiency, + }), + ); + + // Prepare simplified typed/custom skill list + const typedSkillList = Object.entries(this.actor.system.typedSkills).map( + ([key, skill]) => ({ + key, + group: skill.group, + label: skill.label, + targetNumber: skill.proficiency, + }), + ); + + // Prepare the template to feed to Dialog. + const content = await renderTemplate( + "systems/deltagreen/templates/dialog/special-training.html", + { + name: specialTraining?.name || "", + currentAttribute: specialTraining?.attribute || "", + statList, + skillList, + typedSkillList, + }, + ); + + const buttonLabel = game.i18n.localize( + `DG.SpecialTraining.Dialog.${action}SpecialTraining`, + ); + + // Prepare and render dialog with above template. + new Dialog({ + content, + title: game.i18n.localize("DG.SpecialTraining.Dialog.Title"), + default: "confirm", + buttons: { + confirm: { + label: buttonLabel, + callback: (btn) => { + const specialTrainingLabel = btn + .find("[name='special-training-label']") + .val(); + const specialTrainingAttribute = btn + .find("[name='special-training-skill']") + .val(); + if (action === "Create") + this._createSpecialTraining( + specialTrainingLabel, + specialTrainingAttribute, + ); + if (action === "Edit") + this._editSpecialTraining( + specialTrainingLabel, + specialTrainingAttribute, + targetID, + ); + }, + }, + }, + }).render(true); + } + + _createSpecialTraining(label, attribute) { + const specialTrainingArray = duplicate(this.actor.system.specialTraining); + specialTrainingArray.push({ + name: label, + attribute, + id: randomID(), + }); + this.actor.update({ "system.specialTraining": specialTrainingArray }); + } + + _editSpecialTraining(label, attribute, id) { + const specialTrainingArray = duplicate(this.actor.system.specialTraining); + const specialTraining = specialTrainingArray.find( + (training) => training.id === id, + ); + specialTraining.name = label; + specialTraining.attribute = attribute; + this.actor.update({ "system.specialTraining": specialTrainingArray }); + } + /** * Handle creating a new Owned Item for the actor using initial data defined in the HTML dataset * @param {Event} event The originating click event @@ -750,6 +911,7 @@ export default class DeltaGreenActorSheet extends ActorSheet { rollType: dataset.rolltype, key: dataset.key, actor: this.actor, + specialTrainingName: dataset?.name || null, // Only applies to Special Training Rolls item, }; @@ -759,6 +921,7 @@ export default class DeltaGreenActorSheet extends ActorSheet { case "stat": case "skill": case "sanity": + case "special-training": case "weapon": roll = new DGPercentileRoll("1D100", {}, rollOptions); break; diff --git a/module/config.js b/module/config.js new file mode 100644 index 0000000..b55443c --- /dev/null +++ b/module/config.js @@ -0,0 +1,55 @@ +/** + * In config.js we can create constants that may be used all around the code base. + * I tried to get some of these values from `game.system` but it seems they + * aren't loaded yet when this is called. Oh well, this shouldn't really ever + * change. + */ + +const DG = { + // All the base skills + skills: [ + "accounting", + "alertness", + "anthropology", + "archeology", + "artillery", + "athletics", + "bureaucracy", + "computer_science", + "criminology", + "demolitions", + "disguise", + "dodge", + "drive", + "firearms", + "first_aid", + "forensics", + "heavy_machiner", + "heavy_weapons", + "history", + "humint", + "law", + "medicine", + "melee_weapons", + "navigate", + "occult", + "persuade", + "pharmacy", + "psychotherapy", + "ride", + "search", + "sigint", + "stealth", + "surgery", + "survival", + "swim", + "unarmed_combat", + "unnatural", + "ritual", + ], + + // All the base rollable stats. + statistics: ["str", "con", "dex", "int", "pow", "cha"], +}; + +export default DG; diff --git a/module/roll/roll.js b/module/roll/roll.js index d7e9e69..67bff8a 100644 --- a/module/roll/roll.js +++ b/module/roll/roll.js @@ -72,51 +72,38 @@ export class DGPercentileRoll extends DGRoll { * @param {String} [options.key] The key of the skill, stat, etc. to use as a basis for this roll. * @param {DeltaGreenActor} [options.actor] The actor that this roll originates from. * @param {DeltaGreenItem} [options.item] Optional - The item from which the roll originates. + * @param {DeltaGreenItem} [options.specialTrainingName] Optional - Special training rolls have names that are different from the roll key. */ constructor(formula = "1D100", data = {}, options) { super("1D100", {}, options); - const skillKeys = Object.keys(this.actor.system.skills); - const typedSkillKeys = Object.keys(this.actor.system.typedSkills); - const statKeys = Object.keys(this.actor.system.statistics); + // Set roll info for Skill, Stat, Typed Skill, and non-custom Weapon Percentile rolls. + const { target, localizedKey } = this.getRollInfoFromKey( + this.key, + this.actor.system, + ); + this.target = target; + this.localizedKey = localizedKey; + // Set roll info for other Percentile rolls switch (this.type) { - case "stat": - this.target = this.actor.system.statistics[this.key].x5; - this.localizedKey = game.i18n.localize(`DG.Attributes.${this.key}`); + case "special-training": + this.specialTrainingName = options.specialTrainingName; + this.localizedKey = `${this.specialTrainingName} - (${this.localizedKey})`; break; - case "skill": - // Set up a target number and localized roll based on whether the skill is regular or typed. - if (skillKeys.includes(this.key)) { - this.target = this.actor.system.skills[this.key].proficiency; - this.localizedKey = game.i18n.localize(`DG.Skills.${this.key}`); - } - if (typedSkillKeys.includes(this.key)) { - const skill = this.actor.system.typedSkills[this.key]; - this.target = skill.proficiency; - this.localizedKey = `${skill.group} (${skill.label})`; + case "weapon": + // If this weapon uses a custom target for rolls, we set that explicitly. + if (this.key === "custom") { + this.target = this.item.system.customSkillTarget; + this.localizedKey = game.i18n.localize("DG.ItemWindow.Custom"); } + // Add a the weapon's internal modifier. + this.modifier += this.item.system.skillModifier; break; case "sanity": this.target = this.actor.system.sanity.value; this.localizedKey = game.i18n.localize("DG.Attributes.SAN"); break; - case "weapon": - // Set up target number and localized key depending on whether the weapon uses a custom number, - // a skill, or a stat for its roll. - if (this.key === "custom") { - this.target = this.item.system.customSkillTarget; - this.localizedKey = game.i18n.localize("DG.ItemWindow.Custom"); - } else if (skillKeys.includes(this.key)) { - this.target = this.actor.system.skills[this.key].proficiency; - this.localizedKey = game.i18n.localize(`DG.Skills.${this.key}`); - } else if (statKeys.includes(this.key)) { - this.target = this.actor.system.statistics[this.key].x5; - this.localizedKey = game.i18n.localize(`DG.Attributes.${this.key}`); - } - // Add a the weapon's internal modifier. - this.modifier += this.item.system.skillModifier; - break; case "luck": this.target = 50; this.localizedKey = game.i18n.localize("DG.Luck"); @@ -291,6 +278,39 @@ export class DGPercentileRoll extends DGRoll { return this.createMessage(html, label, rollMode); } + /** + * Utility function, called in the DGPercentileRoll constructor. + * If this roll key corresponds to a stat, skill, + * or typedSkill, get pertinent info. + * + * This is used for Stat, Skill, Typed Skill, Weapon, and Special Training Rolls. + * + * @returns {Object} - Contains the roll target and localized version of the key. + */ + getRollInfoFromKey() { + const actorData = this.actor.system; + const skillKeys = Object.keys(actorData.skills); + const typedSkillKeys = Object.keys(actorData.typedSkills); + const statKeys = Object.keys(actorData.statistics); + + let target = null; + let localizedKey = null; + if (statKeys.includes(this.key)) { + target = actorData.statistics[this.key].x5; + localizedKey = game.i18n.localize(`DG.Attributes.${this.key}`); + } + if (skillKeys.includes(this.key)) { + target = actorData.skills[this.key].proficiency; + localizedKey = game.i18n.localize(`DG.Skills.${this.key}`); + } + if (typedSkillKeys.includes(this.key)) { + const skill = actorData.typedSkills[this.key]; + target = skill.proficiency; + localizedKey = `${skill.group} (${skill.label})`; + } + return { target, localizedKey }; + } + /** * "Inhuman" stat being rolled, logic is different per page 188 of the Handler's Guide. * Note - originally implemented by Uriele, but my attempt at merging conficts went poorly, so re-implementing. @@ -504,10 +524,13 @@ export class DGDamageRoll extends DGRoll { this.options.rollMode || game.settings.get("core", "rollMode"); let label = this.formula; try { - label = `${game.i18n.localize("DG.Roll.Rolling",)} ${game.i18n.localize("DG.Roll.Damage"). - toUpperCase()} ${game.i18n.localize("DG.Roll.For",)} ${this.item.name}`; - } catch(ex) { - //console.log(ex); + label = `${game.i18n.localize("DG.Roll.Rolling")} ${game.i18n + .localize("DG.Roll.Damage") + .toUpperCase()} ${game.i18n.localize("DG.Roll.For")} ${ + this.item.name + }`; + } catch (ex) { + // console.log(ex); label = `Rolling DAMAGE for ${label.toUpperCase()}`; } return this.createMessage(this.total, label, rollMode); diff --git a/module/templates.js b/module/templates.js index 33c6e19..7baa2eb 100644 --- a/module/templates.js +++ b/module/templates.js @@ -12,6 +12,7 @@ export default async function preloadHandlebarsTemplates() { "systems/deltagreen/templates/actor/unnatural-sheet.html", "systems/deltagreen/templates/actor/npc-sheet.html", "systems/deltagreen/templates/actor/cv-partial.html", + "systems/deltagreen/templates/actor/custom-skills-partial.html", "systems/deltagreen/templates/dialog/modify-percentile-roll.html", "systems/deltagreen/templates/actor/vehicle-sheet.html", "systems/deltagreen/templates/actor/help-and-licensing-partial.html", diff --git a/template.json b/template.json index f42a412..3e6722d 100644 --- a/template.json +++ b/template.json @@ -234,7 +234,8 @@ "proficiency": 0, "failure": false } - } + }, + "specialTraining": [] }, "unnatural_skills": { "skills": { @@ -423,7 +424,8 @@ "proficiency": 0 } }, - "typedSkills": {} + "typedSkills": {}, + "specialTraining": [] } }, "unnatural": { diff --git a/templates/actor/actor-sheet.html b/templates/actor/actor-sheet.html index 1ad4599..f239ae9 100644 --- a/templates/actor/actor-sheet.html +++ b/templates/actor/actor-sheet.html @@ -112,14 +112,14 @@ {{#if (keepSanityPrivate)}} - {{/if}} {{#unless (keepSanityPrivate)}} - {{/unless}} @@ -128,7 +128,7 @@ {{#if_not_eq key 'ritual' }} - {{/if_not_eq}} @@ -137,29 +137,9 @@ {{/each}} + {{!-- Custom Skills and Special Training --}}
-
- {{localize 'DG.Skills.AddTypedOrCustomSkill'}} - {{localize 'DG.Skills.ApplySkillImprovements'}} -
-
- {{#each actor.system.typedSkills as |skill key|}} -
- - - -
- - -
-
- {{/each}} -
+ {{> "systems/deltagreen/templates/actor/custom-skills-partial.html" actorType="agent"}}
@@ -263,7 +243,7 @@
{{localize 'DG.Mental.Motivations'}}
{{localize 'DG.Mental.Disorders'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -311,7 +291,7 @@ {{localize 'DG.Gear.DamageOrLethality'}} {{localize 'DG.Gear.ArmorPiercing'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -381,7 +361,7 @@ {{localize 'DG.Gear.ArmorRating'}} {{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -425,7 +405,7 @@ {{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -484,7 +464,7 @@
{{localize 'DG.Bonds.Relationship'}}
{{localize 'DG.Bonds.Score'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
diff --git a/templates/actor/custom-skills-partial.html b/templates/actor/custom-skills-partial.html new file mode 100644 index 0000000..34c5c3b --- /dev/null +++ b/templates/actor/custom-skills-partial.html @@ -0,0 +1,40 @@ +
+ {{localize 'DG.Skills.AddTypedOrCustomSkill'}} + {{localize 'Add Special Training'}} + {{#if_eq actorType "agent"}} + {{localize 'DG.Skills.ApplySkillImprovements'}} + {{/if_eq}} +
+
+ {{#each actor.system.typedSkills as |skill key|}} +
+
+ + + {{#if_eq actorType "agent"}} + + {{/if_eq}} +
+
+ + +
+
+ {{/each}} + {{#each specialTraining as |training|}} +
+ +
+ + +
+
+ {{/each}} +
\ No newline at end of file diff --git a/templates/actor/npc-sheet.html b/templates/actor/npc-sheet.html index 1a4c116..78edb51 100644 --- a/templates/actor/npc-sheet.html +++ b/templates/actor/npc-sheet.html @@ -128,29 +128,7 @@
-
- {{localize 'DG.Skills.AddTypedOrCustomSkill'}} -
-
- {{#each actor.system.typedSkills as |skill key|}} - {{#if (hideSkillBasedOnProficiencyAndUserChoice ../actor.system.showUntrainedSkills skill.proficiency)}} -
- - - -
- - -
-
- {{/if}} - {{/each}} -
+ {{> "systems/deltagreen/templates/actor/custom-skills-partial.html"}}

@@ -180,7 +158,7 @@ {{localize 'DG.Gear.DamageOrLethality'}} {{localize 'DG.Gear.ArmorPiercing'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -250,7 +228,7 @@ {{localize 'DG.Gear.ArmorRating'}} {{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -294,7 +272,7 @@
{{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
diff --git a/templates/actor/unnatural-sheet.html b/templates/actor/unnatural-sheet.html index 5faa55e..ba3682f 100644 --- a/templates/actor/unnatural-sheet.html +++ b/templates/actor/unnatural-sheet.html @@ -121,29 +121,7 @@

-
- {{localize 'DG.Skills.AddTypedOrCustomSkill'}} -
-
- {{#each actor.system.typedSkills as |skill key|}} - {{#if (hideSkillBasedOnProficiencyAndUserChoice ../actor.system.showUntrainedSkills skill.proficiency)}} -
- - - -
- - -
-
- {{/if}} - {{/each}} -
+ {{> "systems/deltagreen/templates/actor/custom-skills-partial.html"}}

@@ -173,7 +151,7 @@ {{localize 'DG.Gear.DamageOrLethality'}} {{localize 'DG.Gear.ArmorPiercing'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -242,7 +220,7 @@ {{localize 'DG.Gear.ArmorRating'}} {{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -286,7 +264,7 @@
{{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
diff --git a/templates/actor/vehicle-sheet.html b/templates/actor/vehicle-sheet.html index 2e166a5..57d186c 100644 --- a/templates/actor/vehicle-sheet.html +++ b/templates/actor/vehicle-sheet.html @@ -73,7 +73,7 @@ {{localize 'DG.Gear.ArmorRating'}} {{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
@@ -117,7 +117,7 @@
{{localize 'DG.Gear.Equipped'}}
- {{localize 'DG.Generic.AddButtonLabel'}} + {{localize 'DG.Generic.AddButtonLabel'}}
diff --git a/templates/dialog/special-training.html b/templates/dialog/special-training.html new file mode 100644 index 0000000..21a0d72 --- /dev/null +++ b/templates/dialog/special-training.html @@ -0,0 +1,38 @@ +
+
+ + +
+
+ + {{#select currentAttribute}} + + {{/select}} +
+
\ No newline at end of file