Ajouts combat #68
- gestion de la feinte (sauf initiative) - gestion du bonus à l'attaque de la charge - dégats de corps à corps - bonus dégâts si surprise, début de gestion de surprise totale
This commit is contained in:
@ -1,11 +1,10 @@
|
||||
import { RdDActor } from "./actor.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDItemArme } from "./item-arme.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDRoll } from "./rdd-roll.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
export class RdDCombat {
|
||||
|
||||
@ -75,7 +74,6 @@ export class RdDCombat {
|
||||
ui.notifications.warn("Action automatisée impossible, le jet de l'attaquant a été perdu (suite à un raffraichissement?)")
|
||||
return;
|
||||
}
|
||||
// TODO: enlever le ChatMessage?
|
||||
switch (button) {
|
||||
case '#particuliere-attaque': return await this.choixParticuliere(rollData, event.currentTarget.attributes['data-mode'].value);
|
||||
case '#parer-button': return this.parade(rollData, event.currentTarget.attributes['data-armeid'].value);
|
||||
@ -84,6 +82,41 @@ export class RdDCombat {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEchec(rollData) {
|
||||
switch (rollData.surprise) {
|
||||
case 'demi': return !rollData.rolled.isSign;
|
||||
case 'totale': return true;
|
||||
}
|
||||
return rollData.rolled.isEchec;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isEchecTotal(rollData) {
|
||||
if (rollData.arme && rollData.surprise == 'demi') {
|
||||
return rollData.rolled.isEchec;
|
||||
}
|
||||
return rollData.rolled.isETotal;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isParticuliere(rollData) {
|
||||
if (rollData.arme && rollData.surprise) {
|
||||
return false;
|
||||
}
|
||||
return rollData.rolled.isPart;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isReussite(rollData) {
|
||||
switch (rollData.surprise) {
|
||||
case 'demi': return rollData.rolled.isSign;
|
||||
case 'totale': return false;
|
||||
}
|
||||
return rollData.rolled.isSuccess;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async attaque(competence, arme) {
|
||||
if (!await this.accorderEntite('avant-attaque')) {
|
||||
@ -99,10 +132,10 @@ export class RdDCombat {
|
||||
label: 'Attaque: ' + (arme ? arme.name : competence.name),
|
||||
callbacks: [
|
||||
this.attacker.createCallbackExperience(),
|
||||
{ condition: RdDResolutionTable.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
||||
{ condition: r => (RdDResolutionTable.isReussite(r) && !RdDResolutionTable.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
||||
{ condition: RdDResolutionTable.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
||||
{ condition: RdDResolutionTable.isEchec, action: r => this._onAttaqueEchec(r) }
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
||||
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
||||
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) }
|
||||
]
|
||||
});
|
||||
dialog.render(true);
|
||||
@ -113,16 +146,21 @@ export class RdDCombat {
|
||||
let rollData = {
|
||||
coupsNonMortels: false,
|
||||
competence: competence,
|
||||
surprise: this.attacker.getSurprise()
|
||||
surprise: this.attacker.getSurprise(),
|
||||
surpriseDefenseur: this.defender.getSurprise()
|
||||
};
|
||||
|
||||
if (this.attacker.isCreature()) {
|
||||
this._modifieRollDataCreature(rollData, competence);
|
||||
}
|
||||
else {
|
||||
else if (arme) {
|
||||
// Usual competence
|
||||
rollData.arme = RdDItemArme.armeUneOuDeuxMains(arme, RdDItemCompetence.isArmeUneMain(competence));
|
||||
}
|
||||
else {
|
||||
// sans armes: à mains nues
|
||||
rollData.arme = RdDItemArme.mainsNues();
|
||||
}
|
||||
return rollData;
|
||||
}
|
||||
|
||||
@ -139,6 +177,11 @@ export class RdDCombat {
|
||||
dommagesReels: competence.data.dommages
|
||||
}
|
||||
};
|
||||
|
||||
// rollData.dmg = {
|
||||
// dmgArme: competence.data.dommages,
|
||||
// total: competence.data.dommages
|
||||
// };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -172,13 +215,12 @@ export class RdDCombat {
|
||||
whisper: ChatMessage.getWhisperRecipients(this.attacker.name)
|
||||
});
|
||||
}
|
||||
rollData.dmg = RdDCombat.calculBonusDegats(rollData, this.attacker);
|
||||
rollData.dmg = RdDBonus.dmg(rollData, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
||||
|
||||
if (this.target) {
|
||||
rollData.mortalite = this._calculMortaliteEncaissement(rollData);
|
||||
explications += "<br><strong>Cible</strong> : " + this.defender.data.name;
|
||||
}
|
||||
explications += "<br>Encaissement à "+ Misc.toSignedString(rollData.dmg.total)+ " (" + rollData.dmg.loc.label+")";
|
||||
explications += "<br>Encaissement à " + Misc.toSignedString(rollData.dmg.total) + " (" + rollData.dmg.loc.label + ")";
|
||||
|
||||
// Save rollData for defender
|
||||
game.system.rdd.rollDataHandler[this.attackerId] = duplicate(rollData);
|
||||
@ -202,14 +244,16 @@ export class RdDCombat {
|
||||
|
||||
let content = "<strong>" + this.defender.name + "</strong> doit se défendre :<span class='chat-card-button-area'>";
|
||||
|
||||
// parades
|
||||
for (const arme of this._filterArmesParade(this.defender.data.items, rollData.competence.data.categorie)) {
|
||||
content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "' data-armeid='" + arme._id + "'>Parer avec " + arme.name + "</a>";
|
||||
}
|
||||
|
||||
// esquive
|
||||
if (rollData.competence.data.categorie == 'melee' || rollData.competence.data.categorie == "lancer" || rollData.competence.data.categorie == 'competencecreature') {
|
||||
content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Esquiver</a>";
|
||||
if (this.defender.getSurprise() != 'totale') {
|
||||
// parades
|
||||
for (const arme of this._filterArmesParade(this.defender.data.items, rollData.competence.data.categorie)) {
|
||||
content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "' data-armeid='" + arme._id + "'>Parer avec " + arme.name + "</a>";
|
||||
}
|
||||
|
||||
// esquive
|
||||
if (rollData.competence.data.categorie == 'melee' || rollData.competence.data.categorie == "lancer" || rollData.competence.data.categorie == 'competencecreature') {
|
||||
content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Esquiver</a>";
|
||||
}
|
||||
}
|
||||
|
||||
// encaisser
|
||||
@ -257,13 +301,6 @@ export class RdDCombat {
|
||||
});
|
||||
}
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
_calculMortaliteEncaissement(rollData) {
|
||||
const mortalite = this.defender.isEntiteCauchemar() ? "cauchemar" : (rollData.mortalite ? rollData.mortalite : "mortel");
|
||||
console.log("Mortalité : ", mortalite, this.defender.data.type);
|
||||
return mortalite;
|
||||
}
|
||||
|
||||
|
||||
_onAttaqueEchecTotal(rollData) {
|
||||
console.log("RdDCombat.onEchecTotal >>>", rollData);
|
||||
@ -306,10 +343,10 @@ export class RdDCombat {
|
||||
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
||||
callbacks: [
|
||||
this.defender.createCallbackExperience(),
|
||||
{ condition: RdDResolutionTable.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
||||
{ condition: RdDResolutionTable.isReussite, action: r => this._onParadeNormale(r) },
|
||||
{ condition: RdDResolutionTable.isEchecTotal, action: r => this._onParadeEchecTotal(r) },
|
||||
{ condition: RdDResolutionTable.isEchec, action: r => this._onParadeEchec(r) }
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
||||
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onParadeEchecTotal(r) },
|
||||
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) }
|
||||
]
|
||||
});
|
||||
dialog.render(true);
|
||||
@ -334,6 +371,7 @@ export class RdDCombat {
|
||||
competence: competence,
|
||||
arme: arme.data,
|
||||
surprise: this.defender.getSurprise(),
|
||||
surpriseDefenseur: this.defender.getSurprise(),
|
||||
needSignificative: this._needSignificative(attackerRoll) || RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
|
||||
needResist: this._needResist(armeAttaque, armeParade),
|
||||
carac: this.defender.data.data.carac
|
||||
@ -401,7 +439,7 @@ export class RdDCombat {
|
||||
console.log("RdDCombat._onParadeEchec >>>", rollData);
|
||||
|
||||
let explications = "<br><strong>Parade échouée, encaissement !</strong> ";
|
||||
explications += RdDCombat.descriptionSurprise(rollData.surprise);
|
||||
explications += RdDBonus.description(rollData.surprise);
|
||||
if (rollData.needSignificative) {
|
||||
explications += " Significative nécessaire!";
|
||||
}
|
||||
@ -436,10 +474,10 @@ export class RdDCombat {
|
||||
label: 'Esquiver',
|
||||
callbacks: [
|
||||
this.defender.createCallbackExperience(),
|
||||
{ condition: RdDResolutionTable.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
||||
{ condition: RdDResolutionTable.isReussite, action: r => this._onEsquiveNormale(r) },
|
||||
{ condition: RdDResolutionTable.isEchecTotal, action: r => this._onEsquiveEchecTotal(r) },
|
||||
{ condition: RdDResolutionTable.isEchec, action: r => this._onEsquiveEchec(r) },
|
||||
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
||||
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onEsquiveEchecTotal(r) },
|
||||
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
|
||||
]
|
||||
});
|
||||
dialog.render(true);
|
||||
@ -452,6 +490,7 @@ export class RdDCombat {
|
||||
attackerRoll: attackerRoll,
|
||||
competence: competence,
|
||||
surprise: this.defender.getSurprise(),
|
||||
surpriseDefenseur: this.defender.getSurprise(),
|
||||
needSignificative: this._needSignificative(attackerRoll),
|
||||
carac: this.defender.data.data.carac
|
||||
};
|
||||
@ -497,7 +536,7 @@ export class RdDCombat {
|
||||
console.log("RdDCombat._onEsquiveEchec >>>", rollData);
|
||||
|
||||
let explications = "<br><strong>Esquive échouée, encaissement !</strong> ";
|
||||
explications += RdDCombat.descriptionSurprise(rollData.surprise);
|
||||
explications += RdDBonus.description(rollData.surprise);
|
||||
if (rollData.needSignificative) {
|
||||
explications += " Significative nécessaire!";
|
||||
}
|
||||
@ -567,65 +606,4 @@ export class RdDCombat {
|
||||
return rolled.isSuccess;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static calculBonusDegats(rollData, actor) {
|
||||
let dmg = { total: 0, loc: RdDUtility.getLocalisation() };
|
||||
if (rollData.arme.name.toLowerCase() == "esquive") {
|
||||
// Specific case management
|
||||
ui.notifications.warn("Calcul de bonus dégats sur eswquive")
|
||||
return dmg;
|
||||
}
|
||||
dmg.dmgArme = RdDCombat._dmgArme(rollData);
|
||||
dmg.ignoreArmure = 0; // TODO: calculer pour arcs et arbaletes, gérer pour lmes créatures
|
||||
dmg.dmgTactique= RdDCombat._dmgTactique(rollData);
|
||||
dmg.dmgParticuliere= RdDCombat._dmgParticuliere(rollData);
|
||||
dmg.dmgSurprise= RdDCombat._dmgSurprise(rollData);
|
||||
dmg.dmgActor = RdDCombat._dmgActor(actor.getBonusDegat(), rollData.selectedCarac.label, dmg.dmgArme);
|
||||
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
|
||||
return dmg;
|
||||
}
|
||||
|
||||
static _dmgArme(rollData) {
|
||||
return parseInt(rollData.arme.data.dommages);
|
||||
}
|
||||
|
||||
static _dmgActor(bonusDegat, categorie, dmgArme) {
|
||||
switch (categorie) {
|
||||
case "Tir": return 0;
|
||||
case "Lancer": return Math.max(0, Math.min(dmgArme, bonusDegat));
|
||||
}
|
||||
return bonusDegat;
|
||||
}
|
||||
|
||||
static _dmgTactique(rollData) {
|
||||
return rollData.isCharge ? 2 : 0;
|
||||
}
|
||||
|
||||
static _dmgParticuliere(rollData) {
|
||||
return rollData.particuliereAttaque == 'force' ? 5 : 0;
|
||||
}
|
||||
|
||||
|
||||
static _dmgSurprise(rollData) {
|
||||
if (rollData.surprise) {
|
||||
switch (rollData.surprise) {
|
||||
case 'demi': return 1;
|
||||
case 'totale': return 10;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static descriptionSurprise(surprise) {
|
||||
if (surprise) {
|
||||
switch (surprise) {
|
||||
case 'demi': return 'demi-surprise';
|
||||
case 'totale': return 'surprise totale';
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user