Skip to content

Commit

Permalink
Item containers polished
Browse files Browse the repository at this point in the history
  • Loading branch information
Haxxer committed Aug 23, 2024
1 parent 5125d37 commit f70807a
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 20 deletions.
9 changes: 6 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Item Piles Changelog

## Version 3.1.0

- Added support for "container" type items in D&D5e - this is a custom implementation, so other systems' containers will not work out of the box
- Splitting currencies in item piles takes into account across all currencies across containers in the pile
- Added tree-like display for items in containers

## Version 3.0.11

- Added `ITEM-PILES.Trade` localization for compatibility with Rest Recovery
Expand Down Expand Up @@ -32,9 +38,6 @@

## Version 3.0.7

- Added support for "container" type items in D&D5e - this is a custom implementation, so other systems' containers will not work out of the box
- Splitting currencies in item piles takes into account across all currencies across containers in the pile
- Added tree-like display for items in containers
- Tweaked `game.itempiles.API.createItemPile` with `createActor` set to `true` have the default item piles' settings
- Fixed item pile containers not respecting open/close/lock/unlock settings
- Fixed minor `module.json` manifest warning
Expand Down
23 changes: 15 additions & 8 deletions src/API/private-api.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import CustomDialog from "../applications/components/CustomDialog.svelte";
import ReceiveItemsShell from "../applications/dialogs/receive-items-dialog/receive-items-shell.svelte";
import BankVaultApp from "../applications/vault-app/vault-app.js";
import { hotkeyActionState } from "../hotkeys.js";
import { getCurrenciesInItem } from "../helpers/pile-utilities.js";

const preloadedFiles = new Set();

Expand Down Expand Up @@ -271,12 +270,14 @@ export default class PrivateAPI {

const sourceTransaction = new Transaction(sourceActor);
if (SYSTEMS.DATA.ITEM_TYPE_HANDLERS) {
const newItems = [];
for (const itemData of items) {
const item = sourceActor.items.get(itemData._id ?? itemData.id);
const handler = Utilities.getItemTypeHandler(CONSTANTS.ITEM_TYPE_METHODS.TRANSFER, item.type);
if (!handler) continue;
handler({ actor: sourceActor, item, items });
handler({ item, items: newItems });
}
items = items.concat(newItems);
}
await sourceTransaction.appendItemChanges(items, { remove: true });

Expand Down Expand Up @@ -828,8 +829,6 @@ export default class PrivateAPI {
await targetTransaction.appendDocumentChanges(sourceUpdates.attributeDeltas);
const targetUpdates = targetTransaction.prepare();

debugger;

const hookResult = Helpers.hooks.call(CONSTANTS.HOOKS.ATTRIBUTE.PRE_TRANSFER, sourceDocument, sourceUpdates.actorUpdates, targetDocument, targetUpdates.actorUpdates, interactionId);
if (hookResult === false) return false;

Expand Down Expand Up @@ -1211,6 +1210,16 @@ export default class PrivateAPI {
}
items[i] = itemData;
}
if (SYSTEMS.DATA.ITEM_TYPE_HANDLERS) {
const newItems = [];
for (const itemData of items) {
const item = new Item.implementation(itemData);
const handler = Utilities.getItemTypeHandler(CONSTANTS.ITEM_TYPE_METHODS.TRANSFER, item.type);
if (!handler) continue;
handler({ item, items: newItems });
}
items = items.concat(newItems);
}
} else {
items = []
}
Expand Down Expand Up @@ -1279,7 +1288,7 @@ export default class PrivateAPI {
new Promise(async (resolve) => {
await Helpers.wait(250);
await Helpers.hooks.runWithout(async () => {
await tokenDocument.actor.createEmbeddedDocuments("Item", items);
await tokenDocument.actor.createEmbeddedDocuments("Item", items, { keepId: true });
});
resolve();
});
Expand All @@ -1291,7 +1300,7 @@ export default class PrivateAPI {

if (items.length && !pileActor.prototypeToken.actorLink) {
await Helpers.hooks.runWithout(async () => {
await pileActor.createEmbeddedDocuments("Item", items);
await pileActor.createEmbeddedDocuments("Item", items, { keepId: true });
});
}

Expand Down Expand Up @@ -2152,8 +2161,6 @@ export default class PrivateAPI {

const actorPreparedData = Object.fromEntries(transactionMap.map(entry => [entry[0], entry[1].prepare()]));

debugger;

const hookResult = Helpers.hooks.call(CONSTANTS.HOOKS.PILE.PRE_SPLIT_INVENTORY, itemPileActor, preparedData, actorPreparedData, userId, instigator);
if (hookResult === false) return false;

Expand Down
19 changes: 15 additions & 4 deletions src/helpers/pile-utilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { hotkeyActionState } from "../hotkeys.js";
import * as Utilities from "./utilities.js"
import * as Helpers from "./helpers.js";
import * as CompendiumUtilities from "./compendium-utilities.js";
import { getDocument } from "./utilities.js";

export function getPileDefaults() {
return foundry.utils.mergeObject({}, CONSTANTS.PILE_DEFAULTS, Helpers.getSetting(SETTINGS.PILE_DEFAULTS) ?? {});
Expand Down Expand Up @@ -551,7 +550,11 @@ export function getItemPileTokenImage(token, {

if (!isValidItemPile(pileDocument, itemPileData) || !isItemPileLootable(pileDocument, itemPileData)) return originalImg;

items = items || getActorItems(pileDocument);
items = (items || getActorItems(pileDocument)).filter(itemData => {
const method = Utilities.getItemTypeHandler(CONSTANTS.ITEM_TYPE_METHODS.IS_CONTAINED);
if (!method) return true;
return !method({ item: itemData });
});
currencies = currencies || getActorCurrencies(pileDocument);

const numItems = items.length + currencies.length;
Expand Down Expand Up @@ -604,7 +607,11 @@ export function getItemPileTokenScale(target, {
return baseScale;
}

items = items || getActorItems(pileDocument);
items = (items || getActorItems(pileDocument)).filter(itemData => {
const method = Utilities.getItemTypeHandler(CONSTANTS.ITEM_TYPE_METHODS.IS_CONTAINED);
if (!method) return true;
return !method({ item: itemData });
});
currencies = currencies || getActorCurrencies(pileDocument);

const numItems = items.length + currencies.length;
Expand All @@ -631,7 +638,11 @@ export function getItemPileName(target, { data = false, items = false, currencie
return name;
}

items = items || getActorItems(pileDocument);
items = (items || getActorItems(pileDocument)).filter(itemData => {
const method = Utilities.getItemTypeHandler(CONSTANTS.ITEM_TYPE_METHODS.IS_CONTAINED);
if (!method) return true;
return !method({ item: itemData });
});
currencies = currencies || getActorCurrencies(pileDocument);

const numItems = items.length + currencies.length;
Expand Down
1 change: 0 additions & 1 deletion src/stores/item-pile-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,6 @@ export default class ItemPileStore {
const renderData = updateData?.renderData ?? updateData?.data ?? {};
if (foundry.utils.hasProperty(renderData, CONSTANTS.FLAGS.SHARING)) {
this.shareData.set(SharingUtilities.getItemPileSharingData(this.actor));
13
this.refreshItems();
}
if (foundry.utils.hasProperty(renderData, CONSTANTS.FLAGS.PILE)) {
Expand Down
26 changes: 24 additions & 2 deletions src/systems/dnd5e-3.1.2.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import GiveItems from "../applications/dialogs/give-items-dialog/give-items-dialog.js";
import PrivateAPI from "../API/private-api.js";
import CONSTANTS from "../constants/constants.js";

export default {

"VERSION": "1.0.7",
"VERSION": "1.0.8",

// The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.
"ACTOR_CLASS_TYPE": "character",
Expand Down Expand Up @@ -35,6 +36,8 @@ export default {
}
],

"UNSTACKABLE_ITEM_TYPES": ["container"],

// This function is an optional system handler that specifically transforms an item when it is added to actors
"ITEM_TRANSFORMER": async (itemData) => {
["equipped", "proficient", "prepared"].forEach(key => {
Expand All @@ -53,6 +56,25 @@ export default {
return itemData;
},

"ITEM_TYPE_HANDLERS": {
"GLOBAL": {
[CONSTANTS.ITEM_TYPE_METHODS.IS_CONTAINED]: ({ item }) => {
return item.system.container;
}
},
"container": {
[CONSTANTS.ITEM_TYPE_METHODS.HAS_CURRENCY]: true,
[CONSTANTS.ITEM_TYPE_METHODS.CONTENTS]: ({ item }) => {
return item.system.contents.contents;
},
[CONSTANTS.ITEM_TYPE_METHODS.TRANSFER]: ({ item, items }) => {
for (const containedItem of item.system.contents.contents) {
items.push(containedItem.toObject());
}
}
}
},

// This function is an optional system handler that specifically transforms an item's price into a more unified numeric format
"ITEM_COST_TRANSFORMER": (item, currencies) => {
const overallCost = Number(foundry.utils.getProperty(item, "system.price.value")) ?? 0;
Expand Down Expand Up @@ -131,7 +153,7 @@ export default {
},

// Item similarities determines how item piles detect similarities and differences in the system
"ITEM_SIMILARITIES": ["name", "type"],
"ITEM_SIMILARITIES": ["name", "type", "system.container"],

// Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)
// In the case of attributes, the path is relative to the "actor.system"
Expand Down
4 changes: 2 additions & 2 deletions src/systems/dnd5e.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import CONSTANTS from "../constants/constants.js";

export default {

"VERSION": "1.0.7",
"VERSION": "1.0.8",

// The actor class type is the type of actor that will be used for the default item pile actor that is created on first item drop.
"ACTOR_CLASS_TYPE": "character",
Expand Down Expand Up @@ -152,7 +152,7 @@ export default {
},

// Item similarities determines how item piles detect similarities and differences in the system
"ITEM_SIMILARITIES": ["name", "type"],
"ITEM_SIMILARITIES": ["name", "type", "system.container"],

// Currencies in item piles is a versatile system that can accept actor attributes (a number field on the actor's sheet) or items (actual items in their inventory)
// In the case of attributes, the path is relative to the "actor.system"
Expand Down

0 comments on commit f70807a

Please sign in to comment.