forked from public/foundryvtt-reve-de-dragon
		
	ajout d'un bouton pour aller dans les TMR lors d'une méditation réussie
		
			
				
	
	
		
			151 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
 | |
| 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) && 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.duplicate(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
 | |
|     await Promise.all(ACTOR_EMBEDDED_DOCTYPES.map(async docType => 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
 | |
|   }
 | |
| }
 |