#68 - Merge
This commit is contained in:
commit
0fb9c8f334
56
icons/moral-heureux.svg
Normal file
56
icons/moral-heureux.svg
Normal file
@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 75.00931 75.00931"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="moral-heureux.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs7" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1"
|
||||
inkscape:cx="333.29198"
|
||||
inkscape:cy="333.29198"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3"
|
||||
units="px" />
|
||||
<path
|
||||
id="Sélection"
|
||||
d="m 66.763622,55.801746 c -2.43018,3.864628 -5.706983,7.123491 -9.411048,9.759339 -7.03081,4.846547 -15.837577,7.115739 -24.341337,6.00475 C 25.807644,70.784579 19.08654,67.301555 13.665114,62.614772 9.3359224,58.489365 6.8728307,52.79721 4.9072277,47.257566 2.8341434,38.959612 2.3577605,29.777223 6.3796256,21.960827 8.9043904,16.883034 12.829489,12.457533 17.465047,9.2040308 27.601292,2.8411196 41.10206,0.89353942 52.052456,6.354848 c 7.511064,3.3349698 13.761367,9.512106 16.745031,17.220786 3.774954,9.248512 4.041191,20.107428 -0.497545,29.152314 -0.484077,1.038326 -1.001798,2.06063 -1.53632,3.073798 z M 53.074022,10.263125 C 42.613443,4.1684105 28.294549,4.5690521 18.806476,12.378825 12.904057,16.664573 8.6121134,23.206388 6.8339975,30.265584 5.7018593,36.155804 6.6585098,42.281224 8.2314204,47.992154 11.305017,57.050163 18.814508,64.757877 28.088515,67.393442 36.608062,69.793939 46.019628,68.565828 53.570132,63.920893 60.322168,60.364578 64.59903,53.584735 67.344823,46.686025 69.46186,39.678571 69.137857,31.902665 66.204722,25.171266 63.403219,20.113594 60.194091,14.993649 55.229789,11.796444 54.534807,11.253973 53.83928,10.705202 53.074022,10.263125 Z m -34.5,17.524621 c -2.627361,-2.239264 0.259088,-3.743091 2.144272,-4.879335 1.813444,-1.099784 3.457859,-2.564599 5.420888,-3.342705 2.485732,1.266481 1.070031,3.230373 -0.764858,3.964512 -2.283569,1.383885 -4.331247,3.234058 -6.800302,4.257528 z m 28.29,-5.796 c 0.335112,-2.973907 2.799592,-2.36474 4.401386,-0.89375 2.098276,1.319998 4.165178,2.688185 6.224614,4.06775 -0.333429,3.743981 -3.345506,1.901392 -5.118668,0.385841 -1.83578,-1.186614 -3.671559,-2.373227 -5.507332,-3.559841 z m -22.632,5.86914 c 3.909347,-1.447006 5.131289,5.454209 1.123361,5.508353 -3.699973,0.747498 -4.527027,-4.808106 -1.123361,-5.508353 z m 24.288,0.0041 c 4.715115,-1.511238 4.776422,6.820705 0.115071,5.441899 -2.99057,-0.223498 -2.893321,-5.001148 -0.115071,-5.441899 z m -25.116,18.82872 c 3.265301,1.726263 6.40892,3.97311 10.171497,4.583318 6.094487,1.424781 12.299547,-0.979689 17.256948,-4.463458 0.854814,0.302882 0.795598,4.025722 -0.932445,4.2575 -6.932423,4.290793 -16.025719,4.826964 -23.266434,0.96166 -2.690331,-0.594794 -3.622776,-2.72038 -3.229566,-5.185654 z"
|
||||
style="stroke-width:0.138" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.7 KiB |
57
icons/moral-malheureux.svg
Normal file
57
icons/moral-malheureux.svg
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 75.00931 75.00931"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="moral-malheureux.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs7" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
inkscape:zoom="6.0226229"
|
||||
inkscape:cx="159.51964"
|
||||
inkscape:cy="126.87132"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3"
|
||||
units="px"
|
||||
inkscape:document-rotation="0" />
|
||||
<path
|
||||
id="Sélection #2"
|
||||
d="m 31.388625,2.3182172 c 4.409777,0.1049465 8.850818,-0.238982 13.235505,0.2328545 12.343616,2.5226775 23.044406,11.8898383 26.790636,23.9755673 1.895687,4.47925 1.152474,9.358954 1.298859,14.073386 0.243884,5.666579 -2.268429,11.068801 -5.035,15.869569 -5.408578,8.666803 -14.775017,14.821045 -24.89,16.222248 -4.053365,-0.09512 -8.136018,0.20082 -12.16912,-0.168131 C 19.553649,70.172024 9.6028354,62.593076 5.0519554,52.147322 3.2422814,48.180027 2.0056664,43.880128 2.3186249,39.489636 2.3830349,35.012666 1.8677074,30.399761 3.7434254,26.170285 7.7021134,13.897624 18.761719,4.5969632 31.388625,2.3182172 Z m 5.13,2.868525 C 27.902914,5.4285077 19.395882,9.1781862 13.675723,15.667218 7.2145354,22.522912 4.2422324,32.383446 5.5175124,41.68387 6.9114379,54.433573 16.848647,65.754875 29.321729,68.777804 39.708925,71.461905 51.434955,68.787304 59.314103,61.419959 65.370515,55.787504 69.323332,47.886411 69.753843,39.577891 70.823163,26.172346 62.529369,12.588239 49.98022,7.6540632 45.737872,5.8425747 41.106859,5.1443342 36.518625,5.1867422 Z M 25.543275,19.089042 c 3.582403,1.517397 0.580488,3.887381 -1.590604,4.876635 -1.849564,1.075143 -3.533772,2.669329 -5.542195,3.293175 -3.938358,-3.009638 2.168109,-4.497832 4.038782,-6.246298 1.012957,-0.667156 1.994696,-1.401943 3.094017,-1.923512 z m 23.419875,0.0342 c 1.961351,0.383847 3.479413,2.018322 5.240466,2.974735 1.19966,1.199517 4.361146,1.708698 3.704117,3.68638 -0.794685,2.709419 -2.895477,0.815812 -4.290751,-0.139783 -1.994145,-1.401573 -4.233694,-2.523989 -6.026107,-4.155832 0.114314,-0.924379 0.785346,-1.688663 1.372275,-2.3655 z m -24.842025,8.329125 c 3.53895,-0.901294 5.202723,4.843356 1.541869,5.786659 -3.889946,1.388206 -5.600478,-4.938423 -1.541869,-5.786659 z m 25.365,-0.0085 c 3.543795,-0.687496 4.743854,4.888994 1.336318,5.853985 -4.052187,1.23158 -5.621521,-5.221504 -1.336318,-5.853985 z m -26.3625,27.720525 c -1.645428,-4.409007 3.436948,-5.79006 6.546089,-7.011067 7.253174,-2.83024 15.685954,-1.242533 21.973766,3.135599 1.074232,1.903828 0.444999,5.215737 -1.814737,2.671124 -4.926871,-3.182177 -11.020067,-4.782556 -16.8245,-3.386883 -3.647364,0.701851 -6.693672,2.861951 -9.880618,4.591227 z"
|
||||
style="fill:#000000;stroke:#000000;stroke-width:0.1425" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
57
icons/moral-neutre.svg
Normal file
57
icons/moral-neutre.svg
Normal file
@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="100"
|
||||
height="100"
|
||||
viewBox="0 0 149.99229 149.9923"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="moral-neutre.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs7" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2066"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:zoom="12.02078"
|
||||
inkscape:cx="102.31546"
|
||||
inkscape:cy="83.023164"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3"
|
||||
inkscape:document-rotation="0" />
|
||||
<path
|
||||
id="Sélection"
|
||||
style="fill:#000000;stroke:none"
|
||||
d="M 71.093828,7.6469084 C 97.936924,5.9599987 125.06801,21.804719 136.13292,46.454593 c 5.95881,12.792326 7.72015,27.387982 5.06882,41.232129 C 136.36218,116.13727 111.06015,139.22547 82.427269,142.03918 58.296459,145.00446 33.165221,133.50995 19.511191,113.4043 6.8332316,95.353164 4.0375264,70.991963 12.137453,50.487077 21.051877,27.239578 43.644843,9.8545888 68.585553,7.9893186 l 1.221545,-0.1630972 z m -1.8,6.2160006 C 49.669449,15.684286 31.325321,27.38065 21.722534,44.62169 9.9713207,64.809651 11.253962,91.713801 24.993106,110.62881 c 11.840312,16.80174 32.531342,26.84959 53.057358,25.5921 24.176426,-0.74569 46.838176,-17.56796 54.629626,-40.479285 8.54466,-22.924158 1.66761,-50.535403 -16.88627,-66.569716 -11.86002,-10.632118 -27.972278,-16.232947 -43.856628,-15.309 -0.881121,0 -1.762243,0 -2.643364,0 z m -28.113,31.08001 c 6.159573,-0.465582 12.381769,-0.133464 18.5685,-0.195937 4.496608,3.683946 -0.596896,7.678968 -5.074782,6.273937 -4.559678,-0.156315 -9.204985,0.341414 -13.700718,-0.306 -0.596592,-1.596634 -1.099154,-4.474928 0.207,-5.772 z m 47.013,6.078 c -2.33447,-5.63843 2.385738,-7.032477 6.819282,-6.3 4.381016,0.11131 8.81145,-0.237846 13.15724,0.207563 3.0765,4.612976 -1.36659,7.076384 -5.57774,6.092437 -4.799594,0 -9.599188,0 -14.398782,0 z m -39.3,5.295 c 7.714623,-3.050346 10.51914,10.151423 2.613131,10.84429 -6.545215,1.007026 -8.727993,-8.710097 -2.613131,-10.84429 z m 47.7,0 c 7.672832,-2.993081 10.460522,10.149395 2.591772,10.84354 -6.544141,1.013722 -8.735489,-8.763102 -2.591772,-10.84354 z m -48.9,36.405 c 18.199997,0 36.399995,0 54.599992,0 0,2.4 0,4.8 0,7.2 -18.199997,0 -36.399995,0 -54.599992,0 0,-2.4 0,-4.8 0,-7.2 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
@ -450,6 +450,18 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.actor.stressTest();
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-malheureux').click((event) => {
|
||||
this.actor.jetDeMoral('malheureuse');
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-neutre').click((event) => {
|
||||
this.actor.jetDeMoral('neutre');
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#moral-heureux').click((event) => {
|
||||
this.actor.jetDeMoral('heureuse');
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#ethylisme-test').click((event) => {
|
||||
this.actor.ethylismeTest();
|
||||
this.render(true);
|
||||
|
191
module/actor.js
191
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 = {
|
||||
@ -1189,6 +1051,45 @@ export class RdDActor extends Actor {
|
||||
this.update( { "data.blessures": blessures } );
|
||||
}
|
||||
|
||||
async jetDeMoral(situation) {
|
||||
let jetMoral = new Roll("1d20").roll();
|
||||
RdDDice.show(jetMoral);
|
||||
let compteurs = duplicate(this.data.data.compteurs);
|
||||
compteurs.moral.value = Misc.toInt(compteurs.moral.value);
|
||||
const succes = jetMoral.total <= 10 + compteurs.moral.value;
|
||||
let ajustementMoral = this._calculAjustementMoral(succes, compteurs.moral, situation);
|
||||
if (ajustementMoral != 0) {
|
||||
compteurs.moral.value += ajustementMoral;
|
||||
if (compteurs.moral.value>3) {
|
||||
// exaltation
|
||||
compteurs.moral.value --;
|
||||
compteurs.exaltation.value = Misc.toInt(compteurs.exaltation.value) + 1;
|
||||
}
|
||||
if (compteurs.moral.value<-3) {
|
||||
// dissolution
|
||||
compteurs.moral.value ++;
|
||||
compteurs.dissolution.value = Misc.toInt(compteurs.dissolution.value) + 1;
|
||||
}
|
||||
await this.update( { 'data.compteurs': compteurs} );
|
||||
}
|
||||
ChatMessage.create({
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name),
|
||||
content: "Jet de moral ("+ jetMoral.total + ")" + (succes? "réussi": "manqué") + " en situation "+situation+", vous "+(ajustementMoral>0? "gagnez du moral":ajustementMoral<0? "perdez du moral": "gardez votre moral")
|
||||
});
|
||||
}
|
||||
|
||||
_calculAjustementMoral(succes, moral, situation)
|
||||
{
|
||||
switch (situation) {
|
||||
case 'heureuse': return succes ? 1 : 0;
|
||||
case 'malheureuse':return succes ? 0 : -1;
|
||||
case 'neutre':
|
||||
if (succes && moral <= 0) return 1;
|
||||
if (!succes && moral > 0) return -1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
async ethylismeTest() {
|
||||
let rollData = {
|
||||
@ -1648,7 +1549,7 @@ export class RdDActor extends Actor {
|
||||
// Cas de désir lancinant, pas d'expérience sur particulière
|
||||
if ( this.checkDesirLancinant() ) {
|
||||
ChatMessage.create( { content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name) } ).create();
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name) } );
|
||||
return { result:false, xpcarac:0, xpCompetence: 0 };
|
||||
}
|
||||
|
||||
@ -1672,7 +1573,7 @@ export class RdDActor extends Actor {
|
||||
await this.update( {"data.carac": carac } );
|
||||
} else {
|
||||
ChatMessage.create( { content: `Vous avez ${xpCarac} à répartir pour la caractérisque dérivée ${caracName}. Vous devez le faire manuellement.`,
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name) } ).create();
|
||||
whisper: ChatMessage.getWhisperRecipients(game.user.name) } );
|
||||
}
|
||||
return { result:true, xpcarac:xpCarac, xpCompetence: xpComp }; //XP
|
||||
}
|
||||
@ -1866,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));
|
||||
|
@ -44,6 +44,7 @@ export class RdDItemArme extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static armeUneOuDeuxMains(arme, aUneMain) {
|
||||
if (arme) {
|
||||
arme.data.unemain = arme.data.unemain || !arme.data.deuxmains;
|
||||
const uneOuDeuxMains = arme.data.unemain && arme.data.deuxmains;
|
||||
const containsSlash = !Number.isInteger(arme.data.dommages) && arme.data.dommages.includes("/");
|
||||
@ -63,7 +64,14 @@ export class RdDItemArme extends Item {
|
||||
if (uneOuDeuxMains != containsSlash) {
|
||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||
}
|
||||
}
|
||||
return arme;
|
||||
}
|
||||
|
||||
static mainsNues() {
|
||||
return {
|
||||
name: "Mains nues",
|
||||
data: { unemain: true, deuxmains: false, dommages: 0, dommagesReels: 0, mortalite: 'non-mortel' }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
86
module/rdd-bonus.js
Normal file
86
module/rdd-bonus.js
Normal file
@ -0,0 +1,86 @@
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
const conditionsTactiques = [
|
||||
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
||||
{ type: 'charge', descr: 'Charge', dmg: 2, attaque: 4, parade: -4, esquive: false },
|
||||
{ type: 'feinte', descr: 'Feinte', dmg: 1, attaque: 1, parade: 0, esquive: true },
|
||||
{ type: 'pret', descr: 'prêt', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
||||
{ type: 'demi', descr: 'Demi-surprise', dmg: 1, attaque: 0, parade: 0, esquive: true },
|
||||
{ type: 'totale', descr: 'Surprise totale', dmg: 10, attaque: 6, parade: 0, esquive: true },
|
||||
];
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDBonus {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _find(condition) {
|
||||
return conditionsTactiques.find(e => e.type == condition) || conditionsTactiques.find(e => e.type == 'pret');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static dmg(rollData, dmgActor, isCauchemar = false) {
|
||||
let dmg = { total: 0, loc: RdDUtility.getLocalisation() };
|
||||
if (rollData.arme && rollData.arme.name.toLowerCase() == "esquive") {
|
||||
// Specific case management
|
||||
ui.notifications.warn("Calcul de bonus dégats sur eswquive");
|
||||
} else {
|
||||
dmg.dmgArme = RdDBonus._dmgArme(rollData);
|
||||
dmg.ignoreArmure = 0; // TODO: calculer pour arcs et arbaletes, gérer pour lmes créatures
|
||||
dmg.dmgTactique = RdDBonus.dmgBonus(rollData.tactique);
|
||||
dmg.dmgParticuliere = RdDBonus._dmgParticuliere(rollData);
|
||||
dmg.dmgSurprise = RdDBonus.dmgBonus(rollData.surpriseDefenseur);
|
||||
dmg.dmgActor = rollData.selectedCarac ? RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac.label, dmg.dmgArme) : 0;
|
||||
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
|
||||
dmg.mortalite = RdDBonus._calculMortalite(rollData, isCauchemar)
|
||||
}
|
||||
return dmg;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static description(condition) {
|
||||
return RdDBonus._find(condition).descr;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static dmgBonus(condition) {
|
||||
return RdDBonus._find(condition).dmg;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static bonusAttaque(condition) {
|
||||
return RdDBonus._find(condition).attaque;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _calculMortalite(rollData, isCauchemar) {
|
||||
if (isCauchemar){
|
||||
return "cauchemar";
|
||||
}if (rollData.dmg && rollData.dmg.mortalite) {
|
||||
return rollData.dmg.mortalite;
|
||||
}
|
||||
if (rollData.arme && rollData.arme.data.mortalite) {
|
||||
return rollData.arme.data.mortalite;
|
||||
}
|
||||
return "mortel";
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _dmgArme(rollData) {
|
||||
return rollData.arme ? parseInt(rollData.arme.data.dommages) : 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _dmgPerso(dmgActor, categorie, dmgArme) {
|
||||
switch (categorie) {
|
||||
case "Tir": return 0;
|
||||
case "Lancer": return Math.max(0, Math.min(dmgArme, dmgActor));
|
||||
}
|
||||
return dmgActor;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _dmgParticuliere(rollData) {
|
||||
return rollData.particuliereAttaque == 'force' ? 5 : 0;
|
||||
}
|
||||
|
||||
}
|
@ -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,9 +250,9 @@ export class RdDCombat {
|
||||
|
||||
let content = "<strong>" + this.defender.name + "</strong> doit se défendre :<span class='chat-card-button-area'>";
|
||||
|
||||
if (this.defender.getSurprise() != 'totale') {
|
||||
// parades
|
||||
let filterArmesParade = this._getFilterArmesParade(rollData.competence.data.categorie);
|
||||
for (const arme of this.defender.data.items.filter(filterArmesParade)) {
|
||||
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>";
|
||||
}
|
||||
|
||||
@ -218,6 +260,7 @@ export class RdDCombat {
|
||||
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
|
||||
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>";
|
||||
@ -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 '';
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -242,10 +242,9 @@ export class RdDResolutionTable {
|
||||
static buildHTMLResults( caracValue, levelValue) {
|
||||
let cell = this.computeChances( caracValue, levelValue);
|
||||
let descr = $('<span class="span-valeur competence-label">');
|
||||
descr.append("Réussite : "+cell.score+ " - Particulière : " + cell.part + " - Significative : " + cell.sign);
|
||||
descr.append("Particulière : " + cell.part+ " - Significative : " + cell.sign + " - Réussite : "+cell.score);
|
||||
descr.append("<br>Echec Particulier : " + cell.epart + " - Echec Total : " + cell.etotal );
|
||||
descr.append("</span>");
|
||||
|
||||
return descr;
|
||||
}
|
||||
|
||||
|
@ -37,8 +37,8 @@ export class RdDEncaisser extends Dialog {
|
||||
dmg:{
|
||||
total: Number(this.modifier),
|
||||
loc: { result: 0, label: "Corps" },
|
||||
},
|
||||
mortalite: mortalite
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDItemSort } from "./item-sort.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
|
||||
/**
|
||||
@ -38,7 +39,7 @@ export class RdDRoll extends Dialog {
|
||||
diffLibre: 0,
|
||||
editLibre: true,
|
||||
editConditions: true,
|
||||
forceValue : actor.getForceValue(),
|
||||
forceValue: actor.getForceValue(),
|
||||
malusArmureValue: (actor.type == 'personnage ' && actor.data.data.attributs && actor.data.data.attributs.malusarmure) ? actor.data.data.attributs.malusarmure.value : 0,
|
||||
surencMalusFlag: actor.type == 'personnage ' ? (actor.data.data.compteurs.surenc.value < 0) : false,
|
||||
surencMalusValue: actor.type == 'personnage ' ? actor.data.data.compteurs.surenc.value : 0,
|
||||
@ -48,7 +49,7 @@ export class RdDRoll extends Dialog {
|
||||
encValueForNatation: actor.encombrementTotal ? Math.floor(actor.encombrementTotal) : 0,
|
||||
ajustementAstrologique: actor.ajustementAstrologique()
|
||||
}
|
||||
mergeObject(rollData, defaultRollData, { overwrite: false } );
|
||||
mergeObject(rollData, defaultRollData, { overwrite: false });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -101,19 +102,26 @@ export class RdDRoll extends Dialog {
|
||||
this.bringToTop();
|
||||
|
||||
var rollData = this.rollData;
|
||||
var actor = this.actor;
|
||||
|
||||
function updateRollResult(rollData) {
|
||||
let caracValue = parseInt(rollData.selectedCarac.value)
|
||||
let rollLevel = RdDRoll._computeFinalLevel(rollData);
|
||||
|
||||
rollData.dmg = rollData.attackerRoll ? rollData.attackerRoll.dmg : RdDBonus.dmg(rollData, actor.getBonusDegat());
|
||||
rollData.finalLevel = rollLevel;
|
||||
rollData.caracValue = caracValue
|
||||
rollData.caracValue = caracValue;
|
||||
rollData.diffConditions = RdDBonus.bonusAttaque(rollData.surpriseDefenseur);
|
||||
rollData.coupsNonMortels = (rollData.attackerRoll ? rollData.attackerRoll.dmg.mortalite : rollData.dmg.mortalite) == 'non-mortel';
|
||||
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
||||
if (rollData.coupsNonMortels) {
|
||||
dmgText = '(' + dmgText + ')';
|
||||
}
|
||||
|
||||
HtmlUtility._showControlWhen(".etat-general", !RdDRoll._isIgnoreEtatGeneral(rollData));
|
||||
|
||||
// Sort management
|
||||
if (rollData.selectedSort) {
|
||||
rollData.bonus = RdDItemSort.getCaseBonus( rollData.selectedSort, rollData.coord ),
|
||||
rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord),
|
||||
//console.log("Toggle show/hide", rollData.selectedSort);
|
||||
HtmlUtility._showControlWhen("#div-sort-difficulte", RdDItemSort.isDifficulteVariable(rollData.selectedSort))
|
||||
HtmlUtility._showControlWhen("#div-sort-ptreve", RdDItemSort.isCoutVariable(rollData.selectedSort))
|
||||
@ -122,6 +130,9 @@ export class RdDRoll extends Dialog {
|
||||
// Mise à jour valeurs
|
||||
$("#roll-param").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
|
||||
$("#compdialogTitle").text(RdDRoll._getTitle(rollData));
|
||||
$('#coupsNonMortels').prop('checked', rollData.coupsNonMortels);
|
||||
$("#dmg-arme-actor").text(dmgText);
|
||||
$("#defenseur-surprise").text(RdDBonus.description(rollData.surpriseDefenseur));
|
||||
$(".table-resolution").remove();
|
||||
$("#resolutionTable").append(RdDResolutionTable.buildHTMLTableExtract(caracValue, rollLevel));
|
||||
$(".span-valeur").remove();
|
||||
@ -168,7 +179,7 @@ export class RdDRoll extends Dialog {
|
||||
html.find('#sort').change((event) => {
|
||||
let sortKey = Misc.toInt(event.currentTarget.value);
|
||||
this.rollData.selectedSort = rollData.sortList[sortKey]; // Update the selectedCarac
|
||||
this.rollData.bonus = RdDItemSort.getCaseBonus( rollData.selectedSort, rollData.coord );
|
||||
this.rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord);
|
||||
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
||||
//console.log("RdDRollSelectDialog - Sort selection", rollData.selectedSort);
|
||||
updateRollResult(rollData);
|
||||
@ -186,10 +197,12 @@ export class RdDRoll extends Dialog {
|
||||
updateRollResult(rollData);
|
||||
});
|
||||
html.find('#coupsNonMortels').change((event) => {
|
||||
this.rollData.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
updateRollResult(rollData);
|
||||
});
|
||||
html.find('#isCharge').change((event) => {
|
||||
this.rollData.isCharge = event.currentTarget.checked;
|
||||
html.find('#tactique-combat').change((event) => {
|
||||
this.rollData.tactique = event.currentTarget.value;
|
||||
updateRollResult(rollData);
|
||||
});
|
||||
html.find('#surencMalusApply').change((event) => {
|
||||
this.rollData.surencMalusApply = event.currentTarget.checked;
|
||||
@ -209,11 +222,38 @@ export class RdDRoll extends Dialog {
|
||||
static _computeFinalLevel(rollData) {
|
||||
const etat = RdDRoll._isIgnoreEtatGeneral(rollData) ? 0 : Misc.toInt(rollData.etat);
|
||||
const diffConditions = Misc.toInt(rollData.diffConditions);
|
||||
let malusEnc = (rollData.surencMalusApply) ? rollData.surencMalusValue : 0;
|
||||
let diffLibre = Misc.toInt(rollData.diffLibre);
|
||||
let malusEncNatation = (rollData.useEncForNatation) ? -rollData.encValueForNatation : 0;
|
||||
let ajustementChance = rollData.selectedCarac.label.toLowerCase().includes('chance') ? rollData.ajustementAstrologique : 0;
|
||||
const malusEnc = (rollData.surencMalusApply) ? rollData.surencMalusValue : 0;
|
||||
const bonusTactique = RdDBonus.bonusAttaque(rollData.tactique);
|
||||
const malusEncNatation = (rollData.useEncForNatation) ? -rollData.encValueForNatation : 0;
|
||||
const ajustementChance = rollData.selectedCarac.label.toLowerCase().includes('chance') ? rollData.ajustementAstrologique : 0;
|
||||
// Gestion malus armure
|
||||
const malusArmureValue = RdDRoll._computeMalusArmure(rollData);
|
||||
|
||||
const diffLibre = RdDRoll._computeDiffLibre(rollData);
|
||||
const diffCompetence = RdDRoll._computeDiffCompetence(rollData);
|
||||
|
||||
return etat + diffCompetence + diffLibre + diffConditions + malusEnc + malusEncNatation + malusArmureValue + ajustementChance + bonusTactique;
|
||||
}
|
||||
|
||||
static _computeDiffCompetence(rollData) {
|
||||
if (rollData.competence) {
|
||||
return Misc.toInt(rollData.competence.data.niveau);
|
||||
}
|
||||
if (rollData.draconicList) {
|
||||
return Misc.toInt(rollData.selectedDraconic.data.niveau);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static _computeDiffLibre(rollData) {
|
||||
let diffLibre = Misc.toInt(rollData.diffLibre);
|
||||
if (rollData.draconicList && rollData.selectedSort) {
|
||||
return RdDItemSort.getDifficulte(rollData.selectedSort, diffLibre);
|
||||
}
|
||||
return diffLibre;
|
||||
}
|
||||
|
||||
static _computeMalusArmure(rollData) {
|
||||
let malusArmureValue = 0;
|
||||
if (rollData.malusArmureValue != 0 && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
|
||||
$("#addon-message").text("Malus armure appliqué : " + rollData.malusArmureValue);
|
||||
@ -221,17 +261,7 @@ export class RdDRoll extends Dialog {
|
||||
} else {
|
||||
$("#addon-message").text("");
|
||||
}
|
||||
|
||||
let diffCompetence = 0;
|
||||
if (rollData.competence) {
|
||||
diffCompetence = Misc.toInt(rollData.competence.data.niveau);
|
||||
}
|
||||
else if (rollData.draconicList) {
|
||||
diffCompetence = Misc.toInt(rollData.selectedDraconic.data.niveau);
|
||||
diffLibre = RdDItemSort.getDifficulte(rollData.selectedSort, diffLibre);
|
||||
}
|
||||
|
||||
return etat + diffCompetence + diffLibre + diffConditions + malusEnc + malusEncNatation + malusArmureValue + ajustementChance;
|
||||
return malusArmureValue;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -285,14 +285,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
return rencontre;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
performRoll(html) {
|
||||
if (this.viewOnly) {
|
||||
return;
|
||||
}
|
||||
this.actor.performRoll(this.rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateValuesDisplay() {
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
|
@ -133,7 +133,7 @@
|
||||
<li class="competence flexrow list-item">
|
||||
<span class="generic-label" id="chance-actuelle"><a>Chance actuelle</a></span>
|
||||
<input class="compteur-edit" id="chance-edit" type="text" name="chance" value="{{data.compteurs.chance.value}}" data-dtype="number"/>
|
||||
<a class="item-control stress-test" id="chance-appel">Utiliser</a>
|
||||
<span><a class="item-control stress-test" id="chance-appel">Utiliser</a></span>
|
||||
</li>
|
||||
{{#each data.compteurs as |compteur key|}}
|
||||
{{#if compteur.isChance}}
|
||||
@ -141,15 +141,19 @@
|
||||
<li class="competence flexrow list-item">
|
||||
<span class="generic-label">{{compteur.label}}</span>
|
||||
<input class="compteur-edit" id="{{key}}-edit" type="text" name="{{key}}" value="{{compteur.value}}" data-dtype="number"/>
|
||||
<span>
|
||||
{{#if compteur.isStress}}
|
||||
<a class="item-control stress-test" id="stress-test" title="Transformer">Transformer</a>
|
||||
{{else}}
|
||||
{{#if (eq compteur.label 'Ethylisme')}}
|
||||
{{else if (eq compteur.label 'Ethylisme')}}
|
||||
<a class="item-control ethylisme-test" id="ethylisme-test" title="Jet d'Ethylisme">Jet d'Ethylisme</a>
|
||||
{{else if (eq compteur.label 'Moral')}}
|
||||
<a id="moral-malheureux" title="Jet de moral situation malheureuse"><img class="small-button-container" src="systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg" alt="Jet de moral situation malheureuse"/></a>
|
||||
<a id="moral-neutre" title="Jet de moral situation neutre"><img class="small-button-container" src="systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg" alt="Jet de moral situation neutre"/></a>
|
||||
<a id="moral-heureux" title="Jet de moral situation heureuse"><img class="small-button-container" src="systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg" alt="Jet de moral situation heureuse"/></a>
|
||||
{{else}}
|
||||
<label></label>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</span>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
@ -9,8 +9,13 @@
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
<label></label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
{{#if attackerRoll}}
|
||||
<label for="categorie">Difficulté</label>
|
||||
<label>{{diffLibre}}</label>
|
||||
{{else}}
|
||||
<label for="categorie">Difficulté libre</label>
|
||||
<select name="diffLibre" id="diffLibre" data-dtype="number" {{#unless editLibre}}disabled{{/unless}}>
|
||||
{{#select diffLibre}}
|
||||
@ -19,6 +24,7 @@
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
{{/if}}
|
||||
<label for="categorie"> Conditions</label>
|
||||
<select name="diffConditions" id="diffConditions" data-dtype="number" {{#unless editConditions}}disabled{{/unless}}>
|
||||
{{#select diffConditions}}
|
||||
@ -27,30 +33,38 @@
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
|
||||
</div>
|
||||
{{#if arme}}
|
||||
<div>
|
||||
<label>Arme : {{arme.name}}</label>
|
||||
<label>Degats : {{arme.data.dommagesReels}}</label>
|
||||
<label for="xp">Coups Non Mortels ? </label>
|
||||
<div class="form-group">
|
||||
{{#if attackerRoll}}
|
||||
{{#if attackerRoll.tactique}}
|
||||
<label for="categorie">Tactique: {{attackerRoll.tactique}}</label>
|
||||
{{/if}}
|
||||
<label for="categorie">Dégats:</label><label id="dmg-arme-actor"></label>
|
||||
<label></label>
|
||||
{{else}}
|
||||
<label for="categorie">Tactique:</label>
|
||||
<select name="tactique-combat" id="tactique-combat" data-dtype="String" {{#unless editConditions}}disabled{{/unless}}>
|
||||
<option value="Attaque normale">Attaque normale</option>
|
||||
<option value="charge">Charge</option>
|
||||
<option value="feinte">Feinte</option>
|
||||
</select>
|
||||
<label for="categorie">Dégats:</label><label id="dmg-arme-actor"></label>
|
||||
<label>Non Mortel</label>
|
||||
<input class="attribute-value" type="checkbox" id="coupsNonMortels" name="coupsNonMortels" {{#if coupsNonMortels}}checked{{/if}}/>
|
||||
</div>
|
||||
{{#unless attackerRoll}}
|
||||
<div>
|
||||
<label>Est une charge ?</label>
|
||||
<input class="attribute-value" type="checkbox" id="isCharge" name="isCharge" {{#if isCharge}}checked{{/if}}/>
|
||||
</div>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
{{#if surpriseDefenseur}}
|
||||
<label for="categorie" id="defenseur-surprise"></label>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="form-group">
|
||||
<label for="categorie">Etat général:</label><label>{{numberFormat etat decimals=0 sign=true}}</label>
|
||||
<label>Ajustement final:</label><label id="roll-param">10 / 0</label> <label name="addon-message" id="addon-message"></label>
|
||||
</div>
|
||||
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html"}}
|
||||
{{>"systems/foundryvtt-reve-de-dragon/templates/dialog-roll-natation.html"}}
|
||||
<div class="form-group etat-general">
|
||||
<label for="categorie">Etat général</label><label>{{numberFormat etat decimals=0 sign=true}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Ajustement final : </label><label id="roll-param">10 / 0</label> <label name="addon-message" id="addon-message"></label>
|
||||
</div>
|
||||
<div id="resolutionTable">
|
||||
</div>
|
||||
<div id="resolutionValeurs">
|
||||
|
Loading…
Reference in New Issue
Block a user