Cette ligne était parfois ajoutée aux caracs des personnages. Ajout d'une migration pour nettoyage.
		
			
				
	
	
		
			726 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			24 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import { RdDBaseActor } from "./actor/base-actor.js";
 | |
| import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
 | |
| import { Grammar } from "./grammar.js";
 | |
| import { Monnaie } from "./item-monnaie.js";
 | |
| import { ITEM_TYPES, ACTOR_TYPES } from "./constants.js";
 | |
| import { RdDItem } from "./item.js";
 | |
| import { RdDTimestamp } from "./time/rdd-timestamp.js";
 | |
| import { RdDRaretes } from "./item/raretes.js";
 | |
| import { VOIES_DRACONIC } from "./item-sort.js";
 | |
| import { SystemCompendiums } from "./settings/system-compendiums.js";
 | |
| import { Misc } from "./misc.js";
 | |
| 
 | |
| class Migration {
 | |
|   get code() { return "sample"; }
 | |
|   get version() { return "0.0.0"; }
 | |
|   async migrate() { }
 | |
| 
 | |
|   async applyItemsUpdates(computeUpdates) {
 | |
|     await game.actors.forEach(async (actor) => {
 | |
|       const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
 | |
|       if (actorItemUpdates.length > 0) {
 | |
|         console.log(
 | |
|           this.code,
 | |
|           `Applying updates on actor ${actor.name} items`,
 | |
|           actorItemUpdates
 | |
|         );
 | |
|         await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
 | |
|     if (itemUpdates.length > 0) {
 | |
|       console.log(this.code, "Applying updates on items", itemUpdates);
 | |
|       await Item.updateDocuments(itemUpdates);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| }
 | |
| 
 | |
| class _1_5_34_migrationPngWebp {
 | |
|   get code() { return "migrationPngWebp"; }
 | |
|   get version() { return "1.5.34"; }
 | |
|   async migrate() {
 | |
| 
 | |
|     const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
 | |
|     const replaceWithWebp = '$1.webp';
 | |
|     function convertImgToWebp(img) {
 | |
|       return img.replace(regexOldPngJpg, replaceWithWebp);
 | |
|     }
 | |
|     function prepareDocumentsImgUpdate(documents) {
 | |
|       return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
 | |
|         .map(it => {
 | |
|           return { _id: it.id, img: convertImgToWebp(it.img) }
 | |
|         });
 | |
|     }
 | |
| 
 | |
|     const itemsUpdates = prepareDocumentsImgUpdate(game.items);
 | |
|     const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
 | |
|     //Migrate system png to webp
 | |
|     await Item.updateDocuments(itemsUpdates);
 | |
|     await Actor.updateDocuments(actorsUpdates);
 | |
|     game.actors.forEach(actor => {
 | |
|       if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
 | |
|         actor.update({ "token.img": convertImgToWebp(actor.token.img) });
 | |
|       }
 | |
|       const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
 | |
|       actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
 | |
|     });
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_0_16_MigrationSortsReserve extends Migration {
 | |
|   get code() { return "creation-item-sort-reserve"; }
 | |
|   get version() { return "10.0.16"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     const actors = game.actors.filter((actor) => actor.type == "personnage" && (actor.system.reve?.reserve?.list?.length ?? 0 > 0))
 | |
|     Promise.all(actors.map(async it => await this.convertirSortsReserveActeur(it)))
 | |
|   }
 | |
| 
 | |
|   async convertirSortsReserveActeur(actor) {
 | |
|     const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
 | |
|     console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
 | |
|     await actor.createEmbeddedDocuments("Item", sortsReserve, {
 | |
|       renderSheet: false,
 | |
|     });
 | |
|     await actor.update({ 'system.reve.reserve': undefined });
 | |
|   }
 | |
| 
 | |
|   conversionSortReserve(it) {
 | |
|     return {
 | |
|       type: 'sortreserve',
 | |
|       name: it.sort.name,
 | |
|       img: it.sort.img,
 | |
|       system: {
 | |
|         // ATTENTION, utilisation de data / _id possibles, encore présents pour les anciens sorts en réserve
 | |
|         sortid: it.sort._id,
 | |
|         draconic: it.sort.draconic,
 | |
|         ptreve: (it.sort.system ?? it.sort.data).ptreve_reel,
 | |
|         coord: it.coord,
 | |
|         heurecible: 'Vaisseau',
 | |
|       },
 | |
|     };
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_0_17_MigrationCompetenceCreature extends Migration {
 | |
|   get code() { return "competences-creature-parade"; }
 | |
|   get version() { return "10.0.17"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => it.type == "competencecreature" && it.system.isparade && it.system.categorie_parade == "")
 | |
|       .map(it => { return { _id: it.id, "system.categorie_parade": "armes-naturelles" } }));
 | |
| 
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => it.type == "competencecreature" && it.system.iscombat)
 | |
|       .map(it => { return { _id: it.id, "system.categorie": (Grammar.includesLowerCaseNoAccent(it.name, "lancee") ? "lancer" : "melee") } })
 | |
|     );
 | |
| 
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_0_21_VehiculeStructureResistanceMax extends Migration {
 | |
|   get code() { return "vehicule-structure-resistance-max"; }
 | |
|   get version() { return "10.0.21"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await game.actors
 | |
|       .filter((actor) => actor.type == "vehicule")
 | |
|       .forEach(async (actor) => {
 | |
|         await actor.update({
 | |
|           'system.etat.resistance.value': actor.system.resistance,
 | |
|           'system.etat.resistance.max': actor.system.resistance,
 | |
|           'system.etat.structure.value': actor.system.structure,
 | |
|           'system.etat.structure.max': actor.system.structure
 | |
|         })
 | |
|       });
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_0_33_MigrationNomsDraconic extends Migration {
 | |
|   get code() { return "competences-nom-draconic"; }
 | |
|   get version() { return "10.0.33"; }
 | |
| 
 | |
|   migrationNomDraconic(ancien) {
 | |
|     if (typeof ancien == 'string') {
 | |
|       switch (ancien) {
 | |
|         case 'oniros': case "Voie d'Oniros": return "Voie d'Oniros";
 | |
|         case 'hypnos': case "Voie d'Hypnos": return "Voie d'Hypnos";
 | |
|         case 'narcos': case "Voie de Narcos": return "Voie de Narcos";
 | |
|         case 'thanatos': case "Voie de Thanatos": return "Voie de Thanatos";
 | |
|       }
 | |
|       return ancien;
 | |
|     }
 | |
|     else if (typeof ancien.name == 'string') {
 | |
|       return this.migrationNomDraconic(ancien.name)
 | |
|     }
 | |
|     return ancien;
 | |
|   }
 | |
|   async migrate() {
 | |
| 
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => ["sort", "sortreserve"].includes(it.type)
 | |
|         && (typeof it.system.draconic == 'string') || (typeof it.system.draconic?.name == 'string'))
 | |
|       .map(it => { return { _id: it.id, "system.draconic": this.migrationNomDraconic(it.system.draconic) } }));
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_2_5_ArmesTirLancer extends Migration {
 | |
|   constructor() {
 | |
|     super();
 | |
|     this.dagues = { "system.competence": 'Dague', "system.lancer": 'Dague de jet', "system.portee_courte": 3, "system.portee_moyenne": 8, "system.portee_extreme": 15 }
 | |
|     this.javelot = { "system.competence": 'Lance', "system.lancer": 'Javelot', "system.portee_courte": 6, "system.portee_moyenne": 12, "system.portee_extreme": 20 }
 | |
|     this.fouet = { "system.competence": '', "system.lancer": 'Fouet', "system.portee_courte": 2, "system.portee_moyenne": 2, "system.portee_extreme": 3, "system.penetration": -1 }
 | |
|     this.arc = { "system.competence": '', "system.tir": 'Arc' }
 | |
|     this.arbalete = { "system.competence": '', "system.tir": 'Arbalète' }
 | |
|     this.fronde = { "system.competence": '', "system.tir": 'Fronde' }
 | |
| 
 | |
|     this.mappings = {
 | |
|       'dague': { filter: it => true, updates: this.dagues },
 | |
|       'dague de jet': { filter: it => true, updates: this.dagues },
 | |
|       'javelot': { filter: it => true, updates: this.javelot },
 | |
|       'lance': { filter: it => it.name == 'Javeline', updates: this.javelot },
 | |
|       'fouet': { filter: it => true, updates: this.fouet },
 | |
|       'arc': { filter: it => true, updates: this.arc },
 | |
|       'arbalete': { filter: it => true, updates: this.arbalete },
 | |
|       'fronde': { filter: it => true, updates: this.fronde },
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   get code() { return "separation-competences-tir-lancer"; }
 | |
|   get version() { return "10.2.5"; }
 | |
| 
 | |
|   migrateArmeTirLancer(it) {
 | |
|     let updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates);
 | |
|     console.log(it.name, updates);
 | |
|     return updates;
 | |
|   }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => "arme" == it.type)
 | |
|       .filter(it => this.isTirLancer(it))
 | |
|       .filter(it => this.getMapping(it).filter(it))
 | |
|       .map(it => this.migrateArmeTirLancer(it)));
 | |
|   }
 | |
| 
 | |
| 
 | |
|   isTirLancer(it) {
 | |
|     return Object.keys(this.mappings).includes(this.getCompKey(it));
 | |
|   }
 | |
| 
 | |
|   getMapping(it) {
 | |
|     return this.mappings[this.getCompKey(it)];
 | |
|   }
 | |
| 
 | |
|   getCompKey(it) {
 | |
|     return Grammar.toLowerCaseNoAccent(it.system.competence);
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_2_10_DesirLancinant_IdeeFixe extends Migration {
 | |
|   get code() { return "desir-lancinat-idee-fixe"; }
 | |
|   get version() { return "10.2.10"; }
 | |
| 
 | |
|   migrateQueue(it) {
 | |
|     let categorie = undefined
 | |
|     let name = it.name
 | |
|     if (Grammar.toLowerCaseNoAccent(name).includes('desir')) {
 | |
|       categorie = 'lancinant';
 | |
|       name = it.name.replace('Désir lancinant : ', '');
 | |
| 
 | |
|     }
 | |
|     if (Grammar.toLowerCaseNoAccent(name).includes('idee fixe')) {
 | |
|       categorie = 'ideefixe';
 | |
|       name = it.name.replace('Idée fixe : ', '')
 | |
|     }
 | |
|     return {
 | |
|       _id: it.id, name: name,
 | |
|       'system.ideefixe': undefined,
 | |
|       'system.lancinant': undefined,
 | |
|       'system.categorie': categorie
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => ['queue', 'ombre'].includes(it.type))
 | |
|       .map(it => this.migrateQueue(it))
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_3_0_Inventaire extends Migration {
 | |
|   get code() { return "migration-equipement-inventaire"; }
 | |
|   get version() { return "10.3.0"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => {
 | |
|       return this._updatesMonnaies(items)
 | |
|         .concat(this._updatesNonEquipe(items))
 | |
|         .concat(this._updatesObjets(items))
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   _updatesNonEquipe(items) {
 | |
|     return items
 | |
|       .filter(it => ['munition'].includes(it.type))
 | |
|       .map(it => { return { _id: it.id, 'system.equipe': undefined } });
 | |
|   }
 | |
|   _updatesObjets(items) {
 | |
|     return items
 | |
|       .filter(it => ['objet'].includes(it.type))
 | |
|       .map(it => { return { _id: it.id, 'system.resistance': undefined, 'system.equipe': undefined } });
 | |
|   }
 | |
|   _updatesMonnaies(items) {
 | |
|     return items
 | |
|       .filter(it => ['monnaie'].includes(it.type) && it.system.valeur_deniers != undefined)
 | |
|       .map(it => { return { _id: it.id, 'system.cout': it.system.valeur_deniers / 100, 'system.valeur_deniers': undefined } });
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_3_0_FrequenceEnvironnement extends Migration {
 | |
|   get code() { return "migration-frequence-resources"; }
 | |
|   get version() { return "10.3.0"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items.filter(it => ['herbe', 'ingredient'].includes(it.type))
 | |
|       .map(it => this._updatesFrequences(it)));
 | |
|   }
 | |
| 
 | |
|   _updatesFrequences(it) {
 | |
|     const rarete = RdDRaretes.byCode(it.system.rarete);
 | |
|     return {
 | |
|       _id: it.id,
 | |
|       'system.rarete': undefined,
 | |
|       'system.environnement': [{ milieu: it.system.milieu, rarete: rarete.code, frequence: rarete.frequence }]
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_3_17_Monnaies extends Migration {
 | |
|   constructor() {
 | |
|     super();
 | |
|     this.mapValeur = {
 | |
|       "Etain (1 denier)": { name: 'Denier (étain)', system: { cout: 0.01 } },
 | |
|       "Bronze (10 deniers)": { name: "Sou (bronze)", system: { cout: 0.1 } },
 | |
|       "Argent (1 sol)": { name: "Sol (argent)", system: { cout: 1 } },
 | |
|       "Or (10 sols)": { name: "Dragon (or)", system: { cout: 10 } }
 | |
|     };
 | |
|   }
 | |
|   get code() { return "migration-monnaies"; }
 | |
|   get version() { return "10.3.17"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => this._updatesMonnaies(items));
 | |
|   }
 | |
| 
 | |
|   _updatesMonnaies(items) {
 | |
|     return items
 | |
|       .filter(it => 'monnaie' == it.type)
 | |
|       .filter(it => this.mapValeur[it.name] != undefined)
 | |
|       .map(it => {
 | |
|         const correction = this.mapValeur[it.name];
 | |
|         return {
 | |
|           _id: it.id,
 | |
|           'name': correction.name,
 | |
|           'system.cout': correction.system.cout,
 | |
|           'system.valeur_deniers': undefined
 | |
|         }
 | |
|       });
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_4_6_ServicesEnCommerces extends Migration {
 | |
| 
 | |
|   get code() { return "migration-service-acteurs"; }
 | |
|   get version() { return "10.4.6"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     const servicesToMigrate = game.items.filter(it => it.type == 'service');
 | |
|     servicesToMigrate.forEach(async service => {
 | |
|       const commerce = await this.convertServiceToCommerce(service);
 | |
|       await RdDBaseActor.create(commerce, { renderSheet: false });
 | |
|       await service.delete();
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   async convertServiceToCommerce(service) {
 | |
|     return {
 | |
|       name: service.name, img: service.img, type: 'commerce',
 | |
|       system: {
 | |
|         description: service.system.description,
 | |
|         notesmj: service.system.descriptionmj,
 | |
|         illimite: service.system.illimite
 | |
|       },
 | |
|       items: await this.transformInventaireCommerce(service)
 | |
|     }
 | |
|   }
 | |
|   async transformInventaireCommerce(service) {
 | |
|     const serviceItems = (service.system.items ?? []);
 | |
|     const commerceItems = await Promise.all(serviceItems.map(async (it) => { return await this.transformToItemBoutique(it); }));
 | |
|     return commerceItems.concat(Monnaie.monnaiesStandard());
 | |
|   }
 | |
| 
 | |
|   async transformToItemBoutique(serviceRefItem) {
 | |
|     const item = await RdDItem.getCorrespondingItem(serviceRefItem);
 | |
|     const itemToCreate = {
 | |
|       name: item.name, img: item.img, type: item.type,
 | |
|       system: foundry.utils.mergeObject({ cout: serviceRefItem.system.cout, quantite: serviceRefItem.system.quantite }, item.system, { overwrite: false })
 | |
|     };
 | |
|     return itemToCreate;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_5_0_UpdatePeriodicite extends Migration {
 | |
|   get code() { return "migration-periodicite-poisons-maladies"; }
 | |
|   get version() { return "10.5.0"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => this._updatePeriodicite(items));
 | |
|   }
 | |
| 
 | |
|   _updatePeriodicite(items) {
 | |
|     return items.filter(it => ['poison', 'maladie'].includes(it.type))
 | |
|       .filter(it => it.system.periodicite != "")
 | |
|       .map(it => {
 | |
|         let [incubation, periodicite] = this.getPeriodicite(it);
 | |
|         const periode = periodicite.split(' ');
 | |
|         let unite = periode.length == 2
 | |
|           ? RdDTimestamp.formulesPeriode().find(it => Grammar.includesLowerCaseNoAccent(periode[1], it.code))?.code
 | |
|           : undefined
 | |
|         if (unite && Number(periode[0])) {
 | |
|           return {
 | |
|             _id: it.id,
 | |
|             'system.periodicite': undefined,
 | |
|             'system.incubation': incubation,
 | |
|             'system.periode.nombre': Number.parseInt(periode[0]),
 | |
|             'system.periode.unite': unite
 | |
|           };
 | |
|         }
 | |
|         else {
 | |
|           return {
 | |
|             _id: it.id,
 | |
|             'system.periodicite': undefined,
 | |
|             'system.incubation': it.system.periodicite
 | |
|           };
 | |
|         }
 | |
|       }).filter(it => it != undefined);
 | |
|   }
 | |
| 
 | |
|   getPeriodicite(it) {
 | |
|     let p = it.system.periodicite.split(/[\/\\]/);
 | |
|     switch (p.length) {
 | |
|       case 2: return [p[0].trim(), p[1].trim()];
 | |
|       case 1: return ["", it.system.periodicite.trim()];
 | |
|       default: return [it.system.periodicite.trim(), ""];
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_7_0_MigrationBlessures extends Migration {
 | |
|   get code() { return "migration-blessures"; }
 | |
|   get version() { return "10.7.0"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     const timestamp = game.system.rdd.calendrier.getTimestamp()
 | |
|     await Promise.all(game.actors.filter(it => it.isPersonnage() || it.isCreature())
 | |
|       .map(async (actor) => {
 | |
|         const legeres = actor.system.blessures?.legeres.liste.filter(it => it.active).map(it => this.creerBlessure(2, 'légère', it, timestamp)) ?? [];
 | |
|         const graves = actor.system.blessures?.graves.liste.filter(it => it.active).map(it => this.creerBlessure(4, 'grave', it, timestamp)) ?? [];
 | |
|         const critiques = actor.system.blessures?.critiques.liste.filter(it => it.active).map(it => this.creerBlessure(6, 'critique', it, timestamp));
 | |
|         const blessures = legeres.concat(graves).concat(critiques);
 | |
|         if (blessures.length > 0) {
 | |
|           await actor.createEmbeddedDocuments("Item", blessures);
 | |
|         }
 | |
|         await actor.update({
 | |
|           'system.blessures.legeres.liste': [],
 | |
|           'system.blessures.graves.liste': [],
 | |
|           'system.blessures.critiques.liste': []
 | |
|         })
 | |
|       }));
 | |
|   }
 | |
|   creerBlessure(gravite, graviteTexte, blessure, timestamp) {
 | |
|     const dateBlessure = timestamp.addJours(-blessure.jours);
 | |
|     const datePremiereRecup = dateBlessure.addJours(gravite);
 | |
|     return {
 | |
|       name: `Blessure ${graviteTexte}`,
 | |
|       type: 'blessure',
 | |
|       img: `systems/foundryvtt-reve-de-dragon/icons/sante/blessure${blessure.psdone ? '-soins' : ''}.webp`,
 | |
|       system: {
 | |
|         gravite: gravite,
 | |
|         difficulte: -gravite,
 | |
|         debut: { indexDate: dateBlessure.indexDate, indexMinute: 0 },
 | |
|         fin: { indexDate: datePremiereRecup.indexDate, indexMinute: 0 },
 | |
|         premierssoins: { done: blessure.psdone, bonus: blessure.premiers_soins },
 | |
|         soinscomplets: { done: blessure.scdone, bonus: blessure.soins_complets },
 | |
|         localisation: blessure.localisation
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_7_19_CategorieCompetenceCreature extends Migration {
 | |
|   get code() { return "categorie-competence-creature"; }
 | |
|   get version() { return "10.7.19"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => ITEM_TYPES.competencecreature == it.type)
 | |
|       .map(it => this.migrateCompetenceCreature(it))
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   migrateCompetenceCreature(it) {
 | |
|     const categorie = this.getCategorie(it)
 | |
|     if (categorie == it.system.categorie) {
 | |
|       return undefined
 | |
|     }
 | |
|     return { _id: it.id, 'system.categorie': categorie }
 | |
|   }
 | |
| 
 | |
|   getCategorie(it) {
 | |
|     if (it.system.ispossession) {
 | |
|       return 'possession'
 | |
|     }
 | |
|     switch (it.system.categorie) {
 | |
|       case "melee":
 | |
|         if (it.system.isnaturelle) {
 | |
|           return 'naturelle'
 | |
|         }
 | |
|         return 'melee'
 | |
|       case "particuliere": case "specialisee": case "connaissance":
 | |
|         return "generale"
 | |
|       default:
 | |
|         return it.system.categorie
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _10_7_19_PossessionsEntiteVictime extends Migration {
 | |
|   get code() { return "possessions-entite-victime"; }
 | |
|   get version() { return "10.7.19"; }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => ITEM_TYPES.possession == it.type)
 | |
|       .map(it => this.migratePossession(it))
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   migratePossession(it) {
 | |
|     return {
 | |
|       _id: it.id,
 | |
|       'system.entite.actorid': it.system.possesseurid,
 | |
|       'system.victime.actorid': it.system.possedeid
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _11_2_20_MigrationAstrologie extends Migration {
 | |
|   get code() { return "migration-astrologie" }
 | |
|   get version() { return "11.2.20" }
 | |
| 
 | |
|   async migrate() {
 | |
|     const nombresAstraux = game.system.rdd.calendrier.getNombresAstraux()
 | |
|     nombresAstraux.forEach(na => {
 | |
|       na.lectures = na.valeursFausses
 | |
|       na.valeursFausses = undefined
 | |
|     })
 | |
|     await game.system.rdd.calendrier.setNombresAstraux(nombresAstraux)
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _12_0_26_MigrationVoieSorts extends Migration {
 | |
|   get code() { return "migration-voies-sorts" }
 | |
|   get version() { return "12.0.26" }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => [ITEM_TYPES.sort, ITEM_TYPES.sortreserve].includes(it.type))
 | |
|       .map(it => this.migrateSort(it))
 | |
|     )
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => ITEM_TYPES.competence == it.type && it.system.categorie == 'draconic')
 | |
|       .map(it => this.migrateDraconic(it))
 | |
|     )
 | |
|   }
 | |
|   migrateDraconic(it) {
 | |
|     return {
 | |
|       _id: it.id,
 | |
|       name: this.convertDraconic(it.name),
 | |
|     }
 | |
|   }
 | |
|   migrateSort(it) {
 | |
|     return {
 | |
|       _id: it.id,
 | |
|       'system.draconic': this.convertDraconic(it.system.draconic),
 | |
|     }
 | |
|   }
 | |
|   convertDraconic(draconic) {
 | |
|     for (let v of VOIES_DRACONIC) {
 | |
|       if ([v.label, v.short, v.code].includes(draconic)) {
 | |
|         return v.short
 | |
|       }
 | |
|     }
 | |
|     return draconic
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _12_0_32_MigrationRaces extends Migration {
 | |
|   get code() { return "migration-races" }
 | |
|   get version() { return "12.0.32" }
 | |
| 
 | |
|   async migrate() {
 | |
|     const races = await SystemCompendiums.getItems("races", ITEM_TYPES.race)
 | |
|     await game.actors.filter(it => it.type == ACTOR_TYPES.personnage).forEach(async actor => {
 | |
|       if (actor.itemTypes[ITEM_TYPES.race].length == 0) {
 | |
|         const raceName = actor.system.race ?? 'Humain'
 | |
|         const race = races.find(it => Grammar.equalsInsensitive(raceName, it.name))
 | |
|         if (race) {
 | |
|           console.log(this.code, `Adding race ${race.name} to actor ${actor.name}`)
 | |
|           actor.createEmbeddedDocuments('Item', [race])
 | |
|           console.log(this.code, `Neutralizing race ${race.name} adjustments for actor ${actor.name}`)
 | |
|           actor._applyRaceCaracUpdates(race, -1)
 | |
|         }
 | |
|       }
 | |
|     })
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _12_0_37_MigrationAlchimieEtat extends Migration {
 | |
|   get code() { return "migration-alchimie-etat" }
 | |
|   get version() { return "12.0.37" }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => [ITEM_TYPES.potion].includes(it.type))
 | |
|       .map(it => this.migratePotion(it))
 | |
|     )
 | |
|   }
 | |
| 
 | |
|   mappingCategorie(categorie) {
 | |
|     switch (categorie) {
 | |
|       case 'AlchimieEnchante': return 'Alchimie'
 | |
|       case 'ReposEnchante': return 'Repos'
 | |
|       case 'SoinEnchante': return 'Soin'
 | |
|       case 'AutreEnchante': return 'Autre'
 | |
|     }
 | |
|     return categorie
 | |
|   }
 | |
| 
 | |
|   mappingEtat(categorie) {
 | |
|     return ['Alchimie', 'Repos', 'Soin', 'Autre'].includes(categorie) ? 'Liquide' : 'Autre'
 | |
|   }
 | |
| 
 | |
|   migratePotion(potion) {
 | |
|     const newCategorie = this.mappingCategorie(potion.system.categorie)
 | |
|     return {
 | |
|       _id: potion.id,
 | |
|       'system.etat': this.mappingEtat(potion.system.categorie),
 | |
|       'system.magique': potion.system.pr > 0,
 | |
|       'system.categorie': newCategorie
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _12_0_38_TachesEcriture extends Migration {
 | |
|   get code() { return "migration-tache-ecriture" }
 | |
|   get version() { return "12.0.38" }
 | |
| 
 | |
|   async migrate() {
 | |
|     await this.applyItemsUpdates(items => items
 | |
|       .filter(it => [ITEM_TYPES.tache, ITEM_TYPES.livre, ITEM_TYPES.oeuvre, ITEM_TYPES.meditation].includes(it.type) )
 | |
|       .filter(it => Grammar.equalsInsensitive(it.system.competence, 'ecriture'))
 | |
|       .map(it => { return { _id: it.id, 'system.competence': 'Écriture' } })
 | |
|     )
 | |
|   }
 | |
| }
 | |
| 
 | |
| class _13_0_4_FixReveActuel extends Migration {
 | |
|   get code() { return "fix-revvve-actuel" }
 | |
|   get version() { return "13.0.4" }
 | |
| 
 | |
|   async migrate() {
 | |
|     game.actors.forEach(it => it.update({'system.carac.-=reve-actuel': null}))
 | |
|   }
 | |
| }
 | |
| 
 | |
| export class Migrations {
 | |
|   static getMigrations() {
 | |
|     return [
 | |
|       new _1_5_34_migrationPngWebp(),
 | |
|       new _10_0_16_MigrationSortsReserve(),
 | |
|       new _10_0_17_MigrationCompetenceCreature(),
 | |
|       new _10_0_21_VehiculeStructureResistanceMax(),
 | |
|       new _10_0_33_MigrationNomsDraconic(),
 | |
|       new _10_2_5_ArmesTirLancer(),
 | |
|       new _10_2_10_DesirLancinant_IdeeFixe(),
 | |
|       new _10_3_0_Inventaire(),
 | |
|       new _10_3_0_FrequenceEnvironnement(),
 | |
|       new _10_3_17_Monnaies(),
 | |
|       new _10_4_6_ServicesEnCommerces(),
 | |
|       new _10_5_0_UpdatePeriodicite(),
 | |
|       new _10_7_0_MigrationBlessures(),
 | |
|       new _10_7_19_CategorieCompetenceCreature(),
 | |
|       new _10_7_19_PossessionsEntiteVictime(),
 | |
|       new _11_2_20_MigrationAstrologie(),
 | |
|       new _12_0_26_MigrationVoieSorts(),
 | |
|       new _12_0_32_MigrationRaces(),
 | |
|       new _12_0_37_MigrationAlchimieEtat(),
 | |
|       new _12_0_38_TachesEcriture(),
 | |
|       new _13_0_4_FixReveActuel()
 | |
|     ];
 | |
|   }
 | |
| 
 | |
|   constructor() {
 | |
|     game.settings.register(SYSTEM_RDD, "systemMigrationVersion", {
 | |
|       name: "System Migration Version",
 | |
|       scope: "world",
 | |
|       config: false,
 | |
|       type: String,
 | |
|       default: "0.0.0",
 | |
|     });
 | |
|   }
 | |
| 
 | |
|   migrate() {
 | |
|     let currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion")
 | |
|     if (currentVersion.startsWith("v")) {
 | |
|       currentVersion = currentVersion.substring(1)
 | |
|     }
 | |
|     if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
 | |
|       // if (true) { /* comment previous and uncomment here to test before upgrade  */
 | |
|       const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion));
 | |
|       if (migrations.length > 0) {
 | |
|         migrations.sort((a, b) => this.compareVersions(a, b));
 | |
|         migrations.forEach(async (m) => {
 | |
|           ui.notifications.info(
 | |
|             `${LOG_HEAD} Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
 | |
|           );
 | |
|           await m.migrate();
 | |
|         });
 | |
|         ui.notifications.info(
 | |
|           `Migrations done, version will change to ${game.system.version}`
 | |
|         );
 | |
|       } else {
 | |
|         console.log(`${LOG_HEAD} No migration needeed, version will change to ${game.system.version}`
 | |
|         );
 | |
|       }
 | |
| 
 | |
|       game.settings.set(
 | |
|         SYSTEM_RDD,
 | |
|         "systemMigrationVersion",
 | |
|         game.system.version
 | |
|       );
 | |
|     } else {
 | |
|       console.log(`${LOG_HEAD} No system version changed`);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   compareVersions(a, b) {
 | |
|     return isNewerVersion(a.version, b.version) ? 1 : isNewerVersion(b.version, a.version) ? -1 : 0;
 | |
|   }
 | |
| }
 |