diff --git a/css/deltagreen.css b/css/deltagreen.css index 2f581bb..7f67973 100644 --- a/css/deltagreen.css +++ b/css/deltagreen.css @@ -843,10 +843,14 @@ input.item-sheet-short-input{ text-align: left; } -.add-typed-skill-button{ +.skill-buttons{ margin: 10px; } +.apply-skill-improvements{ + float: right; +} + .yellow-king{ color: #a0912f; } diff --git a/lang/en.json b/lang/en.json index df166af..01310ba 100644 --- a/lang/en.json +++ b/lang/en.json @@ -46,6 +46,12 @@ "DG.Skills.AddTypedOrCustomSkill": "Add Typed or Custom Skill", "DG.Skills.AddSkill": "Add Skill", + "DG.Skills.Apply": "Apply", + "DG.Skills.ApplySkillImprovements": "Apply Skill Improvements", + "DG.Skills.ApplySkillImprovementsChatFlavor": "Improved the following skills by", + "DG.Skills.ApplySkillImprovementsDialogLabel": "Improve skills by the following formula:", + "DG.Skills.ApplySkillImprovementsDialogEffectsFollowing": "Effects the following skills:", + "DG.Skills.ApplySkillImprovementsWarning": "No failed skills to improve.", "DG.Skills.EditTypedOrCustomSkill": "Edit Typed or Custom Skill", "DG.Skills.EditSkill": "Edit Skill", "DG.Skills.SkillGroup": "Skill Group", diff --git a/module/actor/actor-sheet.js b/module/actor/actor-sheet.js index 4f195a5..b826037 100644 --- a/module/actor/actor-sheet.js +++ b/module/actor/actor-sheet.js @@ -246,6 +246,55 @@ export class DeltaGreenActorSheet extends ActorSheet { }); + html.find('.apply-skill-improvements').click(event => { + + event.preventDefault(); + + const failures = Object.entries(this.actor.data.data.skills).filter((skill) => skill[1].failure); + if (failures.length === 0) { + ui.notifications.warn('No Skills to Increase') + return; + } + + let htmlContent = ""; + let failedSkillNames = ""; + failures.forEach(([skill], value) => { + if (value === 0) { + failedSkillNames += (game.i18n.localize("DG.Skills." + skill)); + } else { + failedSkillNames += `, ${(game.i18n.localize("DG.Skills." + skill))}`; + } + }) + + htmlContent += `
`; + htmlContent += ` `; + htmlContent += ` `; + htmlContent += `
`; + htmlContent += ` ${game.i18n.localize("DG.Skills.ApplySkillImprovementsDialogEffectsFollowing")} ${failedSkillNames} `; + htmlContent += `
`; + + new Dialog({ + content: htmlContent, + title: game.i18n.translations.DG?.Skills?.ApplySkillImprovements ?? "Apply Skill Improvements", + default: "add", + buttons: { + apply:{ + label: game.i18n.translations.DG?.Skills?.Apply ?? "Apply", + callback: btn =>{ + const baseRollForumla = btn.find("[name='roll-formula']").val(); + this._applySkillImprovements(baseRollForumla, failures); + }, + } + } + }).render(true); + + }); + // Browse Weapon Compendiums html.find('.weapon-browse').click(ev => { const dialog = new Dialog({ @@ -389,7 +438,7 @@ export class DeltaGreenActorSheet extends ActorSheet { let newTypeSkillLabel = btn.find("[name='new-type-skill-label']").val(); let newTypeSkillGroup = btn.find("[name='new-type-skill-group']").val(); this._addNewTypedSkill(newTypeSkillLabel, newTypeSkillGroup); - } + }, } } }).render(true); @@ -621,6 +670,63 @@ export class DeltaGreenActorSheet extends ActorSheet { } } + _applySkillImprovements(baseRollFormula, failures) { + const actorData = this.actor.data.data; + const resultList = []; + let rollFormula; + + switch (baseRollFormula) { + case "1": + rollFormula = 1; + break; + case "1d3": + rollFormula = `${failures.length}d3`; + break; + case "1d4": + case "1d4-1": + rollFormula = `${failures.length}d4`; + break; + default: + } + + let roll; + if (rollFormula !== 1) { + roll = new Roll(rollFormula, actorData); + roll.evaluate({async: true}); + roll.terms[0].results.forEach((result) => resultList.push(baseRollFormula === "1d4-1" ? result.result - 1 : result.result)); + } + + let updatedSkills = ""; + + failures.forEach(([skill], value) => { + const updatedData = duplicate(actorData); + updatedData.skills[skill].proficiency += resultList[value] ?? 1; + updatedData.skills[skill].failure = false; + this.actor.update({"data": updatedData}); + + // So we can record the skills and how much they were increased by in chat. + if (updatedSkills === "") { + updatedSkills += `${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}%`; + } else { + updatedSkills += `, ${game.i18n.localize("DG.Skills." + skill)}: +${resultList[value] ?? 1}%`; + } + }) + + const chatData = { + speaker: ChatMessage.getSpeaker({actor: this.actor, token: this.token, alias: this.actor.data.name}), + content: updatedSkills, + flavor: `${game.i18n.localize("DG.Skills.ApplySkillImprovementsChatFlavor")} +${baseRollFormula}%:`, + type: baseRollFormula === "1" ? 0 : 5, // 0 = CHAT_MESSAGE_TYPES.OTHER, 5 = CHAT_MESSAGE_TYPES.ROLL + roll: baseRollFormula === "1" ? null : roll, // If adding flat +1, there is no roll. + rollMode: game.settings.get("core", "rollMode") + }; + + // play the dice rolling sound, like a regular in-chat roll + if (roll) AudioHelper.play({src: "sounds/dice.wav", volume: 0.8, autoplay: true, loop: false}, true); + + ChatMessage.create(chatData, {}); + } + _onDragStart(event) { const li = event.currentTarget; if ( event.target.classList.contains("entity-link") ) return; diff --git a/module/settings.js b/module/settings.js index fc569f1..f69ef5e 100644 --- a/module/settings.js +++ b/module/settings.js @@ -33,15 +33,35 @@ export const registerSystemSettings = function() { onChange: value => { // A callback function which triggers when the setting is changed //console.log(value) } - }); + }); - game.settings.register('deltagreen', 'keepSanityPrivate', { - name: "Keep Sanity Private", - hint: "Hide sanity from players on both character sheet and rolls.", - scope: "world", - config: true, - type: Boolean, - default: false - }); + game.settings.register('deltagreen', 'keepSanityPrivate', { + name: "Keep Sanity Private", + hint: "Hide sanity from players on both character sheet and rolls.", + scope: "world", + config: true, + type: Boolean, + default: false + }); + + game.settings.register('deltagreen', 'skillImprovementFormula', { + name: "Default Skill Improvement Roll", + hint: " Default 1d4. There have been multiple errata on this, choose which fits best for the pace of your game.", + scope: "world", // This specifies a world-stored setting + config: true, // This specifies that the setting appears in the configuration view + type: String, + choices: { // If choices are defined, the resulting setting will be a select menu + "1": "Flat +1", + "1d3": "+1D3%", + "1d4": "+1D4%", + "1d4-1": "+1D4-1%" + }, + default: "1d4", // The default value for the setting, per the most recent errata. + onChange: value => { // A callback function which triggers when the setting is changed + //console.log(value) + } + }); + + } \ No newline at end of file diff --git a/templates/actor/actor-sheet.html b/templates/actor/actor-sheet.html index d4694ab..898a447 100644 --- a/templates/actor/actor-sheet.html +++ b/templates/actor/actor-sheet.html @@ -134,8 +134,9 @@
-
- {{localize 'DG.Skills.AddTypedOrCustomSkill'}} +
{{#each actor.data.data.typedSkills as |skill key|}}