Fixes suite aux test de combat

* séparation des bonus dégâts
* jet d'encaissement fait par le défenseur
* début gestion demi surprise ou surprise
* ajout du nom de la personne qui recule
* xp sur maîrise du fleuve
* xp sur combat "courants"
* fix affichage localisation des blessures ("loc")
* fix dommages armes une main (ou 2 mains) seulement
* fix message attaque échouée
* fix esquive
This commit is contained in:
2020-12-15 02:20:24 +01:00
parent 0e5caf048e
commit b77646365c
10 changed files with 175 additions and 118 deletions

View File

@ -17,7 +17,7 @@ export class RdDCombat {
static createUsingTarget(attacker) {
const target = RdDCombat.getTarget();
if (target == undefined) {
ui.notifications.warn("Vous devriez choisir une cible à attaquer!");
ui.notifications.warn("Vous devez choisir une seule cible à attaquer!");
}
return this.create(attacker, target ? target.actor : undefined, target)
}
@ -112,11 +112,11 @@ export class RdDCombat {
let rollData = {
coupsNonMortels: false,
competence: competence,
demiSurprise: this.attacker.isDemiSurprise()
surprise: this.attacker.getSurprise()
};
if (this.attacker.isCreature()) {
this._prepareRollDataCreature(rollData, competence);
this._modifieRollDataCreature(rollData, competence);
}
else {
// Usual competence
@ -125,11 +125,11 @@ export class RdDCombat {
return rollData;
}
_prepareRollDataCreature(rollData, competence) {
_modifieRollDataCreature(rollData, competence) {
competence = duplicate(competence);
competence.data.defaut_carac = "carac_creature";
competence.data.categorie = "creature";
rollData.competence = competence;
rollData.carac = { "carac_creature": { label: competence.name, value: competence.data.carac_value } };
rollData.arme = {
@ -171,16 +171,13 @@ export class RdDCombat {
whisper: ChatMessage.getWhisperRecipients(this.attacker.name)
});
}
rollData.domArmePlusDom = this.attacker._calculBonusDegats(rollData);
rollData.degats = new Roll("2d10").roll().total + rollData.domArmePlusDom; // Dégats totaux
rollData.loc = RdDUtility.getLocalisation();
rollData.dmg = RdDCombat.calculBonusDegats(rollData, this.attacker);
if (this.target) {
rollData.mortalite = this._calculMortaliteEncaissement(rollData);
explications += "<br><strong>Cible</strong> : " + this.defender.data.name;
}
explications += "<br>Encaissement : " + rollData.degats + "<br>Localisation : " + rollData.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,7 +199,7 @@ export class RdDCombat {
_messageDefenseur(rollData) {
console.log("RdDCombat._messageDefenseur", rollData, " / ", this.attacker, this.target, this.target.actor.isToken, this.attacker.data._id, rollData.competence.data.categorie);
let content = "<strong>" + this.defender.name + "</strong> doit se défendre : <br><span class='chat-card-button-area'>";
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);
@ -216,8 +213,7 @@ export class RdDCombat {
}
// encaisser
content += "<br><a class='chat-card-button' id='encaisser-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Encaisser !</a>";
content += "<br><a class='chat-card-button' id='encaisser-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Encaisser à " + Misc.toSignedString(rollData.dmg.total) + " !</a>";
content += "</span>"
let defense = {
@ -271,12 +267,11 @@ export class RdDCombat {
_onAttaqueEchec(rollData) {
console.log("RdDCombat.onAttaqueEchec >>>", rollData);
let target = this._getTarget();
let chatOptions = {
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>"
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat
+ RdDResolutionTable.explain(rolled)
+ (target ? "<br><strong>Cible</strong> : " + this.defender.data.name : "")
+ RdDResolutionTable.explain(rollData.rolled)
+ (this.target ? "<br><strong>Cible</strong> : " + this.defender.data.name : "")
}
ChatUtility.chatWithRollMode(chatOptions, this.attacker.name)
}
@ -329,22 +324,22 @@ export class RdDCombat {
attackerRoll: attackerRoll,
competence: competence,
arme: arme.data,
demiSurprise: this.defender.isDemiSurprise(),
surprise: this.defender.getSurprise(),
needSignificative: this._needSignificative(attackerRoll) || RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
needResist: this._needResist(armeAttaque, armeParade),
carac: this.defender.data.data.carac
};
if (isCreature) {
this._prepareRollDataCreature(rollData, competence);
this._modifieRollDataCreature(rollData, competence);
}
return rollData;
}
/* -------------------------------------------- */
_needSignificative(attackerRoll) {
return attackerRoll.particuliereAttaque == 'finesse';
}
/* -------------------------------------------- */
_needResist(armeAttaque, armeParade) {
// Manage weapon categories when parrying (cf. page 115 )
@ -399,10 +394,8 @@ export class RdDCombat {
async _onParadeEchec(rollData) {
console.log("RdDCombat._onParadeEchec >>>", rollData);
let explications = "<br><strong>Parade échouée, encaissement !</strong>";
if (rollData.demiSurprise) {
explications += " Demi surprise!";
}
let explications = "<br><strong>Parade échouée, encaissement !</strong> ";
explications += this.descriptionSurprise(rollData.surprise);
if (rollData.needSignificative) {
explications += " Significative nécessaire!";
}
@ -452,13 +445,13 @@ export class RdDCombat {
diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll,
competence: competence,
demiSurprise: this.defender.isDemiSurprise(),
surprise: this.defender.getSurprise(),
needSignificative: this._needSignificative(attackerRoll),
carac: this.defender.data.data.carac
};
if (this.defender.isCreature()) {
this._prepareRollDataCreature(rollData, competence);
this._modifieRollDataCreature(rollData, competence);
}
return rollData;
}
@ -497,10 +490,8 @@ export class RdDCombat {
async _onEsquiveEchec(rollData) {
console.log("RdDCombat._onEsquiveEchec >>>", rollData);
let explications = "<br><strong>Esquive échouée, encaissement !</strong>";
if (rollData.demiSurprise) {
explications += " Demi surprise!";
}
let explications = "<br><strong>Esquive échouée, encaissement !</strong> ";
explications += RdDCombat.descriptionSurprise(rollData.surprise);
if (rollData.needSignificative) {
explications += " Significative nécessaire!";
}
@ -517,6 +508,7 @@ export class RdDCombat {
await this.defender.computeRecul(rollData, true);
this.encaisser(rollData.attackerRoll);
}
/* -------------------------------------------- */
encaisser(attackerRoll) {
// TODO: gestion message pour chance/encaissement
@ -569,4 +561,65 @@ 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 '';
}
}