Fix actions/tour
This commit is contained in:
8
module/applications/_module.mjs
Normal file
8
module/applications/_module.mjs
Normal file
@@ -0,0 +1,8 @@
|
||||
export { default as FTLNomadWeaponSheet } from "./sheets/weapon-sheet.mjs"
|
||||
export { default as FTLNomadArmorSheet } from "./sheets/armor-sheet.mjs"
|
||||
export { default as FTLNomadVehicleSheet } from "./sheets/vehicle-sheet.mjs"
|
||||
export { default as FTLNomadPsionicSheet } from "./sheets/psionic-sheet.mjs"
|
||||
export { default as FTLNomadLanguageSheet } from "./sheets/language-sheet.mjs"
|
||||
export { default as FTLNomadTalentSheet } from "./sheets/talent-sheet.mjs"
|
||||
export { default as FTLNomadNPCSheet } from "./sheets/npc-sheet.mjs"
|
||||
|
||||
27
module/applications/sheets/armor-sheet.mjs
Normal file
27
module/applications/sheets/armor-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadArmorSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["armor"],
|
||||
position: {
|
||||
width: 400,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["armor-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/armor.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
230
module/applications/sheets/base-actor-sheet.mjs
Normal file
230
module/applications/sheets/base-actor-sheet.mjs
Normal file
@@ -0,0 +1,230 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
export default class FTLNomadActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||
/**
|
||||
* Different sheet modes.r
|
||||
* @enum {number}
|
||||
*/
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-ftl-nomad", "actor"],
|
||||
position: {
|
||||
width: 1400,
|
||||
height: "auto",
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
dragDrop: [{ dragSelector: '[data-drag="true"], .rollable', dropSelector: null }],
|
||||
actions: {
|
||||
editImage: CthulhuEternalActorSheet.#onEditImage,
|
||||
toggleSheet: CthulhuEternalActorSheet.#onToggleSheet,
|
||||
edit: CthulhuEternalActorSheet.#onItemEdit,
|
||||
delete: CthulhuEternalActorSheet.#onItemDelete,
|
||||
updateCheckboxArray: CthulhuEternalActorSheet.#onUpdateCheckboxArray,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* The current sheet mode.
|
||||
* @type {number}
|
||||
*/
|
||||
_sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Play' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPlayMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Edit' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isEditMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
actor: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isEditable: this.isEditable,
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
// Add listeners to rollable elements
|
||||
const rollables = this.element.querySelectorAll(".rollable")
|
||||
rollables.forEach((d) => d.addEventListener("click", this._onRoll.bind(this)))
|
||||
}
|
||||
|
||||
// #region Drag-and-Drop Workflow
|
||||
/**
|
||||
* Create drag-and-drop workflow handlers for this Application
|
||||
* @returns {DragDrop[]} An array of DragDrop handlers
|
||||
* @private
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return this.options.dragDrop.map((d) => {
|
||||
d.permissions = {
|
||||
dragstart: this._canDragStart.bind(this),
|
||||
drop: this._canDragDrop.bind(this),
|
||||
}
|
||||
d.callbacks = {
|
||||
dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this),
|
||||
}
|
||||
return new DragDrop(d)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback actions which occur when a dragged element is dropped on a target.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
* @protected
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Define whether a user is able to begin a dragstart workflow for a given drag selector
|
||||
* @param {string} selector The candidate HTML selector for dragging
|
||||
* @returns {boolean} Can the current user drag this selector?
|
||||
* @protected
|
||||
*/
|
||||
_canDragStart(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
|
||||
* @param {string} selector The candidate HTML selector for the drop target
|
||||
* @returns {boolean} Can the current user drop on this selector?
|
||||
* @protected
|
||||
*/
|
||||
_canDragDrop(selector) {
|
||||
return true //this.isEditable && this.document.isOwner
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback actions which occur when a dragged element is over a drop target.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
* @protected
|
||||
*/
|
||||
_onDragOver(event) {}
|
||||
|
||||
async _onDropItem(item) {
|
||||
console.log("Dropped item", item)
|
||||
let itemData = item.toObject()
|
||||
await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false })
|
||||
}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Actions
|
||||
/**
|
||||
* Handle toggling between Edit and Play mode.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
*/
|
||||
static #onToggleSheet(event, target) {
|
||||
const modes = this.constructor.SHEET_MODES
|
||||
this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
static #onUpdateCheckboxArray(event, target) {
|
||||
console.log("Update checkbox array", event, target)
|
||||
let arrayName = target.dataset.name
|
||||
let arrayIdx = Number(target.dataset.index)
|
||||
let dataPath = `system.san.${arrayName}`
|
||||
let tab = foundry.utils.duplicate(this.document.system.san[arrayName])
|
||||
tab[arrayIdx] = target.checked
|
||||
this.actor.update( { [dataPath]: tab } )
|
||||
// Dump
|
||||
console.log("Array name", arrayName, arrayIdx, target.checked, dataPath)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle changing a Document's image.
|
||||
*
|
||||
* @this CthulhuEternalCharacterSheet
|
||||
* @param {PointerEvent} event The originating click event
|
||||
* @param {HTMLElement} target The capturing HTML element which defined a [data-action]
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
static async #onEditImage(event, target) {
|
||||
const attr = target.dataset.edit
|
||||
const current = foundry.utils.getProperty(this.document, attr)
|
||||
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: "image",
|
||||
redirectToRoot: img ? [img] : [],
|
||||
callback: (path) => {
|
||||
this.document.update({ [attr]: path })
|
||||
},
|
||||
top: this.position.top + 40,
|
||||
left: this.position.left + 10,
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit an existing item within the Actor
|
||||
* Start with the uuid, if it's not found, fallback to the id (as Embedded item in the actor)
|
||||
* @this CthulhuEternalCharacterSheet
|
||||
* @param {PointerEvent} event The originating click event
|
||||
* @param {HTMLElement} target the capturing HTML element which defined a [data-action]
|
||||
*/
|
||||
static async #onItemEdit(event, target) {
|
||||
const id = target.getAttribute("data-item-id")
|
||||
const uuid = target.getAttribute("data-item-uuid")
|
||||
let item
|
||||
item = await fromUuid(uuid)
|
||||
if (!item) item = this.document.items.get(id)
|
||||
if (!item) return
|
||||
item.sheet.render(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an existing talent within the Actor
|
||||
* Use the uuid to display the talent sheet
|
||||
* @param {PointerEvent} event The originating click event
|
||||
* @param {HTMLElement} target the capturing HTML element which defined a [data-action]
|
||||
*/
|
||||
static async #onItemDelete(event, target) {
|
||||
const itemUuid = target.getAttribute("data-item-uuid")
|
||||
const item = await fromUuid(itemUuid)
|
||||
await item.deleteDialog()
|
||||
}
|
||||
|
||||
// #endregion
|
||||
}
|
||||
193
module/applications/sheets/base-item-sheet.mjs
Normal file
193
module/applications/sheets/base-item-sheet.mjs
Normal file
@@ -0,0 +1,193 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
export default class FTLNomadItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
/**
|
||||
* Different sheet modes.
|
||||
* @enum {number}
|
||||
*/
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-ftl-nomad", "item"],
|
||||
position: {
|
||||
width: 600,
|
||||
height: "auto",
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
|
||||
actions: {
|
||||
toggleSheet: CthulhuEternalItemSheet.#onToggleSheet,
|
||||
editImage: CthulhuEternalItemSheet.#onEditImage,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* The current sheet mode.
|
||||
* @type {number}
|
||||
*/
|
||||
_sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Play' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPlayMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Edit' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isEditMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isEditable: this.isEditable,
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
}
|
||||
|
||||
// #region Drag-and-Drop Workflow
|
||||
/**
|
||||
* Create drag-and-drop workflow handlers for this Application
|
||||
* @returns {DragDrop[]} An array of DragDrop handlers
|
||||
* @private
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return this.options.dragDrop.map((d) => {
|
||||
d.permissions = {
|
||||
dragstart: this._canDragStart.bind(this),
|
||||
drop: this._canDragDrop.bind(this),
|
||||
}
|
||||
d.callbacks = {
|
||||
dragstart: this._onDragStart.bind(this),
|
||||
dragover: this._onDragOver.bind(this),
|
||||
drop: this._onDrop.bind(this),
|
||||
}
|
||||
return new DragDrop(d)
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether a user is able to begin a dragstart workflow for a given drag selector
|
||||
* @param {string} selector The candidate HTML selector for dragging
|
||||
* @returns {boolean} Can the current user drag this selector?
|
||||
* @protected
|
||||
*/
|
||||
_canDragStart(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
/**
|
||||
* Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
|
||||
* @param {string} selector The candidate HTML selector for the drop target
|
||||
* @returns {boolean} Can the current user drop on this selector?
|
||||
* @protected
|
||||
*/
|
||||
_canDragDrop(selector) {
|
||||
return this.isEditable && this.document.isOwner
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback actions which occur at the beginning of a drag start workflow.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
* @protected
|
||||
*/
|
||||
_onDragStart(event) {
|
||||
const el = event.currentTarget
|
||||
if ("link" in event.target.dataset) return
|
||||
|
||||
// Extract the data you need
|
||||
let dragData = null
|
||||
|
||||
if (!dragData) return
|
||||
|
||||
// Set data transfer
|
||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback actions which occur when a dragged element is over a drop target.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
* @protected
|
||||
*/
|
||||
_onDragOver(event) {}
|
||||
|
||||
/**
|
||||
* Callback actions which occur when a dragged element is dropped on a target.
|
||||
* @param {DragEvent} event The originating DragEvent
|
||||
* @protected
|
||||
*/
|
||||
async _onDrop(event) {}
|
||||
|
||||
// #endregion
|
||||
|
||||
// #region Actions
|
||||
/**
|
||||
* Handle toggling between Edit and Play mode.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
*/
|
||||
static #onToggleSheet(event, target) {
|
||||
const modes = this.constructor.SHEET_MODES
|
||||
this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle changing a Document's image.
|
||||
*
|
||||
* @this CthulhuEternalCharacterSheet
|
||||
* @param {PointerEvent} event The originating click event
|
||||
* @param {HTMLElement} target The capturing HTML element which defined a [data-action]
|
||||
* @returns {Promise}
|
||||
* @private
|
||||
*/
|
||||
static async #onEditImage(event, target) {
|
||||
const attr = target.dataset.edit
|
||||
const current = foundry.utils.getProperty(this.document, attr)
|
||||
const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: "image",
|
||||
redirectToRoot: img ? [img] : [],
|
||||
callback: (path) => {
|
||||
this.document.update({ [attr]: path })
|
||||
},
|
||||
top: this.position.top + 40,
|
||||
left: this.position.left + 10,
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
// #endregion
|
||||
}
|
||||
252
module/applications/sheets/character-sheet.mjs
Normal file
252
module/applications/sheets/character-sheet.mjs
Normal file
@@ -0,0 +1,252 @@
|
||||
import FTLNomadActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class FTLNomadCharacterSheet extends FTLNomadActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character"],
|
||||
position: {
|
||||
width: 860,
|
||||
height: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["character-content"],
|
||||
},
|
||||
actions: {
|
||||
setBP: FTLNomadCharacterSheet.#onSetBP,
|
||||
createGear: FTLNomadCharacterSheet.#onCreateGear,
|
||||
createArmor: FTLNomadCharacterSheet.#onCreateArmor,
|
||||
createWeapon: FTLNomadCharacterSheet.#onCreateWeapon,
|
||||
createBond: FTLNomadCharacterSheet.#onCreateBond,
|
||||
createInjury: FTLNomadCharacterSheet.#onCreateInjury,
|
||||
createMentalDisorder: FTLNomadCharacterSheet.#onCreateMentalDisorder,
|
||||
createMotivation: FTLNomadCharacterSheet.#onCreateMotivation,
|
||||
createSkill: FTLNomadCharacterSheet.#onCreateSkill,
|
||||
createRitual: FTLNomadCharacterSheet.#onCreateRitual,
|
||||
createTome: FTLNomadCharacterSheet.#onCreateTome,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-ftl-nomad/templates/protagonist-main.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
skills: {
|
||||
template: "systems/fvtt-ftl-nomad/templates/protagonist-skills.hbs",
|
||||
},
|
||||
status: {
|
||||
template: "systems/fvtt-ftl-nomad/templates/protagonist-status.hbs",
|
||||
},
|
||||
equipment: {
|
||||
template: "systems/fvtt-ftl-nomad/templates/protagonist-equipment.hbs",
|
||||
},
|
||||
biography: {
|
||||
template: "systems/fvtt-ftl-nomad/templates/protagonist-biography.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "skills",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.skills" },
|
||||
status: { id: "status", group: "sheet", icon: "fa-solid fa-file-waveform", label: "FTLNOMAD.Label.status" },
|
||||
equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.equipment" },
|
||||
biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "FTLNOMAD.Label.biography" },
|
||||
}
|
||||
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 TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
|
||||
|
||||
context.tooltipsCharacteristic = {
|
||||
str: game.i18n.localize("FTLNOMAD.Characteristic.Str"),
|
||||
dex: game.i18n.localize("FTLNOMAD.Characteristic.Dex"),
|
||||
con: game.i18n.localize("FTLNOMAD.Characteristic.Con"),
|
||||
int: game.i18n.localize("FTLNOMAD.Characteristic.Int"),
|
||||
pow: game.i18n.localize("FTLNOMAD.Characteristic.Pow"),
|
||||
cha: game.i18n.localize("FTLNOMAD.Characteristic.Cha")
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
break
|
||||
case "skills":
|
||||
context.tab = context.tabs.skills
|
||||
context.skills = doc.itemTypes.skill
|
||||
context.skills.sort((a, b) => a.name.localeCompare(b.name))
|
||||
break
|
||||
case "equipment":
|
||||
context.tab = context.tabs.equipment
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.armors = doc.itemTypes.armor
|
||||
context.armors.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.gears = doc.itemTypes.gear
|
||||
context.gears.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.rituals = doc.itemTypes.ritual
|
||||
context.rituals.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.tomes = doc.itemTypes.tome
|
||||
context.tomes.sort((a, b) => a.name.localeCompare(b.name))
|
||||
break
|
||||
case "status":
|
||||
context.tab = context.tabs.status
|
||||
context.injuries = doc.itemTypes.injury
|
||||
context.injuries.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.mentaldisorders = doc.itemTypes.mentaldisorder
|
||||
context.mentaldisorders.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.motivations = doc.itemTypes.motivation
|
||||
context.motivations.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.bonds = doc.itemTypes.bond
|
||||
context.bonds.sort((a, b) => a.name.localeCompare(b.name))
|
||||
break
|
||||
case "biography":
|
||||
context.tab = context.tabs.biography
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attack item directly from the sheet and embeds it into the document.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
*/
|
||||
static #onSetBP(event, target) {
|
||||
this.document.system.setBP()
|
||||
}
|
||||
|
||||
static #onCreateGear(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newGear"), type: "gear" }])
|
||||
}
|
||||
|
||||
static #onCreateWeapon(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newWeapon"), type: "weapon" }])
|
||||
}
|
||||
|
||||
static #onCreateArmor(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newArmor"), type: "armor" }])
|
||||
}
|
||||
|
||||
static #onCreateBond(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newBond"), type: "bond" }])
|
||||
}
|
||||
|
||||
static #onCreateInjury(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newInjury"), type: "injury" }])
|
||||
}
|
||||
|
||||
static #onCreateMentalDisorder(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newMentalDisorder"), type: "mentaldisorder" }])
|
||||
}
|
||||
|
||||
static #onCreateMotivation(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newMotivation"), type: "motivation" }])
|
||||
}
|
||||
|
||||
static #onCreateSkill(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newSkill"), type: "skill" }])
|
||||
}
|
||||
|
||||
static #onCreateRitual(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newRitual"), type: "ritual" }])
|
||||
}
|
||||
|
||||
static #onCreateTome(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newTome"), type: "tome" }])
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the roll action triggered by user interaction.
|
||||
*
|
||||
* @param {PointerEvent} event The event object representing the user interaction.
|
||||
* @param {HTMLElement} target The target element that triggered the roll.
|
||||
*
|
||||
* @returns {Promise<void>} A promise that resolves when the roll action is complete.
|
||||
*
|
||||
* @throws {Error} Throws an error if the roll type is not recognized.
|
||||
*
|
||||
* @description This method checks the current mode (edit or not) and determines the type of roll
|
||||
* (save, resource, or damage) based on the target element's data attributes. It retrieves the
|
||||
* corresponding value from the document's system and performs the roll.
|
||||
*/
|
||||
async _onRoll(event, target) {
|
||||
const rollType = $(event.currentTarget).data("roll-type")
|
||||
let item
|
||||
let li
|
||||
// Debug : console.log(">>>>", event, target, rollType)
|
||||
// Deprecated : if (this.isEditMode) return
|
||||
switch (rollType) {
|
||||
case "resource":
|
||||
item = foundry.utils.duplicate(this.actor.system.resources)
|
||||
item.name = game.i18n.localize(`FTLNOMAD.Label.Resources`)
|
||||
item.targetScore = item.permanentRating
|
||||
break
|
||||
case "char":
|
||||
let charId = $(event.currentTarget).data("char-id")
|
||||
item = foundry.utils.duplicate(this.actor.system.characteristics[charId])
|
||||
item.name = game.i18n.localize(`FTLNOMAD.Label.${charId}Long`)
|
||||
item.targetScore = item.value * 5
|
||||
break
|
||||
case "skill":
|
||||
li = $(event.currentTarget).parents(".item");
|
||||
item = this.actor.items.get(li.data("item-id"));
|
||||
break
|
||||
case "weapon":
|
||||
case "damage":
|
||||
li = $(event.currentTarget).parents(".item");
|
||||
item = this.actor.items.get(li.data("item-id"));
|
||||
item.damageBonus = this.actor.system.damageBonus
|
||||
break
|
||||
case "san":
|
||||
item = foundry.utils.duplicate(this.actor.system.san)
|
||||
item.name = game.i18n.localize("FTLNOMAD.Label.SAN")
|
||||
item.targetScore = item.value
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unknown roll type ${rollType}`)
|
||||
}
|
||||
await this.document.system.roll(rollType, item)
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = TextEditor.getDragEventData(event)
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
const item = await fromUuid(data.uuid)
|
||||
return super._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
27
module/applications/sheets/equipment-sheet.mjs
Normal file
27
module/applications/sheets/equipment-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadEquipmentSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["equipment"],
|
||||
position: {
|
||||
width: 600,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["equipment-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/equipment.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
28
module/applications/sheets/language-sheet.mjs
Normal file
28
module/applications/sheets/language-sheet.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadLanguageSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["language"],
|
||||
position: {
|
||||
width: 600,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["language-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/language.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
166
module/applications/sheets/npc.mjs
Normal file
166
module/applications/sheets/npc.mjs
Normal file
@@ -0,0 +1,166 @@
|
||||
import FTLNomadActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class FTLNomadNPCSheet extends FTLNomadActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["npc"],
|
||||
position: {
|
||||
width: 860,
|
||||
height: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["npc-content"],
|
||||
},
|
||||
actions: {
|
||||
createArmor: FTLNomadNPCSheet.#onCreateArmor,
|
||||
createWeapon: FTLNomadNPCSheet.#onCreateWeapon,
|
||||
createSkill: FTLNomadNPCSheet.#onCreateSkill,
|
||||
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/npc-main.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
skills: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/npc-skills.hbs",
|
||||
},
|
||||
biography: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/npc-biography.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "skills",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.skills" },
|
||||
biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "FTLNOMAD.Label.biography" },
|
||||
}
|
||||
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 TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
break
|
||||
case "skills":
|
||||
context.tab = context.tabs.skills
|
||||
context.skills = doc.itemTypes.skill
|
||||
context.skills.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.weapons.sort((a, b) => a.name.localeCompare(b.name))
|
||||
context.armors = doc.itemTypes.armor
|
||||
context.armors.sort((a, b) => a.name.localeCompare(b.name))
|
||||
break
|
||||
case "biography":
|
||||
context.tab = context.tabs.biography
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attack item directly from the sheet and embeds it into the document.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
*/
|
||||
static #onCreateWeapon(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newWeapon"), type: "weapon" }])
|
||||
}
|
||||
|
||||
static #onCreateArmor(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newArmor"), type: "armor" }])
|
||||
}
|
||||
|
||||
static #onCreateSkill(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newSkill"), type: "skill" }])
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the roll action triggered by user interaction.
|
||||
*
|
||||
* @param {PointerEvent} event The event object representing the user interaction.
|
||||
* @param {HTMLElement} target The target element that triggered the roll.
|
||||
*
|
||||
* @returns {Promise<void>} A promise that resolves when the roll action is complete.
|
||||
*
|
||||
* @throws {Error} Throws an error if the roll type is not recognized.
|
||||
*
|
||||
* @description This method checks the current mode (edit or not) and determines the type of roll
|
||||
* (save, resource, or damage) based on the target element's data attributes. It retrieves the
|
||||
* corresponding value from the document's system and performs the roll.
|
||||
*/
|
||||
async _onRoll(event, target) {
|
||||
const rollType = $(event.currentTarget).data("roll-type")
|
||||
let item
|
||||
let li
|
||||
// Debug : console.log(">>>>", event, target, rollType)
|
||||
// Deprecated : if (this.isEditMode) return
|
||||
switch (rollType) {
|
||||
case "char":
|
||||
let charId = $(event.currentTarget).data("char-id")
|
||||
item = foundry.utils.duplicate(this.actor.system.characteristics[charId])
|
||||
item.name = game.i18n.localize(`FTLNOMAD.Label.${charId}Long`)
|
||||
item.targetScore = item.value * 5
|
||||
break
|
||||
case "skill":
|
||||
li = $(event.currentTarget).parents(".item");
|
||||
item = this.actor.items.get(li.data("item-id"));
|
||||
break
|
||||
case "weapon":
|
||||
case "damage":
|
||||
li = $(event.currentTarget).parents(".item");
|
||||
item = this.actor.items.get(li.data("item-id"));
|
||||
item.damageBonus = this.actor.system.damageBonus
|
||||
break
|
||||
default:
|
||||
throw new Error(`Unknown roll type ${rollType}`)
|
||||
}
|
||||
await this.document.system.roll(rollType, item)
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = TextEditor.getDragEventData(event)
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
const item = await fromUuid(data.uuid)
|
||||
return super._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
28
module/applications/sheets/psionic-sheet.mjs
Normal file
28
module/applications/sheets/psionic-sheet.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadPsionicSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["psionic"],
|
||||
position: {
|
||||
width: 600,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["psionic-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/psionic.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
28
module/applications/sheets/talent-sheet.mjs
Normal file
28
module/applications/sheets/talent-sheet.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadTalentSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["talent"],
|
||||
position: {
|
||||
width: 600,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["talent-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/talent.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
117
module/applications/sheets/vehicle-sheet.mjs
Normal file
117
module/applications/sheets/vehicle-sheet.mjs
Normal file
@@ -0,0 +1,117 @@
|
||||
import FTLNomadActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class FTLNomadVehicleSheet extends FTLNomadActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["vehicle"],
|
||||
position: {
|
||||
width: 680,
|
||||
height: 540,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["vehicle-content"],
|
||||
},
|
||||
actions: {
|
||||
createGear: CthulhuEternalVehicleSheet.#onCreateGear,
|
||||
createWeapon: CthulhuEternalVehicleSheet.#onCreateWeapon,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-main.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
equipment: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-equipment.hbs",
|
||||
},
|
||||
description: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/vehicle-description.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "equipment",
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare an array of form header tabs.
|
||||
* @returns {Record<string, Partial<ApplicationTab>>}
|
||||
*/
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "CTHULHUETERNAL.Label.equipment" },
|
||||
description: { id: "description", group: "sheet", icon: "fa-solid fa-book", label: "CTHULHUETERNAL.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 TextEditor.enrichHTML(this.document.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
|
||||
|
||||
return context
|
||||
}
|
||||
|
||||
_generateTooltip(type, target) {
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
break
|
||||
case "equipment":
|
||||
context.tab = context.tabs.equipment
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.gears = doc.itemTypes.gear
|
||||
break
|
||||
case "description":
|
||||
context.tab = context.tabs.description
|
||||
context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new attack item directly from the sheet and embeds it into the document.
|
||||
* @param {Event} event The initiating click event.
|
||||
* @param {HTMLElement} target The current target of the event listener.
|
||||
*/
|
||||
static #onCreateGear(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
|
||||
}
|
||||
|
||||
static #onCreateWeapon(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newWeapon"), type: "weapon" }])
|
||||
}
|
||||
|
||||
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = TextEditor.getDragEventData(event)
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
const item = await fromUuid(data.uuid)
|
||||
return super._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
21
module/applications/sheets/weapon-sheet.mjs
Normal file
21
module/applications/sheets/weapon-sheet.mjs
Normal file
@@ -0,0 +1,21 @@
|
||||
import FTLNomadItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class FTLNomadWeaponSheet extends FTLNomadItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["weapon"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["weapon-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-cthulhu-eternal/templates/weapon.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user