Add effects and tabs
This commit is contained in:
@@ -11,3 +11,4 @@ export { default as PrismRPGShieldSheet } from "./sheets/shield-sheet.mjs"
|
||||
export { default as PrismRPGMiracleSheet } from "./sheets/miracle-sheet.mjs"
|
||||
export { default as PrismRPGRaceSheet } from "./sheets/race-sheet.mjs"
|
||||
export { default as PrismRPGClassSheet } from "./sheets/class-sheet.mjs"
|
||||
export { default as PrismRPGCharacterPathSheet } from "./sheets/character-path-sheet.mjs"
|
||||
|
||||
@@ -31,6 +31,9 @@ export default class PrismRPGItemSheet extends HandlebarsApplicationMixin(foundr
|
||||
actions: {
|
||||
toggleSheet: PrismRPGItemSheet.#onToggleSheet,
|
||||
editImage: PrismRPGItemSheet.#onEditImage,
|
||||
"create-effect": PrismRPGItemSheet.#onCreateActiveEffect,
|
||||
"effect-edit": PrismRPGItemSheet.#onEffectEdit,
|
||||
"effect-delete": PrismRPGItemSheet.#onEffectDelete,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -65,6 +68,7 @@ export default class PrismRPGItemSheet extends HandlebarsApplicationMixin(foundr
|
||||
context.system = this.document.system
|
||||
context.source = this.document.toObject()
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
context.effectCategories = this.#prepareActiveEffectCategories(this.document.effects)
|
||||
context.isEditMode = this.isEditMode
|
||||
context.isPlayMode = this.isPlayMode
|
||||
context.isEditable = this.isEditable
|
||||
@@ -203,5 +207,99 @@ export default class PrismRPGItemSheet extends HandlebarsApplicationMixin(foundr
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare Active Effects organized by category (temporary, passive, inactive).
|
||||
* @param {ActiveEffect[]} effects The raw Active Effects collection
|
||||
* @returns {object} The categorized effects
|
||||
* @private
|
||||
*/
|
||||
#prepareActiveEffectCategories(effects) {
|
||||
// Define effect header categories
|
||||
const categories = {
|
||||
temporary: {
|
||||
type: "temporary",
|
||||
label: game.i18n.localize("PRISMRPG.Label.temporary"),
|
||||
effects: [],
|
||||
},
|
||||
passive: {
|
||||
type: "passive",
|
||||
label: game.i18n.localize("PRISMRPG.Label.passive"),
|
||||
effects: [],
|
||||
},
|
||||
inactive: {
|
||||
type: "inactive",
|
||||
label: game.i18n.localize("PRISMRPG.Label.inactive"),
|
||||
effects: [],
|
||||
},
|
||||
}
|
||||
|
||||
// Iterate over active effects, classifying them into categories
|
||||
for (let e of effects) {
|
||||
const effect = e.toObject()
|
||||
if (e.disabled) categories.inactive.effects.push(effect)
|
||||
else if (e.isTemporary) categories.temporary.effects.push(effect)
|
||||
else categories.passive.effects.push(effect)
|
||||
}
|
||||
return categories
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle creating a new Active Effect on the Item.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
* @private
|
||||
*/
|
||||
static async #onCreateActiveEffect(event, target) {
|
||||
const effectType = target.dataset.effectType
|
||||
let durationValue = undefined
|
||||
let disabled = false
|
||||
|
||||
if (effectType === "temporary") {
|
||||
durationValue = 10
|
||||
}
|
||||
if (effectType === "inactive") {
|
||||
disabled = true
|
||||
}
|
||||
|
||||
const effectData = {
|
||||
name: game.i18n.format("DOCUMENT.New", { type: game.i18n.localize("DOCUMENT.ActiveEffect") }),
|
||||
img: "icons/svg/aura.svg",
|
||||
origin: this.document.uuid,
|
||||
disabled: disabled,
|
||||
changes: [],
|
||||
duration: durationValue !== undefined ? { rounds: durationValue } : {},
|
||||
flags: {}
|
||||
}
|
||||
await this.document.createEmbeddedDocuments("ActiveEffect", [effectData])
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle editing an Active Effect on the Item.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
* @private
|
||||
*/
|
||||
static async #onEffectEdit(event, target) {
|
||||
const li = target.closest(".item")
|
||||
const effectId = li.dataset.itemId
|
||||
const effect = this.document.effects.get(effectId)
|
||||
if (!effect) return
|
||||
effect.sheet.render(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle deleting an Active Effect from the Item.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
* @private
|
||||
*/
|
||||
static async #onEffectDelete(event, target) {
|
||||
const li = target.closest(".item")
|
||||
const effectId = li.dataset.itemId
|
||||
const effect = this.document.effects.get(effectId)
|
||||
if (!effect) return
|
||||
await effect.delete()
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import PrismRPGItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class PrismRPGCharacterPathSheet extends PrismRPGItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character-path"],
|
||||
position: {
|
||||
width: 600,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["character-path-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-prism-rpg/templates/character-path.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "description",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
description: { id: "description", group: "primary", label: "PRISMRPG.Label.description" },
|
||||
effects: { id: "effects", group: "primary", label: "PRISMRPG.Label.effects" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.tabs = this.#getTabs()
|
||||
return context
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,9 +20,31 @@ export default class PrismRPGClassSheet extends PrismRPGItemSheet {
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "details",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
details: { id: "details", group: "primary", label: "PRISMRPG.Label.details" },
|
||||
description: { id: "description", group: "primary", label: "PRISMRPG.Label.description" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.tabs = this.#getTabs()
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedAttributeBonuses = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.attributeBonuses, { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.notes, { async: true })
|
||||
|
||||
@@ -19,9 +19,31 @@ export default class PrismRPGRaceSheet extends PrismRPGItemSheet {
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "details",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
details: { id: "details", group: "primary", label: "PRISMRPG.Label.details" },
|
||||
description: { id: "description", group: "primary", label: "PRISMRPG.Label.description" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.tabs = this.#getTabs()
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedRacialPassiveDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.racialPassiveDescription, { async: true })
|
||||
context.enrichedSubraceAbilityDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.subraceAbilityDescription, { async: true })
|
||||
|
||||
@@ -19,4 +19,32 @@ export default class PrismRPGRacialAbilitySheet extends PrismRPGItemSheet {
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "description",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
description: { id: "description", group: "primary", label: "PRISMRPG.Label.description" },
|
||||
effects: { id: "effects", group: "primary", label: "PRISMRPG.Label.effects" },
|
||||
}
|
||||
for (const v of Object.values(tabs)) {
|
||||
v.active = this.tabGroups[v.group] === v.id
|
||||
v.cssClass = v.active ? "active" : ""
|
||||
}
|
||||
return tabs
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.tabs = this.#getTabs()
|
||||
return context
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,7 +7,8 @@ export const defaultItemImg = {
|
||||
shield: "systems/fvtt-prism-rpg/assets/icons/icon_shield.webp",
|
||||
spell: "systems/fvtt-prism-rpg/assets/icons/icon_spell.webp",
|
||||
race: "systems/fvtt-prism-rpg/assets/icons/icon_race.webp",
|
||||
class: "systems/fvtt-prism-rpg/assets/icons/icon_class.webp"
|
||||
class: "systems/fvtt-prism-rpg/assets/icons/icon_class.webp",
|
||||
"character-path": "systems/fvtt-prism-rpg/assets/icons/icon_character_path.webp",
|
||||
}
|
||||
|
||||
export default class PrismRPGItem extends Item {
|
||||
|
||||
@@ -10,4 +10,5 @@ export { default as PrismRPGVulnerability } from "./vulnerability.mjs"
|
||||
export { default as PrismRPGEquipment } from "./equipment.mjs"
|
||||
export { default as PrismRPGMiracle } from "./miracle.mjs"
|
||||
export { default as PrismRPGRace } from "./race.mjs"
|
||||
export { default as PrismRPGClass } from "./class.mjs"
|
||||
export { default as PrismRPGClass } from "./class.mjs"
|
||||
export { default as PrismRPGCharacterPath } from "./character-path.mjs"
|
||||
@@ -0,0 +1,14 @@
|
||||
export default class PrismRPGCharacterPath extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["PRISMRPG.CharacterPath"]
|
||||
|
||||
}
|
||||
@@ -251,4 +251,15 @@ export default class PrismRPGUtils {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Preload Handlebars templates for partials
|
||||
* @returns {Promise}
|
||||
*/
|
||||
static async preloadHandlebarsTemplates() {
|
||||
const templatePaths = [
|
||||
'systems/fvtt-prism-rpg/templates/partial-item-effects.hbs',
|
||||
]
|
||||
return foundry.applications.handlebars.loadTemplates(templatePaths)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user