Compare commits

...

4 Commits

Author SHA1 Message Date
b4f0be5d64 Version 12.0.19 2024-11-07 00:26:59 +01:00
5ff31d462f Fix initiative de masse
L'initiative de masse utilise la première compétence de combat trouvée
2024-11-07 00:16:12 +01:00
be1d109def Corrections actions combat créatures
Les actions de combat des créatures et leurs défenses sont
correctement filtrées
2024-11-06 23:24:53 +01:00
d91bee0f42 Merge pull request 'Version 12.0.18 - A la barbe d'Astrobazzarh' (#719) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: public/foundryvtt-reve-de-dragon#719
2024-11-05 20:27:55 +01:00
10 changed files with 222 additions and 227 deletions

View File

@ -1,4 +1,10 @@
# 12.0 # 12.0
## 12.0.19 - La témérité d'Astrobazzarh
- Fix
- les défenses des créatures sont correctement filtrées
- le lancer d'initiative pour tous les personnages/PNJs fonctionne correctement
- les lieux et commerces n'ont pas d'initiative
## 12.0.18 - A la barbe d'Astrobazzarh ## 12.0.18 - A la barbe d'Astrobazzarh
- Améliorations sur la feuille de PNJ simplifiée - Améliorations sur la feuille de PNJ simplifiée
- Ajout du portrait - Ajout du portrait

View File

@ -36,6 +36,8 @@ import { ITEM_TYPES } from "./item.js";
import { RdDBaseActorSang } from "./actor/base-actor-sang.js"; import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
import { RdDItemArme } from "./item-arme.js";
import { RdDCombatManager } from "./rdd-combat.js";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@ -130,6 +132,23 @@ export class RdDActor extends RdDBaseActorSang {
.reduce(Misc.sum(), 0); .reduce(Misc.sum(), 0);
} }
listActionsCombat() {
// Recupération des armes
const actions = RdDCombatManager.listActionsArmes(
this.itemTypes[ITEM_TYPES.arme]
.filter(it => RdDItemArme.isAttaque(it))
.concat(RdDItemArme.empoignade(this))
.concat(RdDItemArme.mainsNues(this))
,
this.itemTypes[ITEM_TYPES.competence],
this.system.carac)
if (this.system.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
}
return actions
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getTache(id) { return this.findItemLike(id, 'tache') } getTache(id) { return this.findItemLike(id, 'tache') }
getMeditation(id) { return this.findItemLike(id, 'meditation') } getMeditation(id) { return this.findItemLike(id, 'meditation') }
@ -1548,7 +1567,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
if (!Misc.isFirstConnectedGM()){ if (!Misc.isFirstConnectedGM()) {
return return
} }
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
@ -3067,7 +3086,7 @@ export class RdDActor extends RdDBaseActorSang {
incarnation.name = 'Réincarnation de ' + incarnation.name incarnation.name = 'Réincarnation de ' + incarnation.name
incarnation.system = { incarnation.system = {
carac: foundry.utils.duplicate(this.system.carac), carac: foundry.utils.duplicate(this.system.carac),
heure: RdDTimestamp.defHeure(await RdDDice.rollHeure( { rollMode: "selfroll", showDice: SHOW_DICE })).key, heure: RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18, age: 18,
biographie: '', biographie: '',
notes: '', notes: '',

View File

@ -15,7 +15,7 @@ import { StatusEffects } from "../settings/status-effects.js";
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Targets } from "../targets.js"; import { Targets } from "../targets.js";
import { RdDPossession } from "../rdd-possession.js"; import { RdDPossession } from "../rdd-possession.js";
import { RdDCombat } from "../rdd-combat.js"; import { RdDCombat, RdDCombatManager } from "../rdd-combat.js";
import { RdDConfirm } from "../rdd-confirm.js"; import { RdDConfirm } from "../rdd-confirm.js";
import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js"; import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { RdDItemArme } from "../item-arme.js"; import { RdDItemArme } from "../item-arme.js";
@ -83,6 +83,23 @@ export class RdDBaseActorReve extends RdDBaseActor {
getEtatGeneral(options = { ethylisme: false }) { return 0 } getEtatGeneral(options = { ethylisme: false }) { return 0 }
isActorCombat() { return true } isActorCombat() { return true }
getCaracInit(competence) {
if (!competence){
return 0
}
if (competence.type == ITEM_TYPES.competencecreature) {
return competence.system.carac_value
}
return this.system.carac[competence.system.defaut_carac].value;
}
listActionsCombat() {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => RdDItemCompetenceCreature.isAttaque(it))
.map(it => RdDItemCompetenceCreature.armeCreature(it))
.filter(it => it != undefined);
}
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() } async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
async remiseANeuf() { } async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { } async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
@ -155,9 +172,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
getPossession(possessionId) { getPossession(possessionId) {
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId); return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
getPossessions() {
return this.itemTypes[ITEM_TYPES.possession];
}
getEmpoignades() { getEmpoignades() {
return this.itemTypes[ITEM_TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
@ -370,7 +384,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
rollArme(arme, categorieArme, token) { rollArme(arme, categorieArme, token) {
token = token ?? RdDUtility.getSelectedToken(this) token = token ?? RdDUtility.getSelectedToken(this)
const compToUse = this.$getCompetenceArme(arme, categorieArme) const compToUse = this.$getCompetenceArme(arme, categorieArme)
if (!RdDItemArme.isArmeUtilisable(arme)) { if (!RdDItemArme.isUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`) ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`)
return return
} }
@ -452,7 +466,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
alias: defenderToken?.name ?? this.name, alias: defenderToken?.name ?? this.name,
hasPlayerOwner: this.hasPlayerOwner, hasPlayerOwner: this.hasPlayerOwner,
show: show ?? {} show: show ?? {}
}, {overwrite: false}); }, { overwrite: false });
await ChatUtility.createChatWithRollMode( await ChatUtility.createChatWithRollMode(
{ {

View File

@ -710,4 +710,19 @@ export class RdDBaseActor extends Actor {
getItemUse(itemId) { return 0; } getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { } async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false } isActorCombat() { return false }
getCaracInit(competence) { return 0 }
listActionsCombat() { return [] }
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.map(p => {
return {
name: p.name,
action: 'possession',
system: {
competence: p.name,
possessionid: p.system.possessionid,
}
}
})
}
} }

View File

@ -152,8 +152,8 @@ export class Mapping {
} }
static prepareArme(actor, arme, maniement) { static prepareArme(actor, arme, maniement) {
const nameCompArme = RdDItemArme.getCompetenceArme(arme, maniement) const nameCompetenceArme = RdDItemArme.getCompetenceArme(arme, maniement)
const competence = actor.getCompetence(nameCompArme) const competence = actor.getCompetence(nameCompetenceArme)
if (RdDItemCompetence.isNiveauBase(competence)) { if (RdDItemCompetence.isNiveauBase(competence)) {
return undefined return undefined
} }

View File

@ -206,7 +206,7 @@ export class RdDItemArme extends Item {
return arme.system.competence.replace(" 1 main", " 2 mains"); return arme.system.competence.replace(" 1 main", " 2 mains");
} }
static isArmeUtilisable(arme) { static isUtilisable(arme) {
switch (arme.type) { switch (arme.type) {
case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0) case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case ITEM_TYPES.competencecreature: return true case ITEM_TYPES.competencecreature: return true
@ -214,6 +214,26 @@ export class RdDItemArme extends Item {
return false return false
} }
static isAttaque(arme) {
switch (arme.type) {
case ITEM_TYPES.arme:
return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case ITEM_TYPES.competencecreature:
return arme.system.iscombat && RdDItemCompetenceCreature.isAttaque(item)
}
return false
}
static isParade(arme) {
switch (arme.type) {
case ITEM_TYPES.arme:
return arme.system.equipe && arme.system.resistance > 0 && true/* TODO: regarder la categorie d'arme?*/
case ITEM_TYPES.competencecreature:
return arme.system.iscombat && RdDItemCompetenceCreature.isParade(arme)
}
return false
}
static ajoutCorpsACorps(armes, actor) { static ajoutCorpsACorps(armes, actor) {
armes.push(RdDItemArme.mainsNues(actor)); armes.push(RdDItemArme.mainsNues(actor));
armes.push(RdDItemArme.empoignade(actor)); armes.push(RdDItemArme.empoignade(actor));

View File

@ -27,29 +27,28 @@ export class RdDItemCompetenceCreature extends Item {
static armeCreature(item) { static armeCreature(item) {
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item) const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
if (categorieAttaque != undefined) { if (categorieAttaque != undefined) {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence // cloner pour ne pas modifier la compétence
let arme = item.clone(); return foundry.utils.mergeObject(item, {
return foundry.utils.mergeObject(arme, {
action: item.isCompetencePossession() ? 'possession' : 'attaque', action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: { system: {
competence: arme.name, competence: item.name,
cac: categorieAttaque == "naturelle" ? "naturelle" : "", cac: categorieAttaque == "naturelle" ? "naturelle" : "",
niveau: item.system.niveau, niveau: item.system.niveau,
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value), initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
equipe: true, equipe: true,
resistance: 100, resistance: 100,
dommagesReels: arme.system.dommages, dommagesReels: item.system.dommages,
penetration: 0, penetration: 0,
force: 0, force: 0,
rapide: true, rapide: true,
} }
}, { inplace: false }); }, { inplace: false, });
} }
return undefined; return undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceAttaque(item) { static isAttaque(item) {
if (item.type == ITEM_TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
@ -60,7 +59,7 @@ export class RdDItemCompetenceCreature extends Item {
return true return true
} }
} }
return undefined return false
} }
static getCategorieAttaque(item) { static getCategorieAttaque(item) {
@ -77,6 +76,7 @@ export class RdDItemCompetenceCreature extends Item {
} }
return undefined return undefined
} }
static isDommages(item) { static isDommages(item) {
if (item.type == ITEM_TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
@ -89,6 +89,7 @@ export class RdDItemCompetenceCreature extends Item {
} }
return false return false
} }
static isParade(item) { static isParade(item) {
if (item.type == ITEM_TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
@ -101,8 +102,4 @@ export class RdDItemCompetenceCreature extends Item {
return false return false
} }
/* -------------------------------------------- */
static isCompetenceParade(item) {
return item.type == 'competencecreature' && item.system.categorie_parade !== "";
}
} }

View File

@ -72,19 +72,28 @@ export class RdDCombatManager extends Combat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async finDeRound(options = { terminer: false }) { async finDeRound(options = { terminer: false }) {
this.combatants.map(it => RdDCombatManager.getActorCombatant(it, { warning: false }))
.filter(it => it != undefined)
.forEach(async actor => {
await actor.finDeRound(options)
await actor.resetItemUse()
})
}
for (let combatant of this.combatants) { static getActorCombatant(combatant, options = { warning: true }) {
if (!combatant.actor) { if (!combatant.actor) {
if (options.warning) {
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`) ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur!`)
} }
return undefined
}
else if (!combatant.actor.isActorCombat()) { else if (!combatant.actor.isActorCombat()) {
ui.notifications.warn(`Le combatant ${combatant.name} ne peut pas combattre!`) if (options.warning) {
} ui.notifications.warn(`${combatant.name} ne peut pas combattre!`)
else {
await combatant.actor.finDeRound(options)
await combatant.actor.resetItemUse()
} }
return undefined
} }
return combatant.actor
} }
static calculAjustementInit(actor, arme) { static calculAjustementInit(actor, arme) {
@ -95,56 +104,27 @@ export class RdDCombatManager extends Combat {
} }
/************************************************************************************/ /************************************************************************************/
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, messageOptions = {}) {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions); console.log(`${game.system.title} | Combat.rollInitiative()`, ids, messageOptions)
ids = typeof ids === "string" ? [ids] : ids
ids.forEach(async id =>
await this.rollInitRdD(id, undefined, messageOptions)
)
return this
}
ids = typeof ids === "string" ? [ids] : ids; async rollInitRdD(id, formula, messageOptions = {}) {
// calculate initiative const combatant = this.combatants.get(id);
for (let cId = 0; cId < ids.length; cId++) { const actor = RdDCombatManager.getActorCombatant(combatant)
const combatant = this.combatants.get(ids[cId]); if (actor) {
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, undefined); const rollFormula = formula ?? RdDCombatManager.getFirstInitRollFormula(actor)
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
if (competence) {
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, etatGeneral);
}
} else {
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
let compName = "Corps à corps"
if (armeCombat) {
if (armeCombat.system.competence != "") {
compName = armeCombat.system.competence
}
if (armeCombat.system.lancer != "") {
compName = armeCombat.system.lancer
}
if (armeCombat.system.tir != "") {
compName = armeCombat.system.tir
}
}
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
if (competence && competence.system.defaut_carac) {
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
const niveau = competence.system.niveau;
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, armeCombat)
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, ajustement);
} else {
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
}
}
}
const roll = combatant.getInitiativeRoll(rollFormula); const roll = combatant.getInitiativeRoll(rollFormula);
if (!roll.total) { if (!roll.total) {
await roll.evaluate(); await roll.evaluate();
} }
const total = Math.max(roll.total, 0.00); const total = Math.max(roll.total, 0.00);
console.log("Compute init for", rollFormula, roll, total, combatant); console.log("Compute init for", rollFormula, roll, total, combatant);
let id = combatant._id || combatant.id; await this.updateEmbeddedDocuments("Combatant", [{ _id: combatant._id || combatant.id, initiative: total }]);
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: total }]);
// Send a chat message // Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode"); let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
@ -156,7 +136,7 @@ export class RdDCombatManager extends Combat {
alias: combatant.token.name, alias: combatant.token.name,
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
}, },
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})<br>`, flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.info})<br>`
}, },
messageOptions); messageOptions);
roll.toMessage(messageData, { rollMode, create: true }); roll.toMessage(messageData, { rollMode, create: true });
@ -164,7 +144,20 @@ export class RdDCombatManager extends Combat {
RdDCombatManager.processPremierRoundInit(); RdDCombatManager.processPremierRoundInit();
} }
return this; return this;
}; }
static getFirstInitRollFormula(actor) {
const actions = actor.listActionsCombat()
if (actions.length > 0) {
const action = actions[0]
const init = RdDCombatManager.getInitData(actor, action)
const ajustement = RdDCombatManager.calculAjustementInit(actor, action)
return RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
}
let ajustement = RdDCombatManager.calculAjustementInit(actor, undefined);
return RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
}
static formuleInitiative(rang, carac, niveau, bonusMalus) { static formuleInitiative(rang, carac, niveau, bonusMalus) {
return `${rang} +( (${RdDCombatManager.calculInitiative(niveau, carac, bonusMalus)} )/100)`; return `${rang} +( (${RdDCombatManager.calculInitiative(niveau, carac, bonusMalus)} )/100)`;
@ -247,61 +240,6 @@ export class RdDCombatManager extends Combat {
return attaque; return attaque;
} }
/* -------------------------------------------- */
static listActionsCombat(combatant) {
const actor = combatant.actor;
if (!actor.isActorCombat()) {
return
}
let actions = RdDCombatManager.listActionsPossessions(actor);
if (actions.length > 0) {
return actions;
}
if (actor.isCreatureEntite()) {
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
} else if (actor.isPersonnage()) {
// Recupération des items 'arme'
const competences = actor.itemTypes['competence'];
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
.concat(RdDItemArme.empoignade(actor))
.concat(RdDItemArme.mainsNues(actor));
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
if (actor.system.attributs.hautrevant.value) {
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
}
}
return RdDCombatManager._indexActions(actions);
}
static listActionsCreature(competences) {
return competences
.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
.map(it => RdDItemCompetenceCreature.armeCreature(it))
.filter(it => it != undefined);
}
static listActionsPossessions(actor) {
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
return {
name: p.name,
action: 'possession',
system: {
competence: p.name,
possessionid: p.system.possessionid,
}
}
}));
}
static _indexActions(actions) {
for (let index = 0; index < actions.length; index++) {
actions[index].index = index;
}
return actions;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static processPremierRoundInit() { static processPremierRoundInit() {
// Check if we have the whole init ! // Check if we have the whole init !
@ -339,13 +277,13 @@ export class RdDCombatManager extends Combat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static pushInitiativeOptions(html, options) { static pushInitiativeOptions(html, options) {
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
let option = options[i]; let option = options[i]
if (option.name == 'COMBAT.CombatantReroll') { // Replace ! if (option.name == 'COMBAT.CombatantReroll') { // Replace !
option.name = "Sélectionner l'initiative..."; option.name = "Sélectionner l'initiative..."
option.condition = true; option.condition = true
option.icon = '<i class="far fa-question-circle"></i>'; option.icon = '<i class="far fa-question-circle"></i>'
option.callback = target => { option.callback = target => {
RdDCombatManager.displayInitiativeMenu(html, target.data('combatant-id')); RdDCombatManager.displayInitiativeMenu(html, target.data('combatant-id'))
} }
} }
} }
@ -356,95 +294,82 @@ export class RdDCombatManager extends Combat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static rollInitiativeAction(combatantId, action) { static rollInitiativeAction(combatantId, action) {
const combatant = game.combat.combatants.get(combatantId); const combatant = game.combat.combatants.get(combatantId)
if (combatant.actor == undefined) { const actor = RdDCombatManager.getActorCombatant(combatant)
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) if (actor == undefined) { return [] }
return [];
}
let initInfo = "";
let initOffset = 0;
let caracForInit = 0;
let compNiveau = 0;
let compData = { name: "Aucune" };
if (combatant.actor.getSurprise() == "totale") {
initOffset = -1; // To force 0
initInfo = "Surprise Totale"
} else if (combatant.actor.getSurprise() == "demi") {
initOffset = 0;
initInfo = "Demi Surprise"
} else if (action.action == 'possession') {
initOffset = 10;
caracForInit = combatant.actor.getReveActuel();
initInfo = "Possession"
} else if (action.action == 'autre') {
initOffset = 2;
initInfo = "Autre Action"
} else if (action.action == 'haut-reve') {
initOffset = 9;
initInfo = "Draconic"
} else {
compData = RdDItemCompetence.findCompetence(combatant.actor.items, action.system.competence);
compNiveau = compData.system.niveau;
initInfo = action.name + " / " + action.system.competence;
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
caracForInit = compData.system.carac_value;
} else {
caracForInit = combatant.actor.system.carac[compData.system.defaut_carac].value;
}
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
}
// Cas des créatures et entités vs personnages
const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, action)
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, ajustement);
// Garder la trace de l'arme/compétence utilisée pour l'iniative
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0 combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
const init = RdDCombatManager.getInitData(actor, action)
const ajustement = RdDCombatManager.calculAjustementInit(actor, action)
const rollFormula = RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
game.combat.rollInitRdD(combatantId, rollFormula, init);
} }
/* -------------------------------------------- */ static getInitData(actor, action) {
static _baseInitOffset(categorie, arme) { if (actor.getSurprise() == "totale") { return { offset: -1, info: "Surprise Totale", carac: 0, niveau: 0 } }
if (categorie == "tir") { // Offset de principe pour les armes de jet if (actor.getSurprise() == "demi") { return { offset: 0, info: "Demi Surprise", carac: 0, niveau: 0 } }
return 8; if (action.action == 'autre') { return { offset: 2, info: "Autre Action", carac: 0, niveau: 0 } }
if (action.action == 'possession') { return { offset: 10, info: "Possession", carac: actor.getReveActuel(), niveau: 0 } }
if (action.action == 'haut-reve') { return { offset: 9, info: "Draconic", carac: actor.getReveActuel(), niveau: 0 } }
const comp = RdDItemCompetence.findCompetence(actor.items, action.system.competence);
return {
offset: RdDCombatManager.initOffset(comp?.system.categorie, action),
info: action.name + " / " + action.system.competence,
carac: actor.getCaracInit(comp),
niveau: comp?.system.niveau ?? -8
} }
if (categorie == "lancer") { // Offset de principe pour les armes de jet
return 7;
} }
static initOffset(categorie, arme) {
switch (categorie) {
case "tir": return 8
case "lancer": return 7
default:
switch (arme.system.cac) { switch (arme.system.cac) {
case "empoignade": case "empoignade": return 3
return 3; case "pugilat": return 4
case "pugilat": case "naturelle": return 4
case "naturelle": default: return 5
return 4; }
} }
return 5;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static displayInitiativeMenu(html, combatantId) { static displayInitiativeMenu(html, combatantId) {
console.log("Combatant ; ", combatantId); const combatant = game.combat.combatants.get(combatantId)
const combatant = game.combat.combatants.get(combatantId); const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
if (!(combatant?.actor)) { if (actor) {
ui.notifications.warn(`Le combatant ${combatant.name ?? combatantId} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) const actions = RdDCombatManager.listActionsActorCombatant(actor)
return;
}
let actions = RdDCombatManager.listActionsCombat(combatant);
// Build the relevant submenu // Build the relevant submenu
if (actions) { const menuItems = actions.map(action => {
let menuItems = []; return {
for (let action of actions) {
menuItems.push({
name: action.system.competence, name: action.system.competence,
icon: "<i class='fas fa-dice-d6'></i>", icon: "<i class='fas fa-dice-d6'></i>",
callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) } callback: target => { RdDCombatManager.rollInitiativeAction(combatantId, action) }
});
} }
})
if (menuItems.length > 0) {
new ContextMenu(html, ".directory-list", menuItems).render(); new ContextMenu(html, ".directory-list", menuItems).render();
} }
} }
}
/* -------------------------------------------- */
static listActionsActorCombatant( actor) {
const possessions = actor.listActionsPossessions()
const actions = possessions.length > 0
? possessions
: actor.listActionsCombat()
for (let index = 0; index < actions.length; index++) {
actions[index].index = index
}
return actions
}
} }
@ -992,13 +917,13 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_filterArmesParade(defender, competence, arme) { _filterArmesParade(defender, competence, armeAttaque) {
let defenses = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it)) let defenses = defender.items.filter(it => RdDItemArme.isParade(it))
defenses = foundry.utils.duplicate(defenses) defenses = foundry.utils.duplicate(defenses)
defenses.forEach(armeDefense => { defenses.forEach(armeDefense => {
// Ajout du # d'utilisation ce round // Ajout du # d'utilisation ce round
armeDefense.nbUsage = defender.getItemUse(armeDefense.id) armeDefense.nbUsage = defender.getItemUse(armeDefense.id)
armeDefense.typeParade = RdDItemArme.defenseArmeParade(arme, armeDefense) armeDefense.typeParade = RdDItemArme.defenseArmeParade(armeAttaque, armeDefense)
}) })
switch (competence.system.categorie) { switch (competence.system.categorie) {
@ -1353,7 +1278,7 @@ export class RdDCombat {
if (!actor?.isActorCombat()) { if (!actor?.isActorCombat()) {
return return
} }
let formData = { const formData = {
combatId: combat._id, combatId: combat._id,
alias: token.name ?? actor.name, alias: token.name ?? actor.name,
etatGeneral: actor.getEtatGeneral(), etatGeneral: actor.getEtatGeneral(),
@ -1374,6 +1299,6 @@ export class RdDCombat {
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData), content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData),
whisper: ChatUtility.getOwners(actor), whisper: ChatUtility.getOwners(actor),
alias: token.name ?? actor.name alias: token.name ?? actor.name
}); })
} }
} }

View File

@ -28,16 +28,15 @@ export class RdDTokenHud {
await RdDTokenHud.addExtensionHudSoins(html, actor); await RdDTokenHud.addExtensionHudSoins(html, actor);
if (isCombat) { if (isCombat) {
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId); const combatant = game.combat.combatants.find(c => c.tokenId == tokenId)
if (!(combatant?.actor)) { const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) if (actor) {
return; let actions = RdDCombatManager.listActionsActorCombatant(actor)
}
let actions = RdDCombatManager.listActionsCombat(combatant);
// initiative // initiative
await RdDTokenHud.addExtensionHudInit(html, combatant, actions); await RdDTokenHud.addExtensionHudInit(html, combatant, actions)
// combat // combat
await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions); await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions)
}
} }

View File

@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "12.0.18", "version": "12.0.19",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.18.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.19.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": { "compatibility": {