`)
+ /*
+ * TODO: support de plusieurs combats parallèles
+ * il faudrait avoir un id de combat en plus de celui de passe d'armes
+ */
+ for (const key in game.system.rdd.combatStore.attaques) {
+ const attackerRoll = game.system.rdd.combatStore.attaques[key];
+ ChatUtility.removeChatMessageActionsPasseArme(`
`);
+ }
+ for (const key in game.system.rdd.combatStore.defenses) {
+ const defenderRoll = game.system.rdd.combatStore.defenses[key];
+ ChatUtility.removeMyChatMessageContaining(`
`);
+ }
+ RdDCombat.initStorePasseArmes();
+ }
+ }
+
+ /* -------------------------------------------- */
+ static combatNouveauRound(combat) {
+ let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
+ if (game.user.isGM) {
+ // seul le GM notifie le status
+ this.displayActorCombatStatus(combat, turn.actor);
+ // TODO Playaudio for player??
+ }
+ }
+
/* -------------------------------------------- */
static isActive() {
return true;
@@ -58,6 +119,33 @@ export class RdDCombat {
return RdDCombat.createUsingTarget(attacker)
}
+ /* -------------------------------------------- */
+ static handleMsgDefense(data) {
+ let defenderToken = canvas.tokens.get(data.defenderTokenId);
+ if (defenderToken) {
+ if (!game.user.isGM && game.user.character == undefined) { // vérification / sanity check
+ ui.notifications.error("Le joueur " + game.user.name + " n'est connecté à aucun personnage. Impossible de continuer.");
+ return;
+ }
+ if ((game.user.isGM && !defenderToken.actor.hasPlayerOwner) || (defenderToken.actor.hasPlayerOwner && (game.user.character.id == defenderToken.actor.data._id))) {
+ //console.log("User is pushing message...", game.user.name);
+ game.system.rdd.combatStore.attaques[data.attackerId] = duplicate(data.rollData);
+ data.whisper = [game.user];
+ data.blind = true;
+ data.rollMode = "blindroll";
+ ChatMessage.create(data);
+ }
+ }
+ }
+
+ static terminerPasseArmes(data) {
+ if (game.user.isGM) { // Seul le GM nettoie le stockage des données de combat
+ let attackerRoll = game.system.rdd.combatStore.attaques[data.attackerId]; // Retrieve the rolldata from the store
+ game.system.rdd.combatStore.attaques[data.attackerId] = undefined;
+ game.system.rdd.combatStore.defenses[attackerRoll.passeArme] = undefined;
+ }
+ }
+
/* -------------------------------------------- */
static _sendRollMessage(sender, recipient, defenderTokenId, topic, message, rollData) {
let chatMessage = {
@@ -129,7 +217,7 @@ export class RdDCombat {
/* -------------------------------------------- */
async onEvent(button, event) {
- let attackerRoll = game.system.rdd.rollDataHandler.attaques[this.attackerId];
+ let attackerRoll = game.system.rdd.combatStore.attaques[this.attackerId];
if (!attackerRoll) {
ui.notifications.warn("Action automatisée impossible, le jet de l'attaquant a été perdu (suite à un raffraichissement?)")
return;
@@ -163,18 +251,18 @@ export class RdDCombat {
/* -------------------------------------------- */
_consumeDefense(passeArme) {
let defenderRoll = this._getDefense(passeArme);
- game.system.rdd.rollDataHandler.defenses[passeArme] = undefined;
+ game.system.rdd.combatStore.defenses[passeArme] = undefined;
return defenderRoll;
}
/* -------------------------------------------- */
_getDefense(passeArme) {
- return game.system.rdd.rollDataHandler.defenses[passeArme];
+ return game.system.rdd.combatStore.defenses[passeArme];
}
/* -------------------------------------------- */
_storeDefense(defenderRoll) {
- game.system.rdd.rollDataHandler.defenses[defenderRoll.passeArme] = defenderRoll;
+ game.system.rdd.combatStore.defenses[defenderRoll.passeArme] = defenderRoll;
}
/* -------------------------------------------- */
@@ -320,7 +408,7 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onAttaqueParticuliere(rollData) {
- game.system.rdd.rollDataHandler.attaques[this.attackerId] = duplicate(rollData);
+ game.system.rdd.combatStore.attaques[this.attackerId] = duplicate(rollData);
// Finesse et Rapidité seulement en mêlée et si la difficulté libre est de -1 minimum
const isMeleeDiffNegative = rollData.selectedCarac.label == "Mêlée" && rollData.diffLibre < 0;
@@ -342,7 +430,7 @@ export class RdDCombat {
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
// Save rollData for defender
- game.system.rdd.rollDataHandler.attaques[this.attackerId] = duplicate(attackerRoll);
+ game.system.rdd.combatStore.attaques[this.attackerId] = duplicate(attackerRoll);
attackerRoll.show = {
cible: this.target ? this.defender.data.name : 'la cible',
@@ -401,7 +489,7 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onAttaqueEchecTotal(attackerRoll) {
- game.system.rdd.rollDataHandler.attaques[this.attackerId] = duplicate(attackerRoll);
+ game.system.rdd.combatStore.attaques[this.attackerId] = duplicate(attackerRoll);
// Finesse et Rapidité seulement en mêlée et si la difficulté libre est de -1 minimum
ChatMessage.create({
@@ -755,8 +843,9 @@ export class RdDCombat {
}
/* -------------------------------------------- */
- static async displayActorCombatStatus(actor) {
- let rollData = {
+ static async displayActorCombatStatus(combat, actor) {
+ let data = {
+ combatId: combat._id,
alias: actor.name,
etatGeneral: actor.getEtatGeneral(),
isSonne: actor.getSonne(),
@@ -767,22 +856,14 @@ export class RdDCombat {
isCritique: false
}
if (actor.countBlessuresByName("critiques") > 0) { // Pour éviter le cumul grave + critique
- rollData.isCritique = true;
+ data.isCritique = true;
} else if (actor.countBlessuresByName("graves") > 0) {
- rollData.isGrave = true;
+ data.isGrave = true;
}
+
ChatUtility.createChatWithRollMode(actor.name, {
- content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, rollData)
+ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, data)
});
}
- /* -------------------------------------------- */
- static updateCombatRound(combat, data) {
- if (combat.data.round != 0 && combat.turns && combat.data.active) {
- let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
- this.displayActorCombatStatus(turn.actor);
- // TODO Playaudio ??
- }
- }
-
}
\ No newline at end of file
diff --git a/module/rdd-main.js b/module/rdd-main.js
index 18be45a1..80ed4442 100644
--- a/module/rdd-main.js
+++ b/module/rdd-main.js
@@ -45,16 +45,16 @@ const _patch_initiative = () => {
ids = typeof ids === "string" ? [ids] : ids;
const currentId = this.combatant._id;
// calculate initiative
- for ( let cId = 0; cId < ids.length; cId++) {
- const c = this.getCombatant( ids[cId] );
+ for (let cId = 0; cId < ids.length; cId++) {
+ const c = this.getCombatant(ids[cId]);
//if (!c) return results;
let rollFormula = formula; // Init per default
- if ( !rollFormula ) {
+ if (!rollFormula) {
let armeCombat, competence;
- if ( c.actor.data.type == 'creature' || c.actor.data.type == 'entite') {
+ if (c.actor.data.type == 'creature' || c.actor.data.type == 'entite') {
for (const competenceItem of c.actor.data.items) {
- if ( competenceItem.data.iscombat) {
+ if (competenceItem.data.iscombat) {
competence = duplicate(competenceItem);
}
}
@@ -65,17 +65,17 @@ const _patch_initiative = () => {
armeCombat = duplicate(item);
}
}
- let compName = ( armeCombat == undefined ) ? "Corps à corps" : armeCombat.data.competence;
- competence = RdDItemCompetence.findCompetence( c.actor.data.items, compName );
- rollFormula = RdDUtility.calculInitiative(competence.data.niveau, c.actor.data.data.carac[competence.data.defaut_carac].value);
+ let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
+ competence = RdDItemCompetence.findCompetence(c.actor.data.items, compName);
+ rollFormula = RdDUtility.calculInitiative(competence.data.niveau, c.actor.data.data.carac[competence.data.defaut_carac].value);
}
}
//console.log("Combatat", c);
const roll = this._getInitiativeRoll(c, rollFormula);
- if ( roll.total <= 0 ) roll.total = 1;
+ if (roll.total <= 0) roll.total = 1;
//console.log("Compute init for", armeCombat, competence, rollFormula, roll.total);
- await this.updateEmbeddedEntity("Combatant", { _id: c._id, initiative: roll.total });
-
+ await this.updateEmbeddedEntity("Combatant", { _id: c._id, initiative: roll.total });
+
// Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
let messageData = mergeObject(
@@ -98,22 +98,17 @@ const _patch_initiative = () => {
}
/************************************************************************************/
-Hooks.once("init", async function() {
+Hooks.once("init", async function () {
console.log(`Initializing Reve de Dragon System`);
-
+
// preload handlebars templates
RdDUtility.preloadHandlebarsTemplates();
-
// Create useful storage space
game.system.rdd = {
- rollDataHandler: {
- attaques: {},
- defenses: {}
- },
TMRUtility: TMRUtility
}
- /* -------------------------------------------- */
+ /* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "accorder-entite-cauchemar", {
name: "Accorder le rêve aux entités",
hint: "A quel moment les personnages doivent accorder leur rêve aux entités de cauchemar",
@@ -130,7 +125,7 @@ Hooks.once("init", async function() {
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "calendrier", {
- name: "calendrier",
+ name: "calendrier",
scope: "world",
config: false,
type: Object
@@ -138,7 +133,7 @@ Hooks.once("init", async function() {
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "liste-nombre-astral", {
- name: "liste-nombre-astral",
+ name: "liste-nombre-astral",
scope: "world",
config: false,
type: Object
@@ -146,7 +141,7 @@ Hooks.once("init", async function() {
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "calendrier-pos", {
- name: "calendrierPos",
+ name: "calendrierPos",
scope: "world",
config: false,
type: Object
@@ -160,7 +155,7 @@ Hooks.once("init", async function() {
config: true,
default: false,
type: Boolean
- });
+ });
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "supprimer-dialogues-combat-chat", {
@@ -170,7 +165,7 @@ Hooks.once("init", async function() {
config: true,
default: true,
type: Boolean
- });
+ });
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "activer-sons-audio", {
name: "Activer les bruitages intégrés",
@@ -180,37 +175,39 @@ Hooks.once("init", async function() {
default: true,
type: Boolean
});
-
+
/* -------------------------------------------- */
- // Set an initiative formula for the system
- CONFIG.Combat.initiative = {
- formula: "1d20",
+ // Set an initiative formula for the system
+ CONFIG.Combat.initiative = {
+ formula: "1d20",
decimals: 2
};
-
+
/* -------------------------------------------- */
game.socket.on("system.foundryvtt-reve-de-dragon", data => {
- RdDUtility.performSocketMesssage( data );
+ RdDUtility.onSocketMesssage(data);
+ RdDCombat.onSocketMessage(data);
});
/* -------------------------------------------- */
- // Define custom Entity classes
+ // Define custom Entity classes
CONFIG.Actor.entityClass = RdDActor;
- CONFIG.RDD = {
- resolutionTable : RdDResolutionTable.resolutionTable,
- carac_array : RdDUtility.getCaracArray(),
- ajustementsConditions : RdDUtility.getAjustementsConditions(),
- difficultesLibres : RdDUtility.getDifficultesLibres()
+ CONFIG.RDD = {
+ resolutionTable: RdDResolutionTable.resolutionTable,
+ carac_array: RdDUtility.getCaracArray(),
+ ajustementsConditions: RdDUtility.getAjustementsConditions(),
+ difficultesLibres: RdDUtility.getDifficultesLibres()
}
-
+
/* -------------------------------------------- */
// Register sheet application classes
Actors.unregisterSheet("core", ActorSheet);
Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorSheet, {
- types: ["personnage"],
- makeDefault: true }
+ types: ["personnage"],
+ makeDefault: true
+ }
);
- Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorCreatureSheet, {
+ Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorCreatureSheet, {
types: ["creature"],
makeDefault: true
});
@@ -218,44 +215,41 @@ Hooks.once("init", async function() {
types: ["vehicule"],
makeDefault: true
});
- Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, {
+ Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, {
types: ["entite"],
makeDefault: true
});
Items.unregisterSheet("core", ItemSheet);
- Items.registerSheet("foundryvtt-reve-de-dragon", RdDItemSheet, {makeDefault: true});
+ Items.registerSheet("foundryvtt-reve-de-dragon", RdDItemSheet, { makeDefault: true });
// Handlebar function pour container
Handlebars.registerHelper('buildConteneur', (objet) => { return RdDUtility.buildConteneur(objet); });
// Patch the initiative formula
_patch_initiative();
+
+ // préparation des différents modules
+ RdDCommands.init();
+ RdDCombat.init();
+ RdDTokenHud.init();
});
/* -------------------------------------------- */
-function messageDeBienvenue(){
+function messageDeBienvenue() {
ChatUtility.removeMyChatMessageContaining('
Bienvenue dans le Rêve des Dragons !
+ whisper: [game.user._id],
+ content: `
Bienvenue dans le Rêve des Dragons ! Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
La commande /aide dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.