Skip to content

Commit

Permalink
[foundryvtt#1401] Add item choice config
Browse files Browse the repository at this point in the history
  • Loading branch information
arbron committed Aug 22, 2022
1 parent 450d74e commit 0d12e9b
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 25 deletions.
26 changes: 18 additions & 8 deletions dnd5e.css
Original file line number Diff line number Diff line change
Expand Up @@ -1294,6 +1294,9 @@
/* Two Column Configurations */
/* ----------------------------------------- */
/* ----------------------------------------- */
/* Item Choice */
/* ----------------------------------------- */
/* ----------------------------------------- */
/* Scale Value */
/* ----------------------------------------- */
}
Expand Down Expand Up @@ -1342,19 +1345,26 @@
.dnd5e.advancement.two-column form .right-column {
grid-area: right;
}
.dnd5e.advancement.two-column form .right-column.level-list label {
flex: 0.5;
padding-right: 0.5rem;
text-align: end;
}
.dnd5e.advancement.two-column form .right-column.level-list input[type="text"]::placeholder,
.dnd5e.advancement.two-column form .right-column.level-list input[type="number"]::placeholder {
opacity: 0.5;
}
.dnd5e.advancement.two-column form button[type="submit"] {
grid-column-end: span 2;
}
.dnd5e.advancement.scale-value {
--grid-two-column-right-size: 0.6fr;
.dnd5e.advancement.item-choice {
--grid-two-column-right-size: 0.5fr;
}
.dnd5e.advancement.scale-value .right-column label {
flex: 0.5;
padding-right: 0.5rem;
text-align: right;
.dnd5e.advancement.item-choice .level-list .hint {
text-align: end;
}
.dnd5e.advancement.scale-value :is(input[type="text"], input[type="number"])::placeholder {
opacity: 0.5;
.dnd5e.advancement.scale-value {
--grid-two-column-right-size: 0.6fr;
}
.dnd5e.advancement.scale-value select.new-scale-value {
font-weight: bold;
Expand Down
1 change: 1 addition & 0 deletions icons/LICENSE
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ SVG Icons from Game-Icons.net
The dnd5e system for Foundry Virtual Tabletop includes icon artwork licensed from Game-icons.net under the Creative Commons license. These icons are packaged with and provided for use in the dnd5e system under their respective licenses, as noted below.

/svg/hit-points.svg - "Heart plus" by Zeromancer under CC0 PDD
/svg/item-choice.svg - "Choice" by Delapouite under CC BY 3.0
/svg/item-grant.svg - "White book" by Willdabeast under CC BY 3.0
/svg/scale-value.svg - "Dice target" by Delapouite under CC BY 3.0
1 change: 1 addition & 0 deletions icons/svg/item-choice.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@
"DND5E.AdvancementHitPointsRollButton": "Roll {die}",
"DND5E.AdvancementItemChoiceTitle": "Choose Items",
"DND5E.AdvancementItemChoiceHint": "Present the player with a choice of items (such as equipment, features, or spells) that they can choose for their character at one or more levels.",
"DND5E.AdvancementItemChoiceAllowDrops": "Allow Drops",
"DND5E.AdvancementItemChoiceAllowDropsHint": "Should players be able to drop their own choices into this advancement?",
"DND5E.AdvancementItemChoiceDropHint": "Drop Items here to add them to the pool from which a player can choose.",
"DND5E.AdvancementItemChoiceLevelsHint": "Specify how many choices are allowed at each level.",
"DND5E.AdvancementItemGrantTitle": "Grant Items",
"DND5E.AdvancementItemGrantHint": "Grant the character items (such as equipment, features, or spells) when they reach a certain level.",
"DND5E.AdvancementItemGrantDropHint": "Drop Items here to add them to the list granted by this advancement.",
Expand Down
32 changes: 23 additions & 9 deletions less/advancement.less
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,42 @@
}
.right-column {
grid-area: right;

&.level-list {
label {
flex: 0.5;
padding-right: 0.5rem;
text-align: end;
}
input[type="text"]::placeholder,
input[type="number"]::placeholder {
opacity: 0.5;
}
}
}
button[type="submit"] {
grid-column-end: span 2;
}
}
}

/* ----------------------------------------- */
/* Item Choice */
/* ----------------------------------------- */
&.item-choice {
--grid-two-column-right-size: 0.5fr;

.level-list .hint {
text-align: end;
}
}

/* ----------------------------------------- */
/* Scale Value */
/* ----------------------------------------- */
&.scale-value {
--grid-two-column-right-size: 0.6fr;

.right-column label {
flex: 0.5;
padding-right: 0.5rem;
text-align: right;
}
:is(input[type="text"], input[type="number"])::placeholder {
opacity: 0.5;
}

select {
&.new-scale-value {
font-weight: bold;
Expand Down
111 changes: 104 additions & 7 deletions module/advancement/types/item-choice.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Advancement from "../advancement.mjs";
import AdvancementConfig from "../advancement-config.mjs";

/**
* Advancement that presents the player with a choice of multiple items that they can take. Keeps track of which
Expand All @@ -15,13 +16,16 @@ export class ItemChoiceAdvancement extends Advancement {
configuration: {
choices: {},
allowDrops: true,
pool: null
},
order: 50,
icon: "icons/svg/stone-path.svg",
title: game.i18n.localize("DND5E.AdvancementItemChoiceTitle"),
hint: game.i18n.localize("DND5E.AdvancementItemChoiceHint"),
multiLevel: true
pool: []
}
},
order: 50,
icon: "systems/dnd5e/icons/svg/item-choice.svg",
title: game.i18n.localize("DND5E.AdvancementItemChoiceTitle"),
hint: game.i18n.localize("DND5E.AdvancementItemChoiceHint"),
multiLevel: true,
apps: {
config: ItemChoiceConfig
}
});
}
Expand Down Expand Up @@ -61,3 +65,96 @@ export class ItemChoiceAdvancement extends Advancement {
}

}


/**
* Configuration application for item choices.
*
* @extends {AdvancementConfig}
*/
export class ItemChoiceConfig extends AdvancementConfig {

/** @inheritdoc */
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
classes: ["dnd5e", "advancement", "item-choice", "two-column"],
dragDrop: [{ dropSelector: ".drop-target" }],
template: "systems/dnd5e/templates/advancement/item-choice-config.html",
width: 540
});
}

/* -------------------------------------------- */

/** @inheritdoc */
prepareConfigurationUpdate(configuration) {
configuration.choices = this.constructor._cleanedObject(configuration.choices);
return configuration;
}

/* -------------------------------------------- */

activateListeners(html) {
super.activateListeners(html);

// Remove an item from the list
html.on("click", ".item-delete", this._onItemDelete.bind(this));
}

/* -------------------------------------------- */

/**
* Handle deleting an existing Item entry from the Advancement.
* @param {Event} event The originating click event.
* @returns {Promise<Item5e>} The promise for the updated parent Item which resolves after the application re-renders
* @private
*/
async _onItemDelete(event) {
event.preventDefault();
const uuidToDelete = event.currentTarget.closest("[data-item-uuid]")?.dataset.itemUuid;
if ( !uuidToDelete ) return;
const pool = this.advancement.data.configuration.pool.filter(uuid => uuid !== uuidToDelete);
const updates = { configuration: this.prepareConfigurationUpdate({ pool }) };
await this.advancement.update(updates);
this.render();
}

/* -------------------------------------------- */

/** @inheritdoc */
_canDragDrop() {
return this.isEditable;
}

/* -------------------------------------------- */

/** @inheritdoc */
async _onDrop(event) {
// Try to extract the data
let data;
try {
data = JSON.parse(event.dataTransfer.getData("text/plain"));
} catch(err) {
return false;
}

if ( data.type !== "Item" ) return false;
const item = await Item.implementation.fromDropData(data);

const existingPool = this.advancement.data.configuration.pool;

// Abort if this uuid is the parent item
if ( item.uuid === this.item.uuid ) {
return ui.notifications.warn(game.i18n.localize("DND5E.AdvancementItemGrantRecursiveWarning"));
}

// Abort if this uuid exists already
if ( existingPool.includes(item.uuid) ) {
return ui.notifications.warn(game.i18n.localize("DND5E.AdvancementItemGrantDuplicateWarning"));
}

await this.advancement.update({"configuration.pool": [...existingPool, item.uuid]});
this.render();
}

}
44 changes: 44 additions & 0 deletions templates/advancement/item-choice-config.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<form autocomplete="off">
{{log this}}
<div class="left-column">
{{> "systems/dnd5e/templates/advancement/parts/advancement-controls.html"}}
<div class="form-group">
<label>{{localize "DND5E.AdvancementItemChoiceAllowDrops"}}</label>
<div class="form-fields">
<input type="checkbox" name="data.configuration.allowDrops" {{checked data.configuration.allowDrops}}>
</div>
<p class="hint">{{localize "DND5E.AdvancementItemChoiceAllowDropsHint"}}</p>
</div>

<div class="drop-target">
<ol class="items-list">
<li class="items-header flexrow"><h3 class="item-name">{{localize "DOCUMENT.Items"}}</h3></li>
<ol class="item-list">
{{#each data.configuration.pool}}
<li class="item flexrow" data-item-uuid="{{this}}">
<div class="item-name">{{{dnd5e-linkForUuid this}}}</div>
<div class="item-controls flexrow">
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
</div>
</li>
{{/each}}
</ol>
</ol>

<p class="hint centered">{{localize "DND5E.AdvancementItemChoiceDropHint"}}</p>
</div>
</div>

<div class="right-column level-list">
<p class="hint">{{localize "DND5E.AdvancementItemChoiceLevelsHint"}}</p>
{{#each levels as |level|}}
<div class="form-group">
<label>{{level}}</label>
<div class="form-fields">
{{numberInput (lookup ../data.configuration.choices level) placeholder="0"
name=(concat "data.configuration.choices." level) min=1 step=1}}
</div>
</div>
{{/each}}
</div>
</form>
2 changes: 1 addition & 1 deletion templates/advancement/scale-value-config.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
</div>
</div>

<div class="right-column scale-values">
<div class="right-column level-list scale-values">
{{#each levels as |data level|}}
<div class="form-group">
<label>{{level}}</label>
Expand Down

0 comments on commit 0d12e9b

Please sign in to comment.