diff --git a/css/fvtt-prism-rpg.css b/css/fvtt-prism-rpg.css index b6d73b2..ea9fbd9 100644 --- a/css/fvtt-prism-rpg.css +++ b/css/fvtt-prism-rpg.css @@ -720,6 +720,26 @@ i.prismrpg { overflow: hidden; text-overflow: ellipsis; } +.prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-qty { + display: flex; + align-items: center; + gap: 2px; + font-size: 11px; + min-width: 48px; + justify-content: center; +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-qty a { + font-size: 9px; + cursor: pointer; + color: rgba(0, 0, 0, 0.4); +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-qty a:hover { + color: rgba(0, 0, 0, 0.8); +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-qty span { + min-width: 16px; + text-align: center; +} .prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-enc, .prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-uses, .prismrpg .tab.character-equipment .main-div .inv-section .inv-item .inv-capacity { @@ -784,6 +804,26 @@ i.prismrpg { overflow: hidden; text-overflow: ellipsis; } +.prismrpg .tab.character-equipment .main-div .inv-section .inv-container-item .inv-qty { + display: flex; + align-items: center; + gap: 2px; + font-size: 10px; + min-width: 40px; + justify-content: center; +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-container-item .inv-qty a { + font-size: 8px; + cursor: pointer; + color: rgba(0, 0, 0, 0.4); +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-container-item .inv-qty a:hover { + color: rgba(0, 0, 0, 0.8); +} +.prismrpg .tab.character-equipment .main-div .inv-section .inv-container-item .inv-qty span { + min-width: 14px; + text-align: center; +} .prismrpg .tab.character-equipment .main-div .inv-section .inv-container-item .inv-enc { font-size: 10px; color: #555; diff --git a/lang/en.json b/lang/en.json index 0953230..c802579 100644 --- a/lang/en.json +++ b/lang/en.json @@ -15,6 +15,9 @@ "armorType": { "label": "Armor Type" }, + "quantity": { + "label": "Qty" + }, "cost": { "label": "Cost" }, @@ -366,6 +369,9 @@ "description": { "label": "Description" }, + "quantity": { + "label": "Qty" + }, "encLoad": { "label": "Load" }, @@ -479,6 +485,7 @@ "Wounded": "Wounded" }, "Label": { + "quantity": "Qty", "agility": "Dexterity", "gotoToken": "Go to token", "combatAction": "Combat action", @@ -943,13 +950,17 @@ "excessBurden": "Equipped burden exceeds max — excess reduces Movement Rating", "assignToContainer": "Assign to container", "removeFromContainer": "Remove from container", - "packBurden": "Pack Burden" + "packBurden": "Pack Burden", + "quantityPlus": "Increase quantity", + "quantityMinus": "Decrease quantity" }, "RollSavingThrow": "Roll Saving Throw", "Dialog": { "useConsumable": "Use Consumable", "useConsumableContent": "Use one charge of {name}? ({uses} remaining)", - "assignToContainer": "Assign to Container" + "assignToContainer": "Assign to Container", + "deleteItem": "Delete Item", + "deleteItemContent": "Remove last copy of {name}?" }, "Message": { "selectCoreSkill": "You must select a Core Skill for your character. Each character chooses one Core Skill at creation.", @@ -1111,6 +1122,9 @@ "cost": { "label": "Cost" }, + "quantity": { + "label": "Qty" + }, "defense": { "label": "Defense Bonus" }, @@ -1372,6 +1386,9 @@ "cost": { "label": "Cost" }, + "quantity": { + "label": "Qty" + }, "encLoad": { "label": "Encumbrance Load" }, @@ -1480,6 +1497,9 @@ "uses": { "label": "Uses" }, + "quantity": { + "label": "Qty" + }, "encLoad": { "label": "Enc. Load" }, @@ -1496,6 +1516,9 @@ "description": { "label": "Description" }, + "quantity": { + "label": "Qty" + }, "encLoad": { "label": "Enc. Load" }, diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs index cc05a42..d60a57b 100644 --- a/module/applications/sheets/character-sheet.mjs +++ b/module/applications/sheets/character-sheet.mjs @@ -30,6 +30,8 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { hpTempMinus: PrismRPGCharacterSheet.#onHpTempMinus, postItemToChat: PrismRPGCharacterSheet.#onPostItemToChat, useConsumable: PrismRPGCharacterSheet.#onUseConsumable, + quantityPlus: PrismRPGCharacterSheet.#onQuantityPlus, + quantityMinus: PrismRPGCharacterSheet.#onQuantityMinus, toggleContainerEquipped: PrismRPGCharacterSheet.#onToggleContainerEquipped, toggleEquipped: PrismRPGCharacterSheet.#onToggleEquipped, assignToContainer: PrismRPGCharacterSheet.#onAssignToContainer, @@ -129,7 +131,7 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { ] const burdenEquipped = equippableTypes .filter(i => i.system.equipped) - .reduce((sum, i) => sum + (i.system.encLoad ?? 0), 0) + .reduce((sum, i) => sum + (i.system.encLoad ?? 0) * (i.system.quantity ?? 1), 0) context.burdenUsed = burdenEquipped // Excess equipped burden reduces Movement Rating const excessBurden = Math.max(0, burdenEquipped - context.burdenMax) @@ -202,7 +204,7 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { // Pack burden = items stored in an existing container context.packBurdenUsed = allStorable .filter(i => i.system.containerId && containerGroups[i.system.containerId]) - .reduce((sum, i) => sum + (i.system.encLoad ?? 0), 0) + .reduce((sum, i) => sum + (i.system.encLoad ?? 0) * (i.system.quantity ?? 1), 0) break case "biography": context.tab = context.tabs.biography @@ -365,6 +367,31 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet { await item.update({ "system.equipped": !item.system.equipped }) } + static async #onQuantityPlus(event, target) { + const itemElement = target.closest("[data-item-id]") + if (!itemElement) return + const item = this.document.items.get(itemElement.dataset.itemId) + if (!item) return + await item.update({ "system.quantity": (item.system.quantity ?? 1) + 1 }) + } + + static async #onQuantityMinus(event, target) { + const itemElement = target.closest("[data-item-id]") + if (!itemElement) return + const item = this.document.items.get(itemElement.dataset.itemId) + if (!item) return + const newQty = (item.system.quantity ?? 1) - 1 + if (newQty < 1) { + const confirmed = await foundry.applications.api.DialogV2.confirm({ + window: { title: game.i18n.localize("PRISMRPG.Dialog.deleteItem") }, + content: `

${game.i18n.format("PRISMRPG.Dialog.deleteItemContent", { name: item.name })}

`, + }) + if (confirmed) await item.delete() + return + } + await item.update({ "system.quantity": newQty }) + } + static async #onAssignToContainer(event, target) { const itemElement = target.closest("[data-item-id]") if (!itemElement) return diff --git a/module/config/effects.mjs b/module/config/effects.mjs index 7d8e6c1..2c9ac85 100644 --- a/module/config/effects.mjs +++ b/module/config/effects.mjs @@ -4,51 +4,51 @@ */ export const AFFLICTIONS = [ // ── Mundane ──────────────────────────────────────────────────────────────── - { id: "aff-alkalized", name: "PRISMRPG.Status.Alkalized", icon: "icons/svg/acid.svg", category: "affliction", typing: "mundane" }, - { id: "aff-bleed", name: "PRISMRPG.Status.Bleed", icon: "icons/svg/blood.svg", category: "affliction", typing: "mundane" }, - { id: "aff-blind", name: "PRISMRPG.Status.Blind", icon: "icons/svg/blind.svg", category: "affliction", typing: "mundane" }, - { id: "aff-deaf", name: "PRISMRPG.Status.Deaf", icon: "icons/svg/deaf.svg", category: "affliction", typing: "mundane" }, - { id: "aff-diseased", name: "PRISMRPG.Status.Diseased", icon: "icons/svg/biohazard.svg", category: "affliction", typing: "mundane" }, - { id: "aff-distracted", name: "PRISMRPG.Status.Distracted", icon: "icons/svg/daze.svg", category: "affliction", typing: "mundane" }, - { id: "aff-exhaustion", name: "PRISMRPG.Status.Exhaustion", icon: "icons/svg/sleep.svg", category: "affliction", typing: "mundane" }, - { id: "aff-frightened", name: "PRISMRPG.Status.Frightened", icon: "icons/svg/terror.svg", category: "affliction", typing: "mundane" }, - { id: "aff-marked", name: "PRISMRPG.Status.Marked", icon: "icons/svg/target.svg", category: "affliction", typing: "both" }, - { id: "aff-mute", name: "PRISMRPG.Status.Mute", icon: "icons/svg/silenced.svg", category: "affliction", typing: "mundane" }, - { id: "aff-paralyzed", name: "PRISMRPG.Status.Paralyzed", icon: "icons/svg/paralysis.svg", category: "affliction", typing: "mundane" }, - { id: "aff-petrified", name: "PRISMRPG.Status.Petrified", icon: "icons/svg/frozen.svg", category: "affliction", typing: "mundane" }, - { id: "aff-poison", name: "PRISMRPG.Status.Poison", icon: "icons/svg/poison.svg", category: "affliction", typing: "mundane" }, - { id: "aff-prone", name: "PRISMRPG.Status.Prone", icon: "icons/svg/falling.svg", category: "affliction", typing: "mundane" }, - { id: "aff-rage", name: "PRISMRPG.Status.Rage", icon: "icons/svg/fire.svg", category: "affliction", typing: "mundane" }, - { id: "aff-sealed", name: "PRISMRPG.Status.Sealed", icon: "icons/svg/net.svg", category: "affliction", typing: "mundane" }, - { id: "aff-staggered", name: "PRISMRPG.Status.Staggered", icon: "icons/svg/daze.svg", category: "affliction", typing: "mundane" }, - { id: "aff-stunned", name: "PRISMRPG.Status.Stunned", icon: "icons/svg/stun.svg", category: "affliction", typing: "mundane" }, - { id: "aff-taunt", name: "PRISMRPG.Status.Taunt", icon: "icons/svg/eye.svg", category: "affliction", typing: "mundane" }, - { id: "aff-unconscious",name: "PRISMRPG.Status.Unconscious",icon: "icons/svg/unconscious.svg", category: "affliction", typing: "mundane" }, - { id: "aff-wounded", name: "PRISMRPG.Status.Wounded", icon: "icons/svg/degen.svg", category: "affliction", typing: "mundane" }, + { id: "aff-alkalized", name: "PRISMRPG.Status.Alkalized", img: "icons/svg/acid.svg", category: "affliction", typing: "mundane" }, + { id: "aff-bleed", name: "PRISMRPG.Status.Bleed", img: "icons/svg/blood.svg", category: "affliction", typing: "mundane" }, + { id: "aff-blind", name: "PRISMRPG.Status.Blind", img: "icons/svg/blind.svg", category: "affliction", typing: "mundane" }, + { id: "aff-deaf", name: "PRISMRPG.Status.Deaf", img: "icons/svg/deaf.svg", category: "affliction", typing: "mundane" }, + { id: "aff-diseased", name: "PRISMRPG.Status.Diseased", img: "icons/svg/biohazard.svg", category: "affliction", typing: "mundane" }, + { id: "aff-distracted", name: "PRISMRPG.Status.Distracted", img: "icons/svg/daze.svg", category: "affliction", typing: "mundane" }, + { id: "aff-exhaustion", name: "PRISMRPG.Status.Exhaustion", img: "icons/svg/sleep.svg", category: "affliction", typing: "mundane" }, + { id: "aff-frightened", name: "PRISMRPG.Status.Frightened", img: "icons/svg/terror.svg", category: "affliction", typing: "mundane" }, + { id: "aff-marked", name: "PRISMRPG.Status.Marked", img: "icons/svg/target.svg", category: "affliction", typing: "both" }, + { id: "aff-mute", name: "PRISMRPG.Status.Mute", img: "icons/svg/silenced.svg", category: "affliction", typing: "mundane" }, + { id: "aff-paralyzed", name: "PRISMRPG.Status.Paralyzed", img: "icons/svg/paralysis.svg", category: "affliction", typing: "mundane" }, + { id: "aff-petrified", name: "PRISMRPG.Status.Petrified", img: "icons/svg/frozen.svg", category: "affliction", typing: "mundane" }, + { id: "aff-poison", name: "PRISMRPG.Status.Poison", img: "icons/svg/poison.svg", category: "affliction", typing: "mundane" }, + { id: "aff-prone", name: "PRISMRPG.Status.Prone", img: "icons/svg/falling.svg", category: "affliction", typing: "mundane" }, + { id: "aff-rage", name: "PRISMRPG.Status.Rage", img: "icons/svg/fire.svg", category: "affliction", typing: "mundane" }, + { id: "aff-sealed", name: "PRISMRPG.Status.Sealed", img: "icons/svg/net.svg", category: "affliction", typing: "mundane" }, + { id: "aff-staggered", name: "PRISMRPG.Status.Staggered", img: "icons/svg/daze.svg", category: "affliction", typing: "mundane" }, + { id: "aff-stunned", name: "PRISMRPG.Status.Stunned", img: "icons/svg/stun.svg", category: "affliction", typing: "mundane" }, + { id: "aff-taunt", name: "PRISMRPG.Status.Taunt", img: "icons/svg/eye.svg", category: "affliction", typing: "mundane" }, + { id: "aff-unconscious",name: "PRISMRPG.Status.Unconscious",img: "icons/svg/unconscious.svg", category: "affliction", typing: "mundane" }, + { id: "aff-wounded", name: "PRISMRPG.Status.Wounded", img: "icons/svg/degen.svg", category: "affliction", typing: "mundane" }, // ── Magic ────────────────────────────────────────────────────────────────── - { id: "aff-banished", name: "PRISMRPG.Status.Banished", icon: "icons/svg/wing.svg", category: "affliction", typing: "magic" }, - { id: "aff-seep", name: "PRISMRPG.Status.Seep", icon: "icons/svg/acid.svg", category: "affliction", typing: "magic" }, - { id: "aff-sightless", name: "PRISMRPG.Status.Sightless", icon: "icons/svg/blind.svg", category: "affliction", typing: "magic" }, - { id: "aff-cursed", name: "PRISMRPG.Status.Cursed", icon: "icons/svg/sun.svg", category: "affliction", typing: "magic" }, - { id: "aff-soundless", name: "PRISMRPG.Status.Soundless", icon: "icons/svg/deaf.svg", category: "affliction", typing: "magic" }, - { id: "aff-plagued", name: "PRISMRPG.Status.Plagued", icon: "icons/svg/biohazard.svg", category: "affliction", typing: "magic" }, - { id: "aff-compulsed", name: "PRISMRPG.Status.Compulsed", icon: "icons/svg/eye.svg", category: "affliction", typing: "magic" }, - { id: "aff-fatigue", name: "PRISMRPG.Status.Fatigue", icon: "icons/svg/sleep.svg", category: "affliction", typing: "magic" }, - { id: "aff-horror", name: "PRISMRPG.Status.Horror", icon: "icons/svg/terror.svg", category: "affliction", typing: "magic" }, - { id: "aff-madness", name: "PRISMRPG.Status.Madness", icon: "icons/svg/daze.svg", category: "affliction", typing: "magic" }, - { id: "aff-silenced", name: "PRISMRPG.Status.Silenced", icon: "icons/svg/silenced.svg", category: "affliction", typing: "magic" }, - { id: "aff-locked", name: "PRISMRPG.Status.Locked", icon: "icons/svg/net.svg", category: "affliction", typing: "magic" }, - { id: "aff-dazed", name: "PRISMRPG.Status.Dazed", icon: "icons/svg/daze.svg", category: "affliction", typing: "magic" }, - { id: "aff-numbed", name: "PRISMRPG.Status.Numbed", icon: "icons/svg/frozen.svg", category: "affliction", typing: "magic" }, - { id: "aff-comatose", name: "PRISMRPG.Status.Comatose", icon: "icons/svg/unconscious.svg", category: "affliction", typing: "magic" }, - { id: "aff-shattered", name: "PRISMRPG.Status.Shattered", icon: "icons/svg/blood.svg", category: "affliction", typing: "magic" }, + { id: "aff-banished", name: "PRISMRPG.Status.Banished", img: "icons/svg/wing.svg", category: "affliction", typing: "magic" }, + { id: "aff-seep", name: "PRISMRPG.Status.Seep", img: "icons/svg/acid.svg", category: "affliction", typing: "magic" }, + { id: "aff-sightless", name: "PRISMRPG.Status.Sightless", img: "icons/svg/blind.svg", category: "affliction", typing: "magic" }, + { id: "aff-cursed", name: "PRISMRPG.Status.Cursed", img: "icons/svg/sun.svg", category: "affliction", typing: "magic" }, + { id: "aff-soundless", name: "PRISMRPG.Status.Soundless", img: "icons/svg/deaf.svg", category: "affliction", typing: "magic" }, + { id: "aff-plagued", name: "PRISMRPG.Status.Plagued", img: "icons/svg/biohazard.svg", category: "affliction", typing: "magic" }, + { id: "aff-compulsed", name: "PRISMRPG.Status.Compulsed", img: "icons/svg/eye.svg", category: "affliction", typing: "magic" }, + { id: "aff-fatigue", name: "PRISMRPG.Status.Fatigue", img: "icons/svg/sleep.svg", category: "affliction", typing: "magic" }, + { id: "aff-horror", name: "PRISMRPG.Status.Horror", img: "icons/svg/terror.svg", category: "affliction", typing: "magic" }, + { id: "aff-madness", name: "PRISMRPG.Status.Madness", img: "icons/svg/daze.svg", category: "affliction", typing: "magic" }, + { id: "aff-silenced", name: "PRISMRPG.Status.Silenced", img: "icons/svg/silenced.svg", category: "affliction", typing: "magic" }, + { id: "aff-locked", name: "PRISMRPG.Status.Locked", img: "icons/svg/net.svg", category: "affliction", typing: "magic" }, + { id: "aff-dazed", name: "PRISMRPG.Status.Dazed", img: "icons/svg/daze.svg", category: "affliction", typing: "magic" }, + { id: "aff-numbed", name: "PRISMRPG.Status.Numbed", img: "icons/svg/frozen.svg", category: "affliction", typing: "magic" }, + { id: "aff-comatose", name: "PRISMRPG.Status.Comatose", img: "icons/svg/unconscious.svg", category: "affliction", typing: "magic" }, + { id: "aff-shattered", name: "PRISMRPG.Status.Shattered", img: "icons/svg/blood.svg", category: "affliction", typing: "magic" }, // ── Elemental (Magic) ────────────────────────────────────────────────────── - { id: "aff-burning", name: "PRISMRPG.Status.Burning", icon: "icons/svg/fire.svg", category: "affliction", typing: "magic" }, - { id: "aff-chilled", name: "PRISMRPG.Status.Chilled", icon: "icons/svg/frozen.svg", category: "affliction", typing: "magic" }, - { id: "aff-corroded", name: "PRISMRPG.Status.Corroded", icon: "icons/svg/acid.svg", category: "affliction", typing: "magic" }, - { id: "aff-necrosis", name: "PRISMRPG.Status.Necrosis", icon: "icons/svg/degen.svg", category: "affliction", typing: "magic" }, - { id: "aff-radiated", name: "PRISMRPG.Status.Radiated", icon: "icons/svg/lightning.svg", category: "affliction", typing: "magic" }, - { id: "aff-shocked", name: "PRISMRPG.Status.Shocked", icon: "icons/svg/lightning.svg", category: "affliction", typing: "magic" }, + { id: "aff-burning", name: "PRISMRPG.Status.Burning", img: "icons/svg/fire.svg", category: "affliction", typing: "magic" }, + { id: "aff-chilled", name: "PRISMRPG.Status.Chilled", img: "icons/svg/frozen.svg", category: "affliction", typing: "magic" }, + { id: "aff-corroded", name: "PRISMRPG.Status.Corroded", img: "icons/svg/acid.svg", category: "affliction", typing: "magic" }, + { id: "aff-necrosis", name: "PRISMRPG.Status.Necrosis", img: "icons/svg/degen.svg", category: "affliction", typing: "magic" }, + { id: "aff-radiated", name: "PRISMRPG.Status.Radiated", img: "icons/svg/lightning.svg", category: "affliction", typing: "magic" }, + { id: "aff-shocked", name: "PRISMRPG.Status.Shocked", img: "icons/svg/lightning.svg", category: "affliction", typing: "magic" }, ] /** @@ -57,33 +57,33 @@ export const AFFLICTIONS = [ */ export const IMBUEMENTS = [ // ── Mundane ──────────────────────────────────────────────────────────────── - { id: "imb-aided", name: "PRISMRPG.Status.Aided", icon: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-alert", name: "PRISMRPG.Status.Alert", icon: "icons/svg/eye.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-alkalized", name: "PRISMRPG.Status.Alkalized", icon: "icons/svg/acid.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-bestowed", name: "PRISMRPG.Status.Bestowed", icon: "icons/svg/angel.svg", category: "imbuement", typing: "both" }, - { id: "imb-concealed", name: "PRISMRPG.Status.Concealed", icon: "icons/svg/invisible.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-enhance", name: "PRISMRPG.Status.Enhance", icon: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-inspired", name: "PRISMRPG.Status.Inspired", icon: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-keen", name: "PRISMRPG.Status.Keen", icon: "icons/svg/eye.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-life-drain", name: "PRISMRPG.Status.LifeDrain", icon: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-madness", name: "PRISMRPG.Status.Madness", icon: "icons/svg/daze.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-prepared", name: "PRISMRPG.Status.Prepared", icon: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-rage", name: "PRISMRPG.Status.Rage", icon: "icons/svg/fire.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-reinforced", name: "PRISMRPG.Status.Reinforced", icon: "icons/svg/mage-shield.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-renewed", name: "PRISMRPG.Status.Renewed", icon: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-supplied", name: "PRISMRPG.Status.Supplied", icon: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-surged", name: "PRISMRPG.Status.Surged", icon: "icons/svg/lightning.svg", category: "imbuement", typing: "mundane" }, - { id: "imb-trance", name: "PRISMRPG.Status.Trance", icon: "icons/svg/sleep.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-aided", name: "PRISMRPG.Status.Aided", img: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-alert", name: "PRISMRPG.Status.Alert", img: "icons/svg/eye.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-alkalized", name: "PRISMRPG.Status.Alkalized", img: "icons/svg/acid.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-bestowed", name: "PRISMRPG.Status.Bestowed", img: "icons/svg/angel.svg", category: "imbuement", typing: "both" }, + { id: "imb-concealed", name: "PRISMRPG.Status.Concealed", img: "icons/svg/invisible.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-enhance", name: "PRISMRPG.Status.Enhance", img: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-inspired", name: "PRISMRPG.Status.Inspired", img: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-keen", name: "PRISMRPG.Status.Keen", img: "icons/svg/eye.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-life-drain", name: "PRISMRPG.Status.LifeDrain", img: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-madness", name: "PRISMRPG.Status.Madness", img: "icons/svg/daze.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-prepared", name: "PRISMRPG.Status.Prepared", img: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-rage", name: "PRISMRPG.Status.Rage", img: "icons/svg/fire.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-reinforced", name: "PRISMRPG.Status.Reinforced", img: "icons/svg/mage-shield.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-renewed", name: "PRISMRPG.Status.Renewed", img: "icons/svg/regen.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-supplied", name: "PRISMRPG.Status.Supplied", img: "icons/svg/upgrade.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-surged", name: "PRISMRPG.Status.Surged", img: "icons/svg/lightning.svg", category: "imbuement", typing: "mundane" }, + { id: "imb-trance", name: "PRISMRPG.Status.Trance", img: "icons/svg/sleep.svg", category: "imbuement", typing: "mundane" }, // ── Magic ────────────────────────────────────────────────────────────────── - { id: "imb-blessed", name: "PRISMRPG.Status.Blessed", icon: "icons/svg/angel.svg", category: "imbuement", typing: "magic" }, - { id: "imb-anchored", name: "PRISMRPG.Status.Anchored", icon: "icons/svg/net.svg", category: "imbuement", typing: "magic" }, - { id: "imb-saturated", name: "PRISMRPG.Status.Saturated", icon: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, - { id: "imb-invisible", name: "PRISMRPG.Status.Invisible", icon: "icons/svg/invisible.svg", category: "imbuement", typing: "magic" }, - { id: "imb-enchanted", name: "PRISMRPG.Status.Enchanted", icon: "icons/svg/mage-shield.svg", category: "imbuement", typing: "magic" }, - { id: "imb-heroism", name: "PRISMRPG.Status.Heroism", icon: "icons/svg/upgrade.svg", category: "imbuement", typing: "magic" }, - { id: "imb-mana-drain", name: "PRISMRPG.Status.ManaDrain", icon: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, - { id: "imb-fury", name: "PRISMRPG.Status.Fury", icon: "icons/svg/fire.svg", category: "imbuement", typing: "magic" }, - { id: "imb-warded", name: "PRISMRPG.Status.Warded", icon: "icons/svg/holy-shield.svg", category: "imbuement", typing: "magic" }, - { id: "imb-regeneration", name: "PRISMRPG.Status.Regeneration", icon: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, - { id: "imb-haste", name: "PRISMRPG.Status.Haste", icon: "icons/svg/wingfoot.svg", category: "imbuement", typing: "magic" }, + { id: "imb-blessed", name: "PRISMRPG.Status.Blessed", img: "icons/svg/angel.svg", category: "imbuement", typing: "magic" }, + { id: "imb-anchored", name: "PRISMRPG.Status.Anchored", img: "icons/svg/net.svg", category: "imbuement", typing: "magic" }, + { id: "imb-saturated", name: "PRISMRPG.Status.Saturated", img: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, + { id: "imb-invisible", name: "PRISMRPG.Status.Invisible", img: "icons/svg/invisible.svg", category: "imbuement", typing: "magic" }, + { id: "imb-enchanted", name: "PRISMRPG.Status.Enchanted", img: "icons/svg/mage-shield.svg", category: "imbuement", typing: "magic" }, + { id: "imb-heroism", name: "PRISMRPG.Status.Heroism", img: "icons/svg/upgrade.svg", category: "imbuement", typing: "magic" }, + { id: "imb-mana-drain", name: "PRISMRPG.Status.ManaDrain", img: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, + { id: "imb-fury", name: "PRISMRPG.Status.Fury", img: "icons/svg/fire.svg", category: "imbuement", typing: "magic" }, + { id: "imb-warded", name: "PRISMRPG.Status.Warded", img: "icons/svg/holy-shield.svg", category: "imbuement", typing: "magic" }, + { id: "imb-regeneration", name: "PRISMRPG.Status.Regeneration", img: "icons/svg/regen.svg", category: "imbuement", typing: "magic" }, + { id: "imb-haste", name: "PRISMRPG.Status.Haste", img: "icons/svg/wingfoot.svg", category: "imbuement", typing: "magic" }, ] diff --git a/module/models/armor.mjs b/module/models/armor.mjs index 94aca6a..969a58a 100644 --- a/module/models/armor.mjs +++ b/module/models/armor.mjs @@ -19,6 +19,7 @@ export default class PrismRPGArmor extends foundry.abstract.TypeDataModel { schema.augment = new fields.StringField({ required: false, initial: "", label: "Armor Augment" }) schema.augmentDescription = new fields.HTMLField({ required: false, textSearch: true, label: "Augment Description" }) + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.equipped = new fields.BooleanField({ required: true, initial: false }) schema.isHelmet = new fields.BooleanField({ required: true, initial: false }) diff --git a/module/models/consumable.mjs b/module/models/consumable.mjs index 877c373..3e835a2 100644 --- a/module/models/consumable.mjs +++ b/module/models/consumable.mjs @@ -7,6 +7,7 @@ export default class PrismRPGConsumable extends foundry.abstract.TypeDataModel { schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.usesMax = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.uses = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 }) + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) schema.notes = new fields.HTMLField({ required: true }) diff --git a/module/models/equipment.mjs b/module/models/equipment.mjs index 8749565..ceb27ea 100644 --- a/module/models/equipment.mjs +++ b/module/models/equipment.mjs @@ -9,6 +9,7 @@ export default class PrismRPGEquipment extends foundry.abstract.TypeDataModel { schema.description = new fields.HTMLField({ required: true, textSearch: true }) schema.category = new fields.StringField({ required: true, initial: "coppercoin", choices: SYSTEM.EQUIPMENT_CATEGORIES }) + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.money = new fields.StringField({ required: true, initial: "coppercoin", choices: SYSTEM.MONEY }) diff --git a/module/models/loot.mjs b/module/models/loot.mjs index ac8ec83..004e702 100644 --- a/module/models/loot.mjs +++ b/module/models/loot.mjs @@ -5,6 +5,7 @@ export default class PrismRPGLoot extends foundry.abstract.TypeDataModel { const schema = {} schema.description = new fields.HTMLField({ required: true, textSearch: true }) + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }) schema.notes = new fields.HTMLField({ required: true }) diff --git a/module/models/shield.mjs b/module/models/shield.mjs index fab388b..42707f4 100644 --- a/module/models/shield.mjs +++ b/module/models/shield.mjs @@ -59,6 +59,7 @@ export default class PrismRPGShield extends foundry.abstract.TypeDataModel { }) // Equipment properties + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.money = new fields.StringField({ required: true, initial: "coppercoin", choices: SYSTEM.MONEY }) diff --git a/module/models/weapon.mjs b/module/models/weapon.mjs index e04adb0..24e324b 100644 --- a/module/models/weapon.mjs +++ b/module/models/weapon.mjs @@ -122,6 +122,7 @@ export default class PrismRPGWeapon extends foundry.abstract.TypeDataModel { defenseBonus: new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) }) + schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 }) schema.encLoad = new fields.NumberField({ required: true, initial: 0, min: 0 }) schema.cost = new fields.NumberField({ ...requiredInteger, required: true, initial: 0, min: 0 }) schema.money = new fields.StringField({ required: true, initial: "coppercoin", choices: SYSTEM.MONEY }) diff --git a/prism-rpg.mjs b/prism-rpg.mjs index 98b2776..811f7ed 100644 --- a/prism-rpg.mjs +++ b/prism-rpg.mjs @@ -90,7 +90,7 @@ Hooks.once("init", function () { // Status Effects — Afflictions & Imbuements CONFIG.statusEffects = [ - { id: "dead", name: "EFFECT.StatusDead", icon: "icons/svg/skull.svg" }, + { id: "dead", name: "EFFECT.StatusDead", img: "icons/svg/skull.svg" }, ...AFFLICTIONS, ...IMBUEMENTS, ] diff --git a/styles/character.less b/styles/character.less index 3aea457..300786a 100644 --- a/styles/character.less +++ b/styles/character.less @@ -648,6 +648,24 @@ overflow: hidden; text-overflow: ellipsis; } + .inv-qty { + display: flex; + align-items: center; + gap: 2px; + font-size: 11px; + min-width: 48px; + justify-content: center; + a { + font-size: 9px; + cursor: pointer; + color: rgba(0,0,0,0.4); + &:hover { color: rgba(0,0,0,0.8); } + } + span { + min-width: 16px; + text-align: center; + } + } .inv-enc, .inv-uses, .inv-capacity { font-size: 11px; color: #555; @@ -710,6 +728,24 @@ overflow: hidden; text-overflow: ellipsis; } + .inv-qty { + display: flex; + align-items: center; + gap: 2px; + font-size: 10px; + min-width: 40px; + justify-content: center; + a { + font-size: 8px; + cursor: pointer; + color: rgba(0,0,0,0.4); + &:hover { color: rgba(0,0,0,0.8); } + } + span { + min-width: 14px; + text-align: center; + } + } .inv-enc { font-size: 10px; color: #555; diff --git a/templates/armor.hbs b/templates/armor.hbs index a87f9e8..9cd05c7 100644 --- a/templates/armor.hbs +++ b/templates/armor.hbs @@ -46,6 +46,14 @@ label="PRISMRPG.Label.mrr" }} + {{! Quantity }} + {{formField + systemFields.quantity + value=system.quantity + localize=true + label="PRISMRPG.Label.quantity" + }} + {{! Encumbrance Load }} {{formField systemFields.encLoad diff --git a/templates/character-equipment.hbs b/templates/character-equipment.hbs index 408b491..d056d3d 100644 --- a/templates/character-equipment.hbs +++ b/templates/character-equipment.hbs @@ -33,7 +33,12 @@
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
@@ -60,7 +65,12 @@
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
@@ -86,8 +96,13 @@
{{item.name}}
+
+ + {{item.system.quantity}} + +
{{item.system.uses}}/{{item.system.usesMax}}
-
{{item.system.encLoad}}
+
{{mul item.system.encLoad item.system.quantity}}
@@ -111,7 +126,12 @@
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
@@ -137,7 +157,12 @@
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
@@ -163,7 +188,12 @@
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
@@ -203,7 +233,12 @@ {{item.type}}
{{item.name}}
-
{{item.system.encLoad}}
+
+ + {{item.system.quantity}} + +
+
{{mul item.system.encLoad item.system.quantity}}
diff --git a/templates/character-main.hbs b/templates/character-main.hbs index ec0dd65..f601f33 100644 --- a/templates/character-main.hbs +++ b/templates/character-main.hbs @@ -324,13 +324,10 @@
BURDEN
-
+
{{burdenUsed}} / {{burdenMax}} - {{#if excessBurden}} - (-{{excessBurden}} MR) - {{/if}}
{{#if isEditMode}} diff --git a/templates/consumable.hbs b/templates/consumable.hbs index 155d5eb..3611f7e 100644 --- a/templates/consumable.hbs +++ b/templates/consumable.hbs @@ -16,6 +16,7 @@ {{localize "PRISMRPG.Label.consumable"}} {{formField systemFields.usesMax value=system.usesMax localize=true}} {{formField systemFields.uses value=system.uses localize=true}} + {{formField systemFields.quantity value=system.quantity localize=true}} {{formField systemFields.encLoad value=system.encLoad localize=true}} {{formField systemFields.cost value=system.cost localize=true}} diff --git a/templates/equipment.hbs b/templates/equipment.hbs index 9ad86c3..cde1628 100644 --- a/templates/equipment.hbs +++ b/templates/equipment.hbs @@ -19,6 +19,7 @@ {{! Onglet Details }}
+ {{formField systemFields.quantity value=system.quantity localize=true}} {{formField systemFields.encLoad value=system.encLoad localize=true}} {{formField systemFields.cost value=system.cost localize=true}} {{formField systemFields.money value=system.money localize=true}} diff --git a/templates/loot.hbs b/templates/loot.hbs index f025ef1..609ec12 100644 --- a/templates/loot.hbs +++ b/templates/loot.hbs @@ -14,6 +14,7 @@
{{localize "PRISMRPG.Label.loot"}} + {{formField systemFields.quantity value=system.quantity localize=true}} {{formField systemFields.encLoad value=system.encLoad localize=true}} {{formField systemFields.cost value=system.cost localize=true}}
diff --git a/templates/shield.hbs b/templates/shield.hbs index 200679f..abf310a 100644 --- a/templates/shield.hbs +++ b/templates/shield.hbs @@ -68,6 +68,13 @@
+ {{formField + systemFields.quantity + value=system.quantity + localize=true + label="PRISMRPG.Label.quantity" + }} + {{formField systemFields.encLoad value=system.encLoad diff --git a/templates/weapon.hbs b/templates/weapon.hbs index 89fa0c6..4becd0b 100644 --- a/templates/weapon.hbs +++ b/templates/weapon.hbs @@ -92,6 +92,13 @@ label="PRISMRPG.Label.reloadAPC" }} + {{formField + systemFields.quantity + value=system.quantity + localize=true + label="PRISMRPG.Label.quantity" + }} + {{formField systemFields.encLoad value=system.encLoad