Merge branch 'combat-extract' into 'dev_1.1'
Combat #68 See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!78
This commit is contained in:
commit
1bcccec29c
111
module/actor.js
111
module/actor.js
@ -170,69 +170,6 @@ export class RdDActor extends Actor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
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.tactique == 'charge')
|
|
||||||
&& !rollData.rolled.isPart ) {
|
|
||||||
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
|
||||||
let resistance = Misc.toInt(rollData.arme.data.resistance);
|
|
||||||
let msg = "";
|
|
||||||
// Jet de résistance de l'arme de parade (p.132)
|
|
||||||
let resistRoll = await RdDResolutionTable.roll( resistance, - dmg );
|
|
||||||
if (resistRoll.isSuccess) { // Perte de résistance
|
|
||||||
msg = "Votre " + rollData.arme.name + " tient le choc de la parade. "
|
|
||||||
} else {
|
|
||||||
resistance -= dmg;
|
|
||||||
if ( resistance <= 0 ) {
|
|
||||||
this.deleteEmbeddedEntity("OwnedItem", rollData.arme._id);
|
|
||||||
msg = "Sous la violence de la parade, votre " + rollData.arme.name + " s'est brisée sous le coup!";
|
|
||||||
} else {
|
|
||||||
this.updateEmbeddedEntity("OwnedItem", {_id: rollData.arme._id, 'data.resistance': resistance });
|
|
||||||
msg = "En parant, vous endommagez votre " + rollData.arme.name + ", qui perd " + dmg + " de résistance. ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Jet de désarmement
|
|
||||||
if (resistance > 0 && !rollData.arme.name.toLowerCase().includes('bouclier') ) { // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
|
||||||
let desarme = await RdDResolutionTable.roll( this.data.data.carac.force.value, Misc.toInt(rollData.competence.data.niveau) -dmg );
|
|
||||||
if ( desarme.isEchec) {
|
|
||||||
msg += "Vous ne parvenez pas à garder votre arme en main, elle tombe au sol à vos pieds";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChatMessage.create( { content: msg,
|
|
||||||
user: game.user._id,
|
|
||||||
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async computeRecul( rollData, encaisser = undefined ) { // Calcul du recul (p. 132)
|
|
||||||
if ( rollData.arme || encaisser ) {
|
|
||||||
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 = "";
|
|
||||||
if (recul.isSuccess) {
|
|
||||||
msg = " Vous ne reculez pas malgré la force du coup.";
|
|
||||||
} else {
|
|
||||||
let chute = await RdDResolutionTable.roll( this.data.data.carac.agilite.value, reculNiveau );
|
|
||||||
if ( !chute.isSuccess || recul.isETotal ) {
|
|
||||||
msg = "Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round.";
|
|
||||||
} else {
|
|
||||||
msg = "La violence du choc vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ChatMessage.create( {content: msg,
|
|
||||||
user: game.user._id,
|
|
||||||
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getSurprise() {
|
getSurprise() {
|
||||||
if (this.isEntiteCauchemar()) {
|
if (this.isEntiteCauchemar()) {
|
||||||
@ -507,12 +444,10 @@ export class RdDActor extends Actor {
|
|||||||
message += "<br>Vous gagnez une Tête de dragon: " + tete;
|
message += "<br>Vous gagnez une Tête de dragon: " + tete;
|
||||||
}
|
}
|
||||||
if (roll.isEchec) {
|
if (roll.isEchec) {
|
||||||
message += "<br>Vous subissez une Queue de Dragon";
|
message += "<br>Vous subissez une Queue de Dragon: " + await this.ajouterQueue();
|
||||||
this.ajouterQueue();
|
|
||||||
}
|
}
|
||||||
if (roll.isETotal) {
|
if (roll.isETotal) {
|
||||||
message += "<br>A cause de votre échec total, vous subissez une deuxième Queue de Dragon !"
|
message += "<br>A cause de votre échec total, vous subissez une deuxième Queue de Dragon: " + await this.ajouterQueue();
|
||||||
this.ajouterQueue();
|
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
@ -757,7 +692,7 @@ export class RdDActor extends Actor {
|
|||||||
let total = new Roll("1d20").roll().total;
|
let total = new Roll("1d20").roll().total;
|
||||||
if ( total <= refoulement.value ) {
|
if ( total <= refoulement.value ) {
|
||||||
refoulement.value = 0;
|
refoulement.value = 0;
|
||||||
this.ajouterSouffle();
|
this.ajouterSouffle({chat: true});
|
||||||
ret = "souffle";
|
ret = "souffle";
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -766,17 +701,20 @@ export class RdDActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
ajouterSouffle() {
|
async ajouterSouffle(options = {chat : false}) {
|
||||||
let souffle = RdDRollTables.getSouffle();
|
let souffle = RdDRollTables.getSouffle();
|
||||||
// ChatMessage.create({
|
await this.createOwnedItem(souffle);
|
||||||
// title: "Souffle de Dragon",
|
if (options.chat){
|
||||||
// content: this.name + " subit un Souffle de Dragon : " + souffle.name
|
ChatMessage.create({
|
||||||
// });
|
whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ),
|
||||||
// this.actor.createOwnedItem(souffle);
|
content: this.name + " subit un Souffle de Dragon : " + souffle.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return souffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async ajouterQueue() {
|
async ajouterQueue(options = {chat : false}) {
|
||||||
// TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie?
|
// TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie?
|
||||||
let utiliseThanatos = false;
|
let utiliseThanatos = false;
|
||||||
let queue;
|
let queue;
|
||||||
@ -787,17 +725,14 @@ export class RdDActor extends Actor {
|
|||||||
else {
|
else {
|
||||||
queue = await RdDRollTables.getQueue();
|
queue = await RdDRollTables.getQueue();
|
||||||
}
|
}
|
||||||
/*
|
await this.createOwnedItem(queue);
|
||||||
// TODO: convertir la queue obtenue en nouvel item ...
|
if (options.chat){
|
||||||
// ou bien l'ajouter à la liste spécifique => this.data.data.reve.queues
|
ChatMessage.create({
|
||||||
this.createOwnedItem(queue);
|
whisper: ChatUtility.getWhisperRecipientsAndGMs( this.name ),
|
||||||
|
content: this.name + " subit une Queue de Dragon : " + queue.name
|
||||||
ChatMessage.create({
|
});
|
||||||
content: this.name + " subit un Queue de Dragon : " + queue.name
|
}
|
||||||
});
|
return queue;
|
||||||
|
|
||||||
return queue.name;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -1376,6 +1311,10 @@ export class RdDActor extends Actor {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rollCompetence( name ) {
|
async rollCompetence( name ) {
|
||||||
|
if (name == 'queue') {
|
||||||
|
await this.ajouterQueue({chat: true});
|
||||||
|
return;
|
||||||
|
}
|
||||||
let rollData = {
|
let rollData = {
|
||||||
competence: duplicate(this.getCompetence(name)),
|
competence: duplicate(this.getCompetence(name)),
|
||||||
needSignificative : !this.isEntiteCauchemar() && this.data.data.sante.sonne.value
|
needSignificative : !this.isEntiteCauchemar() && this.data.data.sante.sonne.value
|
||||||
|
@ -69,9 +69,10 @@ export class RdDItemArme extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static mainsNues() {
|
static mainsNues() {
|
||||||
return {
|
const mainsNues = {
|
||||||
name: "Mains nues",
|
name: "Mains nues",
|
||||||
data: { unemain: true, deuxmains: false, dommages: 0, dommagesReels: 0, mortalite: 'non-mortel' }
|
data: { unemain: true, deuxmains: false, dommages: 0, dommagesReels: 0, mortalite: 'non-mortel', competence: 'Corps à corps' }
|
||||||
}
|
};
|
||||||
|
return mainsNues
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -234,8 +234,10 @@ export class RdDCalendrier extends Application {
|
|||||||
console.log( request );
|
console.log( request );
|
||||||
let jourDiff = this.getLectureAstrologieDifficulte( request.date);
|
let jourDiff = this.getLectureAstrologieDifficulte( request.date);
|
||||||
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||||
let rolled = await RdDResolutionTable.roll(request.carac_vue, niveau, undefined, false);
|
let rolled = await RdDResolutionTable.rollData({
|
||||||
|
caracValue: request.carac_vue,
|
||||||
|
finalLevel: niveau,
|
||||||
|
showDice: false});
|
||||||
let nbAstral = this.getNombreAstral( request.date );
|
let nbAstral = this.getNombreAstral( request.date );
|
||||||
let nbAstralFaux = nbAstral;
|
let nbAstralFaux = nbAstral;
|
||||||
request.isValid = true;
|
request.isValid = true;
|
||||||
|
@ -81,7 +81,10 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
switch (button) {
|
switch (button) {
|
||||||
case '#particuliere-attaque': return await this.choixParticuliere(rollData, event.currentTarget.attributes['data-mode'].value);
|
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);
|
case '#parer-button': {
|
||||||
|
const armeId = event.currentTarget.attributes['data-armeid'];
|
||||||
|
return this.parade(rollData, armeId ? armeId.value : undefined);
|
||||||
|
}
|
||||||
case '#esquiver-button': return this.esquive(rollData);
|
case '#esquiver-button': return this.esquive(rollData);
|
||||||
case '#encaisser-button': return this.encaisser(rollData, event.currentTarget.attributes['data-defenderTokenId'].value);
|
case '#encaisser-button': return this.encaisser(rollData, event.currentTarget.attributes['data-defenderTokenId'].value);
|
||||||
}
|
}
|
||||||
@ -138,10 +141,10 @@ export class RdDCombat {
|
|||||||
label: 'Attaque: ' + (arme ? arme.name : competence.name),
|
label: 'Attaque: ' + (arme ? arme.name : competence.name),
|
||||||
callbacks: [
|
callbacks: [
|
||||||
this.attacker.createCallbackExperience(),
|
this.attacker.createCallbackExperience(),
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
|
||||||
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) },
|
||||||
|
{ condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) },
|
||||||
|
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) },
|
||||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
{ condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) }
|
|
||||||
]
|
]
|
||||||
} );
|
} );
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
@ -183,11 +186,6 @@ export class RdDCombat {
|
|||||||
dommagesReels: competence.data.dommages
|
dommagesReels: competence.data.dommages
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// rollData.dmg = {
|
|
||||||
// dmgArme: competence.data.dommages,
|
|
||||||
// total: competence.data.dommages
|
|
||||||
// };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -214,31 +212,30 @@ export class RdDCombat {
|
|||||||
|
|
||||||
let explications = "";
|
let explications = "";
|
||||||
|
|
||||||
// Message spécial pour la rapidité, qui reste difficile à gérer automatiquement
|
|
||||||
if (rollData.particuliereAttaque == 'rapidite') {
|
|
||||||
ChatMessage.create({
|
|
||||||
content: "Vous avez attaqué en Rapidité. Vous pourrez faire une deuxième attaque, ou utiliser votre arme pour vous défendre.",
|
|
||||||
whisper: ChatMessage.getWhisperRecipients(this.attacker.name)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
rollData.dmg = RdDBonus.dmg(rollData, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
rollData.dmg = RdDBonus.dmg(rollData, this.attacker.getBonusDegat(), this.defender.isEntiteCauchemar());
|
||||||
|
|
||||||
if (this.target) {
|
if (this.target) {
|
||||||
explications += "<br><strong>Cible</strong> : " + this.defender.data.name;
|
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
|
// Save rollData for defender
|
||||||
game.system.rdd.rollDataHandler[this.attackerId] = duplicate(rollData);
|
game.system.rdd.rollDataHandler[this.attackerId] = duplicate(rollData);
|
||||||
|
|
||||||
|
// Message spécial pour la rapidité, qui reste difficile à gérer automatiquement
|
||||||
|
if (rollData.particuliereAttaque == 'rapidite') {
|
||||||
|
explications += "<br>Vous avez attaqué en Rapidité. Vous pourrez faire une deuxième attaque, ou utiliser votre arme pour vous défendre.";
|
||||||
|
}
|
||||||
|
|
||||||
// Final chat message
|
// Final chat message
|
||||||
let chatOptions = {
|
let chatOptions = {
|
||||||
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>"
|
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
|
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat
|
||||||
+ RdDResolutionTable.explain(rollData.rolled)
|
+ RdDResolutionTable.explain(rollData.rolled)
|
||||||
+ explications
|
+ explications
|
||||||
}
|
}
|
||||||
ChatUtility.chatWithRollMode(chatOptions, this.attacker.name)
|
ChatUtility.chatWithRollMode(chatOptions, this.attacker.name)
|
||||||
|
|
||||||
if (this.target) {
|
if (this.target) {
|
||||||
this._messageDefenseur(rollData);
|
this._messageDefenseur(rollData);
|
||||||
}
|
}
|
||||||
@ -255,7 +252,10 @@ export class RdDCombat {
|
|||||||
for (const arme of this._filterArmesParade(this.defender.data.items, rollData.competence.data.categorie)) {
|
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>";
|
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>";
|
||||||
}
|
}
|
||||||
|
// corps à corps
|
||||||
|
if (rollData.dmg.mortalite != 'mortel') {
|
||||||
|
content += "<br><a class='chat-card-button' id='parer-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Parer à mains nues</a>";
|
||||||
|
}
|
||||||
// esquive
|
// esquive
|
||||||
if (rollData.competence.data.categorie == 'melee' || rollData.competence.data.categorie == "lancer" || rollData.competence.data.categorie == 'competencecreature') {
|
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>";
|
content += "<br><a class='chat-card-button' id='esquiver-button' data-attackerId='" + this.attackerId + "' data-defenderTokenId='" + this.defenderTokenId + "'>Esquiver</a>";
|
||||||
@ -339,7 +339,8 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async parade(attackerRoll, armeParadeId) {
|
async parade(attackerRoll, armeParadeId) {
|
||||||
let arme = this.defender.getOwnedItem(armeParadeId);
|
|
||||||
|
let arme = this._findArmeParade(armeParadeId);
|
||||||
|
|
||||||
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
|
||||||
|
|
||||||
@ -352,22 +353,30 @@ export class RdDCombat {
|
|||||||
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
|
||||||
callbacks: [
|
callbacks: [
|
||||||
this.defender.createCallbackExperience(),
|
this.defender.createCallbackExperience(),
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
|
||||||
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) },
|
||||||
|
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
|
||||||
|
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
|
||||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onParadeEchecTotal(r) },
|
{ condition: RdDCombat.isEchecTotal, action: r => this._onParadeEchecTotal(r) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) }
|
|
||||||
]
|
]
|
||||||
} );
|
} );
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_prepareParade(attackerRoll, arme) {
|
_findArmeParade(armeParadeId) {
|
||||||
|
if (armeParadeId) {
|
||||||
|
const armeItem = this.defender.getOwnedItem(armeParadeId);
|
||||||
|
return armeItem.data;
|
||||||
|
|
||||||
|
}
|
||||||
|
return RdDItemArme.mainsNues()
|
||||||
|
}
|
||||||
|
|
||||||
|
_prepareParade(attackerRoll, armeParade) {
|
||||||
const isCreature = this.defender.isCreature();
|
const isCreature = this.defender.isCreature();
|
||||||
const compName = isCreature ? arme.name : arme.data.data.competence;
|
const compName = isCreature ? armeParade.name : armeParade.data.competence;
|
||||||
const competence = this.defender.getCompetence(compName);
|
const competence = this.defender.getCompetence(compName);
|
||||||
const armeAttaque = attackerRoll.arme;
|
const armeAttaque = attackerRoll.arme;
|
||||||
const armeParade = arme.data;
|
|
||||||
|
|
||||||
if (compName != competence.name) {
|
if (compName != competence.name) {
|
||||||
// TODO: toujours utiliser competence.name ...
|
// TODO: toujours utiliser competence.name ...
|
||||||
ui.notifications.warn("Différence entre compétence " + competence.name + " et compétence de l'arme " + compName);
|
ui.notifications.warn("Différence entre compétence " + competence.name + " et compétence de l'arme " + compName);
|
||||||
@ -378,7 +387,7 @@ export class RdDCombat {
|
|||||||
diffLibre: attackerRoll.diffLibre,
|
diffLibre: attackerRoll.diffLibre,
|
||||||
attackerRoll: attackerRoll,
|
attackerRoll: attackerRoll,
|
||||||
competence: competence,
|
competence: competence,
|
||||||
arme: arme.data,
|
arme: armeParade,
|
||||||
surprise: this.defender.getSurprise(),
|
surprise: this.defender.getSurprise(),
|
||||||
surpriseDefenseur: this.defender.getSurprise(),
|
surpriseDefenseur: this.defender.getSurprise(),
|
||||||
needSignificative: this._needSignificative(attackerRoll) || RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
|
needSignificative: this._needSignificative(attackerRoll) || RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
|
||||||
@ -420,17 +429,16 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onParadeNormale(rollData) {
|
async _onParadeNormale(rollData) {
|
||||||
console.log("RdDCombat._onParadeNormale >>>", rollData);
|
console.log("RdDCombat._onParadeNormale >>>", rollData);
|
||||||
await this.defender.computeDeteriorationArme(rollData);
|
|
||||||
await this.defender.computeRecul(rollData, false);
|
|
||||||
|
|
||||||
let chatOptions = {
|
let chatOptions = {
|
||||||
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + rollData.competence.name + "</strong>"
|
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
|
+ "<br>Difficultés <strong>libre : " + rollData.diffLibre + "</strong> / conditions : " + Misc.toSignedString(rollData.diffConditions) + " / état : " + rollData.etat
|
||||||
+ RdDResolutionTable.explain(rollData.rolled)
|
+ RdDResolutionTable.explain(rollData.rolled)
|
||||||
+ "<br><strong>Attaque parée!</strong>"
|
+ "<br><strong>Attaque parée!</strong>"
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
||||||
|
await this.computeRecul(rollData, false);
|
||||||
|
await this.computeDeteriorationArme(rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -462,7 +470,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
||||||
|
|
||||||
await this.defender.computeRecul(rollData, true);
|
await this.computeRecul(rollData, true);
|
||||||
// TODO: gestion message pour chance/encaissement
|
// TODO: gestion message pour chance/encaissement
|
||||||
this.encaisser(rollData.attackerRoll);
|
this.encaisser(rollData.attackerRoll);
|
||||||
}
|
}
|
||||||
@ -483,10 +491,10 @@ export class RdDCombat {
|
|||||||
label: 'Esquiver',
|
label: 'Esquiver',
|
||||||
callbacks: [
|
callbacks: [
|
||||||
this.defender.createCallbackExperience(),
|
this.defender.createCallbackExperience(),
|
||||||
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
|
||||||
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) },
|
||||||
{ condition: RdDCombat.isEchecTotal, action: r => this._onEsquiveEchecTotal(r) },
|
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
|
||||||
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
|
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
|
||||||
|
{ condition: RdDCombat.isEchecTotal, action: r => this._onEsquiveEchecTotal(r) },
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
@ -559,10 +567,86 @@ export class RdDCombat {
|
|||||||
|
|
||||||
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
ChatUtility.chatWithRollMode(chatOptions, this.defender.name)
|
||||||
|
|
||||||
await this.defender.computeRecul(rollData, true);
|
await this.computeRecul(rollData, true);
|
||||||
this.encaisser(rollData.attackerRoll);
|
this.encaisser(rollData.attackerRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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.tactique == 'charge')
|
||||||
|
&& !rollData.rolled.isPart ) {
|
||||||
|
const dmg = attackerRoll.dmg.dmgArme + attackerRoll.dmg.dmgActor;
|
||||||
|
let resistance = Misc.toInt(rollData.arme.data.resistance);
|
||||||
|
let msg = "";
|
||||||
|
// Jet de résistance de l'arme de parade (p.132)
|
||||||
|
let resistRoll = await RdDResolutionTable.rollData({
|
||||||
|
caracValue: resistance,
|
||||||
|
finalLevel: - dmg,
|
||||||
|
showDice: false});
|
||||||
|
if (resistRoll.isSuccess) { // Perte de résistance
|
||||||
|
msg = "Votre " + rollData.arme.name + " tient le choc de la parade. "
|
||||||
|
} else {
|
||||||
|
resistance -= dmg;
|
||||||
|
if ( resistance <= 0 ) {
|
||||||
|
this.defender.deleteEmbeddedEntity("OwnedItem", rollData.arme._id);
|
||||||
|
msg = "Sous la violence de la parade, votre " + rollData.arme.name + " s'est brisée sous le coup!";
|
||||||
|
} else {
|
||||||
|
this.defender.updateEmbeddedEntity("OwnedItem", {_id: rollData.arme._id, 'data.resistance': resistance });
|
||||||
|
msg = "En parant, vous endommagez votre " + rollData.arme.name + ", qui perd " + dmg + " de résistance. ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Jet de désarmement
|
||||||
|
if (resistance > 0 && !rollData.arme.name.toLowerCase().includes('bouclier') ) { // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||||
|
let desarme = await RdDResolutionTable.rollData({
|
||||||
|
caracValue: this.defender.data.data.carac.force.value,
|
||||||
|
finalLevel: Misc.toInt(rollData.competence.data.niveau) - dmg,
|
||||||
|
showDice: false});
|
||||||
|
if ( desarme.isEchec) {
|
||||||
|
msg += "Vous ne parvenez pas à garder votre arme en main, elle tombe au sol à vos pieds";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChatMessage.create( { content: msg,
|
||||||
|
user: game.user._id,
|
||||||
|
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async computeRecul( rollData, encaisser = undefined ) { // Calcul du recul (p. 132)
|
||||||
|
if ( rollData.arme || encaisser ) {
|
||||||
|
if ( (rollData.attackerRoll.particuliereAttaque && rollData.attackerRoll.particuliereAttaque == 'force') || rollData.attackerRoll.tactique == 'charge') {
|
||||||
|
let reculNiveau = Misc.toInt(this.defender.data.data.carac.taille.value) - (rollData.attackerRoll.forceValue+rollData.attackerRoll.arme.data.dommagesReels);
|
||||||
|
let recul = await RdDResolutionTable.rollData({
|
||||||
|
caracValue: 10,
|
||||||
|
finalLevel: reculNiveau,
|
||||||
|
showDice: false});
|
||||||
|
|
||||||
|
let msg = "";
|
||||||
|
if (recul.isSuccess) {
|
||||||
|
msg = " Vous ne reculez pas malgré la force du coup.";
|
||||||
|
} else {
|
||||||
|
let chute = await RdDResolutionTable.rollData({
|
||||||
|
caracValue: this.defender.data.data.carac.agilite.value,
|
||||||
|
finalLevel: reculNiveau,
|
||||||
|
showDice: false});
|
||||||
|
if ( !chute.isSuccess || recul.isETotal ) {
|
||||||
|
msg = "Sous la violence du coup, vous reculez et chutez au sol ! Vous ne pouvez plus attaquer ce round.";
|
||||||
|
} else {
|
||||||
|
msg = "La violence du choc vous fait reculer de quelques mètres ! Vous ne pouvez plus attaquer ce round.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ChatMessage.create( {content: msg,
|
||||||
|
user: game.user._id,
|
||||||
|
whisper: [game.user._id, ChatMessage.getWhisperRecipients("GM") ] } );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
encaisser(attackerRoll) {
|
encaisser(attackerRoll) {
|
||||||
// TODO: gestion message pour chance/encaissement
|
// TODO: gestion message pour chance/encaissement
|
||||||
|
@ -91,7 +91,8 @@ export class RdDResolutionTable {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async rollData(rollData) {
|
static async rollData(rollData) {
|
||||||
rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData.bonus, rollData.needSignificative);
|
rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData.bonus, rollData.needSignificative, rollData.showDice);
|
||||||
|
return rollData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -6,38 +6,46 @@ export class RdDRollTables {
|
|||||||
const index = await pack.getIndex();
|
const index = await pack.getIndex();
|
||||||
const entry = index.find(e => e.name === tableName);
|
const entry = index.find(e => e.name === tableName);
|
||||||
const table = await pack.getEntity(entry._id);
|
const table = await pack.getEntity(entry._id);
|
||||||
const result = await table.draw({ displayChat: toChat });
|
const draw = await table.draw({ displayChat: toChat });
|
||||||
console.log("RdDRollTables", tableName, toChat, ":", result);
|
console.log("RdDRollTables", tableName, toChat, ":", draw);
|
||||||
return result;
|
console.log("RdDRollTables", tableName, toChat, ":", draw.roll, draw.results);
|
||||||
|
return draw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async drawItemFromRollTable(tableName, toChat) {
|
||||||
|
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||||
|
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
|
||||||
|
const pack = game.packs.get(drawnItemRef.collection);
|
||||||
|
return await pack.getEntity(drawnItemRef.resultId);
|
||||||
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getSouffle(toChat = true) {
|
static async getSouffle(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Souffles de Dragon", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getQueue(toChat = true) {
|
static async getQueue(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Queues de dragon", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTete(toChat = true) {
|
static async getTete(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Têtes de Dragon pour haut-rêvants", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTeteHR(toChat = true) {
|
static async getTeteHR(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Têtes de Dragon pour tous personnages", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour tous personnages", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getOmbre(toChat = true) {
|
static async getOmbre(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Ombre de Thanatos", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Ombre de Thanatos", toChat);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async getTarot(toChat = true) {
|
static async getTarot(toChat = true) {
|
||||||
return RdDRollTables.genericGetTableResult("Tarot Draconique", toChat);
|
return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,10 +342,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
+ RdDResolutionTable.explain(rolled);
|
+ RdDResolutionTable.explain(rolled);
|
||||||
|
|
||||||
if (rolled.isETotal) {
|
if (rolled.isETotal) {
|
||||||
let souffle = await RdDRollTables.getSouffle();
|
let souffle = await this.actor.ajouterSouffle({chat: false});
|
||||||
explication += "<br>Vous avez fait un Echec Total. Vous subissez un Souffle de Dragon : " + souffle.name;
|
explication += "<br>Vous avez fait un Echec Total. Vous subissez un Souffle de Dragon : " + souffle.name;
|
||||||
msg2MJ += "<br>Et a reçu un Souffle de Dragon : " + souffle.name;
|
msg2MJ += "<br>Et a reçu un Souffle de Dragon : " + souffle.name;
|
||||||
this.actor.createOwnedItem(souffle);
|
|
||||||
}
|
}
|
||||||
if (rolled.isPart) {
|
if (rolled.isPart) {
|
||||||
explication += "<br>Vous avez fait une Réussite Particulière";
|
explication += "<br>Vous avez fait une Réussite Particulière";
|
||||||
|
@ -525,18 +525,6 @@ export class TMRUtility {
|
|||||||
}
|
}
|
||||||
return { message: message, state: state };
|
return { message: message, state: state };
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async genericGetTableResult( tableName, toChat)
|
|
||||||
{
|
|
||||||
let pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
|
|
||||||
await pack.getIndex();
|
|
||||||
let entry = pack.index.find(e => e.name === tableName);
|
|
||||||
let rollQueues = await pack.getEntity(entry._id);
|
|
||||||
let result = await rollQueues.draw( { displayChat: toChat } );
|
|
||||||
console.log("CAT", result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getTMRAleatoire()
|
static getTMRAleatoire()
|
||||||
|
@ -470,43 +470,49 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
{{!-- Queues, Souffles, Tetes, Ombre --}}
|
{{!-- Queues, Souffles, Tetes, Ombre --}}
|
||||||
|
<h3>Queues:</h3>
|
||||||
<ul class="flex-group-left">
|
<ul class="flex-group-left">
|
||||||
|
{{#each data.queues as |queue key|}}
|
||||||
<li class="item flexrow" data-attribute={{key}} data-item-id="{{queue._id}}">
|
<li class="item flexrow" data-attribute={{key}} data-item-id="{{queue._id}}">
|
||||||
<h3>Queues:</h3>
|
<span class="queuesouffle-label"> <a data-item-id="{{queue._id}}">{{queue.name}}</a></span>
|
||||||
{{#each data.queues as |queue key|}}
|
<div class="item-controls">
|
||||||
<span class="queuesouffle-label"> <a data-item-id="{{queue._id}}">{{queue.name}}</a></span>
|
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||||
<div class="item-controls">
|
</div>
|
||||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</li>
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
<h3>Souffles:</h3>
|
||||||
|
<ul class="item-list">
|
||||||
|
{{#each data.souffles as |souffle key|}}
|
||||||
<li class="item flexrow" data-attribute={{key}} data-item-id="{{souffle._id}}">
|
<li class="item flexrow" data-attribute={{key}} data-item-id="{{souffle._id}}">
|
||||||
<h3>Souffles:</h3>
|
<span class="queuesouffle-label"> <a data-item-id="{{souffle._id}}">{{souffle.name}}</a></span>
|
||||||
{{#each data.souffles as |souffle key|}}
|
<div class="item-controls">
|
||||||
<span class="queuesouffle-label"> <a data-item-id="{{souffle._id}}">{{souffle.name}}</a></span>
|
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||||
<div class="item-controls">
|
</div>
|
||||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</li>
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
<h3>Tetes:</h3>
|
||||||
|
<ul class="item-list">
|
||||||
|
{{#each data.tetes as |tete key|}}
|
||||||
<li class="item flexrow" data-attribute={{key}} data-item-id="{{tete._id}}">
|
<li class="item flexrow" data-attribute={{key}} data-item-id="{{tete._id}}">
|
||||||
<h3>Tetes:</h3>
|
<span class="queuesouffle-label"> <a data-item-id="{{tete._id}}">{{tete.name}}</a></span>
|
||||||
{{#each data.tetes as |tete key|}}
|
<div class="item-controls">
|
||||||
<span class="queuesouffle-label"> <a data-item-id="{{tete._id}}">{{tete.name}}</a></span>
|
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||||
<div class="item-controls">
|
</div>
|
||||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</li>
|
</li>
|
||||||
|
{{/each}}
|
||||||
|
</ul>
|
||||||
|
<h3>Ombres de Thanatos:</h3>
|
||||||
|
<ul class="item-list">
|
||||||
|
{{#each data.ombres as |ombre key|}}
|
||||||
<li class="item flexrow" data-attribute={{key}} data-item-id="{{ombre._id}}">
|
<li class="item flexrow" data-attribute={{key}} data-item-id="{{ombre._id}}">
|
||||||
<h3>Ombres de Thanatos:</h3>
|
<span class="queuesouffle-label"> <a data-item-id="{{ombre._id}}">{{ombre.name}}</a></span>
|
||||||
{{#each data.ombres as |ombre key|}}
|
<div class="item-controls">
|
||||||
<span class="queuesouffle-label"> <a data-item-id="{{ombre._id}}">{{ombre.name}}</a></span>
|
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
||||||
<div class="item-controls">
|
</div>
|
||||||
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
|
|
||||||
</div>
|
|
||||||
{{/each}}
|
|
||||||
</li>
|
</li>
|
||||||
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user