diff --git a/src/systems/_index.js b/src/systems/_index.js
index cce656ff..8fa0bbf0 100644
--- a/src/systems/_index.js
+++ b/src/systems/_index.js
@@ -40,6 +40,7 @@ import starwarsffg from "./starwarsffg.js";
import demonlord from "./demonlord.js";
import dnd5e241 from "./dnd5e-2.4.1.js";
import dragonbane from "./dragonbane.js";
+import vaarfeu from "./vaarfeu.js";
// ↑ IMPORT SYSTEMS HERE ↑
/**
@@ -162,6 +163,9 @@ export default {
},
"dragonbane": {
"latest": dragonbane
- }
+ },
+ "vaarfeu": {
+ "latest": vaarfeu
+ }
// ↑ ADD SYSTEMS HERE ↑
}
diff --git a/src/systems/vaarfeu.js b/src/systems/vaarfeu.js
new file mode 100644
index 00000000..1871a67b
--- /dev/null
+++ b/src/systems/vaarfeu.js
@@ -0,0 +1,223 @@
+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.0",
+ // 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",
+ // The item class type is the type of item that will be used for the default loot item
+ "ITEM_CLASS_LOOT_TYPE": "loot",
+ // The item class type is the type of item that will be used for the default weapon item
+ "ITEM_CLASS_WEAPON_TYPE": "weapon",
+ // The item class type is the type of item that will be used for the default equipment item
+ "ITEM_CLASS_EQUIPMENT_TYPE": "equipment",
+ // The item quantity attribute is the path to the attribute on items that denote how many of that item that exists
+ "ITEM_QUANTITY_ATTRIBUTE": "system.quantity",
+ // The item price attribute is the path to the attribute on each item that determine how much it costs
+ "ITEM_PRICE_ATTRIBUTE": "system.price.value",
+ // Item filters actively remove items from the item pile inventory UI that users cannot loot, such as spells, feats, and classes
+ "ITEM_FILTERS": [
+ {
+ "path": "type",
+ "filters": "spell,feat,class,subclass,background"
+ },
+ {
+ "path": "system.type.value",
+ "filters": "natural"
+ }
+ ],
+ // 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;
+ const priceDenomination = foundry.utils.getProperty(item, "system.price.denomination");
+ if (priceDenomination) {
+ const currencyDenomination = currencies.filter((currency) => currency.type === "attribute").find((currency) => {
+ return currency.data.path.toLowerCase().endsWith(priceDenomination);
+ });
+ if (currencyDenomination) {
+ return overallCost * currencyDenomination.exchangeRate;
+ }
+ }
+ return overallCost ?? 0;
+ },
+ "PRICE_MODIFIER_TRANSFORMER": ({
+ buyPriceModifier,
+ sellPriceModifier,
+ actor = false,
+ actorPriceModifiers = []
+ } = {}) => {
+ const modifiers = {
+ buyPriceModifier,
+ sellPriceModifier
+ };
+ if (!actor)
+ return modifiers;
+ const groupModifiers = actorPriceModifiers.map((data2) => ({ ...data2, actor: fromUuidSync(data2.actorUuid) })).filter((data2) => {
+ return data2.actor && data2.actor.type === "group" && data2.actor.system.members.some((member) => member === actor);
+ });
+ modifiers.buyPriceModifier = groupModifiers.reduce((acc, data2) => {
+ return data2.override ? data2.buyPriceModifier ?? acc : acc * data2.buyPriceModifier;
+ }, buyPriceModifier);
+ modifiers.sellPriceModifier = groupModifiers.reduce((acc, data2) => {
+ return data2.override ? data2.sellPriceModifier ?? acc : acc * data2.sellPriceModifier;
+ }, sellPriceModifier);
+ return modifiers;
+ },
+
+ "PILE_DEFAULTS": {
+ merchantColumns: [{
+ label: "",
+ path: "system.equipped",
+ formatting: "{#}",
+ buying: false,
+ selling: true,
+ mapping: {
+ "true": "✔",
+ "false": ""
+ }
+ }, {
+ label: "Rarity",
+ path: "system.rarity",
+ formatting: "{#}",
+ buying: true,
+ selling: true,
+ mapping: {
+ "common": "VAARFEU.ItemRarityCommon",
+ "uncommon": "VAARFEU.ItemRarityUncommon",
+ "rare": "VAARFEU.ItemRarityRare",
+ "veryRare": "VAARFEU.ItemRarityVeryRare",
+ "legendary": "VAARFEU.ItemRarityLegendary",
+ "artifact": "VAARFEU.ItemRarityArtifact"
+ }
+ }]
+ },
+
+ // Item similarities determines how item piles detect similarities and differences in the system
+ "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"
+ // In the case of items, it is recommended you export the item with `.toObject()` and strip out any module data
+ "CURRENCIES": [
+ {
+ type: "attribute",
+ name: "VAARFEU.CurrencyPP",
+ img: "icons/commodities/currency/coin-inset-snail-silver.webp",
+ abbreviation: "{#}PP",
+ data: {
+ path: "system.currency.pp"
+ },
+ primary: false,
+ exchangeRate: 10
+ },
+ {
+ type: "attribute",
+ name: "VAARFEU.CurrencyGP",
+ img: "icons/commodities/currency/coin-embossed-crown-gold.webp",
+ abbreviation: "{#}GP",
+ data: {
+ path: "system.currency.gp"
+ },
+ primary: true,
+ exchangeRate: 1
+ },
+ {
+ type: "attribute",
+ name: "VAARFEU.CurrencyEP",
+ img: "icons/commodities/currency/coin-inset-copper-axe.webp",
+ abbreviation: "{#}EP",
+ data: {
+ path: "system.currency.ep"
+ },
+ primary: false,
+ exchangeRate: 0.5
+ },
+ {
+ type: "attribute",
+ name: "VAARFEU.CurrencySP",
+ img: "icons/commodities/currency/coin-engraved-moon-silver.webp",
+ abbreviation: "{#}SP",
+ data: {
+ path: "system.currency.sp"
+ },
+ primary: false,
+ exchangeRate: 0.1
+ },
+ {
+ type: "attribute",
+ name: "VAARFEU.CurrencyCP",
+ img: "icons/commodities/currency/coin-engraved-waves-copper.webp",
+ abbreviation: "{#}CP",
+ data: {
+ path: "system.currency.cp"
+ },
+ primary: false,
+ exchangeRate: 0.01
+ }
+ ],
+
+ "VAULT_STYLES": [
+ {
+ path: "system.rarity",
+ value: "artifact",
+ styling: {
+ "box-shadow": "inset 0px 0px 7px 0px rgba(255,191,0,1)"
+ }
+ },
+ {
+ path: "system.rarity",
+ value: "legendary",
+ styling: {
+ "box-shadow": "inset 0px 0px 7px 0px rgba(255,119,0,1)"
+ }
+ },
+ {
+ path: "system.rarity",
+ value: "veryRare",
+ styling: {
+ "box-shadow": "inset 0px 0px 7px 0px rgba(255,0,247,1)"
+ }
+ },
+ {
+ path: "system.rarity",
+ value: "rare",
+ styling: {
+ "box-shadow": "inset 0px 0px 7px 0px rgba(0,136,255,1)"
+ }
+ },
+ {
+ path: "system.rarity",
+ value: "uncommon",
+ styling: {
+ "box-shadow": "inset 0px 0px 7px 0px rgba(0,255,9,1)"
+ }
+ }
+ ],
+
+ "SYSTEM_HOOKS": () => {
+
+ Hooks.on("vaarfeu.getItemContextOptions", (item, options) => {
+ options.push({
+ name: "Give to character",
+ icon: "",
+ callback: async () => {
+ const result = await GiveItems.show(item);
+ if (!result) return;
+ PrivateAPI._giveItem({
+ itemData: {
+ item: item.toObject(),
+ quantity: result.quantity
+ },
+ source: item.parent.uuid,
+ target: result.target,
+ secret: result.secret,
+ }, { skipQuantityDialog: true })
+ },
+ condition: !game.itempiles.API.isItemInvalid(item)
+ })
+ });
+
+ }
+}