forked from public/foundryvtt-reve-de-dragon
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:
148
module/actor.js
148
module/actor.js
@ -125,6 +125,7 @@ export class RdDActor extends Actor {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getBonusDegat() {
|
||||
// TODO: gérer séparation et +dom créature/entité indépendament de la compétence
|
||||
return Misc.toInt(this.data.data.attributs.plusdom.value);
|
||||
}
|
||||
|
||||
@ -169,54 +170,13 @@ export class RdDActor extends Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async performRoll(rollData, attacker = undefined) {
|
||||
rollData.surprise = this.getSurprise();
|
||||
|
||||
// Manage weapon categories when parrying (cf. page 115 )
|
||||
if (rollData.arme && rollData.attackerRoll) { // Manage parade depending on weapon type, and change roll results
|
||||
let attCategory = RdDItemArme.getCategorieArme(rollData.attackerRoll.arme);
|
||||
let defCategory = RdDItemArme.getCategorieArme(rollData.arme);
|
||||
if (defCategory == "bouclier")
|
||||
rollData.needSignificative = false;
|
||||
else if (attCategory != defCategory)
|
||||
rollData.needSignificative = true;
|
||||
// Do we need to make resistance roll for defender ?
|
||||
if (attCategory.match("epee") && (defCategory == "hache" || defCategory == "lance"))
|
||||
rollData.needResist = true;
|
||||
}
|
||||
if (!this.isEntiteCauchemar() && rollData.particuliereAttaque == "finesse") {
|
||||
rollData.needSignificative = true;
|
||||
}
|
||||
|
||||
// garder le résultat
|
||||
await RdDResolutionTable.rollData(rollData);
|
||||
|
||||
//console.log("performRoll", rollData)
|
||||
if ( !rollData.attackerRoll) {// Store in the registry if not a defense roll
|
||||
game.system.rdd.rollDataHandler[this.data._id] = rollData;
|
||||
}
|
||||
|
||||
if (rollData.rolled.isPart && rollData.arme && !rollData.attackerRoll) { // Réussite particulière avec attaque -> choix !
|
||||
let message = "<strong>Réussite particulière en attaque</strong>";
|
||||
message = message + "<br><a class='chat-card-button' id='particuliere-attaque' data-mode='force' data-attackerId='" + this.data._id + "'>Attaquer en Force</a>";
|
||||
// Finesse et Rapidité seulement en mêlée et si la difficulté libre est de -1 minimum
|
||||
if (rollData.selectedCarac.label == "Mêlée" && rollData.diffLibre < 0 ) {
|
||||
message = message + "<br><a class='chat-card-button' id='particuliere-attaque' data-mode='rapidite' data-attackerId='"+ this.data._id + "'>Attaquer en Rapidité</a>";
|
||||
message = message + "<br><a class='chat-card-button' id='particuliere-attaque' data-mode='finesse' data-attackerId='"+ this.data._id + "'>Attaquer en Finesse</a>";
|
||||
}
|
||||
ChatMessage.create( {content : message, whisper: ChatMessage.getWhisperRecipients( this.name ) } );
|
||||
} else {
|
||||
this.continueRoll(rollData, attacker);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async computeDeteriorationArme( rollData ) {
|
||||
const attackerRoll = rollData.attackerRoll;
|
||||
if (rollData.arme && attackerRoll) { // C'est une parade
|
||||
// Est-ce que l'attaque est une particulière, en force ou charge et que l'attaque n'en est pas une ?
|
||||
if ( (rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.isCharge)
|
||||
if ( (rollData.needResist || attackerRoll.particuliereAttaque == 'force' || attackerRoll.tactique == 'charge')
|
||||
&& !rollData.rolled.isPart ) {
|
||||
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
||||
let resistance = Misc.toInt(rollData.arme.data.resistance);
|
||||
@ -252,7 +212,7 @@ export class RdDActor extends Actor {
|
||||
/* -------------------------------------------- */
|
||||
async computeRecul( rollData, encaisser = undefined ) { // Calcul du recul (p. 132)
|
||||
if ( rollData.arme || encaisser ) {
|
||||
if ( (rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.isCharge) {
|
||||
if ( (rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.tactique == 'charge') {
|
||||
let reculNiveau = Misc.toInt(this.data.data.carac.taille.value) - (rollData.attackerRoll.forceValue+rollData.attackerRoll.arme.data.dommagesReels);
|
||||
let recul = await RdDResolutionTable.roll( 10, reculNiveau );
|
||||
let msg = "";
|
||||
@ -273,103 +233,12 @@ export class RdDActor extends Actor {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async continueRoll(rollData, attacker = undefined) {
|
||||
let rolled = rollData.rolled;
|
||||
let quality = rolled.quality
|
||||
|
||||
console.log(">>> ROLL", rollData, rolled);
|
||||
this._appliquerAjoutExperience(rollData)
|
||||
|
||||
let resumeCompetence = (rollData.competence) ? rollData.competence.name : (rollData.diffLibre + rollData.diffConditions);
|
||||
let explications = "<br>Points de taches : " + rolled.ptTache + ", ajustement qualité: " + rolled.ptQualite;
|
||||
|
||||
// Fight management !
|
||||
let defenseMsg;
|
||||
let encaisser = false;
|
||||
if (rollData.arme || (rollData.competence && rollData.competence.name.toLowerCase() == 'esquive') ) {
|
||||
explications = ""
|
||||
// In case of fight, replace the message per dommages + localization. it indicates if result is OK or not
|
||||
if (rollData.attackerRoll) { // Defense case !
|
||||
if (rolled.isSign || (!rollData.needSignificative && rolled.isSuccess)) {
|
||||
await this.computeDeteriorationArme( rollData );
|
||||
explications += "<br><strong>Attaque parée/esquivée !</strong>";
|
||||
} else {
|
||||
explications += "<br><strong>Esquive/Parade échouée, encaissement !</strong>";
|
||||
if (rollData.needSignificative)
|
||||
explications += " Significative nécessaire!";
|
||||
}
|
||||
encaisser = rollData.needSignificative ? !rolled.isSign : !rolled.isSuccess;
|
||||
await this.computeRecul( rollData, encaisser );
|
||||
} else { // This is the attack roll!
|
||||
if (rolled.isSuccess) {
|
||||
let target = this._getTarget();
|
||||
if (await this.targetEntiteNonAccordee(target, 'avant-defense')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Message spécial pour la rapidité, qui reste difficile à gérer automatiquement
|
||||
if ( rollData.particuliereAttaque == 'rapidite') {
|
||||
ChatMessage.create( { content: "Vous avez attaqué en Rapidité. Ce cas n'est pas géré autmatiquement, donc suivez les directives de votre MJ pour gérer ce cas.",
|
||||
whisper: ChatMessage.getWhisperRecipients( this.name ) } );
|
||||
}
|
||||
|
||||
rollData.dmg = RdDCombat.calculBonusDegats(rollData, this);
|
||||
|
||||
if (target)
|
||||
{
|
||||
rollData.mortalite = RdDActor._calculMortaliteEncaissement(rollData, target);
|
||||
defenseMsg = RdDUtility.buildDefenseChatCard(this, target, rollData);
|
||||
explications += "<br><strong>Cible</strong> : " + target.actor.data.name;
|
||||
}
|
||||
explications += "<br>Encaissement : " + rollData.degats + "<br>Localisation : " + rollData.dmg.loc.label;
|
||||
} else {
|
||||
explications = "<br>Echec ! Pas de dégâts";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save it for fight in the flags area
|
||||
game.system.rdd.rollDataHandler[this.data._id] = duplicate(rollData);
|
||||
|
||||
// Final chat message
|
||||
let chatOptions = {
|
||||
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + resumeCompetence + "</strong>"
|
||||
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) +" / état : " + rollData.etat
|
||||
+ RdDResolutionTable.explain(rolled)
|
||||
+ explications
|
||||
}
|
||||
|
||||
ChatUtility.chatWithRollMode(chatOptions, this.name)
|
||||
|
||||
// This an attack, generate the defense message
|
||||
if (defenseMsg) {
|
||||
defenseMsg.rollData = duplicate(rollData);
|
||||
if (defenseMsg.toSocket) {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_defense",
|
||||
data: defenseMsg
|
||||
});
|
||||
if ( game.user.isGM ) { // Always push the message to the MJ
|
||||
ChatMessage.create(defenseMsg);
|
||||
}
|
||||
} else {
|
||||
defenseMsg.whisper = [game.user];
|
||||
ChatMessage.create(defenseMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Get damages!
|
||||
if (encaisser) {
|
||||
this.encaisserDommages(rollData.attackerRoll, attacker);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getSurprise() {
|
||||
if (this.isEntiteCauchemar()) {
|
||||
return '';
|
||||
}
|
||||
// TODO: gérer une liste de flags demi-surprise (avec icône sur le token)?
|
||||
if ( this.data.data.sante.sonne.value) {
|
||||
return 'demi';
|
||||
}
|
||||
@ -386,13 +255,6 @@ export class RdDActor extends Actor {
|
||||
return this.getSurprise() == 'totale';
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _calculMortaliteEncaissement(rollData, target) {
|
||||
const mortalite = target.actor.isEntiteCauchemar() ? "cauchemar" : (rollData.mortalite ? rollData.mortalite : "mortel");
|
||||
console.log("Mortalité : ", mortalite, target.actor.data.type);
|
||||
return mortalite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async dormirChateauDormant() {
|
||||
let message = {
|
||||
@ -1905,7 +1767,7 @@ export class RdDActor extends Actor {
|
||||
armure: armure
|
||||
}).roll();
|
||||
RdDDice.show(rollEncaissement);
|
||||
let result = RdDUtility.computeBlessuresSante(rollEncaissement.total, attackerRoll.mortalite, attackerRoll.dmg.loc);
|
||||
let result = RdDUtility.computeBlessuresSante(rollEncaissement.total, attackerRoll.dmg.mortalite, attackerRoll.dmg.loc);
|
||||
result.endurance = Math.max(result.endurance, -Number(this.data.data.sante.endurance.value));
|
||||
await this.santeIncDec("vie", result.vie);
|
||||
await this.santeIncDec("endurance", result.endurance, (result.critiques > 0));
|
||||
|
Reference in New Issue
Block a user