Skip to content

Commit 05d224c

Browse files
TinyDragonEggclaude
andcommitted
v1.2.3 - Smart skill selection with fallback
Fixed skill proficiency handling to track selected skills properly: - Checks if default cultural origin skill is already proficient - If already known, shows dialog to pick alternative skill - Stores which skill was actually selected in flags.selectedSkill - Removes the correct skill when changing/removing origin (not always default) Example: - Character already has Survival proficiency - Selects Ashland Heritage (default: Survival) - Module offers alternative skill choices (e.g., Medicine) - User picks Medicine - Later removes Ashland Heritage - Module removes Medicine (not Survival), keeping original proficiency Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 37d505e commit 05d224c

2 files changed

Lines changed: 96 additions & 16 deletions

File tree

module.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"id": "aspects-dual-backgrounds",
33
"title": "Aspects of Verun: Dual Backgrounds",
44
"description": "Enables dual background system for Aspects of Verun setting - choose one Profession background and one Cultural Origin background",
5-
"version": "1.2.2",
5+
"version": "1.2.3",
66
"compatibility": {
77
"minimum": "11",
88
"verified": "13"
@@ -48,7 +48,7 @@
4848
],
4949
"url": "https://github.com/TinyDragonEgg/testmodule",
5050
"manifest": "https://raw.githubusercontent.com/TinyDragonEgg/testmodule/main/module.json",
51-
"download": "https://github.com/TinyDragonEgg/testmodule/releases/download/1.2.2/module.zip",
51+
"download": "https://github.com/TinyDragonEgg/testmodule/releases/download/1.2.3/module.zip",
5252
"license": "MIT",
5353
"readme": "https://raw.githubusercontent.com/TinyDragonEgg/testmodule/main/README.md"
5454
}

scripts/dual-backgrounds.js

Lines changed: 94 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -330,26 +330,24 @@ class DualBackgroundsManager {
330330

331331
const oldCulturalOrigin = actor.getFlag(this.ID, this.FLAGS.CULTURAL_ORIGIN);
332332

333-
// If cultural origin is changing, add skill and language to this update
333+
// If cultural origin is changing, handle skill changes
334334
if (newCulturalOrigin !== oldCulturalOrigin) {
335335
const allOrigins = this.getAllCulturalOrigins();
336336

337-
// Remove old skill proficiency
338-
if (oldCulturalOrigin && allOrigins[oldCulturalOrigin]?.skill) {
339-
const oldSkillPath = `system.skills.${allOrigins[oldCulturalOrigin].skill}.value`;
340-
foundry.utils.setProperty(changes, oldSkillPath, 0);
341-
this.log(`Removing old skill: ${allOrigins[oldCulturalOrigin].skill}`);
337+
// Remove old skill proficiency (use the tracked skill, not the default)
338+
if (oldCulturalOrigin) {
339+
const trackedSkill = actor.getFlag(this.ID, 'selectedSkill');
340+
if (trackedSkill) {
341+
const oldSkillPath = `system.skills.${trackedSkill}.value`;
342+
foundry.utils.setProperty(changes, oldSkillPath, 0);
343+
this.log(`Removing tracked skill: ${trackedSkill}`);
344+
}
342345
}
343346

344-
// Add new skill proficiency
345-
if (newCulturalOrigin && allOrigins[newCulturalOrigin]?.skill) {
346-
const skillPath = `system.skills.${allOrigins[newCulturalOrigin].skill}.value`;
347-
foundry.utils.setProperty(changes, skillPath, 1);
348-
this.log(`Adding skill proficiency in update: ${allOrigins[newCulturalOrigin].skill} at path ${skillPath}`);
349-
this.log(`Changes object after skill set:`, changes);
350-
}
347+
// Don't add new skill here - we need to check if it's already known first
348+
// This will be handled in applyCulturalOriginFeatures after the update completes
351349

352-
// Schedule features/equipment/language to be applied after update completes
350+
// Schedule features/equipment/language/skill to be applied after update completes
353351
setTimeout(() => {
354352
this.applyCulturalOriginFeatures(actor, newCulturalOrigin, oldCulturalOrigin);
355353
}, 100);
@@ -385,6 +383,33 @@ class DualBackgroundsManager {
385383
const allOrigins = this.getAllCulturalOrigins();
386384
if (newOrigin && newOrigin !== '' && allOrigins[newOrigin]) {
387385
const originData = allOrigins[newOrigin];
386+
387+
// Handle skill selection - check if default skill is already proficient
388+
const defaultSkill = originData.skill;
389+
const currentActor = game.actors.get(actor.id);
390+
const currentSkillValue = currentActor.system.skills[defaultSkill]?.value || 0;
391+
392+
let selectedSkill = defaultSkill;
393+
394+
if (currentSkillValue >= 1) {
395+
// Skill already known, offer alternative
396+
this.log(`Skill ${defaultSkill} already proficient, offering alternatives`);
397+
selectedSkill = await this.showSkillSelectionDialog(defaultSkill);
398+
399+
if (!selectedSkill) {
400+
// User cancelled, still use default
401+
selectedSkill = defaultSkill;
402+
}
403+
}
404+
405+
// Apply the selected skill
406+
if (selectedSkill) {
407+
await currentActor.update({
408+
[`system.skills.${selectedSkill}.value`]: 1,
409+
[`flags.${this.ID}.selectedSkill`]: selectedSkill
410+
});
411+
this.log(`Applied skill proficiency: ${selectedSkill}`);
412+
}
388413
const itemsToCreate = [];
389414

390415
// Feature 1: Main cultural heritage feature
@@ -677,6 +702,61 @@ class DualBackgroundsManager {
677702
}
678703
}
679704

705+
/**
706+
* Show skill selection dialog when default skill is already known
707+
*/
708+
static async showSkillSelectionDialog(defaultSkill) {
709+
return new Promise((resolve) => {
710+
const skills = {
711+
'acr': 'Acrobatics', 'ani': 'Animal Handling', 'arc': 'Arcana', 'ath': 'Athletics',
712+
'dec': 'Deception', 'his': 'History', 'ins': 'Insight', 'itm': 'Intimidation',
713+
'inv': 'Investigation', 'med': 'Medicine', 'nat': 'Nature', 'prc': 'Perception',
714+
'prf': 'Performance', 'per': 'Persuasion', 'rel': 'Religion', 'slt': 'Sleight of Hand',
715+
'ste': 'Stealth', 'sur': 'Survival'
716+
};
717+
718+
const defaultSkillName = skills[defaultSkill] || defaultSkill;
719+
720+
const content = `
721+
<form>
722+
<div class="form-group">
723+
<p style="margin-bottom: 12px;">
724+
You already have proficiency in <strong>${defaultSkillName}</strong>.
725+
Choose a different skill proficiency instead:
726+
</p>
727+
<label>Choose an alternative skill:</label>
728+
<select id="skill-select" style="width: 100%; margin-top: 8px;">
729+
${Object.entries(skills).map(([code, name]) => `
730+
<option value="${code}">${name}</option>
731+
`).join('')}
732+
</select>
733+
</div>
734+
</form>
735+
`;
736+
737+
new Dialog({
738+
title: 'Choose Alternative Skill',
739+
content: content,
740+
buttons: {
741+
confirm: {
742+
icon: '<i class="fas fa-check"></i>',
743+
label: 'Confirm',
744+
callback: (html) => {
745+
const selected = html.find('#skill-select').val();
746+
resolve(selected);
747+
}
748+
},
749+
useDefault: {
750+
icon: '<i class="fas fa-star"></i>',
751+
label: `Keep ${defaultSkillName}`,
752+
callback: () => resolve(defaultSkill)
753+
}
754+
},
755+
default: 'confirm'
756+
}).render(true);
757+
});
758+
}
759+
680760
/**
681761
* Show cultural origin selection dialog
682762
*/

0 commit comments

Comments
 (0)