diff --git a/css/fvtt-prism-rpg.css b/css/fvtt-prism-rpg.css
index 34c2800..110e845 100644
--- a/css/fvtt-prism-rpg.css
+++ b/css/fvtt-prism-rpg.css
@@ -4102,6 +4102,109 @@ i.prismrpg {
font-family: var(--font-secondary);
font-size: calc(var(--font-size-standard) * 1.2);
}
+.chat-log .message-content .prismrpg-item-chat-card {
+ font-family: var(--font-primary);
+ border-radius: 4px;
+ overflow: hidden;
+ background: linear-gradient(135deg, rgba(0, 0, 0, 0.05) 0%, rgba(0, 0, 0, 0.02) 100%);
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ margin: 2px 0;
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-header {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ padding: 4px 8px;
+ background: linear-gradient(135deg, #2c2c2c 0%, #1a1a1a 100%);
+ border-bottom: 1px solid #444;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-header h3 {
+ margin: 0;
+ font-size: 0.95em;
+ font-weight: bold;
+ color: #d4af37;
+ text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
+ font-family: var(--font-secondary);
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-header .item-type {
+ padding: 1px 6px;
+ border-radius: 10px;
+ font-size: 0.65em;
+ font-weight: bold;
+ text-transform: uppercase;
+ background: rgba(255, 255, 255, 0.15);
+ color: #fff;
+ border: 1px solid rgba(255, 255, 255, 0.2);
+ letter-spacing: 0.3px;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-image {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding: 6px;
+ background: rgba(0, 0, 0, 0.1);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-image img {
+ max-width: 50px;
+ max-height: 50px;
+ border-radius: 3px;
+ border: 1px solid rgba(212, 175, 55, 0.3);
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
+ transition: transform 0.2s ease;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-image img:hover {
+ transform: scale(1.05);
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-description {
+ padding: 6px 8px;
+ color: #000;
+ font-size: 0.8em;
+ line-height: 1.3;
+ background: rgba(255, 255, 255, 0.8);
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ font-style: italic;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-details {
+ padding: 6px 8px;
+ display: flex;
+ flex-direction: column;
+ gap: 3px;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-details .item-detail {
+ display: flex;
+ align-items: center;
+ padding: 2px 6px;
+ background: rgba(255, 255, 255, 0.03);
+ border-left: 2px solid rgba(212, 175, 55, 0.5);
+ border-radius: 2px;
+ font-size: 0.8em;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-details .item-detail strong {
+ color: #d4af37;
+ margin-right: 6px;
+ min-width: 90px;
+ font-weight: bold;
+}
+.chat-log .message-content .prismrpg-item-chat-card .item-details .item-detail:nth-child(even) {
+ background: rgba(0, 0, 0, 0.05);
+}
+.chat-log .message-content .prismrpg-item-chat-card.weapon-item .item-header {
+ background: linear-gradient(135deg, #c41e3a 0%, #8b0000 100%);
+}
+.chat-log .message-content .prismrpg-item-chat-card.armor-item .item-header {
+ background: linear-gradient(135deg, #4a5cf7 0%, #2c3e9e 100%);
+}
+.chat-log .message-content .prismrpg-item-chat-card.spell-item .item-header {
+ background: linear-gradient(135deg, #9b59b6 0%, #6c3483 100%);
+}
+.chat-log .message-content .prismrpg-item-chat-card.skill-item .item-header {
+ background: linear-gradient(135deg, #16a085 0%, #0e6655 100%);
+}
+.chat-log .message-content .prismrpg-item-chat-card.equipment-item .item-header {
+ background: linear-gradient(135deg, #f39c12 0%, #b8730f 100%);
+}
.application.dialog.prismrpg {
color: var(--color-dark-1);
}
diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs
index 0992d44..caea6b1 100644
--- a/module/applications/sheets/character-sheet.mjs
+++ b/module/applications/sheets/character-sheet.mjs
@@ -18,10 +18,15 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
rollInitiative: PrismRPGCharacterSheet.#onRollInitiative,
armorHitPointsPlus: PrismRPGCharacterSheet.#onArmorHitPointsPlus,
armorHitPointsMinus: PrismRPGCharacterSheet.#onArmorHitPointsMinus,
+ armorPointsPlus: PrismRPGCharacterSheet.#onArmorPointsPlus,
+ armorPointsMinus: PrismRPGCharacterSheet.#onArmorPointsMinus,
+ actionPointsPlus: PrismRPGCharacterSheet.#onActionPointsPlus,
+ actionPointsMinus: PrismRPGCharacterSheet.#onActionPointsMinus,
manaPointsPlus: PrismRPGCharacterSheet.#onManaPointsPlus,
manaPointsMinus: PrismRPGCharacterSheet.#onManaPointsMinus,
hpPlus: PrismRPGCharacterSheet.#onHpPlus,
hpMinus: PrismRPGCharacterSheet.#onHpMinus,
+ postItemToChat: PrismRPGCharacterSheet.#onPostItemToChat,
},
}
@@ -158,43 +163,215 @@ export default class PrismRPGCharacterSheet extends PrismRPGActorSheet {
await this.document.system.rollInitiative()
}
- static #onArmorHitPointsPlus(event, target) {
+ static async #onArmorHitPointsPlus(event, target) {
let armorHP = this.actor.system.combat.armorHitPoints
armorHP += 1
this.actor.update({ "system.combat.armorHitPoints": armorHP })
}
- static #onArmorHitPointsMinus(event, target) {
+ static async #onArmorHitPointsMinus(event, target) {
let armorHP = this.actor.system.combat.armorHitPoints
armorHP -= 1
this.actor.update({ "system.combat.armorHitPoints": Math.max(armorHP, 0) })
}
- static #onManaPointsPlus(event, target) {
+ static async #onManaPointsPlus(event, target) {
let mana = this.actor.system.manaPoints.value
mana += 1
this.actor.update({ "system.manaPoints.value": Math.min(mana, this.actor.system.manaPoints.max) })
}
- static #onManaPointsMinus(event, target) {
+ static async #onManaPointsMinus(event, target) {
let mana = this.actor.system.manaPoints.value
mana -= 1
this.actor.update({ "system.manaPoints.value": Math.max(mana, 0) })
}
- static #onHpPlus(event, target) {
+ static async #onArmorPointsPlus(event, target) {
+ let armor = this.actor.system.armorPoints.value
+ armor += 1
+ this.actor.update({ "system.armorPoints.value": Math.min(armor, this.actor.system.armorPoints.max) })
+ }
+
+ static async #onArmorPointsMinus(event, target) {
+ let armor = this.actor.system.armorPoints.value
+ armor -= 1
+ this.actor.update({ "system.armorPoints.value": Math.max(armor, 0) })
+ }
+
+ static async#onActionPointsPlus(event, target) {
+ let actionPoints = this.actor.system.actionPoints.value
+ actionPoints += 1
+ this.actor.update({ "system.actionPoints.value": Math.min(actionPoints, this.actor.system.actionPoints.max) })
+ }
+
+ static async#onActionPointsMinus(event, target) {
+ let actionPoints = this.actor.system.actionPoints.value
+ actionPoints -= 1
+ this.actor.update({ "system.actionPoints.value": Math.max(actionPoints, 0) })
+ }
+
+ static async#onHpPlus(event, target) {
let hp = this.actor.system.hp.value
hp += 1
this.actor.update({ "system.hp.value": Math.min(hp, this.actor.system.hp.max) })
}
- static #onHpMinus(event, target) {
+ static async#onHpMinus(event, target) {
let hp = this.actor.system.hp.value
hp -= 1
this.actor.update({ "system.hp.value": Math.max(hp, 0) })
}
- static #onCreateEquipment(event, target) {
+ static async #onCreateEquipment(event, target) {
+ }
+
+ static async #onPostItemToChat(event, target) {
+ console.log("PRISM RPG | PostItemToChat action triggered", { event: event, target: target })
+
+ // Try to find the item element from the clicked target or its parents
+ let itemElement = null
+
+ // First try with the target (the actual clicked element)
+ if (event.target) {
+ itemElement = event.target.closest('[data-item-id]')
+ }
+
+ // If not found, try with currentTarget (the element with the action)
+ if (!itemElement && event.currentTarget) {
+ itemElement = event.currentTarget.closest('[data-item-id]')
+ }
+
+ // If still not found, try with the target parameter
+ if (!itemElement && target) {
+ itemElement = target.closest('[data-item-id]')
+ }
+
+ console.log("PRISM RPG | Found item element", { itemElement: itemElement })
+
+ if (!itemElement) {
+ console.warn("PRISM RPG | Could not find item element for posting to chat")
+ return
+ }
+
+ const itemId = itemElement.dataset.itemId
+
+ if (!itemId) {
+ console.warn("PRISM RPG | Item ID not found for posting to chat")
+ return
+ }
+
+ const item = this.actor.items.get(itemId)
+
+ if (!item) {
+ console.warn("PRISM RPG | Item not found for posting to chat", { itemId: itemId })
+ return
+ }
+
+ // Create a chat message with the item data
+ const speaker = ChatMessage.getSpeaker({ actor: this.actor })
+ const content = await this.formatItemForChat(item)
+
+ await ChatMessage.create({
+ content: content,
+ speaker: speaker,
+ })
+ }
+
+ async formatItemForChat(item) {
+ // Format the item data for chat display
+ const itemTypeClass = `${item.type}-item`
+ let htmlContent = `
+
+
+ `
+
+ // Add item image if available
+ if (item.img && !item.img.includes('icons/svg/mystery-man.svg')) {
+ htmlContent += `
`
+ }
+
+ // Add item description if available
+ if (item.system.description && item.system.description.trim() !== '') {
+ const enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(item.system.description, { async: true })
+ htmlContent += `
${enrichedDescription}
`
+ }
+
+ // Add specific item data based on item type
+ htmlContent += `
`
+
+ switch (item.type) {
+ case 'weapon':
+ htmlContent += `
+
Type: ${item.system.weaponType || 'Unknown'}
+
Damage: ${item.system.damage || 'N/A'}
+
APC: ${item.system.apc || 0}
+ `
+ if (item.system.damageType) {
+ const damageTypes = []
+ if (item.system.damageType.piercing) damageTypes.push('Piercing')
+ if (item.system.damageType.bludgeoning) damageTypes.push('Bludgeoning')
+ if (item.system.damageType.slashing) damageTypes.push('Slashing')
+ if (damageTypes.length > 0) {
+ htmlContent += `
Damage Type: ${damageTypes.join('/')}
`
+ }
+ }
+ break
+
+ case 'armor':
+ htmlContent += `
+
Armor Type: ${item.system.armorType || 'Unknown'}
+
Armor Points: ${item.system.armorPoints || 0}
+
APC: ${item.system.apc || 0}
+ `
+ break
+
+ case 'shield':
+ htmlContent += `
+
Shield Type: ${item.system.shieldType || 'Unknown'}
+
Armor Points: ${item.system.armorPoints || 0}
+
APC: ${item.system.apc || 0}
+ `
+ break
+
+ case 'skill':
+ htmlContent += `
+
Modifier: ${item.system.modifier || 0}
+
Core Skill: ${item.system.isCoreSkill ? 'Yes' : 'No'}
+ `
+ break
+
+ case 'spell':
+ htmlContent += `
+
Level: ${item.system.level || 'Unknown'}
+
Mana Cost: ${item.system.manaCost || 0}
+
Casting Time: ${item.system.castingTime || 'N/A'}
+ `
+ break
+
+ case 'miracle':
+ htmlContent += `
+
Prayer Time: ${item.system.prayerTime || 'N/A'}
+ `
+ break
+
+ case 'equipment':
+ htmlContent += `
+
Weight: ${item.system.weight || 'N/A'}
+ `
+ break
+
+ default:
+ // For other item types, just show basic info
+ htmlContent += `
Item Type: ${item.type}
`
+ }
+
+ htmlContent += `
`
+
+ return htmlContent
}
_onRender(context, options) {
diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs
index 56dadca..2af5daf 100644
--- a/module/documents/actor.mjs
+++ b/module/documents/actor.mjs
@@ -159,38 +159,14 @@ export default class PrismRPGActor extends Actor {
case "weapon-damage-medium":
case "weapon-attack": {
let weapon = this.items.find((i) => i.type === "weapon" && i.id === rollKey)
- let skill
- let skills = this.items.filter((i) => i.type === "skill" && i.name.toLowerCase() === weapon.name.toLowerCase())
- if (skills.length > 0) {
- skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
- } else {
- skills = this.items.filter((i) => i.type === "skill" && i.name.toLowerCase().replace(" skill", "") === weapon.name.toLowerCase())
- if (skills.length > 0) {
- skill = this.getBestWeaponClassSkill(skills, rollType, 1.0)
- } else {
- skills = this.items.filter((i) => i.type === "skill" && i.system.weaponClass === weapon.system.weaponClass)
- if (skills.length > 0) {
- skill = this.getBestWeaponClassSkill(skills, rollType, 0.5)
- } else {
- skills = this.items.filter((i) => i.type === "skill" && i.system.weaponClass.includes(SYSTEM.WEAPON_CATEGORIES[weapon.system.weaponClass]))
- if (skills.length > 0) {
- skill = this.getBestWeaponClassSkill(skills, rollType, 0.25)
- } else {
- ui.notifications.warn(game.i18n.localize("PRISMRPG.Notifications.skillNotFound"))
- return
- }
- }
- }
- }
- if (!weapon || !skill) {
- console.error("Weapon or skill not found", weapon, skill)
+ if (!weapon) {
+ console.error("Weapon not found", weapon, skill)
ui.notifications.warn(game.i18n.localize("PRISMRPG.Notifications.skillNotFound"))
return
}
// Create a plain object for rollTarget to ensure weapon data is preserved
rollTarget = {
- ...skill.toObject(),
weapon: weapon.toObject(),
rollKey: rollKey,
combat: foundry.utils.duplicate(this.system.combat),
diff --git a/module/documents/roll-old.mjs b/module/documents/roll-old.mjs
deleted file mode 100644
index caa2cc5..0000000
--- a/module/documents/roll-old.mjs
+++ /dev/null
@@ -1,1095 +0,0 @@
-import { SYSTEM } from "../config/system.mjs"
-import PrismRPGUtils from "../utils.mjs"
-
-export default class PrismRPGRoll extends Roll {
- /**
- * The HTML template path used to render dice checks of this type
- * @type {string}
- */
- static CHAT_TEMPLATE = "systems/fvtt-prism-rpg/templates/chat-message.hbs"
-
- get type() {
- return this.options.type
- }
-
- get titleFormula() {
- return this.options.titleFormula
- }
-
- get rollName() {
- return this.options.rollName
- }
-
- get target() {
- return this.options.target
- }
-
- get value() {
- return this.options.value
- }
-
- get treshold() {
- return this.options.treshold
- }
-
- get actorId() {
- return this.options.actorId
- }
-
- get actorName() {
- return this.options.actorName
- }
-
- get actorImage() {
- return this.options.actorImage
- }
-
- get modifier() {
- return this.options.modifier
- }
-
- get resultType() {
- return this.options.resultType
- }
-
- get isFailure() {
- return this.resultType === "failure"
- }
-
- get hasTarget() {
- return this.options.hasTarget
- }
-
- get targetName() {
- return this.options.targetName
- }
-
- get targetArmor() {
- return this.options.targetArmor
- }
-
- get targetMalus() {
- return this.options.targetMalus
- }
-
- get realDamage() {
- return this.options.realDamage
- }
-
- get rollTotal() {
- return this.options.rollTotal
- }
-
- get diceResults() {
- return this.options.diceResults
- }
-
- get rollTarget() {
- return this.options.rollTarget
- }
-
- get D30result() {
- return this.options.D30result
- }
-
- get badResult() {
- return this.options.badResult
- }
-
- get rollData() {
- return this.options.rollData
- }
-
- /**
- * Prompt the user with a dialog to configure and execute a roll (D&D 5e style).
- *
- * @param {Object} options Configuration options for the roll.
- * @param {string} options.rollType The type of roll being performed.
- * @param {Object} options.rollTarget The target of the roll.
- * @param {string} options.actorId The ID of the actor performing the roll.
- * @param {string} options.actorName The name of the actor performing the roll.
- * @param {string} options.actorImage The image of the actor performing the roll.
- * @param {boolean} options.hasTarget Whether the roll has a target.
- * @param {Object} options.data Additional data for the roll.
- *
- * @returns {Promise