This commit is contained in:
2020-12-16 23:34:27 +01:00
14 changed files with 531 additions and 330 deletions

View File

@ -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 {
@ -80,7 +79,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);
@ -89,6 +87,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')) {
@ -105,10 +138,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);
@ -119,16 +152,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;
}
@ -145,6 +183,11 @@ export class RdDCombat {
dommagesReels: competence.data.dommages
}
};
// rollData.dmg = {
// dmgArme: competence.data.dommages,
// total: competence.data.dommages
// };
}
/* -------------------------------------------- */
@ -178,13 +221,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);
@ -208,15 +250,16 @@ export class RdDCombat {
let content = "<strong>" + this.defender.name + "</strong> doit se défendre :<span class='chat-card-button-area'>";
// parades
let filterArmesParade = this._getFilterArmesParade(rollData.competence.data.categorie);
for (const arme of this.defender.data.items.filter(filterArmesParade)) {
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
@ -246,24 +289,25 @@ export class RdDCombat {
}
/* -------------------------------------------- */
_getFilterArmesParade(categorie) {
_filterArmesParade(items, categorie) {
switch (categorie) {
case 'tir':
case 'lancer':
return arme => arme.type == "arme" && arme.data.competence.toLowerCase().match("bouclier");
return items.filter(item => item.data.competence.toLowerCase().match("bouclier"));
default:
return arme => (arme.type == "arme" && RdDItemCompetence.isCompetenceMelee(arme.data.competence)) || (arme.type == "competencecreature" && arme.data.isparade)
return items.filter(item => {
if (item.type == 'competencecreature') {
return item.data.isparade;
}
if (item.type == 'arme') {
const comp = this.defender.getCompetence(item.data.competence);
return comp && comp.data.categorie == 'melee';
}
return false;
});
}
}
/* -------------------------------------------- */
_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);
@ -308,10 +352,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);
@ -336,6 +380,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
@ -403,7 +448,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!";
}
@ -438,10 +483,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);
@ -454,6 +499,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
};
@ -499,7 +545,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!";
}
@ -569,65 +615,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 '';
}
}