Migration datamodels !
This commit is contained in:
27
modules/applications/sheets/_module.mjs
Normal file
27
modules/applications/sheets/_module.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Index des applications AppV2 pour Yggdrasill
|
||||
* Ce fichier centralise tous les exports des applications
|
||||
*/
|
||||
|
||||
// Applications de feuilles d'acteurs
|
||||
export { default as YggdrasillPersonnageSheet } from './yggdrasill-personnage-sheet.mjs';
|
||||
export { default as YggdrasillFigurantSheet } from './yggdrasill-figurant-sheet.mjs';
|
||||
|
||||
// Applications de feuilles d'items
|
||||
export { default as YggdrasillCompetenceSheet } from './yggdrasill-competence-sheet.mjs';
|
||||
export { default as YggdrasillDonSheet } from './yggdrasill-don-sheet.mjs';
|
||||
export { default as YggdrasillFaiblesseSheet } from './yggdrasill-faiblesse-sheet.mjs';
|
||||
export { default as YggdrasillBlessureSheet } from './yggdrasill-blessure-sheet.mjs';
|
||||
export { default as YggdrasillMaladieSheet } from './yggdrasill-maladie-sheet.mjs';
|
||||
export { default as YggdrasillPoisonSheet } from './yggdrasill-poison-sheet.mjs';
|
||||
export { default as YggdrasillProuesseSheet } from './yggdrasill-prouesse-sheet.mjs';
|
||||
export { default as YggdrasillSortsejdrSheet } from './yggdrasill-sortsejdr-sheet.mjs';
|
||||
export { default as YggdrasillSortgaldrSheet } from './yggdrasill-sortgaldr-sheet.mjs';
|
||||
export { default as YggdrasillRuneSheet } from './yggdrasill-rune-sheet.mjs';
|
||||
export { default as YggdrasillArmeccSheet } from './yggdrasill-armecc-sheet.mjs';
|
||||
export { default as YggdrasillArmedistSheet } from './yggdrasill-armedist-sheet.mjs';
|
||||
export { default as YggdrasillArmureSheet } from './yggdrasill-armure-sheet.mjs';
|
||||
export { default as YggdrasillBouclierSheet } from './yggdrasill-bouclier-sheet.mjs';
|
||||
export { default as YggdrasillEquipementSheet } from './yggdrasill-equipement-sheet.mjs';
|
||||
export { default as YggdrasillMonnaieSheet } from './yggdrasill-monnaie-sheet.mjs';
|
||||
export { default as YggdrasillEffetmagiqueSheet } from './yggdrasill-effetmagique-sheet.mjs';
|
||||
449
modules/applications/sheets/base-actor-sheet.mjs
Normal file
449
modules/applications/sheets/base-actor-sheet.mjs
Normal file
@@ -0,0 +1,449 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
import { YggdrasillUtility } from "../../yggdrasill-utility.js"
|
||||
|
||||
export default class YggdrasillActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
|
||||
/**
|
||||
* Different sheet modes.
|
||||
* @enum {number}
|
||||
*/
|
||||
static SHEET_MODES = { EDIT: 0, PLAY: 1 }
|
||||
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-yggdrasill", "sheet", "actor"],
|
||||
position: {
|
||||
width: 750,
|
||||
height: 720,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
closeOnSubmit: false,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
navSelector: 'nav[data-group="primary"]',
|
||||
contentSelector: "section.sheet-body",
|
||||
initial: "principal",
|
||||
},
|
||||
],
|
||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
|
||||
actions: {
|
||||
editImage: YggdrasillActorSheet.#onEditImage,
|
||||
toggleSheet: YggdrasillActorSheet.#onToggleSheet,
|
||||
editItem: YggdrasillActorSheet.#onEditItem,
|
||||
deleteItem: YggdrasillActorSheet.#onDeleteItem,
|
||||
createItem: YggdrasillActorSheet.#onCreateItem,
|
||||
equipItem: YggdrasillActorSheet.#onEquipItem,
|
||||
rollCarac: YggdrasillActorSheet.#onRollCarac,
|
||||
rollCompetence: YggdrasillActorSheet.#onRollCompetence,
|
||||
rollArme: YggdrasillActorSheet.#onRollArme,
|
||||
rollSort: YggdrasillActorSheet.#onRollSort,
|
||||
rollProuesse: YggdrasillActorSheet.#onRollProuesse,
|
||||
rollDamage: YggdrasillActorSheet.#onRollDamage,
|
||||
lockUnlock: YggdrasillActorSheet.#onLockUnlock,
|
||||
incrementPV: YggdrasillActorSheet.#onIncrementPV,
|
||||
decrementPV: YggdrasillActorSheet.#onDecrementPV,
|
||||
updateCompetence: YggdrasillActorSheet.#onUpdateCompetence,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Play' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isPlayMode() {
|
||||
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.PLAY
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the sheet currently in 'Edit' mode?
|
||||
* @type {boolean}
|
||||
*/
|
||||
get isEditMode() {
|
||||
if (this._sheetMode === undefined) this._sheetMode = this.constructor.SHEET_MODES.PLAY
|
||||
return this._sheetMode === this.constructor.SHEET_MODES.EDIT
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab groups state
|
||||
* @type {object}
|
||||
*/
|
||||
tabGroups = {
|
||||
primary: "principal",
|
||||
}
|
||||
|
||||
/** @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,
|
||||
isGM: game.user.isGM,
|
||||
config: game.system.yggdrasill.config,
|
||||
editScore: this.isEditMode,
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
|
||||
// Activate tab navigation manually
|
||||
const nav = this.element.querySelector('nav.tabs[data-group], nav.sheet-tabs[data-group]')
|
||||
if (nav) {
|
||||
const group = nav.dataset.group
|
||||
// Activate the current tab
|
||||
const activeTab = this.tabGroups[group] || "principal"
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
const tab = link.dataset.tab
|
||||
link.classList.toggle('active', tab === activeTab)
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
this.tabGroups[group] = tab
|
||||
this.render()
|
||||
})
|
||||
})
|
||||
|
||||
// Show/hide tab content
|
||||
this.element.querySelectorAll('[data-group="' + group + '"][data-tab]').forEach(content => {
|
||||
content.classList.toggle('active', content.dataset.tab === activeTab)
|
||||
})
|
||||
}
|
||||
|
||||
// Add change listener for competence niveau selects
|
||||
this.element.querySelectorAll('select.competence-niveau').forEach(select => {
|
||||
select.addEventListener('change', async (event) => {
|
||||
const itemId = event.target.dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (item) {
|
||||
const newNiveau = parseInt(event.target.value)
|
||||
await item.update({ "system.niveau": newNiveau })
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates drag-and-drop handlers for this application
|
||||
* @returns {DragDrop[]} An array of DragDrop handlers
|
||||
* @private
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle changing a Document's image
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onEditImage(event, target) {
|
||||
const attr = target.dataset.edit
|
||||
const current = foundry.utils.getProperty(this.document, attr)
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: "image",
|
||||
callback: (path) => {
|
||||
this.document.update({ [attr]: path })
|
||||
},
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle sheet mode between Edit and Play
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onToggleSheet(event, target) {
|
||||
this._sheetMode = this.isEditMode
|
||||
? this.constructor.SHEET_MODES.PLAY
|
||||
: this.constructor.SHEET_MODES.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item editing
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onEditItem(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (item) item.sheet.render(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item deletion
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onDeleteItem(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (item) {
|
||||
await item.delete()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item creation
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onCreateItem(event, target) {
|
||||
const itemType = target.dataset.itemType
|
||||
const itemData = {
|
||||
name: `Nouveau ${itemType}`,
|
||||
type: itemType,
|
||||
}
|
||||
await this.document.createEmbeddedDocuments("Item", [itemData])
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle item equip toggle
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onEquipItem(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (item && item.system.equipe !== undefined) {
|
||||
await item.update({ "system.equipe": !item.system.equipe })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle characteristic roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollCarac(event, target) {
|
||||
const caracCateg = target.dataset.caracCateg
|
||||
const caracKey = target.dataset.caracKey
|
||||
this.document.rollCarac(caracCateg, caracKey)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle competence roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollCompetence(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
this.document.rollCompetence(itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle weapon roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollArme(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
this.document.rollArme(itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle lock/unlock toggle
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onLockUnlock(event, target) {
|
||||
this._sheetMode = this.isEditMode
|
||||
? this.constructor.SHEET_MODES.PLAY
|
||||
: this.constructor.SHEET_MODES.EDIT
|
||||
this.render()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle incrementing PV
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onIncrementPV(event, target) {
|
||||
const currentPV = this.document.system.caracsecondaire.pv.value || 0
|
||||
const maxPV = this.document.system.caracsecondaire.pv.max || 0
|
||||
const newPV = Math.min(currentPV + 1, maxPV)
|
||||
await this.document.update({ "system.caracsecondaire.pv.value": newPV })
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle decrementing PV
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onDecrementPV(event, target) {
|
||||
const currentPV = this.document.system.caracsecondaire.pv.value || 0
|
||||
const newPV = Math.max(currentPV - 1, 0)
|
||||
await this.document.update({ "system.caracsecondaire.pv.value": newPV })
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle competence niveau update
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {Event} event - The triggering event
|
||||
* @param {HTMLElement} target - The select element
|
||||
*/
|
||||
static async #onUpdateCompetence(event, target) {
|
||||
const itemId = target.dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (!item) return
|
||||
const newNiveau = parseInt(target.value)
|
||||
await item.update({ "system.niveau": newNiveau })
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle sort roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollSort(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
const sortType = target.dataset.sortType || "sejdr"
|
||||
this.document.rollSort(itemId, sortType)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle prouesse roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollProuesse(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
this.document.rollProuesse(itemId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle damage roll
|
||||
* @this {YggdrasillActorSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static #onRollDamage(event, target) {
|
||||
const itemId = target.closest("[data-item-id]").dataset.itemId
|
||||
const weapon = this.document.items.get(itemId)
|
||||
if (weapon) {
|
||||
this.document.rollDamage(weapon, 'damage')
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle beginning of a drag operation
|
||||
* @param {DragEvent} event - The originating drag event
|
||||
* @protected
|
||||
*/
|
||||
_onDragStart(event) {
|
||||
const li = event.currentTarget
|
||||
const itemId = li.dataset.itemId
|
||||
const item = this.document.items.get(itemId)
|
||||
if (!item) return
|
||||
|
||||
const dragData = item.toDragData()
|
||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a drop event
|
||||
* @param {DragEvent} event - The originating drop event
|
||||
* @protected
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
const data = TextEditor.getDragEventData(event)
|
||||
const actor = this.document
|
||||
|
||||
// Handle different data types
|
||||
switch (data.type) {
|
||||
case "Item":
|
||||
return this._onDropItem(event, data)
|
||||
case "ActiveEffect":
|
||||
return this._onDropActiveEffect(event, data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dropping an Item on the sheet
|
||||
* @param {DragEvent} event - The originating drop event
|
||||
* @param {object} data - The dropped data
|
||||
* @protected
|
||||
*/
|
||||
async _onDropItem(event, data) {
|
||||
if (!this.isEditable) return false
|
||||
const item = await Item.implementation.fromDropData(data)
|
||||
const itemData = item.toObject()
|
||||
|
||||
// Handle item from same actor
|
||||
if (this.document.uuid === item.parent?.uuid) return this._onSortItem(event, itemData)
|
||||
|
||||
// Create the item
|
||||
return this._onDropItemCreate(itemData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle creating an owned item from drop data
|
||||
* @param {object} itemData - The item data to create
|
||||
* @protected
|
||||
*/
|
||||
async _onDropItemCreate(itemData) {
|
||||
itemData = itemData instanceof Array ? itemData : [itemData]
|
||||
return this.document.createEmbeddedDocuments("Item", itemData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle sorting items
|
||||
* @param {DragEvent} event - The originating drop event
|
||||
* @param {object} itemData - The item data being sorted
|
||||
* @protected
|
||||
*/
|
||||
_onSortItem(event, itemData) {
|
||||
// Implement sorting logic if needed
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle dropping an ActiveEffect on the sheet
|
||||
* @param {DragEvent} event - The originating drop event
|
||||
* @param {object} data - The dropped data
|
||||
* @protected
|
||||
*/
|
||||
async _onDropActiveEffect(event, data) {
|
||||
const effect = await ActiveEffect.implementation.fromDropData(data)
|
||||
if (!this.isEditable || !effect) return false
|
||||
|
||||
if (this.document.uuid === effect.parent?.uuid) return false
|
||||
return ActiveEffect.create(effect.toObject(), { parent: this.document })
|
||||
}
|
||||
}
|
||||
178
modules/applications/sheets/base-item-sheet.mjs
Normal file
178
modules/applications/sheets/base-item-sheet.mjs
Normal file
@@ -0,0 +1,178 @@
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api
|
||||
|
||||
export default class YggdrasillItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
constructor(options = {}) {
|
||||
super(options)
|
||||
this.#dragDrop = this.#createDragDropHandlers()
|
||||
}
|
||||
|
||||
#dragDrop
|
||||
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-yggdrasill", "item"],
|
||||
position: {
|
||||
width: 620,
|
||||
height: 600,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
tabs: [
|
||||
{
|
||||
navSelector: 'nav[data-group="primary"]',
|
||||
contentSelector: "section.sheet-body",
|
||||
initial: "description",
|
||||
},
|
||||
],
|
||||
dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
|
||||
actions: {
|
||||
editImage: YggdrasillItemSheet.#onEditImage,
|
||||
postItem: YggdrasillItemSheet.#onPostItem,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab groups state
|
||||
* @type {object}
|
||||
*/
|
||||
tabGroups = { primary: "description" }
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
// Import config
|
||||
const YGGDRASILL_CONFIG = game.system.yggdrasill?.config || game.system.config || {};
|
||||
|
||||
// Create options for niveau 0-5
|
||||
const optionsNiveaux4 = {};
|
||||
for (let i = 0; i <= 5; i++) {
|
||||
optionsNiveaux4[`${i}`] = `${i}`;
|
||||
}
|
||||
|
||||
// Create options for base (0-20)
|
||||
const optionsBase = {};
|
||||
for (let i = 0; i <= 20; i++) {
|
||||
optionsBase[`${i}`] = `${i}`;
|
||||
}
|
||||
|
||||
const context = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
data: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description || "", { async: true }),
|
||||
enrichedEffet: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.effet || "", { async: true }),
|
||||
isEditMode: true,
|
||||
isEditable: this.isEditable,
|
||||
editable: this.isEditable,
|
||||
isGM: game.user.isGM,
|
||||
config: YGGDRASILL_CONFIG,
|
||||
optionsBase: optionsBase,
|
||||
optionsNiveaux4: optionsNiveaux4,
|
||||
}
|
||||
return context
|
||||
}
|
||||
|
||||
/** @override */
|
||||
_onRender(context, options) {
|
||||
super._onRender(context, options)
|
||||
|
||||
// Activate tab navigation manually
|
||||
const nav = this.element.querySelector('nav.tabs[data-group]')
|
||||
if (nav) {
|
||||
const group = nav.dataset.group
|
||||
// Activate the current tab
|
||||
const activeTab = this.tabGroups[group] || "description"
|
||||
nav.querySelectorAll('[data-tab]').forEach(link => {
|
||||
const tab = link.dataset.tab
|
||||
link.classList.toggle('active', tab === activeTab)
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault()
|
||||
this.tabGroups[group] = tab
|
||||
this.render()
|
||||
})
|
||||
})
|
||||
// Show/hide tab content
|
||||
const body = this.element.querySelector('section.sheet-body')
|
||||
if (body) {
|
||||
body.querySelectorAll('[data-tab]').forEach(content => {
|
||||
const tab = content.dataset.tab
|
||||
content.style.display = tab === activeTab ? 'block' : 'none'
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates drag-and-drop handlers for this application
|
||||
* @returns {DragDrop[]} An array of DragDrop handlers
|
||||
* @private
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle changing a Document's image
|
||||
* @this {YggdrasillItemSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onEditImage(event, target) {
|
||||
const attr = target.dataset.edit || "img"
|
||||
const current = foundry.utils.getProperty(this.document, attr)
|
||||
const fp = new FilePicker({
|
||||
current,
|
||||
type: "image",
|
||||
callback: (path) => {
|
||||
this.document.update({ [attr]: path })
|
||||
},
|
||||
})
|
||||
return fp.browse()
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle posting item to chat
|
||||
* @this {YggdrasillItemSheet}
|
||||
* @param {PointerEvent} event - The triggering event
|
||||
* @param {HTMLElement} target - The button element
|
||||
*/
|
||||
static async #onPostItem(event, target) {
|
||||
const item = this.document
|
||||
const chatData = {
|
||||
user: game.user.id,
|
||||
speaker: ChatMessage.getSpeaker(),
|
||||
content: await foundry.applications.handlebars.renderTemplate("systems/fvtt-yggdrasill/templates/chat-item-card.hbs", {
|
||||
item: item,
|
||||
system: item.system,
|
||||
description: await TextEditor.enrichHTML(item.system.description || "", { async: true })
|
||||
})
|
||||
}
|
||||
ChatMessage.create(chatData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle beginning of a drag operation
|
||||
* @param {DragEvent} event - The originating drag event
|
||||
* @protected
|
||||
*/
|
||||
_onDragStart(event) {
|
||||
const dragData = this.document.toDragData()
|
||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a drop event
|
||||
* @param {DragEvent} event - The originating drop event
|
||||
* @protected
|
||||
*/
|
||||
async _onDrop(event) {
|
||||
// Items generally don't handle drops, but method exists for extensibility
|
||||
return false
|
||||
}
|
||||
}
|
||||
44
modules/applications/sheets/create-sheets.sh
Executable file
44
modules/applications/sheets/create-sheets.sh
Executable file
@@ -0,0 +1,44 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Liste des types d'items restants à créer
|
||||
items=(
|
||||
"poison:Poison"
|
||||
"prouesse:Prouesse"
|
||||
"sortsejdr:Sortsejdr"
|
||||
"sortgaldr:Sortgaldr"
|
||||
"rune:Rune"
|
||||
"armecc:Armecc"
|
||||
"armedist:Armedist"
|
||||
"armure:Armure"
|
||||
"bouclier:Bouclier"
|
||||
"equipement:Equipement"
|
||||
"monnaie:Monnaie"
|
||||
"effetmagique:Effetmagique"
|
||||
)
|
||||
|
||||
for item in "${items[@]}"; do
|
||||
type="${item%%:*}"
|
||||
class="${item##*:}"
|
||||
|
||||
cat > "yggdrasill-${type}-sheet.mjs" << EOF
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class Yggdrasill${class}Sheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "${type}"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-${type}-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
EOF
|
||||
done
|
||||
|
||||
echo "Created all item sheets"
|
||||
ls -1 yggdrasill-*-sheet.mjs | wc -l
|
||||
16
modules/applications/sheets/yggdrasill-armecc-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-armecc-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillArmeccSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "armecc"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-armecc-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-armedist-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-armedist-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillArmedistSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "armedist"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-armedist-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-armure-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-armure-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillArmureSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "armure"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-armure-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-blessure-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-blessure-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillBlessureSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "blessure"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-blessure-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-bouclier-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-bouclier-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillBouclierSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "bouclier"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-bouclier-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
21
modules/applications/sheets/yggdrasill-competence-sheet.mjs
Normal file
21
modules/applications/sheets/yggdrasill-competence-sheet.mjs
Normal file
@@ -0,0 +1,21 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillCompetenceSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "competence"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-competence-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "details",
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-don-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-don-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillDonSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "don"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-don-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillEffetmagiqueSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "effetmagique"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-effetmagique-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-equipement-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-equipement-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillEquipementSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "equipement"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-equipement-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-faiblesse-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-faiblesse-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillFaiblesseSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "faiblesse"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-faiblesse-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
40
modules/applications/sheets/yggdrasill-figurant-sheet.mjs
Normal file
40
modules/applications/sheets/yggdrasill-figurant-sheet.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
import YggdrasillActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class YggdrasillFigurantSheet extends YggdrasillActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "figurant"],
|
||||
window: {
|
||||
...super.DEFAULT_OPTIONS.window,
|
||||
title: "Feuille de Figurant",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-yggdrasill/templates/actor-figurant-sheet.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "principal",
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const actor = this.document
|
||||
|
||||
// System fields for formInput helpers
|
||||
context.systemFields = actor.system.schema.fields
|
||||
|
||||
// Enrich HTML fields
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.notes || "", { async: true })
|
||||
|
||||
return context
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-maladie-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-maladie-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillMaladieSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "maladie"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-maladie-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-monnaie-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-monnaie-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillMonnaieSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "monnaie"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-monnaie-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
99
modules/applications/sheets/yggdrasill-personnage-sheet.mjs
Normal file
99
modules/applications/sheets/yggdrasill-personnage-sheet.mjs
Normal file
@@ -0,0 +1,99 @@
|
||||
import YggdrasillActorSheet from "./base-actor-sheet.mjs"
|
||||
|
||||
export default class YggdrasillPersonnageSheet extends YggdrasillActorSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "personnage"],
|
||||
window: {
|
||||
...super.DEFAULT_OPTIONS.window,
|
||||
title: "Feuille de Personnage",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-yggdrasill/templates/actor-personnage-sheet-new.hbs",
|
||||
},
|
||||
}
|
||||
|
||||
/** @override */
|
||||
tabGroups = {
|
||||
primary: "principal",
|
||||
}
|
||||
|
||||
/** @override */
|
||||
async _prepareContext() {
|
||||
const context = await super._prepareContext()
|
||||
const actor = this.document
|
||||
|
||||
// Prepare items by type
|
||||
context.competencesGenerales = actor.items.filter(i => i.type === 'competence' && i.system.categorie === 'generale')
|
||||
context.competencesMartiales = actor.items.filter(i => i.type === 'competence' && i.system.categorie === 'martiale')
|
||||
context.competencesMagiques = actor.items.filter(i => i.type === 'competence' && i.system.categorie === 'magique')
|
||||
context.dons = actor.items.filter(i => i.type === 'don')
|
||||
context.faiblesses = actor.items.filter(i => i.type === 'faiblesse')
|
||||
context.blessures = actor.items.filter(i => i.type === 'blessure')
|
||||
context.maladies = actor.items.filter(i => i.type === 'maladie')
|
||||
context.poisons = actor.items.filter(i => i.type === 'poison')
|
||||
context.prouesses = actor.items.filter(i => i.type === 'prouesse')
|
||||
context.sortsSejdr = actor.items.filter(i => i.type === 'sortsejdr')
|
||||
context.sortsGaldr = actor.items.filter(i => i.type === 'sortgaldr')
|
||||
context.runes = actor.items.filter(i => i.type === 'rune')
|
||||
context.armesCC = actor.items.filter(i => i.type === 'armecc')
|
||||
context.armesDist = actor.items.filter(i => i.type === 'armedist')
|
||||
context.armures = actor.items.filter(i => i.type === 'armure')
|
||||
context.boucliers = actor.items.filter(i => i.type === 'bouclier')
|
||||
context.equipements = actor.items.filter(i => i.type === 'equipement')
|
||||
context.monnaies = actor.items.filter(i => i.type === 'monnaie')
|
||||
context.effetsMagiques = actor.items.filter(i => i.type === 'effetmagique')
|
||||
|
||||
// Prepare equipped items
|
||||
context.armesEquipees = actor.items.filter(i => (i.type === 'armecc' || i.type === 'armedist') && i.system.equipe)
|
||||
context.armureEquipee = actor.items.find(i => i.type === 'armure' && i.system.equipe)
|
||||
context.bouclierEquipe = actor.items.find(i => i.type === 'bouclier' && i.system.equipe)
|
||||
|
||||
// Calculate total protection from equipped armors
|
||||
context.protectionTotal = context.armures
|
||||
.filter(a => a.system.equipe)
|
||||
.reduce((sum, a) => sum + (parseInt(a.system.protection) || 0), 0)
|
||||
|
||||
// Calculate shield defense bonus from equipped shield
|
||||
context.dpBouclier = context.boucliers
|
||||
.filter(b => b.system.equipe)
|
||||
.reduce((sum, b) => sum + (parseInt(b.system.defensebonus) || 0), 0)
|
||||
|
||||
// Calculate total encumbrance from equipements
|
||||
context.encTotal = context.equipements
|
||||
.reduce((sum, e) => sum + ((parseInt(e.system.quantite) || 0) * (parseInt(e.system.enc) || 0)), 0)
|
||||
|
||||
// Options for selects
|
||||
context.optionsCarac = {}
|
||||
for (let i = 0; i <= 10; i++) {
|
||||
context.optionsCarac[i] = i.toString()
|
||||
}
|
||||
|
||||
context.optionsBase = {}
|
||||
for (let i = 0; i <= 5; i++) {
|
||||
context.optionsBase[i] = i.toString()
|
||||
}
|
||||
|
||||
// Options for bonus/malus (-10 to +10)
|
||||
context.optionsDMDP = []
|
||||
for (let i = -10; i <= 10; i++) {
|
||||
context.optionsDMDP.push({ value: i, text: i >= 0 ? `+${i}` : i.toString() })
|
||||
}
|
||||
|
||||
// System fields for formInput helpers
|
||||
context.systemFields = actor.system.schema.fields
|
||||
|
||||
// Enrich HTML fields
|
||||
context.enrichedDescription = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.description || "", { async: true })
|
||||
context.enrichedNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.notes || "", { async: true })
|
||||
context.enrichedGMNotes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.gmnotes || "", { async: true })
|
||||
context.enrichedTirageRunes = await foundry.applications.ux.TextEditor.implementation.enrichHTML(actor.system.biodata?.tiragerunes || "", { async: true })
|
||||
|
||||
return context
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-poison-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-poison-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillPoisonSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "poison"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-poison-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-prouesse-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-prouesse-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillProuesseSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "prouesse"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-prouesse-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-rune-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-rune-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillRuneSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "rune"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-rune-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-sortgaldr-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-sortgaldr-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillSortgaldrSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "sortgaldr"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-sortgaldr-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
16
modules/applications/sheets/yggdrasill-sortsejdr-sheet.mjs
Normal file
16
modules/applications/sheets/yggdrasill-sortsejdr-sheet.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import YggdrasillItemSheet from "./base-item-sheet.mjs"
|
||||
|
||||
export default class YggdrasillSortsejdrSheet extends YggdrasillItemSheet {
|
||||
/** @override */
|
||||
static DEFAULT_OPTIONS = {
|
||||
...super.DEFAULT_OPTIONS,
|
||||
classes: [...super.DEFAULT_OPTIONS.classes, "sortsejdr"],
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static PARTS = {
|
||||
main: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-sortsejdr-sheet.hbs",
|
||||
},
|
||||
}
|
||||
}
|
||||
334
modules/applications/yggdrasill-roll-dialog.mjs
Normal file
334
modules/applications/yggdrasill-roll-dialog.mjs
Normal file
@@ -0,0 +1,334 @@
|
||||
import { YggdrasillUtility } from "../yggdrasill-utility.js"
|
||||
|
||||
const dureeGaldrSD = { "1d5a": 3, "1d10t": 6, "1d10m": 9, "1d10h": 12, "1d5j": 15}
|
||||
const ciblesGaldrSD = { "1": 3, "2_4": 6, "5_9": 9, "10_49": 12, "50plus": 15}
|
||||
const zonesciblesGaldrSD = { "INS10cm3": 3, "INS50cm3": 6, "INS1m3": 9, "INS5m3": 12, "INS10m3": 15}
|
||||
|
||||
/**
|
||||
* Dialogue de jet de dé pour Yggdrasill - Version DialogV2
|
||||
*/
|
||||
export class YggdrasillRollDialog {
|
||||
|
||||
/**
|
||||
* Create and display the roll dialog
|
||||
* @param {YggdrasillActor} actor - The actor making the roll
|
||||
* @param {Object} rollData - Data for the roll
|
||||
* @returns {Promise}
|
||||
*/
|
||||
static async create(actor, rollData) {
|
||||
// Initialiser attackData pour les armes si nécessaire
|
||||
if ((rollData.mode === "armecc" || rollData.mode === "armetir" || rollData.mode === "armedist") && rollData.attackDef) {
|
||||
// Les données sont déjà calculées dans attackDef par getAttaqueData/getTirData
|
||||
// On les copie simplement dans attackData pour le template
|
||||
rollData.attackData = { ...rollData.attackDef }
|
||||
}
|
||||
|
||||
// Calculer srTotal pour les sorts
|
||||
if (rollData.mode === "galdr") {
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
} else if (rollData.mode === "sejdr") {
|
||||
rollData.srTotal = 14 + (rollData.bonusdefense || 0)
|
||||
} else if (rollData.mode === "rune") {
|
||||
this._updateRuneData(rollData, actor)
|
||||
}
|
||||
|
||||
// Préparer le contexte pour le template
|
||||
const context = {
|
||||
...rollData,
|
||||
img: actor.img,
|
||||
name: actor.name,
|
||||
config: game.system.yggdrasill.config,
|
||||
}
|
||||
|
||||
// Titre selon le mode
|
||||
let title = "Test"
|
||||
if (rollData.mode === "competence") title = "Test de Compétence"
|
||||
else if (rollData.mode === "carac") title = "Test de Caractéristique"
|
||||
else if (rollData.mode === "attribut") title = "Test d'Attribut"
|
||||
else if (rollData.mode === "armecc") title = "Attaque au Corps à Corps"
|
||||
else if (rollData.mode === "armetir" || rollData.mode === "armedist") title = "Attaque à Distance"
|
||||
else if (rollData.mode === "sejdr") title = "Sort Sejdr"
|
||||
else if (rollData.mode === "galdr") title = "Sort Galdr"
|
||||
else if (rollData.mode === "rune") title = "Rune"
|
||||
|
||||
// Rendre le template en HTML
|
||||
const content = await foundry.applications.handlebars.renderTemplate(
|
||||
"systems/fvtt-yggdrasill/templates/roll-dialog-generic-new.hbs",
|
||||
context
|
||||
)
|
||||
|
||||
// Utiliser DialogV2.wait avec le HTML rendu
|
||||
return foundry.applications.api.DialogV2.wait({
|
||||
window: {
|
||||
title: title,
|
||||
icon: "fa-solid fa-dice-d20"
|
||||
},
|
||||
classes: ["yggdrasill-roll-dialog"],
|
||||
position: { width: 600 },
|
||||
modal: false,
|
||||
content,
|
||||
buttons: [
|
||||
{
|
||||
action: "roll",
|
||||
label: "Lancer le Test",
|
||||
icon: "fa-solid fa-dice",
|
||||
default: true,
|
||||
callback: (event, button, dialog) => {
|
||||
this._updateRollDataFromForm(rollData, button.form.elements, actor)
|
||||
this._performRoll(rollData)
|
||||
}
|
||||
},
|
||||
],
|
||||
actions: {},
|
||||
render: (event, dialog) => {
|
||||
// Pour Galdr: recalculer srTotal quand durée, cibles ou zone changent
|
||||
if (rollData.mode === "galdr") {
|
||||
$("#dureeGaldr, #nbCibles, #zoneGaldr").on("change", () => {
|
||||
rollData.dureeGaldr = $("#dureeGaldr").val()
|
||||
rollData.nbCibles = $("#nbCibles").val()
|
||||
rollData.zoneGaldr = $("#zoneGaldr").val()
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
|
||||
// Pour Sejdr: recalculer srTotal quand DM change
|
||||
if (rollData.mode === "sejdr") {
|
||||
$("#bonusdefense").on("change", () => {
|
||||
rollData.bonusdefense = parseInt($("#bonusdefense").val()) || 0
|
||||
rollData.srTotal = 14 + rollData.bonusdefense
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
|
||||
// Pour Rune: recalculer srTotal quand support ou puissance changent
|
||||
if (rollData.mode === "rune") {
|
||||
$("#supportRune, #puissanceRune").on("change", () => {
|
||||
rollData.supportRune = $("#supportRune").val()
|
||||
rollData.puissanceRune = parseInt($("#puissanceRune").val()) || 1
|
||||
this._updateRuneData(rollData, actor)
|
||||
$("#runeDuree").text(rollData.runeDuree)
|
||||
$("#runeDureeVie").text(rollData.runeDureeVie)
|
||||
$("#srTotal").text(rollData.srTotal)
|
||||
})
|
||||
}
|
||||
},
|
||||
rejectClose: false,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the roll based on mode
|
||||
* @param {Object} rollData - The roll data
|
||||
* @private
|
||||
*/
|
||||
static _performRoll(rollData) {
|
||||
if (rollData.mode === "attribut") {
|
||||
YggdrasillUtility.rollAttribute(rollData)
|
||||
} else {
|
||||
YggdrasillUtility.rollYggdrasill(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mettre à jour rollData avec les valeurs du formulaire
|
||||
* @param {Object} rollData - L'objet rollData à mettre à jour
|
||||
* @param {HTMLFormControlsCollection} formElements - Les éléments du formulaire
|
||||
* @param {YggdrasillActor} actor - L'acteur pour récupérer les données
|
||||
* @private
|
||||
*/
|
||||
static _updateRollDataFromForm(rollData, formElements, actor) {
|
||||
// Caractéristique (pour compétences)
|
||||
if (formElements.caracName) {
|
||||
const caracKey = formElements.caracName.value
|
||||
rollData.caracName = caracKey
|
||||
rollData.selectedCarac = this._findCaracByKey(actor, caracKey)
|
||||
}
|
||||
|
||||
// Type d'attaque (pour armes)
|
||||
if (formElements.typeAttack) {
|
||||
rollData.attackDef = rollData.attackDef || {}
|
||||
rollData.attackDef.typeAttack = formElements.typeAttack.value
|
||||
this._updateAttackData(rollData, actor)
|
||||
}
|
||||
|
||||
// Bonus/Malus
|
||||
if (formElements.bonusMalus) {
|
||||
rollData.bonusMalus = parseInt(formElements.bonusMalus.value) || 0
|
||||
}
|
||||
|
||||
// Furor
|
||||
if (formElements.furorUsage) {
|
||||
rollData.furorUsage = parseInt(formElements.furorUsage.value) || 0
|
||||
}
|
||||
|
||||
// Seuil de Réussite
|
||||
if (formElements.sr) {
|
||||
rollData.sr = parseInt(formElements.sr.value) || 9
|
||||
}
|
||||
|
||||
// Galdr options
|
||||
if (formElements.dureeGaldr) {
|
||||
rollData.dureeGaldr = formElements.dureeGaldr.value
|
||||
}
|
||||
if (formElements.nbCibles) {
|
||||
rollData.nbCibles = formElements.nbCibles.value
|
||||
}
|
||||
if (formElements.zoneGaldr) {
|
||||
rollData.zoneGaldr = formElements.zoneGaldr.value
|
||||
}
|
||||
if (rollData.mode === "galdr") {
|
||||
this._updateGaldrSD(rollData)
|
||||
rollData.srTotal = 14 + (rollData.sdGaldr || 0)
|
||||
}
|
||||
|
||||
// Sejdr options
|
||||
if (formElements.bonusdefense) {
|
||||
rollData.bonusdefense = parseInt(formElements.bonusdefense.value) || 0
|
||||
}
|
||||
if (rollData.mode === "sejdr") {
|
||||
rollData.srTotal = 14 + (rollData.bonusdefense || 0)
|
||||
}
|
||||
|
||||
// Rune options
|
||||
if (formElements.runeDuree) {
|
||||
rollData.runeDuree = formElements.runeDuree.value
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find characteristic by key in actor
|
||||
* @param {YggdrasillActor} actor
|
||||
* @param {String} caracKey
|
||||
* @returns {Object}
|
||||
* @private
|
||||
*/
|
||||
static _findCaracByKey(actor, caracKey) {
|
||||
for (let [categKey, categ] of Object.entries(actor.system.carac)) {
|
||||
for (let [key, carac] of Object.entries(categ.carac)) {
|
||||
if (key === caracKey) {
|
||||
return { ...carac, categName: categKey, caracName: key }
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Update attack data based on attack type
|
||||
* @param {Object} rollData
|
||||
* @param {YggdrasillActor} actor
|
||||
* @private
|
||||
*/
|
||||
static _updateAttackData(rollData, actor) {
|
||||
const config = game.system.yggdrasill.config
|
||||
const attackType = rollData.attackDef.typeAttack
|
||||
const attackMode = config.attackMode?.[attackType]
|
||||
|
||||
if (attackMode) {
|
||||
rollData.attackData = rollData.attackData || {}
|
||||
rollData.attackData.categName = attackMode.categName
|
||||
rollData.attackData.caracName = attackMode.caracName
|
||||
rollData.attackData.malus = this._computeValue(attackMode.malus, actor)
|
||||
rollData.attackData.bonusdegats = this._computeValue(attackMode.bonusdegats, actor)
|
||||
rollData.attackData.protection = this._computeValue(attackMode.protection, actor)
|
||||
rollData.attackData.label = attackMode.label
|
||||
rollData.attackData.description = attackMode.description
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute value from string formula like "puissance;3"
|
||||
* @param {String|Number} value
|
||||
* @param {YggdrasillActor} actor
|
||||
* @returns {Number}
|
||||
* @private
|
||||
*/
|
||||
static _computeValue(value, actor) {
|
||||
if (typeof value === 'number') return value
|
||||
if (!value || value === "0") return 0
|
||||
|
||||
const parts = String(value).split(';')
|
||||
if (parts.length === 2) {
|
||||
const caracName = parts[0]
|
||||
const multiplier = parseInt(parts[1]) || 1
|
||||
const caracValue = this._getCaracValue(actor, caracName)
|
||||
return caracValue * multiplier
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Get characteristic value by name
|
||||
* @param {YggdrasillActor} actor
|
||||
* @param {String} caracName
|
||||
* @returns {Number}
|
||||
* @private
|
||||
*/
|
||||
static _getCaracValue(actor, caracName) {
|
||||
for (let categ of Object.values(actor.system.carac)) {
|
||||
if (categ.carac && categ.carac[caracName]) {
|
||||
return categ.carac[caracName].value || 0
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Update rune data based on support and power
|
||||
* @param {Object} rollData
|
||||
* @param {YggdrasillActor} actor
|
||||
* @private
|
||||
*/
|
||||
static _updateRuneData(rollData, actor) {
|
||||
let support = 0
|
||||
|
||||
rollData.dureeRune = 6 - (rollData.agiliteCarac?.value || 0)
|
||||
|
||||
if (rollData.supportRune === "peau") {
|
||||
support = 3
|
||||
rollData.echelleDuree = "Actions"
|
||||
rollData.echelleDureeVie = "Heures"
|
||||
} else if (rollData.supportRune === "tissu") {
|
||||
support = 6
|
||||
rollData.echelleDuree = "Tours"
|
||||
rollData.echelleDureeVie = "Jours"
|
||||
} else if (rollData.supportRune === "cuir") {
|
||||
support = 9
|
||||
rollData.echelleDuree = "Minutes"
|
||||
rollData.echelleDureeVie = "Semaines"
|
||||
} else if (rollData.supportRune === "bois") {
|
||||
support = 12
|
||||
rollData.echelleDuree = "Heures"
|
||||
rollData.echelleDureeVie = "Mois"
|
||||
} else if (rollData.supportRune === "pierremetal") {
|
||||
support = 15
|
||||
rollData.echelleDuree = "Jours"
|
||||
rollData.echelleDureeVie = "Années"
|
||||
}
|
||||
|
||||
rollData.runeDuree = `${rollData.dureeRune} ${rollData.echelleDuree}`
|
||||
rollData.runeDureeVie = `${rollData.competence?.system.niveau || 1} ${rollData.echelleDureeVie}`
|
||||
rollData.srTotal = (rollData.puissanceRune || 1) + (Number(rollData.sort?.system.niveau || 0) * 3) + support
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Galdr SD based on duration and targets
|
||||
* @param {Object} rollData
|
||||
* @private
|
||||
*/
|
||||
static _updateGaldrSD(rollData) {
|
||||
let sdDuree = Number(dureeGaldrSD[rollData.dureeGaldr]) || 0
|
||||
let sdVar = 0
|
||||
|
||||
if (rollData.sort?.system.voie === "illusion") {
|
||||
sdVar = Number(zonesciblesGaldrSD[rollData.zoneGaldr]) || 0
|
||||
} else {
|
||||
sdVar = Number(ciblesGaldrSD[rollData.nbCibles]) || 0
|
||||
}
|
||||
|
||||
rollData.sdGaldr = sdDuree + sdVar
|
||||
}
|
||||
}
|
||||
17
modules/models/armecc.mjs
Normal file
17
modules/models/armecc.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Data model pour les armes de corps à corps
|
||||
*/
|
||||
export default class ArmeccDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
equipe: new fields.BooleanField({ initial: false }),
|
||||
degat: new fields.NumberField({ initial: 0, integer: true }),
|
||||
solidite: new fields.NumberField({ initial: 0, integer: true }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
valeur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
18
modules/models/armedist.mjs
Normal file
18
modules/models/armedist.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Data model pour les armes à distance
|
||||
*/
|
||||
export default class ArmedistDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
equipe: new fields.BooleanField({ initial: false }),
|
||||
degat: new fields.NumberField({ initial: 0, integer: true }),
|
||||
solidite: new fields.NumberField({ initial: 0, integer: true }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
portee: new fields.StringField({ initial: "" }),
|
||||
valeur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
16
modules/models/armure.mjs
Normal file
16
modules/models/armure.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Data model pour les armures
|
||||
*/
|
||||
export default class ArmureDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
equipe: new fields.BooleanField({ initial: false }),
|
||||
protection: new fields.StringField({ initial: "" }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
valeur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
11
modules/models/blessure.mjs
Normal file
11
modules/models/blessure.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Data model pour les blessures
|
||||
*/
|
||||
export default class BlessureDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
18
modules/models/bouclier.mjs
Normal file
18
modules/models/bouclier.mjs
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* Data model pour les boucliers
|
||||
*/
|
||||
export default class BouclierDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
equipe: new fields.BooleanField({ initial: false }),
|
||||
defensebonus: new fields.NumberField({ initial: 0, integer: true }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
enccomb: new fields.NumberField({ initial: 0, integer: true }),
|
||||
solidite: new fields.NumberField({ initial: 0, integer: true }),
|
||||
valeur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
16
modules/models/competence.mjs
Normal file
16
modules/models/competence.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Data model pour les compétences
|
||||
*/
|
||||
export default class CompetenceDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
isspecialisation: new fields.BooleanField({ initial: false }),
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
specialisation: new fields.StringField({ initial: "" }),
|
||||
description: new fields.HTMLField({ initial: "" }),
|
||||
niveau: new fields.NumberField({ initial: 0, integer: true }),
|
||||
niveauunrequis: new fields.BooleanField({ initial: false })
|
||||
};
|
||||
}
|
||||
}
|
||||
11
modules/models/don.mjs
Normal file
11
modules/models/don.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Data model pour les dons
|
||||
*/
|
||||
export default class DonDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
12
modules/models/effetmagique.mjs
Normal file
12
modules/models/effetmagique.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Data model pour les effets magiques
|
||||
*/
|
||||
export default class EffetmagiqueDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
origine: new fields.StringField({ initial: "" }),
|
||||
effet: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
15
modules/models/equipement.mjs
Normal file
15
modules/models/equipement.mjs
Normal file
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Data model pour l'équipement
|
||||
*/
|
||||
export default class EquipementDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
equipe: new fields.BooleanField({ initial: false }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
valeur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
quantite: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
11
modules/models/faiblesse.mjs
Normal file
11
modules/models/faiblesse.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
/**
|
||||
* Data model pour les faiblesses
|
||||
*/
|
||||
export default class FaiblesseDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
87
modules/models/figurant.mjs
Normal file
87
modules/models/figurant.mjs
Normal file
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Data model pour les figurants
|
||||
*/
|
||||
export default class FigurantDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
biodata: new fields.SchemaField({
|
||||
age: new fields.NumberField({ initial: 0, integer: true }),
|
||||
taille: new fields.StringField({ initial: "" }),
|
||||
description: new fields.HTMLField({ initial: "" }),
|
||||
poids: new fields.NumberField({ initial: 0, integer: true }),
|
||||
notes: new fields.HTMLField({ initial: "" })
|
||||
}),
|
||||
attributs: new fields.SchemaField({
|
||||
conflit: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
offensif: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Offensif" }),
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
degats: new fields.BooleanField({ initial: true })
|
||||
}),
|
||||
defensif: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Défensif" }),
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: false }),
|
||||
label: new fields.StringField({ initial: "Conflit" })
|
||||
}),
|
||||
relationnel: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
defaut: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: true }),
|
||||
label: new fields.StringField({ initial: "Relationnel" })
|
||||
}),
|
||||
physique: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
defaut: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: true }),
|
||||
label: new fields.StringField({ initial: "Physique" })
|
||||
}),
|
||||
mental: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
defaut: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: true }),
|
||||
label: new fields.StringField({ initial: "Mental" })
|
||||
}),
|
||||
mystique: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
actif: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Actif" }),
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
}),
|
||||
passif: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Passif" }),
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: false }),
|
||||
label: new fields.StringField({ initial: "Mystique" })
|
||||
}),
|
||||
vitalite: new fields.SchemaField({
|
||||
values: new fields.SchemaField({
|
||||
defaut: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true })
|
||||
})
|
||||
}),
|
||||
rollable: new fields.BooleanField({ initial: false }),
|
||||
label: new fields.StringField({ initial: "Vitalité" })
|
||||
})
|
||||
}),
|
||||
etat: new fields.SchemaField({
|
||||
etat: new fields.StringField({ initial: "fringant" })
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
27
modules/models/index.mjs
Normal file
27
modules/models/index.mjs
Normal file
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Index des DataModels pour Yggdrasill
|
||||
* Ce fichier centralise tous les exports des modèles de données
|
||||
*/
|
||||
|
||||
// Modèles d'acteurs
|
||||
export { default as PersonnageDataModel } from './personnage.mjs';
|
||||
export { default as FigurantDataModel } from './figurant.mjs';
|
||||
|
||||
// Modèles d'items
|
||||
export { default as CompetenceDataModel } from './competence.mjs';
|
||||
export { default as DonDataModel } from './don.mjs';
|
||||
export { default as FaiblesseDataModel } from './faiblesse.mjs';
|
||||
export { default as BlessureDataModel } from './blessure.mjs';
|
||||
export { default as MaladieDataModel } from './maladie.mjs';
|
||||
export { default as PoisonDataModel } from './poison.mjs';
|
||||
export { default as ProuesseDataModel } from './prouesse.mjs';
|
||||
export { default as SortsejdrDataModel } from './sortsejdr.mjs';
|
||||
export { default as SortgaldrDataModel } from './sortgaldr.mjs';
|
||||
export { default as RuneDataModel } from './rune.mjs';
|
||||
export { default as ArmeccDataModel } from './armecc.mjs';
|
||||
export { default as ArmedistDataModel } from './armedist.mjs';
|
||||
export { default as ArmureDataModel } from './armure.mjs';
|
||||
export { default as BouclierDataModel } from './bouclier.mjs';
|
||||
export { default as EquipementDataModel } from './equipement.mjs';
|
||||
export { default as MonnaieDataModel } from './monnaie.mjs';
|
||||
export { default as EffetmagiqueDataModel } from './effetmagique.mjs';
|
||||
13
modules/models/maladie.mjs
Normal file
13
modules/models/maladie.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Data model pour les maladies
|
||||
*/
|
||||
export default class MaladieDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
periode: new fields.StringField({ initial: "" }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
13
modules/models/monnaie.mjs
Normal file
13
modules/models/monnaie.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Data model pour la monnaie
|
||||
*/
|
||||
export default class MonnaieDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
quantite: new fields.NumberField({ initial: 0, integer: true }),
|
||||
enc: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
158
modules/models/personnage.mjs
Normal file
158
modules/models/personnage.mjs
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* Data model pour les personnages
|
||||
*/
|
||||
export default class PersonnageDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
biodata: new fields.SchemaField({
|
||||
nom: new fields.StringField({ initial: "" }),
|
||||
archetype: new fields.StringField({ initial: "" }),
|
||||
profession: new fields.StringField({ initial: "" }),
|
||||
royaume: new fields.StringField({ initial: "" }),
|
||||
age: new fields.NumberField({ initial: 0, integer: true }),
|
||||
taille: new fields.NumberField({ initial: 0, integer: true }),
|
||||
poids: new fields.NumberField({ initial: 0, integer: true }),
|
||||
don: new fields.StringField({ initial: "" }),
|
||||
faiblesse: new fields.StringField({ initial: "" }),
|
||||
pointlegende: new fields.NumberField({ initial: 0, integer: true }),
|
||||
renomee: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" }),
|
||||
notes: new fields.HTMLField({ initial: "" }),
|
||||
tiragerunes: new fields.StringField({ initial: "" }),
|
||||
gmnotes: new fields.HTMLField({ initial: "" })
|
||||
}),
|
||||
carac: new fields.SchemaField({
|
||||
corps: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Corps" }),
|
||||
carac: new fields.SchemaField({
|
||||
puissance: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Puissance" }),
|
||||
categorie: new fields.StringField({ initial: "corps" }),
|
||||
abbrev: new fields.StringField({ initial: "pui" })
|
||||
}),
|
||||
vigueur: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Vigueur" }),
|
||||
categorie: new fields.StringField({ initial: "corps" }),
|
||||
abbrev: new fields.StringField({ initial: "vig" })
|
||||
}),
|
||||
agilite: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Agilité" }),
|
||||
categorie: new fields.StringField({ initial: "corps" }),
|
||||
abbrev: new fields.StringField({ initial: "agi" })
|
||||
})
|
||||
})
|
||||
}),
|
||||
esprit: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Esprit" }),
|
||||
carac: new fields.SchemaField({
|
||||
intellect: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Intellect" }),
|
||||
categorie: new fields.StringField({ initial: "esprit" }),
|
||||
abbrev: new fields.StringField({ initial: "int" })
|
||||
}),
|
||||
perception: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Perception" }),
|
||||
categorie: new fields.StringField({ initial: "esprit" }),
|
||||
abbrev: new fields.StringField({ initial: "per" })
|
||||
}),
|
||||
tenacite: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Tenacité" }),
|
||||
categorie: new fields.StringField({ initial: "esprit" }),
|
||||
abbrev: new fields.StringField({ initial: "ten" })
|
||||
})
|
||||
})
|
||||
}),
|
||||
ame: new fields.SchemaField({
|
||||
label: new fields.StringField({ initial: "Ame" }),
|
||||
carac: new fields.SchemaField({
|
||||
charisme: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Charisme" }),
|
||||
categorie: new fields.StringField({ initial: "ame" }),
|
||||
abbrev: new fields.StringField({ initial: "cha" })
|
||||
}),
|
||||
communication: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Communication" }),
|
||||
categorie: new fields.StringField({ initial: "ame" }),
|
||||
abbrev: new fields.StringField({ initial: "com" })
|
||||
}),
|
||||
instinct: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Instinct" }),
|
||||
categorie: new fields.StringField({ initial: "ame" }),
|
||||
abbrev: new fields.StringField({ initial: "ins" })
|
||||
})
|
||||
})
|
||||
})
|
||||
}),
|
||||
furor: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 1, integer: true }),
|
||||
max: new fields.NumberField({ initial: 1, integer: true }),
|
||||
label: new fields.StringField({ initial: "Furor" })
|
||||
}),
|
||||
xp: new fields.SchemaField({
|
||||
total: new fields.NumberField({ initial: 1, integer: true }),
|
||||
current: new fields.NumberField({ initial: 1, integer: true }),
|
||||
label: new fields.StringField({ initial: "XP" })
|
||||
}),
|
||||
renommee: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 1, integer: true }),
|
||||
label: new fields.StringField({ initial: "Renommée" })
|
||||
}),
|
||||
status: new fields.SchemaField({
|
||||
epuise: new fields.BooleanField({ initial: false }),
|
||||
blesse: new fields.BooleanField({ initial: false }),
|
||||
meurtri: new fields.BooleanField({ initial: false })
|
||||
}),
|
||||
caracsecondaire: new fields.SchemaField({
|
||||
reaction: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
max: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Réaction" }),
|
||||
abbrev: new fields.StringField({ initial: "rea" })
|
||||
}),
|
||||
defensephy: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
bonusmalus: new fields.NumberField({ initial: 0, integer: true }),
|
||||
max: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Défense Physique" }),
|
||||
abbrev: new fields.StringField({ initial: "dp" })
|
||||
}),
|
||||
defensemen: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
bonusmalus: new fields.NumberField({ initial: 0, integer: true }),
|
||||
max: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Défense Mentale" }),
|
||||
abbrev: new fields.StringField({ initial: "dm" })
|
||||
}),
|
||||
deplacement: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
max: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Déplacement" }),
|
||||
abbrev: new fields.StringField({ initial: "dep" })
|
||||
}),
|
||||
capaenc: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 0, integer: true }),
|
||||
max: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Capacité d'Encombrement" }),
|
||||
abbrev: new fields.StringField({ initial: "cpe" })
|
||||
}),
|
||||
pv: new fields.SchemaField({
|
||||
value: new fields.NumberField({ initial: 10, integer: true }),
|
||||
max: new fields.NumberField({ initial: 10, integer: true }),
|
||||
min: new fields.NumberField({ initial: 0, integer: true }),
|
||||
label: new fields.StringField({ initial: "Points de Vie" }),
|
||||
abbrev: new fields.StringField({ initial: "pv" })
|
||||
})
|
||||
})
|
||||
};
|
||||
}
|
||||
}
|
||||
13
modules/models/poison.mjs
Normal file
13
modules/models/poison.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Data model pour les poisons
|
||||
*/
|
||||
export default class PoisonDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
type: new fields.StringField({ initial: "" }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
16
modules/models/prouesse.mjs
Normal file
16
modules/models/prouesse.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Data model pour les prouesses
|
||||
*/
|
||||
export default class ProuesseDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
categorie: new fields.StringField({ initial: "" }),
|
||||
niveau: new fields.NumberField({ initial: 0, integer: true }),
|
||||
armes: new fields.StringField({ initial: "" }),
|
||||
prerequis: new fields.StringField({ initial: "" }),
|
||||
modificateur: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
12
modules/models/rune.mjs
Normal file
12
modules/models/rune.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Data model pour les runes
|
||||
*/
|
||||
export default class RuneDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
niveau: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
13
modules/models/sortgaldr.mjs
Normal file
13
modules/models/sortgaldr.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Data model pour les sorts Galdr
|
||||
*/
|
||||
export default class SortgaldrDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
voie: new fields.StringField({ initial: "" }),
|
||||
sd: new fields.NumberField({ initial: 0, integer: true }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
17
modules/models/sortsejdr.mjs
Normal file
17
modules/models/sortsejdr.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Data model pour les sorts Sejdr
|
||||
*/
|
||||
export default class SortsejdrDataModel extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields;
|
||||
return {
|
||||
forme: new fields.StringField({ initial: "" }),
|
||||
preparation: new fields.StringField({ initial: "" }),
|
||||
niveau: new fields.NumberField({ initial: 0, integer: true }),
|
||||
malus: new fields.NumberField({ initial: 0, integer: true }),
|
||||
duree: new fields.StringField({ initial: "" }),
|
||||
zone: new fields.StringField({ initial: "" }),
|
||||
description: new fields.HTMLField({ initial: "" })
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/* -------------------------------------------- */
|
||||
import { YggdrasillUtility } from "./yggdrasill-utility.js";
|
||||
import { YggdrasillRoll } from "./yggdrasill-roll-dialog.js";
|
||||
import { YggdrasillRollDialog } from "./applications/yggdrasill-roll-dialog.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const statusEffects = [
|
||||
@@ -441,45 +441,37 @@ export class YggdrasillActor extends Actor {
|
||||
let sumame = baseame.charisme.value + baseame.communication.value + baseame.instinct.value
|
||||
|
||||
let newPV = (sumcorps*3) + (sumesprit *2) + sumame;
|
||||
if ( newPV != this.system.caracsecondaire.pv.max) {
|
||||
this.system.caracsecondaire.pv.max = newPV;
|
||||
this.update( { 'system.caracsecondaire.pv.max': newPV });
|
||||
}
|
||||
this.system.caracsecondaire.pv.max = newPV;
|
||||
|
||||
this.system.caracsecondaire.reaction.value = baseesprit.intellect.value + baseesprit.perception.value + baseame.instinct.value;
|
||||
let newReac = baseesprit.intellect.value + baseesprit.perception.value + baseame.instinct.value;
|
||||
if ( newReac != this.system.caracsecondaire.reaction.max) {
|
||||
this.system.caracsecondaire.reaction.max = newReac
|
||||
this.update( { 'system.caracsecondaire.reaction.max': newReac });
|
||||
}
|
||||
this.system.caracsecondaire.reaction.max = newReac
|
||||
|
||||
this.system.caracsecondaire.defensephy.value = basecorps.agilite.value + basecorps.vigueur.value + baseame.instinct.value;
|
||||
let newDef = basecorps.agilite.value + basecorps.vigueur.value + baseame.instinct.value;
|
||||
if ( newDef != this.system.caracsecondaire.defensephy.max) {
|
||||
this.system.caracsecondaire.defensephy.max = newDef
|
||||
this.update( { 'system.caracsecondaire.defensephy.max': newDef });
|
||||
this.system.caracsecondaire.defensephy.max = newDef
|
||||
// Initialize bonusmalus if not set
|
||||
if (this.system.caracsecondaire.defensephy.bonusmalus === undefined) {
|
||||
this.system.caracsecondaire.defensephy.bonusmalus = 0
|
||||
}
|
||||
this.system.caracsecondaire.defensephy.total = newDef + this.system.caracsecondaire.defensephy.bonusmalus
|
||||
|
||||
this.system.caracsecondaire.defensemen.value = baseesprit.tenacite.value + baseame.instinct.value + baseesprit.intellect.value;
|
||||
newDef = baseesprit.tenacite.value + baseame.instinct.value + baseesprit.intellect.value;
|
||||
if ( newDef != this.system.caracsecondaire.defensemen.max) {
|
||||
this.system.caracsecondaire.defensemen.max = newDef
|
||||
this.update( { 'system.caracsecondaire.defensemen.max': newDef });
|
||||
this.system.caracsecondaire.defensemen.max = newDef
|
||||
// Initialize bonusmalus if not set
|
||||
if (this.system.caracsecondaire.defensemen.bonusmalus === undefined) {
|
||||
this.system.caracsecondaire.defensemen.bonusmalus = 0
|
||||
}
|
||||
this.system.caracsecondaire.defensemen.total = newDef + this.system.caracsecondaire.defensemen.bonusmalus
|
||||
|
||||
this.system.caracsecondaire.deplacement.value = basecorps.agilite.value + basecorps.vigueur.value;
|
||||
let depl = basecorps.agilite.value + basecorps.vigueur.value;
|
||||
if ( depl != this.system.caracsecondaire.deplacement.max) {
|
||||
this.system.caracsecondaire.deplacement.max = depl
|
||||
this.update( { 'system.caracsecondaire.deplacement.max': depl });
|
||||
}
|
||||
this.system.caracsecondaire.deplacement.max = depl
|
||||
|
||||
this.system.caracsecondaire.capaenc.value = (basecorps.puissance.value * 2) + basecorps.vigueur.value;
|
||||
let enc = (basecorps.puissance.value * 2) + basecorps.vigueur.value;
|
||||
if ( enc != this.system.caracsecondaire.capaenc.max ) {
|
||||
this.system.caracsecondaire.capaenc.max = enc
|
||||
this.update( { 'system.caracsecondaire.capaenc.max': enc });
|
||||
}
|
||||
this.system.caracsecondaire.capaenc.max = enc
|
||||
|
||||
//console.log("CARAC SEC", this.system.caracsecondaire)
|
||||
}
|
||||
@@ -531,9 +523,7 @@ export class YggdrasillActor extends Actor {
|
||||
isBlesse: this.system.etat.etat == "blesse",
|
||||
}
|
||||
this.addDefaultRoll(rollData)
|
||||
let rollDialog = await YggdrasillRoll.create( this, rollData);
|
||||
console.log(rollDialog);
|
||||
rollDialog.render( true );
|
||||
await YggdrasillRollDialog.create( this, rollData);
|
||||
} else {
|
||||
ui.notifications.warn("Attribut non trouvée");
|
||||
}
|
||||
@@ -541,11 +531,11 @@ export class YggdrasillActor extends Actor {
|
||||
/* -------------------------------------------- */
|
||||
addDefaultRoll(rollData) {
|
||||
rollData.optionsBonusMalus= YggdrasillUtility.createOptions(-15, 15)
|
||||
rollData.bonusMalus= "0"
|
||||
rollData.bonusMalus= 0
|
||||
rollData.optionsFuror= YggdrasillUtility.createOptions(0, this.getCurrentFuror())
|
||||
rollData.furorUsage= "0"
|
||||
rollData.furorUsage= 0
|
||||
rollData.optionsBD= YggdrasillUtility.createOptions(0, +15)
|
||||
rollData.sr= "0"
|
||||
rollData.sr= 0
|
||||
rollData.puissanceRune = 1
|
||||
rollData.optionsPuissanceRune= YggdrasillUtility.createOptions(1, +15)
|
||||
rollData.supportRune= "peau"
|
||||
@@ -571,9 +561,7 @@ export class YggdrasillActor extends Actor {
|
||||
}
|
||||
this.addDefaultRoll(rollData)
|
||||
console.log("CARAC : ", rollData, this.system.carac);
|
||||
let rollDialog = await YggdrasillRoll.create( this, rollData);
|
||||
console.log(rollDialog);
|
||||
rollDialog.render( true );
|
||||
await YggdrasillRollDialog.create( this, rollData);
|
||||
} else {
|
||||
ui.notifications.warn("Caractéristique non trouvée");
|
||||
}
|
||||
@@ -598,9 +586,7 @@ export class YggdrasillActor extends Actor {
|
||||
isMeurtri: this.isMeurtri(),
|
||||
}
|
||||
this.addDefaultRoll(rollData)
|
||||
let rollDialog = await YggdrasillRoll.create( this, rollData);
|
||||
console.log(rollDialog);
|
||||
rollDialog.render( true );
|
||||
await YggdrasillRollDialog.create( this, rollData);
|
||||
} else {
|
||||
ui.notifications.warn("Compétence non trouvée");
|
||||
}
|
||||
@@ -691,9 +677,7 @@ export class YggdrasillActor extends Actor {
|
||||
}
|
||||
this.addDefaultRoll(rollData)
|
||||
rollData.sr = 14
|
||||
let rollDialog = await YggdrasillRoll.create( this, rollData);
|
||||
console.log(rollDialog);
|
||||
rollDialog.render( true );
|
||||
await YggdrasillRollDialog.create( this, rollData);
|
||||
} else {
|
||||
ui.notifications.warn("Sortilège ou Compétence non trouvée !", sort, compName);
|
||||
}
|
||||
@@ -734,9 +718,7 @@ export class YggdrasillActor extends Actor {
|
||||
}
|
||||
this.addDefaultRoll(rollData)
|
||||
rollData.sr = 14
|
||||
let rollDialog = await YggdrasillRoll.create( this, rollData);
|
||||
console.log(rollDialog);
|
||||
rollDialog.render( true );
|
||||
await YggdrasillRollDialog.create( this, rollData);
|
||||
} else {
|
||||
ui.notifications.warn("Arme ou Compétence Martiale non trouvée !", arme, compName);
|
||||
}
|
||||
|
||||
@@ -55,16 +55,16 @@ export const YGGDRASILL_CONFIG = {
|
||||
{ key:"visee", label:"Attaque Visée" }
|
||||
],
|
||||
optionsSR : [
|
||||
{key: "0", label: "Aucun"},
|
||||
{key: "5", label: "Très Simple (5)"},
|
||||
{key: "7", label: "Simple (7)"},
|
||||
{key: "10", label: "Aisé (10)"},
|
||||
{key: "14", label: "Moyen (14)"},
|
||||
{key: "19", label: "Difficile (19)"},
|
||||
{key: "25", label: "Très Difficile (25)"},
|
||||
{key: "32", label: "Exceptionnel (32)"},
|
||||
{key: "40", label: "Légendaire (40)"},
|
||||
{key: "49", label: "Divin (49)"}
|
||||
{key: 0, label: "Aucun"},
|
||||
{key: 5, label: "Très Simple (5)"},
|
||||
{key: 7, label: "Simple (7)"},
|
||||
{key: 10, label: "Aisé (10)"},
|
||||
{key: 14, label: "Moyen (14)"},
|
||||
{key: 19, label: "Difficile (19)"},
|
||||
{key: 25, label: "Très Difficile (25)"},
|
||||
{key: 32, label: "Exceptionnel (32)"},
|
||||
{key: 40, label: "Légendaire (40)"},
|
||||
{key: 49, label: "Divin (49)"}
|
||||
|
||||
],
|
||||
optionsCarac: [
|
||||
|
||||
@@ -1,103 +1,115 @@
|
||||
import { YggdrasillUtility } from "./yggdrasill-utility.js";
|
||||
import { YGGDRASILL_CONFIG } from "./yggdrasill-config.js";
|
||||
|
||||
const { HandlebarsApplicationMixin } = foundry.applications.api;
|
||||
|
||||
/**
|
||||
* Extend the basic ItemSheet with some very simple modifications
|
||||
* @extends {ItemSheet}
|
||||
* @extends {ItemSheetV2}
|
||||
*/
|
||||
export class YggdrasillItemSheet extends foundry.appv1.sheets.ItemSheet {
|
||||
export class YggdrasillItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
|
||||
constructor(options = {}) {
|
||||
super(options);
|
||||
this.#dragDrop = this.#createDragDropHandlers();
|
||||
}
|
||||
|
||||
#dragDrop;
|
||||
|
||||
/** @override */
|
||||
static get defaultOptions() {
|
||||
return foundry.utils.mergeObject(super.defaultOptions, {
|
||||
classes: ["fvtt-yggdrasill", "sheet", "item"],
|
||||
template: "systems/fvtt-yggdrasill/templates/item-sheet.html",
|
||||
width: 550,
|
||||
height: 550
|
||||
//tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
|
||||
});
|
||||
}
|
||||
static DEFAULT_OPTIONS = {
|
||||
classes: ["fvtt-yggdrasill", "item"],
|
||||
position: {
|
||||
width: 550,
|
||||
height: 550,
|
||||
},
|
||||
form: {
|
||||
submitOnChange: true,
|
||||
},
|
||||
window: {
|
||||
resizable: true,
|
||||
},
|
||||
actions: {
|
||||
editImage: YggdrasillItemSheet.#onEditImage,
|
||||
},
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
// Add "Post to chat" button
|
||||
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
|
||||
buttons.unshift(
|
||||
{
|
||||
class: "post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: ev => {}
|
||||
})
|
||||
return buttons
|
||||
}
|
||||
/**
|
||||
* Tab groups state
|
||||
* @type {object}
|
||||
*/
|
||||
tabGroups = { primary: "description" };
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
const position = super.setPosition(options);
|
||||
const sheetBody = this.element.find(".sheet-body");
|
||||
const bodyHeight = position.height - 192;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
const objectData = foundry.utils.duplicate(this.object);
|
||||
|
||||
let formData = {
|
||||
title: this.title,
|
||||
id: objectData.id,
|
||||
type: objectData.type,
|
||||
img: objectData.img,
|
||||
name: objectData.name,
|
||||
editable: this.isEditable,
|
||||
cssClass: this.isEditable ? "editable" : "locked",
|
||||
data: foundry.utils.deepClone(this.object.system),
|
||||
optionsBase: YggdrasillUtility.createDirectOptionList(0, 20),
|
||||
optionsNiveaux4: Array.fromRange(5, 1),
|
||||
description: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.object.system.description, {async: true}),
|
||||
limited: this.object.limited,
|
||||
options: this.options,
|
||||
owner: this.document.isOwner,
|
||||
isGM: game.user.isGM,
|
||||
config: game.system.config
|
||||
static PARTS = {
|
||||
sheet: {
|
||||
template: "systems/fvtt-yggdrasill/templates/item-{type}-sheet.hbs"
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.object.options.actor.items.get(li.data("item-id"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Update Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.object.options.actor.deleteEmbeddedDocuments( "Item", [li.data("item-id") ] ).then( this.render(true));
|
||||
});
|
||||
|
||||
async _prepareContext() {
|
||||
// Ensure config is always available with fallback to direct import
|
||||
const config = game.system?.config || game.system?.yggdrasill?.config || YGGDRASILL_CONFIG || {};
|
||||
|
||||
// Create options for niveau 0-5
|
||||
const optionsNiveaux4 = {};
|
||||
for (let i = 0; i <= 5; i++) {
|
||||
optionsNiveaux4[`${i}`] = `${i}`;
|
||||
}
|
||||
|
||||
const optionsBase = YggdrasillUtility.createDirectOptionList(0, 20) || {};
|
||||
|
||||
const context = {
|
||||
fields: this.document.schema.fields,
|
||||
systemFields: this.document.system.schema.fields,
|
||||
item: this.document,
|
||||
system: this.document.system,
|
||||
data: this.document.system,
|
||||
source: this.document.toObject(),
|
||||
enrichedDescription: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.description || "", { async: true }),
|
||||
enrichedEffet: await foundry.applications.ux.TextEditor.implementation.enrichHTML(this.document.system.effet || "", { async: true }),
|
||||
isEditMode: true,
|
||||
isEditable: this.isEditable,
|
||||
editable: this.isEditable,
|
||||
isGM: game.user.isGM,
|
||||
config: config,
|
||||
optionsBase: optionsBase,
|
||||
optionsNiveaux4: optionsNiveaux4,
|
||||
};
|
||||
return context;
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get template()
|
||||
{
|
||||
let type = this.item.type;
|
||||
return `systems/fvtt-yggdrasill/templates/item-${type}-sheet.html`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
return this.object.update(formData);
|
||||
_onRender(context, options) {
|
||||
super._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
|
||||
*/
|
||||
#createDragDropHandlers() {
|
||||
return [];
|
||||
}
|
||||
|
||||
// #region Actions
|
||||
|
||||
/**
|
||||
* Handle editing the item image
|
||||
* @param {Event} event - The triggering event
|
||||
*/
|
||||
static async #onEditImage(event) {
|
||||
event.preventDefault();
|
||||
const filePicker = new FilePicker({
|
||||
type: "image",
|
||||
current: this.document.img,
|
||||
callback: (path) => {
|
||||
this.document.update({ img: path });
|
||||
},
|
||||
});
|
||||
filePicker.browse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,17 @@
|
||||
/* -------------------------------------------- */
|
||||
// Import Modules
|
||||
import { YggdrasillActor } from "./yggdrasill-actor.js";
|
||||
import { YggdrasillItemSheet } from "./yggdrasill-item-sheet.js";
|
||||
import { YggdrasillActorSheet } from "./yggdrasill-actor-sheet.js";
|
||||
import { YggdrasillFigurantSheet } from "./yggdrasill-figurant-sheet.js";
|
||||
import { YggdrasillUtility } from "./yggdrasill-utility.js";
|
||||
import { YggdrasillCombat } from "./yggdrasill-combat.js";
|
||||
import { YGGDRASILL_CONFIG } from "./yggdrasill-config.js";
|
||||
import { ClassCounter} from "https://www.uberwald.me/fvtt_appcount/count-class-ready.js"
|
||||
|
||||
// Import DataModels
|
||||
import * as models from "./models/index.mjs";
|
||||
|
||||
// Import AppV2 Sheets
|
||||
import * as sheets from "./applications/sheets/_module.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* -------------------------------------------- */
|
||||
@@ -46,30 +49,82 @@ Hooks.once("init", async function () {
|
||||
/* -------------------------------------------- */
|
||||
// Define custom Entity classes
|
||||
CONFIG.Actor.documentClass = YggdrasillActor;
|
||||
CONFIG.Actor.dataModels = {
|
||||
personnage: models.PersonnageDataModel,
|
||||
figurant: models.FigurantDataModel
|
||||
};
|
||||
|
||||
CONFIG.Combat.documentClass = YggdrasillCombat;
|
||||
|
||||
CONFIG.Item.dataModels = {
|
||||
competence: models.CompetenceDataModel,
|
||||
don: models.DonDataModel,
|
||||
faiblesse: models.FaiblesseDataModel,
|
||||
blessure: models.BlessureDataModel,
|
||||
maladie: models.MaladieDataModel,
|
||||
poison: models.PoisonDataModel,
|
||||
prouesse: models.ProuesseDataModel,
|
||||
sortsejdr: models.SortsejdrDataModel,
|
||||
sortgaldr: models.SortgaldrDataModel,
|
||||
rune: models.RuneDataModel,
|
||||
armecc: models.ArmeccDataModel,
|
||||
armedist: models.ArmedistDataModel,
|
||||
armure: models.ArmureDataModel,
|
||||
bouclier: models.BouclierDataModel,
|
||||
equipement: models.EquipementDataModel,
|
||||
monnaie: models.MonnaieDataModel,
|
||||
effetmagique: models.EffetmagiqueDataModel
|
||||
};
|
||||
|
||||
CONFIG.Yggdrasill = {
|
||||
}
|
||||
|
||||
game.system.yggdrasill = {
|
||||
config: YGGDRASILL_CONFIG,
|
||||
models,
|
||||
sheets
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// Register sheet application classes
|
||||
|
||||
// Register AppV2 Actor Sheets
|
||||
foundry.documents.collections.Actors.unregisterSheet("core", foundry.appv1.sheets.ActorSheet);
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-yggdrasill", YggdrasillActorSheet, { types: ["personnage"], makeDefault: true });
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-yggdrasill", YggdrasillFigurantSheet, { types: ["figurant"], makeDefault: false });
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-yggdrasill", sheets.YggdrasillPersonnageSheet, { types: ["personnage"], makeDefault: true });
|
||||
foundry.documents.collections.Actors.registerSheet("fvtt-yggdrasill", sheets.YggdrasillFigurantSheet, { types: ["figurant"], makeDefault: true });
|
||||
|
||||
// Register AppV2 Item Sheets
|
||||
foundry.documents.collections.Items.unregisterSheet("core", foundry.appv1.sheets.ItemSheet);
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", YggdrasillItemSheet, { makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillCompetenceSheet, { types: ["competence"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillDonSheet, { types: ["don"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillFaiblesseSheet, { types: ["faiblesse"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillBlessureSheet, { types: ["blessure"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillMaladieSheet, { types: ["maladie"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillPoisonSheet, { types: ["poison"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillProuesseSheet, { types: ["prouesse"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillSortsejdrSheet, { types: ["sortsejdr"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillSortgaldrSheet, { types: ["sortgaldr"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillRuneSheet, { types: ["rune"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillArmeccSheet, { types: ["armecc"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillArmedistSheet, { types: ["armedist"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillArmureSheet, { types: ["armure"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillBouclierSheet, { types: ["bouclier"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillEquipementSheet, { types: ["equipement"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillMonnaieSheet, { types: ["monnaie"], makeDefault: true });
|
||||
foundry.documents.collections.Items.registerSheet("fvtt-yggdrasill", sheets.YggdrasillEffetmagiqueSheet, { types: ["effetmagique"], makeDefault: true });
|
||||
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
function welcomeMessage() {
|
||||
async function welcomeMessage() {
|
||||
const templateData = {};
|
||||
const html = await foundry.applications.handlebars.renderTemplate("systems/fvtt-yggdrasill/templates/chat-welcome-message.hbs", templateData);
|
||||
|
||||
ChatMessage.create({
|
||||
user: game.user.id,
|
||||
whisper: [game.user.id],
|
||||
content: `<div id="welcome-message-yggdrasill"><span class="rdd-roll-part"><strong>Bienvenue à Yggdrasill !</strong>
|
||||
<p>Yggdrasill est un Jeu de Rôle publié par 7ième Cercle : https://www.7emecercle.com/7C_site/jeux-de-roles/yggdrasill/</p>
|
||||
<br>Yggdrasill est une propriété de 7ième Cercle.
|
||||
</div>
|
||||
` });
|
||||
content: html
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -101,3 +156,28 @@ Hooks.on("chatMessage", (html, content, msg) => {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Chat Message Rendering */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.on("renderChatMessageHTML", (message, html, data) => {
|
||||
// Handle collapsible magic details
|
||||
html.querySelector('.magic-header.collapsible')?.addEventListener('click', function() {
|
||||
const header = this;
|
||||
const content = header.parentElement.querySelector('.magic-content');
|
||||
|
||||
// Toggle collapsed state
|
||||
content?.classList.toggle('collapsed');
|
||||
header.classList.toggle('expanded');
|
||||
});
|
||||
|
||||
// Handle collapsible weapon details
|
||||
html.querySelector('.weapon-header.collapsible')?.addEventListener('click', function() {
|
||||
const header = this;
|
||||
const content = header.parentElement.querySelector('.weapon-content');
|
||||
|
||||
// Toggle collapsed state
|
||||
content?.classList.toggle('collapsed');
|
||||
header.classList.toggle('expanded');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,212 +0,0 @@
|
||||
import { YggdrasillUtility } from "./yggdrasill-utility.js";
|
||||
const dureeGaldrSD = { "1d5a": 3, "1d10t": 6, "1d10m": 9, "1d10h": 12, "1d5j": 15};
|
||||
const ciblesGaldrSD = { "1": 3, "2_4": 6, "5_9": 9, "10_49": 12, "50plus": 15};
|
||||
const zonesciblesGaldrSD = { "INS10cm3": 3, "INS50cm3": 6, "INS1m3": 9, "INS5m3": 12, "INS10m3": 15};
|
||||
|
||||
export class YggdrasillRoll extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, rollData ) {
|
||||
|
||||
let html
|
||||
let h = 440;
|
||||
if ( rollData.mode == "competence") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-competence.html', rollData);
|
||||
h = 340;
|
||||
} else if (rollData.mode == "carac") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-carac.html', rollData);
|
||||
h = 320;
|
||||
} else if (rollData.mode == "attribut") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-attribut.html', rollData);
|
||||
h = 320;
|
||||
} else if (rollData.mode == "armecc") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-armecc.html', rollData);
|
||||
} else if (rollData.mode == "sejdr") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-sejdr.html', rollData);
|
||||
} else if (rollData.mode == "rune") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-rune.html', rollData);
|
||||
} else if (rollData.mode == "galdr") {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-galdr.html', rollData);
|
||||
} else {
|
||||
html = await foundry.applications.handlebars.renderTemplate('systems/fvtt-yggdrasill/templates/roll-dialog-armetir.html', rollData);
|
||||
}
|
||||
let options = { classes: ["yggdrasilldialog"], width: 600, height: h, 'z-index': 99999 };
|
||||
return new YggdrasillRoll(actor, rollData, html, options );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(actor, rollData, html, options, close = undefined) {
|
||||
let conf = {
|
||||
title: (rollData.mode == "competence") ? "Compétence" : "Caractéristique",
|
||||
content: html,
|
||||
buttons: {
|
||||
roll: {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Lancer le Test",
|
||||
callback: () => { this.roll() }
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: "Annuler",
|
||||
callback: () => { this.close() }
|
||||
} },
|
||||
default: "Roll",
|
||||
close: close
|
||||
}
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.actor = actor;
|
||||
this.rollData = rollData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
roll () {
|
||||
if ( this.rollData.mode == "attribut") {
|
||||
YggdrasillUtility.rollAttribute(this.rollData)
|
||||
} else {
|
||||
YggdrasillUtility.rollYggdrasill( this.rollData )
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateGaldrSR( ) {
|
||||
let sdDuree = Number(dureeGaldrSD[this.rollData.dureeGaldr]);
|
||||
let sdVar = 0;
|
||||
if ( this.rollData.sort.system.voie == "illusion") {
|
||||
sdVar = Number(zonesciblesGaldrSD[this.rollData.zoneGaldr]);
|
||||
} else {
|
||||
sdVar = Number(ciblesGaldrSD[this.rollData.nbCibles]);
|
||||
}
|
||||
let SR = Number(this.rollData.sort.system.sd) + sdDuree + sdVar;
|
||||
$("#srTotal").text(SR);
|
||||
this.rollData.sr = SR;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateRuneSR() {
|
||||
let support = 0;
|
||||
|
||||
this.rollData.dureeRune = 6 - this.rollData.agiliteCarac.value;
|
||||
if ( this.rollData.supportRune == "peau") {
|
||||
support = 3;
|
||||
this.rollData.echelleDuree = "Actions";
|
||||
this.rollData.echelleDureeVie = "Heures"
|
||||
}
|
||||
if ( this.rollData.supportRune == "tissu") {
|
||||
support = 6;
|
||||
this.rollData.echelleDuree = "Tours";
|
||||
this.rollData.echelleDureeVie = "Jours"
|
||||
}
|
||||
if ( this.rollData.supportRune == "cuir") {
|
||||
support = 9;
|
||||
this.rollData.echelleDuree = "Minutes";
|
||||
this.rollData.echelleDureeVie = "Semaines"
|
||||
}
|
||||
if ( this.rollData.supportRune == "bois") {
|
||||
support = 12;
|
||||
this.rollData.echelleDuree = "Heures";
|
||||
this.rollData.echelleDureeVie = "Mois"
|
||||
}
|
||||
if ( this.rollData.supportRune == "pierremetal") {
|
||||
support = 15;
|
||||
this.rollData.echelleDuree = "Jours";
|
||||
this.rollData.echelleDureeVie = "Années"
|
||||
}
|
||||
let SR = this.rollData.puissanceRune + (Number(this.rollData.sort.system.niveau)*3) + support;
|
||||
$("#srTotal").text(SR);
|
||||
$("#runeDuree").text( this.rollData.dureeRune + " " + this.rollData.echelleDuree);
|
||||
$("#runeDureeVie").text( this.rollData.competence.system.niveau + " " + this.rollData.echelleDureeVie);
|
||||
this.rollData.sr = SR;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
let dialog = this;
|
||||
function onLoad() {
|
||||
if (dialog.rollData.mode == "competence") {
|
||||
let carac = dialog.actor.getCarac( "Puissance" );
|
||||
dialog.rollData.selectedCarac = carac;
|
||||
} else if (dialog.rollData.mode == "armecc" || dialog.rollData.mode == "armedist" ) {
|
||||
$("#caracName").text(dialog.rollData.selectedCarac.label);
|
||||
$("#attackDescr").text(dialog.rollData.attackDef.description);
|
||||
} else if ( dialog.rollData.mode == "sejdr" || dialog.rollData.mode == "rune" || dialog.rollData.mode == "galdr" ) {
|
||||
$("#caracName").text(dialog.rollData.selectedCarac.label);
|
||||
}
|
||||
if (dialog.rollData.mode == "rune" ) {
|
||||
dialog.updateRuneSR();
|
||||
}
|
||||
if (dialog.rollData.mode == "galdr" ) {
|
||||
dialog.updateGaldrSR();
|
||||
}
|
||||
if (dialog.rollData.mode == "attribut") {
|
||||
$("#attrValue").text("2d10+"+dialog.rollData.subAttr.value);
|
||||
} else {
|
||||
$("#caracValue").text(dialog.rollData.selectedCarac.value+"d10");
|
||||
}
|
||||
}
|
||||
$(function () { onLoad(); });
|
||||
|
||||
html.find('#caracName').change((event) => {
|
||||
let caracKey = event.currentTarget.value;
|
||||
let carac = this.actor.getCarac( caracKey );
|
||||
this.rollData.selectedCarac = carac;
|
||||
$("#caracValue").text(carac.value+"d10");
|
||||
});
|
||||
|
||||
html.find('#typeAttack').change((event) => {
|
||||
let attackType = event.currentTarget.value;
|
||||
let attackDef
|
||||
if ( this.rollData.mode == 'armecc')
|
||||
attackDef = this.actor.getAttaqueData( attackType);
|
||||
else
|
||||
attackDef = this.actor.getTirData( attackType);
|
||||
this.rollData.attackDef = attackDef;
|
||||
this.rollData.selectedCarac = attackDef.carac;
|
||||
$("#caracValue").text(attackDef.carac.value+"d10");
|
||||
$("#caracName").text(attackDef.carac.label);
|
||||
$("#attackDescr").text(attackDef.description);
|
||||
$("#malus").text(attackDef.malus);
|
||||
});
|
||||
|
||||
html.find('#supportRune').change((event) => {
|
||||
this.rollData.supportRune = event.currentTarget.value;
|
||||
this.updateRuneSR();
|
||||
});
|
||||
html.find('#puissanceRune').change((event) => {
|
||||
this.rollData.puissanceRune = Number(event.currentTarget.value);
|
||||
this.updateRuneSR();
|
||||
});
|
||||
|
||||
html.find('#dureeGaldr').change((event) => {
|
||||
this.rollData.dureeGaldr = event.currentTarget.value;
|
||||
this.updateGaldrSR();
|
||||
});
|
||||
html.find('#nbCibles').change((event) => {
|
||||
this.rollData.nbCibles = event.currentTarget.value;
|
||||
this.updateGaldrSR();
|
||||
});
|
||||
html.find('#zoneGaldr').change((event) => {
|
||||
this.rollData.zoneGaldr = event.currentTarget.value;
|
||||
this.updateGaldrSR();
|
||||
});
|
||||
|
||||
|
||||
html.find('#bonusMalus').change((event) => {
|
||||
this.rollData.bonusMalus = Number(event.currentTarget.value);
|
||||
});
|
||||
html.find('#furorUsage').change((event) => {
|
||||
this.rollData.furorUsage = Number(event.currentTarget.value);
|
||||
});
|
||||
html.find('#sr').change((event) => {
|
||||
this.rollData.sr = Number(event.currentTarget.value);
|
||||
});
|
||||
html.find('#bonusdefense').change((event) => {
|
||||
this.rollData.bonusdefense = Number(event.currentTarget.value);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -156,7 +156,7 @@ export class YggdrasillUtility {
|
||||
console.log("ROLLLL ATTR!!!!", rollData);
|
||||
|
||||
this.createChatWithRollMode( rollData.alias, {
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-yggdrasill/templates/chat-generic-result.html`, rollData)
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-yggdrasill/templates/chat-generic-result-new.hbs`, rollData)
|
||||
});
|
||||
}
|
||||
|
||||
@@ -218,9 +218,14 @@ export class YggdrasillUtility {
|
||||
rollData.niveauCompetence = niveauCompetence
|
||||
|
||||
// Compute total SR
|
||||
rollData.srFinal = rollData.sr;
|
||||
if ( rollData.bonusdefense ) {
|
||||
rollData.srFinal += rollData.bonusdefense;
|
||||
// Pour les sorts, utiliser srTotal si calculé, sinon sr + bonusdefense
|
||||
if (rollData.srTotal !== undefined) {
|
||||
rollData.srFinal = rollData.srTotal
|
||||
} else {
|
||||
rollData.srFinal = rollData.sr
|
||||
if (rollData.bonusdefense) {
|
||||
rollData.srFinal += rollData.bonusdefense
|
||||
}
|
||||
}
|
||||
|
||||
if ( rollData.srFinal > 0 ) {
|
||||
@@ -272,7 +277,7 @@ export class YggdrasillUtility {
|
||||
console.log("ROLLLL!!!!", rollData);
|
||||
|
||||
this.createChatWithRollMode( rollData.alias, {
|
||||
content: await renderTemplate(`systems/fvtt-yggdrasill/templates/chat-generic-result.html`, rollData)
|
||||
content: await foundry.applications.handlebars.renderTemplate(`systems/fvtt-yggdrasill/templates/chat-generic-result-new.hbs`, rollData)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user