485 lines
16 KiB
JavaScript
485 lines
16 KiB
JavaScript
import { RdDBaseActor } from "./actor/base-actor.js";
|
|
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
|
import { Environnement } from "./environnement.js";
|
|
import { Grammar } from "./grammar.js";
|
|
import { Monnaie } from "./item-monnaie.js";
|
|
import { RdDItem } from "./item.js";
|
|
import { RdDTimestamp } from "./rdd-timestamp.js";
|
|
import { RdDRaretes } from "./tirage/raretes.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);
|
|
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);
|
|
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() {
|
|
await game.actors
|
|
.filter((actor) => actor.type == "personnage")
|
|
.filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0)
|
|
.forEach(async (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-creature-parade"; }
|
|
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 = 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.getRarete(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: 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(), ""];
|
|
}
|
|
}
|
|
}
|
|
|
|
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(),
|
|
];
|
|
}
|
|
|
|
constructor() {
|
|
game.settings.register(SYSTEM_RDD, "systemMigrationVersion", {
|
|
name: "System Migration Version",
|
|
scope: "world",
|
|
config: false,
|
|
type: String,
|
|
default: "0.0.0",
|
|
});
|
|
}
|
|
|
|
migrate() {
|
|
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
|
if (isNewerVersion(game.system.version, currentVersion)) {
|
|
//if (true) { /* comment previous and uncomment here to test before upgrade */
|
|
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
|
if (migrations.length > 0) {
|
|
migrations.sort((a, b) => this.compareVersions(a, b));
|
|
migrations.forEach(async (m) => {
|
|
ui.notifications.info(
|
|
`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;
|
|
}
|
|
}
|