Files
foundryvtt-reve-de-dragon/module/technical/actor-impacts.mjs
T
fabres 25e3df1f5d Migration Foundry v14 : classes V1→V2, corrections CSS et bugs
- 21 classes Dialog → DialogV2
- 2 classes Application → ApplicationV2 + HandlebarsApplicationMixin
- 1 classe FormApplication → ApplicationV2
- 10 appels new Dialog() → DialogV2 (rdd-confirm, rdd-commands, etc.)
- base-actor-sheet.mjs : 3 appels new Dialog → DialogV2
- Sheet journal : JournalTextPageSheet → JournalEntryPageProseMirrorSheet
- CSS : backdrop-filter, box-shadow, bordures V2 supprimes pour calendar/astrologie
- FenetreRechercheTirage : _getWindowControls + dragDrop ajoutes
- HtmlUtility.showControlWhen : compat jQuery + DOM natif
- rdd-main.js : init calendrier en setTimeout
- Constantes : duplicate → deepClone, _id → id
- renderTemplate global → foundry.applications.handlebars.renderTemplate
2026-07-22 00:29:56 +02:00

156 lines
4.8 KiB
JavaScript

import { RollBasicParts } from "../roll/roll-basic-parts.mjs"
const ACTOR_EMBEDDED_DOCTYPES = ['Item', 'ActiveEffect']
/**
* class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these
*/
export class ActorImpacts {
static $newDocumentImpacts(docType) {
return { creates: [], deletes: [], updates: [], docType: docType }
}
static $checkDocType(docType) {
if (!ACTOR_EMBEDDED_DOCTYPES.includes(docType)) {
throw `Unsupported document type ${docType}`
}
}
constructor(actorToken) {
this.actorToken = actorToken
this.updates = []
this.deltas = []
ACTOR_EMBEDDED_DOCTYPES.forEach(
docType => this[docType] = ActorImpacts.$newDocumentImpacts(docType)
)
}
addActorUpdate(path, value) {
this.updates.push([path, value])
}
addActorDelta(path, value) {
const intValue = Number.parseInt(value)
if (Number.isInteger(intValue) && intValue != 0) {
const delta = [path, intValue]
this.deltas.push(delta)
}
else {
console.error('Cannot use non integer value {} for delta update', value)
}
}
addDeleted(docType, document) {
ActorImpacts.$checkDocType(docType)
this[docType].deletes.push(document)
}
addCreated(docType, document) {
ActorImpacts.$checkDocType(docType)
this[docType].creates.push(document)
}
addUpdate(docType, document, path, value) {
ActorImpacts.$checkDocType(docType)
const update = [path, value]
const existing = this[docType].updates.find(it => it.id == document.id)
if (existing) {
existing.updates.push(update)
}
else {
this[docType].updates.push({ id: document.id, updates: [update], deltas: [] })
}
}
addDelta(document, path, value) {
ActorImpacts.$checkDocType(document)
const intValue = Number.parseInt(value)
if (Number.isInteger(intValue)) {
if (intValue != 0){
const delta = [path, intValue]
const existing = this[docType].updates.find(it => it.id == document.id)
if (existing) {
existing.deltas.push(delta)
}
else {
this[docType].updates.push({ id: document.id, updates: [], deltas: [delta] })
}
}
}
else {
console.error('Cannot use non-integer value {} for delta update', value)
}
}
reverseImpacts() {
const reverse = ActorImpacts.$computeReverts(new ActorImpacts(this.actorToken), this, __ => this.actorToken.actor)
ACTOR_EMBEDDED_DOCTYPES.forEach(
docType => {
reverse[docType].creates = this[docType].deletes.map(it => foundry.utils.deepClone(it))
reverse[docType].deletes = this[docType].creates.map(it => { return { id: it.id } })
reverse[docType].updates = this[docType].updates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getEmbeddedDocument(docType, id)))
}
)
return reverse
}
toStorable() {
delete this.actorToken
return this
}
async applyImpacts() {
const actor = this.actorToken.actor
for (let docType of ACTOR_EMBEDDED_DOCTYPES) {
await this.$applyDocumentsImpacts(actor, docType)
}
const updates = ActorImpacts.$computeUpdates(this, id => actor)
await actor.update(updates, { render: true })
}
async $applyDocumentsImpacts(actor, docType) {
if (this[docType].deletes.length > 0) {
const deletes = this[docType].deletes.map(it => it.id)
await actor.deleteEmbeddedDocuments(docType, deletes, { render: false })
}
if (this[docType].creates.length > 0) {
const creates = this[docType].creates
const created = await actor.createEmbeddedDocuments(docType, creates, { render: false })
for (let i = 0; i < creates.length; i++) {
creates[i].createdId = created[i].id
}
}
if (this[docType].updates.length > 0) {
const updates = this[docType].updates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getEmbeddedDocument(docType, id)))
await actor.updateEmbeddedDocuments(docType, updates, { render: false })
}
}
findCreatedId(docType, origId) {
return this[docType].creates.find(it => it.id = origId)?.createdId
}
$getEmbeddedDocument(docType, id) {
return this.actorToken.actor.getEmbeddedDocument(docType, id)
}
static $computeUpdates(u, getSource) {
if (u.updates.length == 0 && u.deltas.length == 0) {
return {}
}
const source = getSource(u.id)
const instruction = { _id: u.id }
u.updates.forEach(u => instruction[u[0]] = u[1])
u.deltas.forEach(u => instruction[u[0]] = foundry.utils.getProperty(source, u[0]) + u[1])
return instruction
}
static $computeReverts(target, u, getSource) {
const source = getSource(u.id)
target.updates = u.updates.map(u => [u[0], foundry.utils.getProperty(source, u[0])])
target.deltas = u.deltas.map(d => [d[0], -d[1]])
return target
}
}