forked from public/foundryvtt-reve-de-dragon
RdDResolutionTable rolls
This commit is contained in:
279
module/actor.js
279
module/actor.js
@ -7,6 +7,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { RdDRollDialog } from "./rdd-roll-dialog.js";
|
||||
import { RdDTMRDialog } from "./rdd-tmr-dialog.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
|
||||
export class RdDActor extends Actor {
|
||||
|
||||
@ -119,148 +120,110 @@ export class RdDActor extends Actor {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async performRoll( rollData ) {
|
||||
|
||||
let result = new Roll("d100").roll().total;
|
||||
let quality = "Echec";
|
||||
let xpmsg = "";
|
||||
let tache = 0;
|
||||
//console.log(">>> ROLL", rollData.selectedCarac.label, rollData.rollTarget.score, myroll.total );
|
||||
if (result <= rollData.rollTarget.part) {
|
||||
quality = "Réussite Particulière!";
|
||||
if ( rollData.finalLevel < 0 ) {
|
||||
let xpcarac = Math.floor( Math.abs(rollData.finalLevel) / 2);
|
||||
let xpcomp = (Math.abs(rollData.finalLevel) % 2 == 1) ? xpcarac+1 : xpcarac;
|
||||
xpmsg = "<br>Points d'expérience gagné ! " + xpcarac + " - " + xpcomp;
|
||||
}
|
||||
rollData.pointsDeTache = 4;
|
||||
rollData.qualite = 2;
|
||||
} else if (result <= (rollData.rollTarget.score /2) ) {
|
||||
quality = "Réussite Significative";
|
||||
rollData.pointsDeTache = 2;
|
||||
rollData.qualite = 1;
|
||||
} else if (result <= (rollData.rollTarget.score) ) {
|
||||
quality = "Réussite Normale";
|
||||
rollData.pointsDeTache = 1;
|
||||
rollData.qualite = 0;
|
||||
} else if (result < (rollData.rollTarget.epart) ) {
|
||||
quality = "Echec Normal";
|
||||
rollData.pointsDeTache = 0;
|
||||
rollData.qualite = -2;
|
||||
} else if (result < (rollData.rollTarget.etotal) ) {
|
||||
quality = "Echec Particulier";
|
||||
rollData.pointsDeTache = -2;
|
||||
rollData.qualite = -4;
|
||||
} else if (result >= (rollData.rollTarget.etotal) ) {
|
||||
quality = "Echec Total";
|
||||
rollData.pointsDeTache = -4;
|
||||
rollData.qualite = -6;
|
||||
}
|
||||
|
||||
async performRoll(rollData) {
|
||||
|
||||
// Manage weapon categories when parrying (cf. page 115 )
|
||||
let need_significative = false; // Do we need to have a sgnificative ?
|
||||
let need_resist = false; // Do we need to have a sgnificative ?
|
||||
if ( rollData.arme && rollData.attackerRoll ) { // Manage parade depeding on weapon type, and change roll results
|
||||
let attCategory = RdDUtility.getArmeCategory( rollData.attackerRoll.arme );
|
||||
let defCategory = RdDUtility.getArmeCategory( rollData.arme );
|
||||
if ( defCategory == "bouclier" )
|
||||
need_significative = true;
|
||||
else if ( attCategory != defCategory )
|
||||
need_significative = true;
|
||||
if ( attCategory.match("epee") && ( defCategory == "hache" || defCategory == "lance") )
|
||||
let need_resist = false; // Do we need to make resistance roll for defender ?
|
||||
if (rollData.arme && rollData.attackerRoll) { // Manage parade depeding on weapon type, and change roll results
|
||||
let attCategory = RdDUtility.getArmeCategory(rollData.attackerRoll.arme);
|
||||
let defCategory = RdDUtility.getArmeCategory(rollData.arme);
|
||||
if (defCategory == "bouclier")
|
||||
rollData.needSignificative = true;
|
||||
else if (attCategory != defCategory)
|
||||
rollData.needSignificative = true;
|
||||
if (attCategory.match("epee") && (defCategory == "hache" || defCategory == "lance"))
|
||||
need_resist = true;
|
||||
}
|
||||
|
||||
// Sonne management or if need_significative is set
|
||||
if ( this.data.data.sante.sonne.value || need_significative) {
|
||||
if (rollData.pointsDeTache >= 2 ) { // Reussite normale dès que significative
|
||||
quality = "Réussite Normale";
|
||||
rollData.pointsDeTache = 1;
|
||||
rollData.qualite = 0;
|
||||
} else if (rollData.pointsDeTache < 2 ) { // Not a "significative"
|
||||
quality = "Echec Normal";
|
||||
rollData.pointsDeTache = 0;
|
||||
rollData.qualite = -2;
|
||||
}
|
||||
if (this.data.data.sante.sonne.value)
|
||||
{
|
||||
rollData.needSignificative = true;
|
||||
}
|
||||
|
||||
|
||||
let rolled = RdDResolutionTable.rollChances(rollData.rollTarget);
|
||||
let result = rolled.roll;
|
||||
let quality = rolled.quality
|
||||
|
||||
console.log(">>> ROLL", rollData, rolled);
|
||||
let xpmsg = RdDResolutionTable.buildXpMessage(rolled, rollData.finalLevel);
|
||||
|
||||
let specialStr = "<br>Points de taches : " + rolled.tache + ", Points de qualité: " + rolled.qualite;
|
||||
|
||||
// Fight management !
|
||||
let defenseMsg;
|
||||
let encaisser = false;
|
||||
let specialStr = "<br>Points de taches : " + rollData.pointsDeTache; // Per default
|
||||
if ( rollData.arme ) { // In case of fight, replace the "tache" message per dommages + localization. "tache" indicates if result is OK or not
|
||||
if ( rollData.attackerRoll) { // Defense case !
|
||||
if ( rollData.pointsDeTache > 0 ) { // Réussite !
|
||||
if (rollData.arme) {
|
||||
// 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.isSuccess) {
|
||||
specialStr = "<br><strong>Attaque parée/esquivée !</strong>";
|
||||
} else {
|
||||
specialStr = "<br><strong>Esquive/Parade échouée, encaissement !</strong>";
|
||||
encaisser = true;
|
||||
}
|
||||
encaisser = true;
|
||||
}
|
||||
} else { // This is the attack roll!
|
||||
if ( rollData.pointsDeTache > 0 ) {
|
||||
let myroll = new Roll("2d10");
|
||||
myroll.roll();
|
||||
if (rolled.isSuccess > 0) {
|
||||
rollData.domArmePlusDom = parseInt(rollData.arme.data.dommages);
|
||||
if ( rollData.selectedCarac.label == "Mêlée" ) // +dom only for Melee
|
||||
if (rollData.selectedCarac.label == "Mêlée") // +dom only for Melee
|
||||
rollData.domArmePlusDom += parseInt(this.data.data.attributs.plusdom.value);
|
||||
if ( rollData.selectedCarac.label == "Lancer" ) { // +dom only for Melee/Lancer
|
||||
if (rollData.selectedCarac.label == "Lancer") { // +dom only for Melee/Lancer
|
||||
let bdom = parseInt(this.data.data.attributs.plusdom.value);
|
||||
if ( bdom > parseInt(rollData.arme.data.dommages))
|
||||
if (bdom > parseInt(rollData.arme.data.dommages))
|
||||
bdom = parseInt(rollData.arme.data.dommages);
|
||||
rollData.domArmePlusDom += bdom
|
||||
}
|
||||
rollData.degats = parseInt(myroll.result) + rollData.domArmePlusDom;
|
||||
let encaissement = new Roll("2d10 + @domArmePlusDom", {domArmePlusDom : rollData.domArmePlusDom});
|
||||
rollData.degats = parseInt(encaissement.roll().total);
|
||||
rollData.loc = RdDUtility.getLocalisation();
|
||||
for (let target of game.user.targets) {
|
||||
defenseMsg = RdDUtility.buildDefenseChatCard(this, target, rollData );
|
||||
defenseMsg = RdDUtility.buildDefenseChatCard(this, target, rollData);
|
||||
specialStr = "<br><strong>Cible</strong> : " + target.actor.data.name;
|
||||
}
|
||||
specialStr += "<br>Dommages : " + rollData.degats + "<br>Localisation : " + rollData.loc.label;
|
||||
} else {
|
||||
specialStr = "<br>Echec ! Pas de dommages";
|
||||
specialStr = "<br>Echec ! Pas de dommages";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Sort management
|
||||
let lvl = ""
|
||||
if ( rollData.selectedSort) { // Lancement de sort !
|
||||
if (rollData.selectedSort) { // Lancement de sort !
|
||||
let draconic = rollData.selectedSort.data.draconic;
|
||||
specialStr = "<br>Lancement du sort <strong>" + rollData.selectedSort.name + "</strong> : " + draconic.charAt(0).toUpperCase() + draconic.slice(1) + "/" + rollData.selectedSort.data.difficulte +
|
||||
"/" + rollData.selectedSort.data.caseTMR + "/R" + rollData.selectedSort.data.ptreve;
|
||||
specialStr = "<br>Lancement du sort <strong>" + rollData.selectedSort.name + "</strong> : " + draconic.charAt(0).toUpperCase() + draconic.slice(1) + "/" + rollData.selectedSort.data.difficulte +
|
||||
"/" + rollData.selectedSort.data.caseTMR + "/R" + rollData.selectedSort.data.ptreve;
|
||||
specialStr += "<br>Depuis la case " + rollData.coord + " (" + TMRUtility.getTMRDescription(rollData.coord).label + ")";
|
||||
lvl = rollData.selectedDraconic.name +"/"+ rollData.selectedSort.name;
|
||||
lvl = rollData.selectedDraconic.name + "/" + rollData.selectedSort.name;
|
||||
let costReve = rollData.selectedSort.data.ptreve;
|
||||
let myReve = duplicate(this.data.data.reve.reve);
|
||||
if ( rollData.pointsDeTache > 0 ) { // Réussite du sort !
|
||||
if (rollData.pointsDeTache >= 4 ) costReve = Math.ceil(costReve/2);
|
||||
if (costReve < 1 ) costReve = 1;
|
||||
if (rollData.tache > 0) { // Réussite du sort !
|
||||
if (rollData.tache >= 4) costReve = Math.ceil(costReve / 2);
|
||||
if (costReve < 1) costReve = 1;
|
||||
myReve.value = myReve.value - costReve; // Todo 0 pts de reve !!!!
|
||||
if (myReve.value < 0) myReve.value = 0;
|
||||
await this.update( {"data.reve.reve": myReve } );
|
||||
await this.update({ "data.reve.reve": myReve });
|
||||
specialStr += "<br>Réussite du sort pour " + costReve + " Points de Rêve";
|
||||
if ( !rollData.isSortReserve) {
|
||||
if (!rollData.isSortReserve) {
|
||||
this.currentTMR.close(); // Close TMR !
|
||||
} else { // Mise en réserve
|
||||
let reserve = duplicate(this.data.data.reve.reserve);
|
||||
reserve.list.push( { coord: rollData.coord, sort: duplicate(rollData.selectedSort), draconic: duplicate(rollData.selectedDraconic) });
|
||||
await this.update( {"data.reve.reserve": reserve} );
|
||||
reserve.list.push({ coord: rollData.coord, sort: duplicate(rollData.selectedSort), draconic: duplicate(rollData.selectedDraconic) });
|
||||
await this.update({ "data.reve.reserve": reserve });
|
||||
this.currentTMR.updateSortReserve();
|
||||
}
|
||||
} else {
|
||||
if ( rollData.pointsDeTache == -4) { // Echec total !
|
||||
if (rollData.tache == -4) { // Echec total !
|
||||
costReve *= 2;
|
||||
myReve.value = myReve.value - costReve; // Todo 0 pts de reve !!!!
|
||||
if (myReve.value < 0) myReve.value = 0;
|
||||
await this.update( {"data.reve.reve": myReve } );
|
||||
await this.update({ "data.reve.reve": myReve });
|
||||
specialStr += "<br><strong>Echec TOTAL</strong> du sort : " + costReve + " Points de Rêve";
|
||||
} else {
|
||||
} else {
|
||||
specialStr += "<br>Echec du sort !";
|
||||
}
|
||||
this.currentTMR.close(); // Close TMR !
|
||||
}
|
||||
if (myReve.value == 0) { // 0 points de reve
|
||||
ChatMessage.create( {title: "Zero Points de Reve !", content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" } );
|
||||
ChatMessage.create({ title: "Zero Points de Reve !", content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" });
|
||||
this.currentTMR.close(); // Close TMR !
|
||||
}
|
||||
} else {
|
||||
@ -268,37 +231,38 @@ export class RdDActor extends Actor {
|
||||
}
|
||||
|
||||
// Save it for fight in the flags area
|
||||
await this.setFlag( 'world', 'rollData', null );
|
||||
await this.setFlag( 'world', 'rollData', rollData );
|
||||
|
||||
await this.setFlag('world', 'rollData', null);
|
||||
await this.setFlag('world', 'rollData', rollData);
|
||||
|
||||
// Final chat message
|
||||
let chatOptions = { content: "<strong>Test : " + rollData.selectedCarac.label + " / " + lvl + "</strong><br>Jet : " +
|
||||
rollData.selectedCarac.value + " / " + rollData.finalLevelStr + " -> " + rollData.rollTarget.score + "%<br><strong>Résutat : </strong>" + result + "<br>" +
|
||||
"<strong>" + quality + "</strong>" + specialStr + xpmsg,
|
||||
user: game.user._id,
|
||||
title: "Résultat du test"
|
||||
}
|
||||
ChatMessage.create( chatOptions );
|
||||
|
||||
let chatOptions = {
|
||||
content: "<strong>Test : " + rollData.selectedCarac.label + " / " + lvl + "</strong><br>Jet : " +
|
||||
rollData.selectedCarac.value + " / " + rollData.finalLevelStr + " -> " + rolled.score + "%<br><strong>Résutat : </strong>" + result + "<br>" +
|
||||
"<strong>" + quality + "</strong>" + specialStr + xpmsg,
|
||||
user: game.user._id,
|
||||
title: "Résultat du test"
|
||||
}
|
||||
ChatMessage.create(chatOptions);
|
||||
|
||||
// This an attack, generate the defense message
|
||||
if ( defenseMsg ) {
|
||||
if ( defenseMsg.toSocket) {
|
||||
if (defenseMsg) {
|
||||
if (defenseMsg.toSocket) {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_defense",
|
||||
data: defenseMsg
|
||||
} );
|
||||
} else {
|
||||
defenseMsg.whisper = [ game.user];
|
||||
ChatMessage.create( defenseMsg );
|
||||
data: defenseMsg
|
||||
});
|
||||
} else {
|
||||
defenseMsg.whisper = [game.user];
|
||||
ChatMessage.create(defenseMsg);
|
||||
}
|
||||
}
|
||||
|
||||
// Get damages!
|
||||
if ( encaisser ) {
|
||||
this.encaisserDommages( rollData.attackerRoll );
|
||||
if (encaisser) {
|
||||
this.encaisserDommages(rollData.attackerRoll);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateCarac( caracName, caracValue )
|
||||
{
|
||||
@ -635,62 +599,45 @@ export class RdDActor extends Actor {
|
||||
|
||||
this.update( { "data.blessures": blessures } );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async stressTest( ) {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async stressTest() {
|
||||
let target = RdDResolutionTable.computeChances(this.data.data.carac.reve.value, 0);
|
||||
let stressRoll = this._stressRoll(target);
|
||||
|
||||
let compteurs = duplicate(this.data.data.compteurs);
|
||||
let stress = compteurs.stress;
|
||||
let xp = compteurs.experience;
|
||||
let convertion = Math.floor(compteurs.stress.value * stressRoll.factor);
|
||||
|
||||
compteurs.experience.value += convertion;
|
||||
compteurs.stress.value = Math.max(compteurs.stress.value - convertion - 1, 0);
|
||||
|
||||
let scoreTarget = RdDUtility.getResolutionField( this.data.data.carac.reve.value, 0 );
|
||||
scoreTarget.sig = Math.floor(scoreTarget.score / 2);
|
||||
|
||||
let scoreValue = new Roll("d100").roll().total;
|
||||
let newXP = xp.value;
|
||||
let factor = 0;
|
||||
let comment = "Echec Total (0%)"
|
||||
|
||||
if (scoreValue <= scoreTarget.part ) {
|
||||
scoreValue = new Roll("d100").roll().total;
|
||||
if (scoreValue <= scoreTarget.sig) {
|
||||
factor = 1.5;
|
||||
comment = "Double Particulière (150%)"
|
||||
} else {
|
||||
factor = 1;
|
||||
comment = "Particulière (100%)"
|
||||
}
|
||||
} else {
|
||||
if ( scoreValue <= scoreTarget.sig ) {
|
||||
factor = 0.75;
|
||||
comment = "Significative (75%)"
|
||||
} else {
|
||||
if ( scoreValue <= scoreTarget.score ) {
|
||||
factor = 0.5;
|
||||
comment = "Normale (50%)"
|
||||
} else if (scoreValue <= scoreTarget.epart) {
|
||||
factor = 0.2;
|
||||
comment = "Echec (20%)"
|
||||
} else if (scoreValue <= scoreTarget.etotal) {
|
||||
factor = 0.1;
|
||||
comment = "Echec (10%)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let xpValue = Math.floor(stress.value * factor);
|
||||
stress.value -= xpValue;
|
||||
stress.value -= 1;
|
||||
if (stress.value < 0 ) stress.value = 0;
|
||||
|
||||
ChatMessage.create( { title: "Jet de Stress", content: "Vous avez transformé "+ xpValue + " points de Stress en Expérience avec une réussite " + comment ,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name) } );
|
||||
|
||||
xp.value += xpValue;
|
||||
await this.update( { "data.compteurs": compteurs } );
|
||||
ChatMessage.create({
|
||||
title: "Jet de Stress", content: "Vous avez transformé " + convertion + " points de Stress en Expérience avec une réussite " + stressRoll.comment,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||
});
|
||||
await this.update({ "data.compteurs": compteurs });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollUnSort( coord ) {
|
||||
_stressRoll(target) {
|
||||
let result = RdDResolutionTable.rollChances(target)
|
||||
switch (result.quality) {
|
||||
case "sign": return { factor: 0.75, comment: "Significative (75%) - " + result.roll }
|
||||
case "norm": return { factor: 0.5, comment: "Normale (50%) - " + result.roll }
|
||||
case "echec": return { factor: 0.2, comment: "Echec (20%) - " + result.roll }
|
||||
case "epart": return { factor: 0.1, comment: "Echec particulier(10%) - " + result.roll }
|
||||
case "etotal": return { factor: 0, comment: "Echec Total (0%) - " + result.roll }
|
||||
}
|
||||
let second = RdDResolutionTable.rollChances(target)
|
||||
switch (second.qualite) {
|
||||
case "part": case "sign":
|
||||
return { factor: 1.5, comment: "Double Particulière (150%) - " + result + " puis " + second }
|
||||
default:
|
||||
return { factor: 1, comment: "Particulière (100%) - " + result + " puis " + second }
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollUnSort(coord) {
|
||||
let draconicList = this.getDraconicList();
|
||||
let sortList = this.getSortList();
|
||||
|
||||
|
Reference in New Issue
Block a user