Initial import
This commit is contained in:
13
module/applications/_module.mjs
Normal file
13
module/applications/_module.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
export { default as OathHammerCharacterSheet } from "./sheets/character-sheet.mjs"
|
||||
export { default as OathHammerNPCSheet } from "./sheets/npc-sheet.mjs"
|
||||
export { default as OathHammerWeaponSheet } from "./sheets/weapon-sheet.mjs"
|
||||
export { default as OathHammerArmorSheet } from "./sheets/armor-sheet.mjs"
|
||||
export { default as OathHammerShieldSheet } from "./sheets/shield-sheet.mjs"
|
||||
export { default as OathHammerAmmunitionSheet } from "./sheets/ammunition-sheet.mjs"
|
||||
export { default as OathHammerEquipmentSheet } from "./sheets/equipment-sheet.mjs"
|
||||
export { default as OathHammerSpellSheet } from "./sheets/spell-sheet.mjs"
|
||||
export { default as OathHammerMiracleSheet } from "./sheets/miracle-sheet.mjs"
|
||||
export { default as OathHammerMagicItemSheet } from "./sheets/magic-item-sheet.mjs"
|
||||
export { default as OathHammerAbilitySheet } from "./sheets/ability-sheet.mjs"
|
||||
export { default as OathHammerOathSheet } from "./sheets/oath-sheet.mjs"
|
||||
export { default as OathHammerConditionSheet } from "./sheets/condition-sheet.mjs"
|
||||
27
module/applications/sheets/ability-sheet.mjs
Normal file
27
module/applications/sheets/ability-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerAbilitySheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["ability"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["ability-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/ability-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/ammunition-sheet.mjs
Normal file
27
module/applications/sheets/ammunition-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerAmmunitionSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["ammunition"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["ammunition-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/ammunition-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/armor-sheet.mjs
Normal file
27
module/applications/sheets/armor-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerArmorSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["armor"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["armor-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/armor-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
138
module/applications/sheets/base-actor-sheet.mjs
Normal file
138
module/applications/sheets/base-actor-sheet.mjs
Normal file
@@ -0,0 +1,138 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
export default class OathHammerActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["oathhammer", "actor"],
|
||||
position: {
|
||||
width: 900,
|
||||
height: "auto",
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
dragDrop: [{ dragSelector: '[data-drag="true"], .rollable', dropSelector: null }],
|
||||
actions: {
|
||||
editImage: OathHammerActorSheet.#onEditImage,
|
||||
toggleSheet: OathHammerActorSheet.#onToggleSheet,
|
||||
edit: OathHammerActorSheet.#onItemEdit,
|
||||
delete: OathHammerActorSheet.#onItemDelete,
|
||||
},
|
||||
}
|
||||
|
||||
_sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
|
||||
get isPlayMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
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(),
|
||||
isEditMode: this.isEditMode,
|
||||
isPlayMode: this.isPlayMode,
|
||||
isEditable: this.isEditable,
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
}
|
||||
|
||||
#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 foundry.applications.ux.DragDrop.implementation(d)
|
||||
})
|
||||
}
|
||||
|
||||
async _onDrop(event) {}
|
||||
|
||||
_canDragStart(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
_canDragDrop(selector) {
|
||||
return this.isEditable && this.document.isOwner
|
||||
}
|
||||
|
||||
_onDragStart(event) {
|
||||
if ("link" in event.target.dataset) return
|
||||
}
|
||||
|
||||
_onDragOver(event) {}
|
||||
|
||||
async _onDropItem(item) {
|
||||
const itemData = item.toObject()
|
||||
await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false })
|
||||
}
|
||||
|
||||
static #onToggleSheet(event, target) {
|
||||
const modes = this.constructor.SHEET_MODES
|
||||
this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
|
||||
static async #onItemEdit(event, target) {
|
||||
const id = target.getAttribute("data-item-id")
|
||||
const uuid = target.getAttribute("data-item-uuid")
|
||||
let item = await fromUuid(uuid)
|
||||
if (!item) item = this.document.items.get(id)
|
||||
if (!item) return
|
||||
item.sheet.render(true)
|
||||
}
|
||||
|
||||
static async #onItemDelete(event, target) {
|
||||
const itemUuid = target.getAttribute("data-item-uuid")
|
||||
const item = await fromUuid(itemUuid)
|
||||
await item.deleteDialog()
|
||||
}
|
||||
}
|
||||
119
module/applications/sheets/base-item-sheet.mjs
Normal file
119
module/applications/sheets/base-item-sheet.mjs
Normal file
@@ -0,0 +1,119 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
export default class OathHammerItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["oathhammer", "item"],
|
||||
position: {
|
||||
width: 600,
|
||||
height: "auto",
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
|
||||
actions: {
|
||||
toggleSheet: OathHammerItemSheet.#onToggleSheet,
|
||||
editImage: OathHammerItemSheet.#onEditImage,
|
||||
},
|
||||
}
|
||||
|
||||
_sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
|
||||
get isPlayMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
get isEditMode() {
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.fields = this.document.schema.fields
|
||||
context.systemFields = this.document.system.schema.fields
|
||||
context.item = this.document
|
||||
context.system = this.document.system
|
||||
context.source = this.document.toObject()
|
||||
context.isEditMode = this.isEditMode
|
||||
context.isPlayMode = this.isPlayMode
|
||||
context.isEditable = this.isEditable
|
||||
if (this.document.system.description !== undefined) {
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description ?? "", { async: true })
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
this.#dragDrop.forEach((d) => d.bind(this.element))
|
||||
}
|
||||
|
||||
#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 foundry.applications.ux.DragDrop.implementation(d)
|
||||
})
|
||||
}
|
||||
|
||||
_canDragStart(selector) {
|
||||
return this.isEditable
|
||||
}
|
||||
|
||||
_canDragDrop(selector) {
|
||||
return this.isEditable && this.document.isOwner
|
||||
}
|
||||
|
||||
_onDragStart(event) {
|
||||
if ("link" in event.target.dataset) return
|
||||
}
|
||||
|
||||
_onDragOver(event) {}
|
||||
|
||||
async _onDrop(event) {}
|
||||
|
||||
static #onToggleSheet(event, target) {
|
||||
const modes = this.constructor.SHEET_MODES
|
||||
this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
136
module/applications/sheets/character-sheet.mjs
Normal file
136
module/applications/sheets/character-sheet.mjs
Normal file
@@ -0,0 +1,136 @@
|
||||
import OathHammerActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class OathHammerCharacterSheet extends OathHammerActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["character"],
|
||||
position: {
|
||||
width: 972,
|
||||
height: 780,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["character-content"],
|
||||
},
|
||||
actions: {
|
||||
createWeapon: OathHammerCharacterSheet.#onCreateWeapon,
|
||||
createSpell: OathHammerCharacterSheet.#onCreateSpell,
|
||||
createMiracle: OathHammerCharacterSheet.#onCreateMiracle,
|
||||
createEquipment: OathHammerCharacterSheet.#onCreateEquipment,
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-sheet.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
identity: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-identity.hbs",
|
||||
},
|
||||
combat: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-combat.hbs",
|
||||
},
|
||||
magic: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-magic.hbs",
|
||||
},
|
||||
equipment: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-equipment.hbs",
|
||||
},
|
||||
notes: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/character-notes.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "identity",
|
||||
}
|
||||
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
identity: { id: "identity", group: "sheet", icon: "fa-solid fa-person", label: "OATHHAMMER.Tab.Identity" },
|
||||
combat: { id: "combat", group: "sheet", icon: "fa-solid fa-swords", label: "OATHHAMMER.Tab.Combat" },
|
||||
magic: { id: "magic", group: "sheet", icon: "fa-solid fa-wand-magic-sparkles", label: "OATHHAMMER.Tab.Magic" },
|
||||
equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-backpack", label: "OATHHAMMER.Tab.Equipment" },
|
||||
notes: { id: "notes", group: "sheet", icon: "fa-solid fa-book", label: "OATHHAMMER.Tab.Notes" },
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
break
|
||||
case "identity":
|
||||
context.tab = context.tabs.identity
|
||||
context.abilities = doc.itemTypes.ability
|
||||
context.oaths = doc.itemTypes.oath
|
||||
break
|
||||
case "combat":
|
||||
context.tab = context.tabs.combat
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
context.armors = doc.itemTypes.armor
|
||||
context.shields = doc.itemTypes.shield
|
||||
context.ammunition = doc.itemTypes.ammunition
|
||||
break
|
||||
case "magic":
|
||||
context.tab = context.tabs.magic
|
||||
context.spells = doc.itemTypes.spell
|
||||
context.miracles = doc.itemTypes.miracle
|
||||
break
|
||||
case "equipment":
|
||||
context.tab = context.tabs.equipment
|
||||
context.equipment = doc.itemTypes.equipment
|
||||
context.magicItems = doc.itemTypes["magic-item"]
|
||||
context.conditions = doc.itemTypes.condition
|
||||
break
|
||||
case "notes":
|
||||
context.tab = context.tabs.notes
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||
if (data.type === "Item") {
|
||||
const item = await fromUuid(data.uuid)
|
||||
return this._onDropItem(item)
|
||||
}
|
||||
}
|
||||
|
||||
static #onCreateWeapon(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("OATHHAMMER.NewItem.Weapon"), type: "weapon" }])
|
||||
}
|
||||
|
||||
static #onCreateSpell(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("OATHHAMMER.NewItem.Spell"), type: "spell" }])
|
||||
}
|
||||
|
||||
static #onCreateMiracle(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("OATHHAMMER.NewItem.Miracle"), type: "miracle" }])
|
||||
}
|
||||
|
||||
static #onCreateEquipment(event, target) {
|
||||
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("OATHHAMMER.NewItem.Equipment"), type: "equipment" }])
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/condition-sheet.mjs
Normal file
27
module/applications/sheets/condition-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerConditionSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["condition"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["condition-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/condition-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/equipment-sheet.mjs
Normal file
27
module/applications/sheets/equipment-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerEquipmentSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["equipment"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["equipment-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/equipment-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/magic-item-sheet.mjs
Normal file
27
module/applications/sheets/magic-item-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerMagicItemSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["magic-item"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["magic-item-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/magic-item-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
28
module/applications/sheets/miracle-sheet.mjs
Normal file
28
module/applications/sheets/miracle-sheet.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerMiracleSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["miracle"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["miracle-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/miracle-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedEffect = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.effect, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
83
module/applications/sheets/npc-sheet.mjs
Normal file
83
module/applications/sheets/npc-sheet.mjs
Normal file
@@ -0,0 +1,83 @@
|
||||
import OathHammerActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class OathHammerNPCSheet extends OathHammerActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["npc"],
|
||||
position: {
|
||||
width: 720,
|
||||
height: "auto",
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["npc-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/npc-sheet.hbs",
|
||||
},
|
||||
tabs: {
|
||||
template: "templates/generic/tab-navigation.hbs",
|
||||
},
|
||||
combat: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/npc-combat.hbs",
|
||||
},
|
||||
notes: {
|
||||
template: "systems/fvtt-oath-hammer/templates/actor/npc-notes.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
sheet: "combat",
|
||||
}
|
||||
|
||||
#getTabs() {
|
||||
const tabs = {
|
||||
combat: { id: "combat", group: "sheet", icon: "fa-solid fa-swords", label: "OATHHAMMER.Tab.Combat" },
|
||||
notes: { id: "notes", group: "sheet", icon: "fa-solid fa-book", label: "OATHHAMMER.Tab.Notes" },
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _preparePartContext(partId, context) {
|
||||
const doc = this.document
|
||||
switch (partId) {
|
||||
case "main":
|
||||
break
|
||||
case "combat":
|
||||
context.tab = context.tabs.combat
|
||||
context.weapons = doc.itemTypes.weapon
|
||||
break
|
||||
case "notes":
|
||||
context.tab = context.tabs.notes
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.description, { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(doc.system.notes, { async: true })
|
||||
break
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
async _onDrop(event) {
|
||||
if (!this.isEditable || !this.isEditMode) return
|
||||
const data = foundry.applications.ux.TextEditor.implementation.getDragEventData(event)
|
||||
if (data.type === "Item") {
|
||||
const item = await fromUuid(data.uuid)
|
||||
return this._onDropItem(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
29
module/applications/sheets/oath-sheet.mjs
Normal file
29
module/applications/sheets/oath-sheet.mjs
Normal file
@@ -0,0 +1,29 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerOathSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["oath"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["oath-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/oath-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedBenefit = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.benefit, { async: true })
|
||||
context.enrichedViolation = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.violation, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/shield-sheet.mjs
Normal file
27
module/applications/sheets/shield-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerShieldSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["shield"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["shield-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/shield-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
28
module/applications/sheets/spell-sheet.mjs
Normal file
28
module/applications/sheets/spell-sheet.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerSpellSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["spell"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["spell-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/spell-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
context.enrichedEffect = await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.effect, { async: true })
|
||||
return context
|
||||
}
|
||||
}
|
||||
27
module/applications/sheets/weapon-sheet.mjs
Normal file
27
module/applications/sheets/weapon-sheet.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
import OathHammerItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class OathHammerWeaponSheet extends OathHammerItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["weapon"],
|
||||
position: {
|
||||
width: 620,
|
||||
},
|
||||
window: {
|
||||
contentClasses: ["weapon-content"],
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-oath-hammer/templates/item/weapon-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
return context
|
||||
}
|
||||
}
|
||||
194
module/config/system.mjs
Normal file
194
module/config/system.mjs
Normal file
@@ -0,0 +1,194 @@
|
||||
export const SYSTEM_ID = "fvtt-oath-hammer"
|
||||
|
||||
export const ATTRIBUTES = {
|
||||
might: { id: "might", abbrev: "M", label: "OATHHAMMER.Attribute.Might" },
|
||||
toughness: { id: "toughness", abbrev: "T", label: "OATHHAMMER.Attribute.Toughness" },
|
||||
agility: { id: "agility", abbrev: "A", label: "OATHHAMMER.Attribute.Agility" },
|
||||
willpower: { id: "willpower", abbrev: "WP", label: "OATHHAMMER.Attribute.Willpower" },
|
||||
intelligence: { id: "intelligence", abbrev: "I", label: "OATHHAMMER.Attribute.Intelligence" },
|
||||
fate: { id: "fate", abbrev: "F", label: "OATHHAMMER.Attribute.Fate" }
|
||||
}
|
||||
|
||||
export const LINEAGE_CHOICES = {
|
||||
dwarf: { id: "dwarf", label: "OATHHAMMER.Lineage.Dwarf" },
|
||||
human: { id: "human", label: "OATHHAMMER.Lineage.Human" },
|
||||
elf: { id: "elf", label: "OATHHAMMER.Lineage.Elf" },
|
||||
halfelf: { id: "halfelf", label: "OATHHAMMER.Lineage.HalfElf" },
|
||||
halfling: { id: "halfling", label: "OATHHAMMER.Lineage.Halfling" }
|
||||
}
|
||||
|
||||
export const CLASS_CHOICES = {
|
||||
fighter: { id: "fighter", label: "OATHHAMMER.Class.Fighter" },
|
||||
ranger: { id: "ranger", label: "OATHHAMMER.Class.Ranger" },
|
||||
wizard: { id: "wizard", label: "OATHHAMMER.Class.Wizard" },
|
||||
cleric: { id: "cleric", label: "OATHHAMMER.Class.Cleric" },
|
||||
rogue: { id: "rogue", label: "OATHHAMMER.Class.Rogue" },
|
||||
paladin: { id: "paladin", label: "OATHHAMMER.Class.Paladin" }
|
||||
}
|
||||
|
||||
export const OATH_TYPES = {
|
||||
"oath-of-justice": { id: "oath-of-justice", label: "OATHHAMMER.Oath.Justice" },
|
||||
"oath-of-courage": { id: "oath-of-courage", label: "OATHHAMMER.Oath.Courage" },
|
||||
"oath-of-honor": { id: "oath-of-honor", label: "OATHHAMMER.Oath.Honor" },
|
||||
"oath-of-mercy": { id: "oath-of-mercy", label: "OATHHAMMER.Oath.Mercy" },
|
||||
"oath-of-truth": { id: "oath-of-truth", label: "OATHHAMMER.Oath.Truth" },
|
||||
"oath-of-valor": { id: "oath-of-valor", label: "OATHHAMMER.Oath.Valor" },
|
||||
"oath-of-protection": { id: "oath-of-protection", label: "OATHHAMMER.Oath.Protection" },
|
||||
"oath-of-vengeance": { id: "oath-of-vengeance", label: "OATHHAMMER.Oath.Vengeance" },
|
||||
"oath-of-sacrifice": { id: "oath-of-sacrifice", label: "OATHHAMMER.Oath.Sacrifice" },
|
||||
"oath-of-faith": { id: "oath-of-faith", label: "OATHHAMMER.Oath.Faith" },
|
||||
"oath-of-service": { id: "oath-of-service", label: "OATHHAMMER.Oath.Service" },
|
||||
"oath-of-brotherhood": { id: "oath-of-brotherhood", label: "OATHHAMMER.Oath.Brotherhood" }
|
||||
}
|
||||
|
||||
export const SORCEROUS_TRADITIONS = {
|
||||
elemental: { id: "elemental", label: "OATHHAMMER.Tradition.Elemental" },
|
||||
illusionist: { id: "illusionist", label: "OATHHAMMER.Tradition.Illusionist" },
|
||||
imperial: { id: "imperial", label: "OATHHAMMER.Tradition.Imperial" },
|
||||
infernal: { id: "infernal", label: "OATHHAMMER.Tradition.Infernal" },
|
||||
runic: { id: "runic", label: "OATHHAMMER.Tradition.Runic" },
|
||||
stygian: { id: "stygian", label: "OATHHAMMER.Tradition.Stygian" }
|
||||
}
|
||||
|
||||
export const WEAPON_TYPE_CHOICES = {
|
||||
melee: "OATHHAMMER.WeaponType.Melee",
|
||||
ranged: "OATHHAMMER.WeaponType.Ranged"
|
||||
}
|
||||
|
||||
export const DAMAGE_TYPE_CHOICES = {
|
||||
slashing: "OATHHAMMER.DamageType.Slashing",
|
||||
piercing: "OATHHAMMER.DamageType.Piercing",
|
||||
bludgeoning: "OATHHAMMER.DamageType.Bludgeoning",
|
||||
fire: "OATHHAMMER.DamageType.Fire",
|
||||
cold: "OATHHAMMER.DamageType.Cold",
|
||||
lightning: "OATHHAMMER.DamageType.Lightning",
|
||||
acid: "OATHHAMMER.DamageType.Acid",
|
||||
poison: "OATHHAMMER.DamageType.Poison",
|
||||
necrotic: "OATHHAMMER.DamageType.Necrotic",
|
||||
radiant: "OATHHAMMER.DamageType.Radiant"
|
||||
}
|
||||
|
||||
export const ATTRIBUTE_BONUS_CHOICES = {
|
||||
might: "OATHHAMMER.Attribute.Might",
|
||||
agility: "OATHHAMMER.Attribute.Agility",
|
||||
none: "OATHHAMMER.Label.None"
|
||||
}
|
||||
|
||||
export const RANGE_CHOICES = {
|
||||
short: "OATHHAMMER.Range.Short",
|
||||
medium: "OATHHAMMER.Range.Medium",
|
||||
long: "OATHHAMMER.Range.Long"
|
||||
}
|
||||
|
||||
export const HANDS_CHOICES = {
|
||||
"one-handed": "OATHHAMMER.Hands.OneHanded",
|
||||
"two-handed": "OATHHAMMER.Hands.TwoHanded"
|
||||
}
|
||||
|
||||
export const CURRENCY_CHOICES = {
|
||||
gp: "OATHHAMMER.Currency.GP",
|
||||
sp: "OATHHAMMER.Currency.SP",
|
||||
cp: "OATHHAMMER.Currency.CP"
|
||||
}
|
||||
|
||||
export const ARMOR_TYPE_CHOICES = {
|
||||
light: "OATHHAMMER.ArmorType.Light",
|
||||
medium: "OATHHAMMER.ArmorType.Medium",
|
||||
heavy: "OATHHAMMER.ArmorType.Heavy"
|
||||
}
|
||||
|
||||
export const AMMO_TYPE_CHOICES = {
|
||||
arrow: "OATHHAMMER.AmmoType.Arrow",
|
||||
bolt: "OATHHAMMER.AmmoType.Bolt",
|
||||
stone: "OATHHAMMER.AmmoType.Stone",
|
||||
javelin: "OATHHAMMER.AmmoType.Javelin",
|
||||
"throwing-knife": "OATHHAMMER.AmmoType.ThrowingKnife"
|
||||
}
|
||||
|
||||
export const EQUIPMENT_TYPE_CHOICES = {
|
||||
potion: "OATHHAMMER.EquipmentType.Potion",
|
||||
container: "OATHHAMMER.EquipmentType.Container",
|
||||
tool: "OATHHAMMER.EquipmentType.Tool",
|
||||
consumable: "OATHHAMMER.EquipmentType.Consumable",
|
||||
misc: "OATHHAMMER.EquipmentType.Misc",
|
||||
"healing-supply": "OATHHAMMER.EquipmentType.HealingSupply",
|
||||
food: "OATHHAMMER.EquipmentType.Food",
|
||||
mount: "OATHHAMMER.EquipmentType.Mount",
|
||||
vehicle: "OATHHAMMER.EquipmentType.Vehicle",
|
||||
"war-machine": "OATHHAMMER.EquipmentType.WarMachine"
|
||||
}
|
||||
|
||||
export const MAGIC_ITEM_TYPE_CHOICES = {
|
||||
weapon: "OATHHAMMER.MagicItemType.Weapon",
|
||||
armor: "OATHHAMMER.MagicItemType.Armor",
|
||||
wondrous: "OATHHAMMER.MagicItemType.Wondrous",
|
||||
potion: "OATHHAMMER.MagicItemType.Potion",
|
||||
ring: "OATHHAMMER.MagicItemType.Ring",
|
||||
staff: "OATHHAMMER.MagicItemType.Staff",
|
||||
wand: "OATHHAMMER.MagicItemType.Wand",
|
||||
scroll: "OATHHAMMER.MagicItemType.Scroll",
|
||||
rod: "OATHHAMMER.MagicItemType.Rod"
|
||||
}
|
||||
|
||||
export const RARITY_CHOICES = {
|
||||
common: "OATHHAMMER.Rarity.Common",
|
||||
uncommon: "OATHHAMMER.Rarity.Uncommon",
|
||||
rare: "OATHHAMMER.Rarity.Rare",
|
||||
"very-rare": "OATHHAMMER.Rarity.VeryRare",
|
||||
legendary: "OATHHAMMER.Rarity.Legendary"
|
||||
}
|
||||
|
||||
export const ABILITY_TYPE_CHOICES = {
|
||||
"class-ability": "OATHHAMMER.AbilityType.ClassAbility",
|
||||
"lineage-trait": "OATHHAMMER.AbilityType.LineageTrait",
|
||||
feat: "OATHHAMMER.AbilityType.Feat"
|
||||
}
|
||||
|
||||
export const CONDITION_TYPE_CHOICES = {
|
||||
blinded: "OATHHAMMER.Condition.Blinded",
|
||||
deafened: "OATHHAMMER.Condition.Deafened",
|
||||
prone: "OATHHAMMER.Condition.Prone",
|
||||
stunned: "OATHHAMMER.Condition.Stunned",
|
||||
frightened: "OATHHAMMER.Condition.Frightened",
|
||||
poisoned: "OATHHAMMER.Condition.Poisoned",
|
||||
restrained: "OATHHAMMER.Condition.Restrained",
|
||||
wounded: "OATHHAMMER.Condition.Wounded",
|
||||
other: "OATHHAMMER.Condition.Other"
|
||||
}
|
||||
|
||||
export const ATTRIBUTE_RANK_CHOICES = { 1: "1", 2: "2", 3: "3", 4: "4" }
|
||||
|
||||
export const ASCII = `
|
||||
·················································
|
||||
: ___ _ _ _ _ :
|
||||
: / _ \\ __ _| |_| |__ | | | | __ _ _ __ ___ :
|
||||
: | | | / _\` | __| '_ \\ | |_| |/ _\` | '_ \` _ \\:
|
||||
: | |_| | (_| | |_| | | | | _ | (_| | | | | | |
|
||||
: \\___/ \\__,_|\\__|_| |_| |_| |_|\\__,_|_| |_| |_|
|
||||
: :
|
||||
·················································
|
||||
`
|
||||
|
||||
export const SYSTEM = {
|
||||
id: SYSTEM_ID,
|
||||
ATTRIBUTES,
|
||||
LINEAGE_CHOICES,
|
||||
CLASS_CHOICES,
|
||||
OATH_TYPES,
|
||||
SORCEROUS_TRADITIONS,
|
||||
WEAPON_TYPE_CHOICES,
|
||||
DAMAGE_TYPE_CHOICES,
|
||||
ATTRIBUTE_BONUS_CHOICES,
|
||||
RANGE_CHOICES,
|
||||
HANDS_CHOICES,
|
||||
CURRENCY_CHOICES,
|
||||
ARMOR_TYPE_CHOICES,
|
||||
AMMO_TYPE_CHOICES,
|
||||
EQUIPMENT_TYPE_CHOICES,
|
||||
MAGIC_ITEM_TYPE_CHOICES,
|
||||
RARITY_CHOICES,
|
||||
ABILITY_TYPE_CHOICES,
|
||||
CONDITION_TYPE_CHOICES,
|
||||
ATTRIBUTE_RANK_CHOICES,
|
||||
ASCII
|
||||
}
|
||||
2
module/documents/_module.mjs
Normal file
2
module/documents/_module.mjs
Normal file
@@ -0,0 +1,2 @@
|
||||
export { default as OathHammerActor } from "./actor.mjs"
|
||||
export { default as OathHammerItem } from "./item.mjs"
|
||||
35
module/documents/actor.mjs
Normal file
35
module/documents/actor.mjs
Normal file
@@ -0,0 +1,35 @@
|
||||
export default class OathHammerActor extends Actor {
|
||||
async _preCreate(data, options, user) {
|
||||
await super._preCreate(data, options, user)
|
||||
const prototypeToken = {}
|
||||
if (this.type === "character") {
|
||||
Object.assign(prototypeToken, {
|
||||
sight: { enabled: true },
|
||||
actorLink: true,
|
||||
disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
|
||||
})
|
||||
this.updateSource({ prototypeToken })
|
||||
}
|
||||
if (this.type === "npc") {
|
||||
Object.assign(prototypeToken, {
|
||||
sight: { enabled: false },
|
||||
actorLink: false,
|
||||
disposition: CONST.TOKEN_DISPOSITIONS.HOSTILE,
|
||||
})
|
||||
this.updateSource({ prototypeToken })
|
||||
}
|
||||
}
|
||||
|
||||
getArmorRating() {
|
||||
let rating = 0
|
||||
for (const item of this.items) {
|
||||
if (item.type === "armor" && item.system.equipped) {
|
||||
rating += Number(item.system.armorRating) || 0
|
||||
}
|
||||
if (item.type === "shield" && item.system.equipped) {
|
||||
rating += Number(item.system.shieldBonus) || 0
|
||||
}
|
||||
}
|
||||
return rating
|
||||
}
|
||||
}
|
||||
22
module/documents/item.mjs
Normal file
22
module/documents/item.mjs
Normal file
@@ -0,0 +1,22 @@
|
||||
const defaultItemImg = {
|
||||
weapon: "systems/fvtt-oath-hammer/assets/icons/icon_weapon.webp",
|
||||
armor: "systems/fvtt-oath-hammer/assets/icons/icon_armor.webp",
|
||||
shield: "systems/fvtt-oath-hammer/assets/icons/icon_shield.webp",
|
||||
ammunition: "systems/fvtt-oath-hammer/assets/icons/icon_ammunition.webp",
|
||||
equipment: "systems/fvtt-oath-hammer/assets/icons/icon_equipment.webp",
|
||||
spell: "systems/fvtt-oath-hammer/assets/icons/icon_spell.webp",
|
||||
miracle: "systems/fvtt-oath-hammer/assets/icons/icon_miracle.webp",
|
||||
"magic-item": "systems/fvtt-oath-hammer/assets/icons/icon_magic_item.webp",
|
||||
ability: "systems/fvtt-oath-hammer/assets/icons/icon_ability.webp",
|
||||
oath: "systems/fvtt-oath-hammer/assets/icons/icon_oath.webp",
|
||||
condition: "systems/fvtt-oath-hammer/assets/icons/icon_condition.webp"
|
||||
}
|
||||
|
||||
export default class OathHammerItem extends Item {
|
||||
constructor(data, context) {
|
||||
if (!data.img && defaultItemImg[data.type]) {
|
||||
data.img = defaultItemImg[data.type]
|
||||
}
|
||||
super(data, context)
|
||||
}
|
||||
}
|
||||
13
module/models/_module.mjs
Normal file
13
module/models/_module.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
export { default as OathHammerCharacter } from "./character.mjs"
|
||||
export { default as OathHammerNPC } from "./npc.mjs"
|
||||
export { default as OathHammerWeapon } from "./weapon.mjs"
|
||||
export { default as OathHammerArmor } from "./armor.mjs"
|
||||
export { default as OathHammerShield } from "./shield.mjs"
|
||||
export { default as OathHammerAmmunition } from "./ammunition.mjs"
|
||||
export { default as OathHammerEquipment } from "./equipment.mjs"
|
||||
export { default as OathHammerSpell } from "./spell.mjs"
|
||||
export { default as OathHammerMiracle } from "./miracle.mjs"
|
||||
export { default as OathHammerMagicItem } from "./magic-item.mjs"
|
||||
export { default as OathHammerAbility } from "./ability.mjs"
|
||||
export { default as OathHammerOath } from "./oath.mjs"
|
||||
export { default as OathHammerCondition } from "./condition.mjs"
|
||||
18
module/models/ability.mjs
Normal file
18
module/models/ability.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerAbility extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.abilityType = new fields.StringField({ required: true, initial: "class-ability", choices: SYSTEM.ABILITY_TYPE_CHOICES })
|
||||
schema.source = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.prerequisite = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.passiveBonus = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Ability"]
|
||||
}
|
||||
20
module/models/ammunition.mjs
Normal file
20
module/models/ammunition.mjs
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerAmmunition extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.ammoType = new fields.StringField({ required: true, initial: "arrow", choices: SYSTEM.AMMO_TYPE_CHOICES })
|
||||
schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
schema.properties = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Ammunition"]
|
||||
}
|
||||
22
module/models/armor.mjs
Normal file
22
module/models/armor.mjs
Normal file
@@ -0,0 +1,22 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerArmor extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.armorType = new fields.StringField({ required: true, initial: "light", choices: SYSTEM.ARMOR_TYPE_CHOICES })
|
||||
schema.armorRating = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.movementPenalty = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.equipped = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.encumbrance = new fields.NumberField({ required: true, initial: 1, min: 0 })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Armor"]
|
||||
}
|
||||
83
module/models/character.mjs
Normal file
83
module/models/character.mjs
Normal file
@@ -0,0 +1,83 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerCharacter extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.notes = new fields.HTMLField({ required: true, textSearch: true })
|
||||
|
||||
const attributeField = () => new fields.SchemaField({
|
||||
rank: new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 4 })
|
||||
})
|
||||
schema.attributes = new fields.SchemaField({
|
||||
might: attributeField(),
|
||||
toughness: attributeField(),
|
||||
agility: attributeField(),
|
||||
willpower: attributeField(),
|
||||
intelligence: attributeField(),
|
||||
fate: attributeField()
|
||||
})
|
||||
|
||||
schema.grit = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 })
|
||||
})
|
||||
|
||||
schema.luck = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
})
|
||||
|
||||
schema.arcaneStress = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
threshold: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 })
|
||||
})
|
||||
|
||||
schema.movement = new fields.SchemaField({
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 30, min: 0 }),
|
||||
adjusted: new fields.NumberField({ ...requiredInteger, initial: 30, min: 0 })
|
||||
})
|
||||
|
||||
schema.defense = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 }),
|
||||
armorRating: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
bonus: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
schema.experience = new fields.SchemaField({
|
||||
current: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
total: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
level: new fields.NumberField({ ...requiredInteger, initial: 1, min: 1 })
|
||||
})
|
||||
|
||||
schema.biodata = new fields.SchemaField({
|
||||
lineage: new fields.StringField({ required: true, initial: "dwarf", choices: SYSTEM.LINEAGE_CHOICES }),
|
||||
class: new fields.StringField({ required: true, initial: "fighter", choices: SYSTEM.CLASS_CHOICES }),
|
||||
age: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
gender: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
height: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
weight: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
eyes: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
hair: new fields.StringField({ required: true, nullable: false, initial: "" }),
|
||||
alignment: new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
})
|
||||
|
||||
schema.currency = new fields.SchemaField({
|
||||
gold: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
silver: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
copper: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Character"]
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData()
|
||||
this.grit.max = this.attributes.might.rank + this.attributes.toughness.rank
|
||||
this.defense.value = 10 + this.attributes.agility.rank + this.defense.armorRating + this.defense.bonus
|
||||
}
|
||||
}
|
||||
17
module/models/condition.mjs
Normal file
17
module/models/condition.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerCondition extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.conditionType = new fields.StringField({ required: true, initial: "stunned", choices: SYSTEM.CONDITION_TYPE_CHOICES })
|
||||
schema.duration = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.source = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Condition"]
|
||||
}
|
||||
20
module/models/equipment.mjs
Normal file
20
module/models/equipment.mjs
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerEquipment extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.itemType = new fields.StringField({ required: true, initial: "misc", choices: SYSTEM.EQUIPMENT_TYPE_CHOICES })
|
||||
schema.quantity = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
schema.weight = new fields.NumberField({ required: true, initial: 0, min: 0 })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Equipment"]
|
||||
}
|
||||
26
module/models/magic-item.mjs
Normal file
26
module/models/magic-item.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerMagicItem extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.itemType = new fields.StringField({ required: true, initial: "wondrous", choices: SYSTEM.MAGIC_ITEM_TYPE_CHOICES })
|
||||
schema.rarity = new fields.StringField({ required: true, initial: "common", choices: SYSTEM.RARITY_CHOICES })
|
||||
schema.attunement = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.charges = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
})
|
||||
schema.recharge = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.equipped = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.MagicItem"]
|
||||
}
|
||||
26
module/models/miracle.mjs
Normal file
26
module/models/miracle.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerMiracle extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.effect = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.piety = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
schema.castingTime = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.range = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField(),
|
||||
somatic: new fields.BooleanField(),
|
||||
material: new fields.BooleanField()
|
||||
})
|
||||
schema.materialComponent = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Miracle"]
|
||||
}
|
||||
50
module/models/npc.mjs
Normal file
50
module/models/npc.mjs
Normal file
@@ -0,0 +1,50 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerNPC extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.notes = new fields.HTMLField({ required: true, textSearch: true })
|
||||
|
||||
const attributeField = () => new fields.SchemaField({
|
||||
rank: new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 4 })
|
||||
})
|
||||
schema.attributes = new fields.SchemaField({
|
||||
might: attributeField(),
|
||||
toughness: attributeField(),
|
||||
agility: attributeField(),
|
||||
willpower: attributeField(),
|
||||
intelligence: attributeField(),
|
||||
fate: attributeField()
|
||||
})
|
||||
|
||||
schema.grit = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 }),
|
||||
max: new fields.NumberField({ ...requiredInteger, initial: 2, min: 0 })
|
||||
})
|
||||
|
||||
schema.defense = new fields.SchemaField({
|
||||
value: new fields.NumberField({ ...requiredInteger, initial: 10, min: 0 })
|
||||
})
|
||||
|
||||
schema.movement = new fields.SchemaField({
|
||||
base: new fields.NumberField({ ...requiredInteger, initial: 30, min: 0 })
|
||||
})
|
||||
|
||||
schema.attackBonus = new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
schema.damageBonus = new fields.NumberField({ ...requiredInteger, initial: 0 })
|
||||
schema.challengeRating = new fields.StringField({ required: true, nullable: false, initial: "1" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.NPC"]
|
||||
|
||||
prepareDerivedData() {
|
||||
super.prepareDerivedData()
|
||||
this.grit.max = this.attributes.might.rank + this.attributes.toughness.rank
|
||||
}
|
||||
}
|
||||
17
module/models/oath.mjs
Normal file
17
module/models/oath.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerOath extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const schema = {}
|
||||
|
||||
schema.benefit = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.violation = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.oathType = new fields.StringField({ required: true, initial: "oath-of-justice", choices: SYSTEM.OATH_TYPES })
|
||||
schema.violated = new fields.BooleanField({ required: true, initial: false })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Oath"]
|
||||
}
|
||||
20
module/models/shield.mjs
Normal file
20
module/models/shield.mjs
Normal file
@@ -0,0 +1,20 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerShield extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.shieldBonus = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
schema.equipped = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.encumbrance = new fields.NumberField({ required: true, initial: 1, min: 0 })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Shield"]
|
||||
}
|
||||
29
module/models/spell.mjs
Normal file
29
module/models/spell.mjs
Normal file
@@ -0,0 +1,29 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerSpell extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.effect = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.tradition = new fields.StringField({ required: true, initial: "elemental", choices: SYSTEM.SORCEROUS_TRADITIONS })
|
||||
schema.level = new fields.NumberField({ ...requiredInteger, initial: 1, min: 1, max: 6 })
|
||||
schema.castingTime = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.range = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.duration = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.arcaneStress = new fields.NumberField({ ...requiredInteger, initial: 1, min: 0 })
|
||||
schema.components = new fields.SchemaField({
|
||||
verbal: new fields.BooleanField(),
|
||||
somatic: new fields.BooleanField(),
|
||||
material: new fields.BooleanField()
|
||||
})
|
||||
schema.materialComponent = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.savingThrow = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.enhancement = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Spell"]
|
||||
}
|
||||
26
module/models/weapon.mjs
Normal file
26
module/models/weapon.mjs
Normal file
@@ -0,0 +1,26 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
|
||||
export default class OathHammerWeapon extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
const requiredInteger = { required: true, nullable: false, integer: true }
|
||||
const schema = {}
|
||||
|
||||
schema.description = new fields.HTMLField({ required: true, textSearch: true })
|
||||
schema.weaponType = new fields.StringField({ required: true, initial: "melee", choices: SYSTEM.WEAPON_TYPE_CHOICES })
|
||||
schema.damageFormula = new fields.StringField({ required: true, nullable: false, initial: "1d6" })
|
||||
schema.damageType = new fields.StringField({ required: true, initial: "slashing", choices: SYSTEM.DAMAGE_TYPE_CHOICES })
|
||||
schema.attributeBonus = new fields.StringField({ required: true, initial: "might", choices: SYSTEM.ATTRIBUTE_BONUS_CHOICES })
|
||||
schema.range = new fields.StringField({ required: true, initial: "short", choices: SYSTEM.RANGE_CHOICES })
|
||||
schema.hands = new fields.StringField({ required: true, initial: "one-handed", choices: SYSTEM.HANDS_CHOICES })
|
||||
schema.properties = new fields.StringField({ required: true, nullable: false, initial: "" })
|
||||
schema.equipped = new fields.BooleanField({ required: true, initial: false })
|
||||
schema.encumbrance = new fields.NumberField({ required: true, initial: 1, min: 0 })
|
||||
schema.cost = new fields.NumberField({ ...requiredInteger, initial: 0, min: 0 })
|
||||
schema.currency = new fields.StringField({ required: true, initial: "gp", choices: SYSTEM.CURRENCY_CHOICES })
|
||||
|
||||
return schema
|
||||
}
|
||||
|
||||
static LOCALIZATION_PREFIXES = ["OATHHAMMER.Weapon"]
|
||||
}
|
||||
19
module/utils.mjs
Normal file
19
module/utils.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
export default class OathHammerUtils {
|
||||
static registerHandlebarsHelpers() {
|
||||
Handlebars.registerHelper("ifThen", (condition, trueVal, falseVal) => condition ? trueVal : falseVal)
|
||||
Handlebars.registerHelper("capitalize", (str) => {
|
||||
if (typeof str !== "string") return str
|
||||
return str.charAt(0).toUpperCase() + str.slice(1)
|
||||
})
|
||||
Handlebars.registerHelper("concat", (...args) => {
|
||||
args.pop() // remove handlebars options object
|
||||
return args.join("")
|
||||
})
|
||||
}
|
||||
|
||||
static async loadCompendium(packId) {
|
||||
const pack = game.packs.get(packId)
|
||||
if (!pack) return []
|
||||
return await pack.getDocuments()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user