Compare commits

..

No commits in common. "2bbf606f3053b6b62d980ee415260bc05142bd5b" and "a1032392887a40e3ac319519095a897cabc486de" have entirely different histories.

24 changed files with 85 additions and 115 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

View File

@ -1,4 +0,0 @@
[Dolphin]
Timestamp=2024,5,29,20,57,41.954
Version=4
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails

View File

@ -38,22 +38,10 @@ export class ChatVente {
return foundry.utils.mergeObject(detail, { acheteur })
}
static async diminuerQuantiteAchatVente(chatMessageId, quantite) {
const chatMessage = game.messages.get(chatMessageId)
const vente = ChatVente.getDetailVente(chatMessageId)
vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
chatMessage.update({ content: html });
chatMessage.render(true);
}
static async displayAchatVente(vente) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {
static async setDetailAchatVente(chatMessage, vente) {
await chatMessage?.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage?.setFlag(SYSTEM_RDD, DETAIL_VENTE, {
item: vente.item,
properties: vente.item.getProprietes(),
vendeurId: vente.vendeurId,
@ -62,4 +50,21 @@ export class ChatVente {
prixLot: vente.prixLot
})
}
static async diminuerQuantite(chatMessageId, quantite) {
const chatMessage = game.messages.get(chatMessageId)
const vente = ChatVente.getDetailVente(chatMessageId)
vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage?.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
chatMessage.update({ content: html });
chatMessage.render(true);
}
static async displayAchatVente(venteData) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData);
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await ChatVente.setDetailAchatVente(chatMessage, venteData)
}
}

View File

@ -902,7 +902,7 @@ export class RdDActor extends RdDBaseActorSang {
async ajouterRefoulement(value = 1, refouler) {
let refoulement = this.system.reve.refoulement.value + value;
const roll = new Roll("1d20");
await roll.evaluate();
await roll.evaluate({ async: true });
await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` });
if (roll.total <= refoulement) {
refoulement = 0;
@ -991,7 +991,9 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
buildTMRInnaccessible() {
return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord)
return this.items[TYPES.casetmr]
.filter(it => EffetsDraconiques.isInnaccessible(it))
.map(it => it.system.coord)
}
/* -------------------------------------------- */
@ -2626,13 +2628,13 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async resetItemUse() {
await this.unsetFlag(SYSTEM_RDD, 'itemUse');
await this.setFlag(SYSTEM_RDD, 'itemUse', {});
}
/* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) {
const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
let itemUse = foundry.utils.duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {});
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse);

View File

@ -32,10 +32,10 @@ export class RdDBaseActor extends Actor {
}
static init() {
Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id))
Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id));
Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id));
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
}
static onSocketMessage(sockmsg) {
@ -82,6 +82,10 @@ export class RdDBaseActor extends Actor {
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
static getParentActor(document) {
return document?.parent instanceof Actor ? document.parent : undefined
}
/**
* Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
* compétences et monnaies.
@ -377,7 +381,7 @@ export class RdDBaseActor extends Actor {
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
}
else if (achat.chatMessageIdVente) {
await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
await ChatVente.diminuerQuantite(achat.chatMessageIdVente, achat.choix.nombreLots)
}
}
}

View File

@ -149,13 +149,14 @@ export class ChatUtility {
}
static async setMessageData(chatMessage, key, flag) {
if (flag && chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, key, flag)
if (flag) {
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag));
}
}
static getMessageData(chatMessage, key) {
return chatMessage.getFlag(SYSTEM_RDD, key);
const json = chatMessage.getFlag(SYSTEM_RDD, key);
return json ? JSON.parse(json) : undefined;
}
static getChatMessage(event) {
@ -174,8 +175,6 @@ export class ChatUtility {
}
static async onCreateChatMessage(chatMessage, options, id) {
if (chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
}

View File

@ -117,8 +117,8 @@ export class RdDCoeur {
}
ChatUtility.removeChatMessageId(infoCoeur.chatMessageId)
infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate())).total
infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate())).total
infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total
infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total
const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre)
for (let amoureux of [infoCoeur.source, infoCoeur.target]) {
const actorAmoureux = game.actors.get(amoureux.actor.id);

View File

@ -29,25 +29,5 @@ export const RDD_CONFIG = {
"incarne": "Incarnée",
"nonincarne": "Non Incarnée",
"blurette": "Blurette"
},
heuresRdD : [
{value : "vaisseau", label: "Vaisseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd01.webp"},
{value : "sirene", label: "Sirène", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd02.webp"},
{value : "faucon", label: "Faucon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd03.webp"},
{value : "couronne", label: "Couronne", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd04.webp"},
{value : "dragon", label: "Dragon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd05.webp"},
{value : "epees", label: "Epées", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd06.webp"},
{value : "lyre", label: "Lyre", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd07.webp"},
{value : "serpent", label: "Serpent", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd08.webp"},
{value : "poissonacrobate", label: "Poisson Acrobate", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd09.webp"},
{value : "araignee", label: "Araignée", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd10.webp"},
{value : "roseau", label: "Roseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd11.webp"},
{value : "chateaudormant", label: "Chateau Dormant", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd12.webp"}
],
raretes: [
{value: "Commune", label: "Commune"},
{value: "Frequente", label: "Fréquente"},
{value: "Rare", label: "Rare"},
{value: "Rarissime", label: "Rarissime"}
]
}
}

View File

@ -108,8 +108,8 @@ export class RdDItemSheet extends ItemSheet {
const competences = await SystemCompendiums.getCompetences('personnage');
formData.categories = this.item.getCategories()
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
formData.caracList = foundry.utils.duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.system.model.Actor.personnage.reve.reve)
formData.competences = competences;
}
if (this.item.type == 'arme') {

View File

@ -48,7 +48,7 @@ export class RdDItemBlessure extends RdDItem {
let lostEndurance = 0
let lostVie = 0
if (definition.endurance) {
lostEndurance = await new Roll(definition.endurance).roll().total;
lostEndurance = new Roll(definition.endurance).roll({async: false}).total;
actor.santeIncDec("endurance", -Number(lostEndurance));
}
if (definition.vie) {

View File

@ -567,7 +567,7 @@ export class Migrations {
if (currentVersion.startsWith("v")) {
currentVersion = currentVersion.substring(1)
}
if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
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) {

View File

@ -166,39 +166,15 @@ export class Misc {
}
static firstConnectedGM() {
return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
}
static connectedGMs() {
return game.users.filter(u => u.isGM && u.active);
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
}
/**
* This helper method allows to get the docuument, for a single user (either first connected GM, or the owner
* if there is no connected GMs), or else return undefined.
*
* This allows for example update hooks that should apply modifications to actors to be called only for one
* user (preventing the "User ... lacks permission to update Item" that was occuring on hooks when Item updates
* were triggering other changes)
*
* @param {*} document the Document with is potentially an Actor
* @returns the actor if either the game.user is the first connected GM, or if the game.user is the owner
* and there is no connected GM
*/
static documentIfResponsible(document) {
if (document instanceof Document) {
if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
return document
}
}
return undefined
static isOwnerPlayer(actor, user = undefined) {
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
}
static isOwnerPlayer(actor) {
return actor.testUserPermission(game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
}
static isOwnerPlayerOrUniqueConnectedGM(actor) {
return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM();
static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) {
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
}
/**

View File

@ -119,7 +119,7 @@ export class RdDCombatManager extends Combat {
//console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula);
if (!roll.total) {
await roll.evaluate();
roll.evaluate({ async: false });
}
const total = Math.max(roll.total, 0.00);
console.log("Compute init for", rollFormula, roll, total, combatant);

View File

@ -138,7 +138,7 @@ export class RdDDice {
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
const roll = new Roll(RdDDice._formulaOrFake(formula, options));
await roll.evaluate();
await roll.evaluate({ async: true });
await this.showDiceSoNice(roll, options);
return roll;
}
@ -216,7 +216,7 @@ export class RdDDice {
static async fakeD10(faces) {
let roll = new Roll(`1d${faces}`);
await roll.evaluate();
await roll.evaluate({ async: true });
return roll.total;
}

View File

@ -56,7 +56,7 @@ const temperatures = [
export class RdDMeteo {
static async getForce() {
const roll = new Roll(`1dr`);
await roll.evaluate();
await roll.evaluate({ async: true });
return roll.total;
}
@ -67,14 +67,14 @@ export class RdDMeteo {
static async getTemperature() {
const degre = await RdDMeteo.getForce();
const rollChaudFroid = new Roll('1d2');
await rollChaudFroid.evaluate();
await rollChaudFroid.evaluate({ async: true });
const chaudFroid = rollChaudFroid.total == 1;
return chaudFroid.total ? degre : -degre;
}
static async getDirection(direction) {
const roll = new Roll(`1d16`);
await roll.evaluate();
await roll.evaluate({ async: true });
switch (roll.total % 16) {
case 0: return 'Nord';
case 1: return 'Nord Nord Est';

View File

@ -300,14 +300,6 @@ export class RdDUtility {
Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff))
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
return loadTemplates(templatePaths);
}
@ -632,7 +624,7 @@ export class RdDUtility {
/* -------------------------------------------- */
static async _evaluatePerte(formula, over20) {
let perte = new Roll(formula, { over20: over20 });
await perte.evaluate();
await perte.evaluate({ async: true });
return perte.total;
}

View File

@ -17,7 +17,7 @@ export class AutoAdjustDarkness {
static async adjust(darkness) {
if (AutoAdjustDarkness.isAuto()) {
const scene = game.scenes.viewed;
if (scene?.environment?.globalLight?.enabled && scene?.tokenVision) {
if (scene?.globalLight && scene?.tokenVision) {
await scene.update({ darkness });
}
}

View File

@ -2,7 +2,7 @@
{{#if effects}}
{{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.id}}">
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
</span>
{{/each}}
{{#if calc.surprise}}<span>{{calc.surprise}}!</span>{{/if}}

View File

@ -2,6 +2,8 @@
<div class="flexrow">
<input type="number" name="{{path}}.nombre" value="{{nombre}}" data-dtype="Number"/>
<select name="{{path}}.unite" data-dtype="String" >
{{selectOptions (timestamp-formulesPeriode) selected=unite labelAttr="label" nameAttr="code" valueAttr="code"}}
{{#select unite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-periode.html"}}
{{/select}}
</select>
</div>

View File

@ -6,7 +6,9 @@
type="number" data-dtype="Number" min="1" max="28"
name="{{path}}.jourDuMois" value="{{jourDuMois}}" />
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.mois" class="calendar-signe-heure" data-dtype="String">
{{select config.heuresRdD selected=mois.key labelAttr="label" nameAttr="value" valueAttr="value"}}
{{#select mois.key}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
</select>
{{timestamp-imgSigne mois}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.annee" value="{{annee}}" data-dtype="Number"/>
@ -15,7 +17,9 @@
<label></label>
<label>heure</label>
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.heure" class="calendar-signe-heure" data-dtype="String">
{{select config.heuresRdD selected=heure.key labelAttr="label" nameAttr="value" valueAttr="value"}}
{{#select heure.key}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
</select>
{{timestamp-imgSigne heure}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.minute" value="{{minute}}" data-dtype="Number"/>

View File

@ -26,7 +26,9 @@
</label>
<span class="flexrow">
<select name="milieu-{{key}}-rarete" class="environnement-rarete flex-shrink" data-dtype="String">
{{selectOptions config.rarete selected=env.rarete labelAttr="label" valueAttr="value" nameAttr="value"}}
{{#select env.rarete}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}}
</select>
{{rangePicker name="milieu-{{key}}-frequence" value=env.frequence min=(rarete-getChamp env.rarete 'min') max=(rarete-getChamp env.rarete 'max') step=1}}
<label>[{{rarete-getChamp env.rarete 'min'}}-{{rarete-getChamp env.rarete 'max'}}]</label>

View File

@ -7,7 +7,7 @@
{{else}}
<input class="resource-content select-effect" type="checkbox" name="{{effect.id}}" {{#if effect.active}}checked{{/if}}/>
{{/if}}
<img class="button-effect-img" height="16" width="16" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" />
<img class="button-effect-img" height="16" width="16" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" />
<label>{{localize effect.name}}</label>
</li>
{{/each}}

View File

@ -1,11 +1,19 @@
<div>
<label>Conditions</label>
<select name="diffConditions" data-dtype="Number">
{{selectOptions actorAstrologie.ajustements selected='0'}}
{{#select '0'}}
{{#each actorAstrologie.ajustements as |ajustement|}}
<option value={{ajustement}}>{{ajustement}}</option>
{{/each}}
{{/select}}
</select>
<label>&nbsp;&nbsp;Jours</label>
<select name="joursAstrologie" data-dtype="Number">
{{selectOptions dates selected='' labelAttr='label' valueAttr='index' nameAttr='index'}}
{{#select ''}}
{{#each dates as |date|}}
<option value={{date.index}}>{{date.label}}</option>
{{/each}}
{{/select}}
</select>
<label>
&nbsp;&nbsp;Etat Général: {{actorAstrologie.etat}}