diff --git a/CHANGELOG.md b/CHANGELOG.md index fcc5913e..2b09a37f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,11 +3,12 @@ * Updated "item cards" to match the Mandar theme * This change includes many minor improvements to the cards, such as showing damage on weapons and purchased talents on specializations * The action to take when removing a combatant from combat is now configurable. This is in place of the previously-confusing (and quite annoying) behavior where you had to claim a slot in order to remove a combatant + * Dragging-and-dropping items on actors now prompts for spending XP to purchase that item ([#1588](https://github.com/StarWarsFoundryVTT/StarWarsFFG/issues/1588)) * Fixes: * Includes species characteristics bonus when calculating upgrade cost ([#1638](https://github.com/StarWarsFoundryVTT/StarWarsFFG/issues/1638)) * Specializations: Talents are now correctly looked up in compendium * Removed "unused" slot checking (on combatant defeat) as they would sometimes lead to actors being unable to act - * Weapon "special" text now properly renders dice icons ([#1625](https://github.com/StarWarsFoundryVTT/StarWarsFFG/issues/1625)) + * Weapon `special` text now properly renders dice icons ([#1625](https://github.com/StarWarsFoundryVTT/StarWarsFFG/issues/1625)) `1.902` * Features: diff --git a/lang/en.json b/lang/en.json index b0bd69bb..430e39f2 100644 --- a/lang/en.json +++ b/lang/en.json @@ -723,5 +723,9 @@ "SWFFG.Settings.Purchase.SignatureAbility.Name": "Signature Abilities Compendiums", "SWFFG.Settings.Purchase.SignatureAbility.Hint": "Comma seperated compendiums to search for buying Signature Abilities (no spaces)", "SWFFG.Settings.Purchase.Talent.Name": "Talent Compendiums", - "SWFFG.Settings.Purchase.Talent.Hint": "Comma seperated compendiums to search for buying Talents (no spaces)" + "SWFFG.Settings.Purchase.Talent.Hint": "Comma seperated compendiums to search for buying Talents (no spaces)", + "SWFFG.DragDrop.Title": "Purchase item, or grant for 0 xp?", + "SWFFG.DragDrop.PurchaseItem": "Purchase", + "SWFFG.DragDrop.GrantItem": "Grant", + "SWFFG.DragDrop.XPLog": "drag-and-drop" } diff --git a/modules/actors/actor-sheet-ffg.js b/modules/actors/actor-sheet-ffg.js index c5131f7b..c8a572d0 100644 --- a/modules/actors/actor-sheet-ffg.js +++ b/modules/actors/actor-sheet-ffg.js @@ -83,6 +83,48 @@ export class ActorSheetFFG extends ActorSheet { await xpLogEarn(this.actor, startingXP, curAvailable + startingXP, curTotal + startingXP, game.i18n.format("SWFFG.GrantXPSpecies", {species: itemData.name}) ); } + if (this.actor.type === "character" && ["talent", "specialization", "signatureability", "forcepower"].includes(itemData.type)) { + const cost = await this.calcPurchasePrice(itemData); + const availableXP = this.actor.system.experience.available; + if (cost > 0 && cost < availableXP) { + new Dialog( + { + title: game.i18n.localize("SWFFG.DragDrop.Title"), + buttons: { + purchase: { + icon: '', + label: game.i18n.localize("SWFFG.DragDrop.PurchaseItem"), + callback: async (that) => { + if (cost > 0) { + await this.object.update({ + system: { + experience: { + available: availableXP - cost, + } + } + }); + await xpLogSpend( + this.actor, `${game.i18n.localize("SWFFG.DragDrop.XPLog")} ${itemData.type} ${itemData.name}`, + cost, + this.actor.system.experience.available, + this.actor.system.experience.total + ); + } + }, + }, + grant: { + icon: '', + label: game.i18n.localize("SWFFG.DragDrop.GrantItem"), + }, + }, + }, + { + classes: ["dialog", "starwarsffg"], + } + ).render(true); + } + } + // Create the owned item return this._onDropItemCreate(itemData); } else { @@ -90,6 +132,39 @@ export class ActorSheetFFG extends ActorSheet { } } + async calcPurchasePrice(itemData) { + let cost = 0; + if (itemData.type === "specialization") { + // check if the specialization is in career + const career = this.actor.items.find(i => i.type === "career"); + if (career) { + const inCareerSpecializations = Object.values(career?.system?.specializations) || []; + let inCareer = false; + for (const careerSpecialization of inCareerSpecializations) { + if (careerSpecialization.name === itemData.name) { + inCareer = true; + break; + } + } + const specializationCount = (this.actor.items.filter(i => i.type === "specialization") || []).length; + cost = (specializationCount + 1) * 10; + if (!inCareer) { + cost += 10; + } + return cost; + } else { + return -1; + } + } else if (itemData.type === "talent") { + return -1; + } else if (itemData.type === "signatureability") { + return itemData.system.base_cost; + } else if (itemData.type === "forcepower") { + return itemData.system.base_cost; + } + return -1; + } + /* -------------------------------------------- */ /** @override */ @@ -1990,7 +2065,7 @@ export class ActorSheetFFG extends ActorSheet { } worldItemsPack = sortDataBy(worldItemsPack, "name"); selectableItems.push({pack: game.i18n.localize("SWFFG.Actors.Sheets.Purchase.Talent.WorldItemsGroup"), items: worldItemsPack}); - + for (const source of sources) { const pack = game.packs.get(source); if (!pack) { @@ -2080,7 +2155,7 @@ export class ActorSheetFFG extends ActorSheet { const characteristicCurrentRank = this.actor.system.attributes[characteristic].value; // this is the value without items that modify it const characteristicCostValue = ModifierHelpers.getBaseValue(this.actor.items, characteristic, "Characteristic") + characteristicCurrentRank; - + if (characteristicValue >= game.settings.get("starwarsffg", "maxAttribute")) { ui.notifications.warn(game.i18n.localize("SWFFG.Actors.Sheets.Purchase.Characteristic.Max")); return;