Add roll windows from actor sheet

This commit is contained in:
2026-03-15 23:20:32 +01:00
parent 82fddb0cb3
commit 49347370c7
57 changed files with 6372 additions and 184 deletions

View File

@@ -95,8 +95,8 @@ export default class OathHammerActorSheet extends HandlebarsApplicationMixin(fou
async _onDropItem(item) {
const itemData = item.toObject()
// Lineage and class are unique: replace any existing item of the same type
if (item.type === "lineage" || item.type === "class") {
// Class is unique: replace any existing item of the same type
if (item.type === "class") {
const existing = this.document.itemTypes[item.type]
if (existing.length > 0) {
await this.document.deleteEmbeddedDocuments("Item", existing.map(i => i.id))

View File

@@ -1,5 +1,6 @@
const { HandlebarsApplicationMixin } = foundry.applications.api
import { ARMOR_TYPE_CHOICES, WEAPON_PROFICIENCY_GROUPS } from "../../config/system.mjs"
import { rollRarityCheck } from "../../rolls.mjs"
export default class OathHammerItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
@@ -28,6 +29,7 @@ export default class OathHammerItemSheet extends HandlebarsApplicationMixin(foun
actions: {
toggleSheet: OathHammerItemSheet.#onToggleSheet,
editImage: OathHammerItemSheet.#onEditImage,
rollRarity: OathHammerItemSheet.#onRollRarity,
},
}
@@ -134,4 +136,20 @@ export default class OathHammerItemSheet extends HandlebarsApplicationMixin(foun
})
return fp.browse()
}
static async #onRollRarity(event, target) {
const rarity = this.document.system.rarity
if (!rarity) return
// Find the owning actor (embedded item) or prompt user to select a character
let actor = this.document.parent
if (!actor || actor.documentName !== "Actor") {
// Item not embedded — use the user's selected character
actor = game.user.character
if (!actor) {
ui.notifications.warn(game.i18n.localize("OATHHAMMER.Roll.NoActor"))
return
}
}
await rollRarityCheck(actor, rarity, this.document.name)
}
}

View File

@@ -1,5 +1,10 @@
import OathHammerActorSheet from "./base-actor-sheet.mjs"
import { SYSTEM } from "../../config/system.mjs"
import OathHammerRollDialog from "../roll-dialog.mjs"
import OathHammerWeaponDialog from "../weapon-dialog.mjs"
import OathHammerSpellDialog from "../spell-dialog.mjs"
import OathHammerMiracleDialog from "../miracle-dialog.mjs"
import { rollSkillCheck, rollWeaponAttack, rollWeaponDamage, rollSpellCast, rollMiracleCast } from "../../rolls.mjs"
export default class OathHammerCharacterSheet extends OathHammerActorSheet {
/** @override */
@@ -13,10 +18,15 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
contentClasses: ["character-content"],
},
actions: {
createWeapon: OathHammerCharacterSheet.#onCreateWeapon,
createSpell: OathHammerCharacterSheet.#onCreateSpell,
createMiracle: OathHammerCharacterSheet.#onCreateMiracle,
createWeapon: OathHammerCharacterSheet.#onCreateWeapon,
createSpell: OathHammerCharacterSheet.#onCreateSpell,
createMiracle: OathHammerCharacterSheet.#onCreateMiracle,
createEquipment: OathHammerCharacterSheet.#onCreateEquipment,
rollSkill: OathHammerCharacterSheet.#onRollSkill,
attackWeapon: OathHammerCharacterSheet.#onAttackWeapon,
damageWeapon: OathHammerCharacterSheet.#onDamageWeapon,
castSpell: OathHammerCharacterSheet.#onCastSpell,
castMiracle: OathHammerCharacterSheet.#onCastMiracle,
},
}
@@ -57,9 +67,8 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
async _prepareContext() {
const context = await super._prepareContext()
context.tabs = this.#getTabs()
// lineage/class/experience available to all parts (header + identity tab)
// class/experience available to all parts (header + identity tab)
const doc = this.document
context.lineage = doc.itemTypes.lineage?.[0] ?? null
context.characterClass = doc.itemTypes["class"]?.[0] ?? null
return context
}
@@ -236,4 +245,52 @@ export default class OathHammerCharacterSheet extends OathHammerActorSheet {
static #onCreateEquipment(event, target) {
this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("OATHHAMMER.NewItem.Equipment"), type: "equipment" }])
}
static async #onRollSkill(event, target) {
const skillKey = target.dataset.skill
if (!skillKey) return
const result = await OathHammerRollDialog.prompt(this.document, skillKey)
if (!result) return
await rollSkillCheck(this.document, skillKey, result.dv, result)
}
static async #onAttackWeapon(event, target) {
const weaponId = target.dataset.itemId
if (!weaponId) return
const weapon = this.document.items.get(weaponId)
if (!weapon) return
const opts = await OathHammerWeaponDialog.promptAttack(this.document, weapon)
if (!opts) return
await rollWeaponAttack(this.document, weapon, opts)
}
static async #onDamageWeapon(event, target) {
const weaponId = target.dataset.itemId
if (!weaponId) return
const weapon = this.document.items.get(weaponId)
if (!weapon) return
const opts = await OathHammerWeaponDialog.promptDamage(this.document, weapon, 0)
if (!opts) return
await rollWeaponDamage(this.document, weapon, opts)
}
static async #onCastSpell(event, target) {
const spellId = target.dataset.itemId
if (!spellId) return
const spell = this.document.items.get(spellId)
if (!spell) return
const opts = await OathHammerSpellDialog.prompt(this.document, spell)
if (!opts) return
await rollSpellCast(this.document, spell, opts)
}
static async #onCastMiracle(event, target) {
const miracleId = target.dataset.itemId
if (!miracleId) return
const miracle = this.document.items.get(miracleId)
if (!miracle) return
const opts = await OathHammerMiracleDialog.prompt(this.document, miracle)
if (!opts) return
await rollMiracleCast(this.document, miracle, opts)
}
}

View File

@@ -1,30 +0,0 @@
import OathHammerItemSheet from "./base-item-sheet.mjs"
export default class OathHammerLineageSheet extends OathHammerItemSheet {
/** @override */
static DEFAULT_OPTIONS = {
classes: ["lineage"],
position: {
width: 640,
},
window: {
contentClasses: ["lineage-content"],
},
}
/** @override */
static PARTS = {
main: {
template: "systems/fvtt-oath-hammer/templates/item/lineage-sheet.hbs",
},
}
/** @override */
async _prepareContext() {
const context = await super._prepareContext()
context.enrichedTraits = await foundry.applications.ux.TextEditor.implementation.enrichHTML(
this.document.system.traits ?? "", { async: true }
)
return context
}
}