forked from public/foundryvtt-reve-de-dragon
Gestion attaques v2 et initiative
This commit is contained in:
1
assets/ui/part-finesse.svg
Normal file
1
assets/ui/part-finesse.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,-28)" style=""><path d="M45.95 14.553c-19.38.81-30.594 11.357-30.282 30.283l19.768 30.78c4.43-1.213 9.36-3.838 14.248-7.335l42.474 59.935c-17.018 20.83-31.258 44.44-42.71 70.836l26.55 26.552c11.275-23.6 24.634-44.826 39.918-63.864l210.82 297.475 166.807 33.213L460.33 325.62 162.78 114.745c19.907-16.108 41.842-29.91 65.652-41.578l-26.553-26.55c-27.206 11.803-51.442 26.576-72.735 44.292L69.39 48.56c3.443-4.823 6.062-9.735 7.342-14.242l-30.78-19.765zm400.84 86.933v.008l.003-.008h-.002zm0 .008-28.028 124.97-25.116-80.593-18.105 70.667-26.862-49.64-.584 57.818 128.484 91.69 15.184 87.017-1.168-186.885-34.457 39.713-9.346-154.756zm-300.95 27.98 222.224 196.368 25.645 66.75-66.75-25.645L130.6 144.734a308.453 308.453 0 0 1 15.238-15.26zm32.305 196.274v.004h.005l-.005-.004zm.005.004 28.028 22.775-36.21 4.088 57.82 19.272-105.706 4.09 115.05 27.45L136.1 422.114l127.316 25.696-67.164 43.803 208.494 1.752-87.017-15.185-104.54-150.676-35.037-1.752z" fill="#fff" fill-opacity="1" transform="translate(25.6, 25.6) scale(0.9, 0.9) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
1
assets/ui/part-force.svg
Normal file
1
assets/ui/part-force.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,-28)" style=""><path d="M227.227 21.777c-1.845 0-3.704.05-5.567.157-15.314.875-30.76 5.305-39.494 10.863l-.008 73.15c2.884-.094 5.777-.147 8.676-.142 23.382.036 47.104 3.286 68.47 9.513l.01-87.507c-7.034-3.518-19.178-6.03-32.087-6.033zm80.74 9.16c-11.925.15-23.077 2.364-29.967 5.596l-.008 77.602v7.658c38.486 15.67 64.814 42.48 58.735 78.764l-.96 5.73-5.562 1.674c-17.45 5.253-34.872 9.703-52.225 13.335v25.234c25.562-.704 51.327-2.687 77.145-6.098l.02-197.928c-8.284-5.563-23.508-10.243-38.842-11.328a100.065 100.065 0 0 0-8.336-.238zM143.223 46.294a99.206 99.206 0 0 0-16.491 1.172c-15.67 2.454-31.477 8.565-40.406 15.402l-.01 72.955c18.808-15.81 46.704-25.143 77.15-28.54l.007-57.966c-4.82-1.752-12.018-2.916-20.25-3.023zm258.394 3.46c-10.804.117-20.722 1.93-27.043 4.655l-.02 183.182c25.074-4.02 50.16-9.412 75.122-16.358l1.99-158.447c-8.352-5.9-23.648-11.025-39.05-12.553a100.98 100.98 0 0 0-11-.478zm-222.775 74.202c-53.72.702-101.407 20.365-97.887 66.6 15.836-3.918 30.84-5.893 44.94-6.1 34.84-.51 64.213 9.704 87.318 27.613 34.608-3.11 69.852-10 105.412-20.314.14-41.287-74.098-68.657-139.783-67.8zm-48.877 78.65c-1.296-.003-2.603.012-3.92.045-17.256.436-36.45 4.03-57.566 11.037 5.79 53.808 26.325 106.41 58.5 143.346 6.226 7.15 12.856 13.712 19.875 19.615 29.303 9.282 69.26 12.917 110.534 12.14 3.777-55.805-8.717-108.357-36.193-142.74-21.265-26.61-51.064-43.39-91.232-43.444zm129.326 22.282a545.177 545.177 0 0 1-27.995 4.15 138.77 138.77 0 0 1 4.502 5.346c3.146 3.937 6.094 8.062 8.873 12.334 9.916.144 19.868.125 29.857-.106H259.29v-21.723zm191.817 15.343c-65.406 17.826-131.462 25.41-195.85 25.315 16.998 35.144 23.828 78.093 21.013 122.6 42.482-2.08 85.03-8.23 118.187-15.983 26.693-32.78 47.37-77.118 56.65-131.932zM400.51 389.9c-38.334 9.145-87.95 16.056-136.873 17.454-47.67 1.36-94.336-2.228-129.448-15.262l-.01 78.93c27.187 12.568 76.414 20.205 127.318 20.298 51.224.094 104.214-7.173 139-20.773l.012-80.647z" fill="#fff" fill-opacity="1" transform="translate(25.6, 25.6) scale(0.9, 0.9) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
After Width: | Height: | Size: 2.1 KiB |
1
assets/ui/part-rapidite.svg
Normal file
1
assets/ui/part-rapidite.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,-28)" style=""><path d="M275.03 20c35.223 49.563 53.59 113.64 55.69 173.47C315.154 143 289.092 88.423 250.81 48.75c40.294 79.527 51.15 172.312 37.938 256.094-12.287-75.777-40.564-159.524-92.375-227.156 29.6 70.937 36.64 149.785 24.813 221.843-8.745-51.804-25.41-107.4-52.594-158.81 13.023 54.315 12.854 107.64 3.437 159.28l21.657 6.813 15 4.718-11.28 10.908c-10.68 10.332-19.868 21.905-27.345 34.343 93.614 35.486 232.952 64.53 298.032 41.376-41.02 56.466-210.332 13.822-309.313-18.687-1.514 3.775-2.918 7.594-4.124 11.467a152.536 152.536 0 0 0-6.062 29.657l176.47 66.375c98.5 31.095 150.5-24.62 158.655-81.72C505.253 254.472 485.016 105.66 426.06 20h-22.187c40.092 65.52 66.67 154.216 60.47 255.344-8.154-79.833-42.8-157.214-98.44-219.5 38.676 85.094 56.566 185.746 34.376 288.625.057-118.816-33.1-225.865-105.092-324.47H275.03zm-110.186 1.594c41.255 29.176 74.328 74.093 97.5 120.656-7.702-46.15-21.3-86.79-44-120.656h-53.5zm176.375 0c28.882 15.143 52.096 36.614 71.28 66.78-7.14-27.79-17.217-49.85-31.438-66.78H341.22zM123.686 304.406a179.344 179.344 0 0 1-4.062 64L18.812 336.344V366l91.938 29.094a178.602 178.602 0 0 1-30.313 48.28l50.094 15.75c-3.038-24.898-1.136-49.885 6.282-73.718 7.446-23.92 20.223-46.108 37.032-65.22l-50.156-15.78z" fill="#fff" fill-opacity="1" transform="translate(25.6, 25.6) scale(0.9, 0.9) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
After Width: | Height: | Size: 1.5 KiB |
@@ -655,7 +655,8 @@ select,
|
|||||||
width: 1.5rem;
|
width: 1.5rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat {
|
||||||
font-family: CaslonAntique;
|
font-family: CaslonAntique;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions";
|
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions";
|
||||||
@@ -663,51 +664,61 @@ select,
|
|||||||
grid-template-rows: max-content max-content max-content max-content;
|
grid-template-rows: max-content max-content max-content max-content;
|
||||||
gap: 0 0.5rem;
|
gap: 0 0.5rem;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-img {
|
||||||
grid-area: img;
|
grid-area: img;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img img {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-img img,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-img img {
|
||||||
border: 0;
|
border: 0;
|
||||||
max-height: 3rem;
|
max-height: 3rem;
|
||||||
max-width: 3rem;
|
max-width: 3rem;
|
||||||
object-fit: contain;
|
object-fit: contain;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-header {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-header,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-header {
|
||||||
grid-area: header;
|
grid-area: header;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-resume {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-resume,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-resume {
|
||||||
grid-area: resume;
|
grid-area: resume;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-details {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-details,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-details {
|
||||||
grid-area: details;
|
grid-area: details;
|
||||||
text-align: justify;
|
text-align: justify;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions {
|
||||||
grid-area: actions;
|
grid-area: actions;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a img {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions a img,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a img {
|
||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons {
|
||||||
grid-area: buttons;
|
grid-area: buttons;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons a {
|
||||||
border-radius: 0.2rem;
|
border-radius: 0.2rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0.2rem;
|
padding: 0.2rem;
|
||||||
@@ -718,14 +729,17 @@ select,
|
|||||||
display: inline-block;
|
display: inline-block;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a img {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a img,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons a img {
|
||||||
max-width: 1rem;
|
max-width: 1rem;
|
||||||
max-height: 1rem;
|
max-height: 1rem;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:hover {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:hover,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons a:hover {
|
||||||
background: var(--background-custom-button-hover);
|
background: var(--background-custom-button-hover);
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:active {
|
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons a:active,
|
||||||
|
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons a:active {
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
}
|
}
|
||||||
@@ -1975,14 +1989,18 @@ select,
|
|||||||
width: 9rem;
|
width: 9rem;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
min-width: 6rem;
|
min-width: 8rem;
|
||||||
flex-basis: auto;
|
flex-basis: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
line-height: 0.95rem;
|
line-height: 1.6rem;
|
||||||
margin: 0.2rem;
|
margin: 0.2rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .rdd-hud-menu label {
|
.system-foundryvtt-reve-de-dragon div.control-icon.token-hud-icon select,
|
||||||
font-size: 0.8rem;
|
.system-foundryvtt-reve-de-dragon div.control-icon.token-hud-icon label {
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
.system-foundryvtt-reve-de-dragon .item-checkbox {
|
.system-foundryvtt-reve-de-dragon .item-checkbox {
|
||||||
height: 25px;
|
height: 25px;
|
||||||
|
@@ -1341,14 +1341,18 @@
|
|||||||
width: 9rem;
|
width: 9rem;
|
||||||
height: fit-content;
|
height: fit-content;
|
||||||
border-radius: 0.3rem;
|
border-radius: 0.3rem;
|
||||||
min-width: 6rem;
|
min-width: 8rem;
|
||||||
flex-basis: auto;
|
flex-basis: auto;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
line-height: 0.95rem;
|
line-height: 1.6rem;
|
||||||
margin: 0.2rem;
|
margin: 0.2rem;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
select, label {
|
||||||
|
font-size: 1rem;
|
||||||
}
|
}
|
||||||
.rdd-hud-menu label {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
}
|
}
|
||||||
/* ======================================== */
|
/* ======================================== */
|
||||||
.item-checkbox {
|
.item-checkbox {
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
.chat-message {
|
.chat-message div.roll-chat,
|
||||||
div.roll-chat {
|
.dialog-content div.roll-chat {
|
||||||
font-family: CaslonAntique;
|
font-family: CaslonAntique;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-areas:
|
grid-template-areas:
|
||||||
@@ -84,4 +84,3 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
@@ -2,6 +2,9 @@
|
|||||||
* class providing the actor and token, and choosing the name and image from the token if available.
|
* class providing the actor and token, and choosing the name and image from the token if available.
|
||||||
*/
|
*/
|
||||||
export class ActorToken {
|
export class ActorToken {
|
||||||
|
static fromTokenActor(token, actor){
|
||||||
|
return token ? ActorToken.fromToken(token) : ActorToken.fromActor(actor)
|
||||||
|
}
|
||||||
|
|
||||||
static fromActorId(actorId, onError = () => undefined) {
|
static fromActorId(actorId, onError = () => undefined) {
|
||||||
actorId = actorId ?? (canvas.tokens.controlled.length > 0
|
actorId = actorId ?? (canvas.tokens.controlled.length > 0
|
||||||
|
@@ -136,12 +136,12 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
}
|
}
|
||||||
|
|
||||||
listActions({ isAttaque = false, isEquipe = false }) {
|
listActions({ isAttaque = false, isEquipe = false }) {
|
||||||
// Recupération des armes
|
// Recupération des attaques
|
||||||
const actions = this.listActionsAttaque()
|
const actions = this.listActionsAttaque()
|
||||||
.filter(it => !isEquipe || it.arme.system.equipe)
|
.filter(it => !isEquipe || it.arme.system.equipe)
|
||||||
|
|
||||||
if (!isAttaque && this.system.attributs.hautrevant.value) {
|
if (!isAttaque && this.system.attributs.hautrevant.value) {
|
||||||
actions.push({ name: "Draconic", action: 'haut-reve', initOnly: true })
|
actions.push({ label: "Draconic", action: 'haut-reve', initOnly: true })
|
||||||
}
|
}
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
const actions = []
|
const actions = []
|
||||||
const uniques = []
|
const uniques = []
|
||||||
|
|
||||||
const addAttaque = (arme, main) => {
|
const addAttaque = (arme, main = undefined, action = 'attaque') => {
|
||||||
const dommagesArme = RdDItemArme.valeurMain(arme.system.dommages, main)
|
const dommagesArme = RdDItemArme.valeurMain(arme.system.dommages, main)
|
||||||
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
|
||||||
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
|
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
|
||||||
@@ -196,7 +196,7 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + ecaillesEfficacite
|
const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + ecaillesEfficacite
|
||||||
|
|
||||||
actions.push({
|
actions.push({
|
||||||
name: arme.name + (main ? ' ' + main : ''),
|
label: arme.name + (main ? ' ' + main : ''),
|
||||||
action: 'attaque',
|
action: 'attaque',
|
||||||
initOnly: false,
|
initOnly: false,
|
||||||
arme: arme,
|
arme: arme,
|
||||||
@@ -206,22 +206,23 @@ export class RdDActor extends RdDBaseActorSang {
|
|||||||
equipe: arme.system.equipe,
|
equipe: arme.system.equipe,
|
||||||
dommagesArme: dommagesArme,
|
dommagesArme: dommagesArme,
|
||||||
forceRequise: forceRequise,
|
forceRequise: forceRequise,
|
||||||
initiative: RdDInitiative.calculInitiative(niveau, caracValue, ajustement)
|
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addAttaque(RdDItemArme.empoignade(this))
|
|
||||||
addAttaque(RdDItemArme.corpsACorps(this))
|
|
||||||
|
|
||||||
this.itemTypes[ITEM_TYPES.arme]
|
this.itemTypes[ITEM_TYPES.arme]
|
||||||
.filter(it => it.isAttaque())
|
.filter(it => it.isAttaque())
|
||||||
.sort(Misc.ascending(it => it.name))
|
.sort(Misc.ascending(it => it.name))
|
||||||
.forEach(arme => {
|
.forEach(arme => {
|
||||||
if (arme.system.unemain && arme.system.competence) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
|
if (arme.system.unemain && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
|
||||||
if (arme.system.deuxmains && arme.system.competence) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
|
if (arme.system.deuxmains && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
|
||||||
if (arme.system.lancer) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
|
if (arme.system.lancer && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
|
||||||
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
|
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
|
||||||
})
|
})
|
||||||
|
|
||||||
|
addAttaque(RdDItemArme.corpsACorps(this), ATTAQUE_TYPE.CORPS_A_CORPS)
|
||||||
|
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS, 'empoignade')
|
||||||
|
|
||||||
return actions
|
return actions
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,6 +25,8 @@ import { RdDPossession } from "../rdd-possession.js";
|
|||||||
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js";
|
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js";
|
||||||
import { RollDataAjustements } from "../rolldata-ajustements.js";
|
import { RollDataAjustements } from "../rolldata-ajustements.js";
|
||||||
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
|
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
|
||||||
|
import RollDialog from "../roll/roll-dialog.mjs";
|
||||||
|
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE } from "../roll/roll-constants.mjs";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
||||||
@@ -407,6 +409,20 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
async rollCompetenceV2(rollData) {
|
||||||
|
foundry.utils.mergeObject(rollData, {
|
||||||
|
ids: {
|
||||||
|
actorId: this.id
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
allowed: [ROLL_TYPE_COMP, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION],
|
||||||
|
|
||||||
|
}
|
||||||
|
})
|
||||||
|
rollData.ids.actorId = rollData.ids.actorId ?? this.id
|
||||||
|
await RollDialog.create(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
|
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
|
||||||
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||||
const competence = this.getCompetence(idOrName);
|
const competence = this.getCompetence(idOrName);
|
||||||
@@ -449,6 +465,46 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rollAttaque(token) {
|
||||||
|
token = token ?? RdDUtility.getSelectedToken(this)
|
||||||
|
|
||||||
|
if (Targets.hasTargets()) {
|
||||||
|
Targets.selectOneTargetToken(target => {
|
||||||
|
if (Targets.isTargetEntite(target)) {
|
||||||
|
ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée!!!!`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
RdDCombat.rddCombatTarget(target, this, token).attaqueV2();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return RdDConfirm.confirmer({
|
||||||
|
settingConfirmer: "confirmer-combat-sans-cible",
|
||||||
|
content: `<p>Voulez vous faire une attaque sans choisir de cible valide?
|
||||||
|
<br>Tous les jets de combats devront être gérés à la main
|
||||||
|
</p>`,
|
||||||
|
title: 'Ne pas utiliser les automatisation de combat',
|
||||||
|
buttonLabel: "Pas d'automatisation",
|
||||||
|
onAction: async () => {
|
||||||
|
this.rollCompetenceV2({
|
||||||
|
ids: {
|
||||||
|
actorId: this.id,
|
||||||
|
actorTokenId: token?.id,
|
||||||
|
},
|
||||||
|
selected: {
|
||||||
|
conditions: { value: 0 }
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
allowed: [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE, ROLL_TYPE_JEU],
|
||||||
|
current: ROLL_TYPE_COMP
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** --------------------------------------------
|
/** --------------------------------------------
|
||||||
* @param {*} arme item d'arme/compétence de créature
|
* @param {*} arme item d'arme/compétence de créature
|
||||||
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
||||||
|
@@ -195,7 +195,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
|||||||
const endActuelle = this.getEnduranceActuelle();
|
const endActuelle = this.getEnduranceActuelle();
|
||||||
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken);
|
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken);
|
||||||
if (blessure.isCritique()) {
|
if (blessure.isCritique()) {
|
||||||
encaissement.endurance = endActuelle;
|
encaissement.endurance = endActuelle
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blessure.isMort()) {
|
if (blessure.isMort()) {
|
||||||
|
@@ -56,10 +56,8 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
|
|||||||
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
|
formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
|
||||||
.forEach(it => {
|
.forEach(it => it.isdommages = it.isDommages()
|
||||||
const competenceCreature = new RdDItemCompetenceCreature(it.toObject(), { parent: it.parent });
|
)
|
||||||
it.isdommages = competenceCreature.isDommages();
|
|
||||||
})
|
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
@@ -769,11 +769,15 @@ export class RdDBaseActor extends Actor {
|
|||||||
return this.itemTypes[ITEM_TYPES.possession]
|
return this.itemTypes[ITEM_TYPES.possession]
|
||||||
.map(p => {
|
.map(p => {
|
||||||
return {
|
return {
|
||||||
name: p.name,
|
label: p.name,
|
||||||
action: 'possession',
|
action: 'possession',
|
||||||
possessionid: p.system.possessionid,
|
possessionid: p.system.possessionid,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
listActionsCombat() {
|
||||||
|
const possessions = this.listActionsPossessions()
|
||||||
|
return possessions.length > 0 ? possessions : this.listActions({})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
@@ -33,26 +33,32 @@ export const RDD_CONFIG = {
|
|||||||
"blurette": "Blurette"
|
"blurette": "Blurette"
|
||||||
},
|
},
|
||||||
heuresRdD: [
|
heuresRdD: [
|
||||||
{value : "vaisseau", label: "Vaisseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd01.webp"},
|
{ value: "vaisseau", label: "Vaisseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp" },
|
||||||
{value : "sirene", label: "Sirène", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd02.webp"},
|
{ value: "sirene", label: "Sirène", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp" },
|
||||||
{value : "faucon", label: "Faucon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd03.webp"},
|
{ value: "faucon", label: "Faucon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp" },
|
||||||
{value : "couronne", label: "Couronne", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd04.webp"},
|
{ value: "couronne", label: "Couronne", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp" },
|
||||||
{value : "dragon", label: "Dragon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd05.webp"},
|
{ value: "dragon", label: "Dragon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp" },
|
||||||
{value : "epees", label: "Epées", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd06.webp"},
|
{ value: "epees", label: "Epées", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp" },
|
||||||
{value : "lyre", label: "Lyre", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd07.webp"},
|
{ value: "lyre", label: "Lyre", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp" },
|
||||||
{value : "serpent", label: "Serpent", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd08.webp"},
|
{ value: "serpent", label: "Serpent", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp" },
|
||||||
{value : "poissonacrobate", label: "Poisson Acrobate", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd09.webp"},
|
{ value: "poissonacrobate", label: "Poisson Acrobate", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp" },
|
||||||
{value : "araignee", label: "Araignée", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd10.webp"},
|
{ value: "araignee", label: "Araignée", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp" },
|
||||||
{value : "roseau", label: "Roseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd11.webp"},
|
{ value: "roseau", label: "Roseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp" },
|
||||||
{value : "chateaudormant", label: "Chateau Dormant", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd12.webp"}
|
{ value: "chateaudormant", label: "Chateau Dormant", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp" }
|
||||||
],
|
],
|
||||||
raretes: [
|
raretes: [
|
||||||
{ value: "Commune", label: "Commune" },
|
{ value: "Commune", label: "Commune" },
|
||||||
{ value: "Frequente", label: "Fréquente" },
|
{ value: "Frequente", label: "Fréquente" },
|
||||||
{ value: "Rare", label: "Rare" },
|
{ value: "Rare", label: "Rare" },
|
||||||
{ value: "Rarissime", label: "Rarissime" }
|
{ value: "Rarissime", label: "Rarissime" }
|
||||||
]
|
],
|
||||||
|
particuliere: {
|
||||||
|
force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg'},
|
||||||
|
finesse: { key: 'finesse', descr: 'en finesse', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-finesse.svg'},
|
||||||
|
rapidite: { key: 'finesse', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.svg'},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
export const ACTOR_TYPES = {
|
export const ACTOR_TYPES = {
|
||||||
personnage: 'personnage',
|
personnage: 'personnage',
|
||||||
@@ -109,13 +115,3 @@ export const ITEM_TYPES = {
|
|||||||
extraitpoetique: 'extraitpoetique',
|
extraitpoetique: 'extraitpoetique',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CATEGORIES_COMPETENCES = {
|
|
||||||
"generale": { base: -4, label: "Générales" },
|
|
||||||
"particuliere": { base: -8, label: "Particulières" },
|
|
||||||
"specialisee": { base: -11, label: "Spécialisées" },
|
|
||||||
"connaissance": { base: -11, label: "Connaissances" },
|
|
||||||
"draconic": { base: -11, label: "Draconic" },
|
|
||||||
"melee": { base: -6, label: "Mêlée" },
|
|
||||||
"tir": { base: -8, label: "Tir" },
|
|
||||||
"lancer": { base: -8, label: "Lancer" }
|
|
||||||
}
|
|
||||||
|
@@ -1,7 +1,65 @@
|
|||||||
|
export const MAP_PHASE = {
|
||||||
|
possession: { label: "possession", rang: 10 },
|
||||||
|
draconic: { label: "draconic", rang: 9 },
|
||||||
|
tir: { label: "tir", rang: 8 },
|
||||||
|
lancer: { label: "lancer", rang: 7 },
|
||||||
|
arme: { label: "mêlée", rang: 5 },
|
||||||
|
pugilat: { label: "pugilat", rang: 4 },
|
||||||
|
naturelle: { label: "créature", rang: 4 },
|
||||||
|
empoignade: { label: "empoignade", rang: 3 },
|
||||||
|
autre: { label: "autre action", rang: 2 },
|
||||||
|
demi: { label: "demi-surprise", rang: 0 },
|
||||||
|
totale: { label: "surprise totale", rang: -1 },
|
||||||
|
}
|
||||||
|
export const PHASE = Object.values(MAP_PHASE)
|
||||||
|
|
||||||
export class RdDInitiative {
|
export class RdDInitiative {
|
||||||
|
|
||||||
static calculInitiative(niveau, caracValue, bonus = 0) {
|
static getRollInitiative(caracValue, niveau, bonus = 0) {
|
||||||
let base = niveau + Math.floor(caracValue / 2) + bonus;
|
const base = RdDInitiative.ajustementInitiative(caracValue, niveau, bonus)
|
||||||
return "1d6" + (base >= 0 ? "+" : "") + base;
|
return "1d6" + (base >= 0 ? "+" : "") + base
|
||||||
|
}
|
||||||
|
|
||||||
|
static ajustementInitiative(caracValue, niveau, bonus) {
|
||||||
|
return niveau + Math.floor(caracValue / 2) + bonus
|
||||||
|
}
|
||||||
|
|
||||||
|
static formule(phase, carac, niveau, bonusMalus) {
|
||||||
|
const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus)
|
||||||
|
return { phase, ajustement }
|
||||||
|
}
|
||||||
|
|
||||||
|
static phaseArme(categorie, arme) {
|
||||||
|
switch (categorie) {
|
||||||
|
case "tir":
|
||||||
|
case "lancer":
|
||||||
|
return MAP_PHASE[categorie]
|
||||||
|
default:
|
||||||
|
switch (arme.system.cac) {
|
||||||
|
case "empoignade":
|
||||||
|
case "pugilat":
|
||||||
|
case "naturelle":
|
||||||
|
return MAP_PHASE[arme.system.cac]
|
||||||
|
default:
|
||||||
|
return MAP_PHASE['arme']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static phase(keyOrRang) {
|
||||||
|
return MAP_PHASE[keyOrRang] ?? PHASE.find(it => it.rang == keyOrRang) ?? MAP_PHASE.autre
|
||||||
|
}
|
||||||
|
|
||||||
|
static async roll(formule) {
|
||||||
|
const sign = formule.ajustement >= 0 ? "+" : ""
|
||||||
|
const roll = new Roll(`1d6 + ${sign} + ${formule.ajustement}`)
|
||||||
|
await roll.evaluate()
|
||||||
|
const value = Math.max(roll.total, 0)
|
||||||
|
return {
|
||||||
|
roll: roll,
|
||||||
|
value: value,
|
||||||
|
init: formule.phase.rang + value / 100,
|
||||||
|
label: formule.phase.label
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,15 +10,15 @@ export class RdDItemCompetenceCreature extends RdDItem {
|
|||||||
|
|
||||||
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
|
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
|
||||||
|
|
||||||
|
isAttaque() { return this.getCategorieAttaque() != undefined }
|
||||||
isParade() { return this.system.iscombat && (this.system.categorie_parade ?? '') != '' }
|
isParade() { return this.system.iscombat && (this.system.categorie_parade ?? '') != '' }
|
||||||
isBouclier() { return this.system.categorie_parade.includes('bouclier') }
|
isBouclier() { return this.system.categorie_parade.includes('bouclier') }
|
||||||
|
|
||||||
attaqueCreature() {
|
attaqueCreature() {
|
||||||
const categorieAttaque = this.getCategorieAttaque()
|
const categorieAttaque = this.getCategorieAttaque()
|
||||||
if (categorieAttaque != undefined) {
|
if (categorieAttaque != undefined) {
|
||||||
const initative = RdDInitiative.calculInitiative(this.system.niveau, this.system.carac_value);
|
const initative = RdDInitiative.getRollInitiative(this.system.carac_value, this.system.niveau);
|
||||||
const attaque = {
|
const attaque = {
|
||||||
name: this.name,
|
label: this.name,
|
||||||
action: this.isCompetencePossession() ? 'possession' : 'attaque',
|
action: this.isCompetencePossession() ? 'possession' : 'attaque',
|
||||||
initOnly: false,
|
initOnly: false,
|
||||||
arme: new RdDItemArme({
|
arme: new RdDItemArme({
|
||||||
@@ -51,10 +51,6 @@ export class RdDItemCompetenceCreature extends RdDItem {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
isAttaque() {
|
|
||||||
return this.getCategorieAttaque() != undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
getCategorieAttaque() {
|
getCategorieAttaque() {
|
||||||
switch (this.system.categorie) {
|
switch (this.system.categorie) {
|
||||||
case "melee":
|
case "melee":
|
||||||
|
@@ -21,6 +21,7 @@ const nomCategorieParade = {
|
|||||||
export const ATTAQUE_TYPE = {
|
export const ATTAQUE_TYPE = {
|
||||||
UNE_MAIN: '(1 main)',
|
UNE_MAIN: '(1 main)',
|
||||||
DEUX_MAINS: '(2 mains)',
|
DEUX_MAINS: '(2 mains)',
|
||||||
|
CORPS_A_CORPS: '(corps à corps)',
|
||||||
COMPETENCE: 'competence',
|
COMPETENCE: 'competence',
|
||||||
TIR: '(tir)',
|
TIR: '(tir)',
|
||||||
LANCER: '(lancer)'
|
LANCER: '(lancer)'
|
||||||
@@ -244,7 +245,7 @@ export class RdDItemArme extends RdDItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
isAttaque() {
|
isAttaque() {
|
||||||
return this.system.resistance > 0 || this.system.portee_courte > 0
|
return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
static corpsACorps(actor) {
|
static corpsACorps(actor) {
|
||||||
@@ -256,7 +257,7 @@ export class RdDItemArme extends RdDItem {
|
|||||||
type: ITEM_TYPES.arme,
|
type: ITEM_TYPES.arme,
|
||||||
img: competence.img,
|
img: competence.img,
|
||||||
system: {
|
system: {
|
||||||
initiative: RdDInitiative.calculInitiative(competence.system.niveau, melee),
|
initiative: RdDInitiative.getRollInitiative(melee, competence.system.niveau),
|
||||||
equipe: true,
|
equipe: true,
|
||||||
rapide: true,
|
rapide: true,
|
||||||
force: 0,
|
force: 0,
|
||||||
@@ -273,10 +274,10 @@ export class RdDItemArme extends RdDItem {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static mainsNues(actor) {
|
static pugilat(actor) {
|
||||||
const mainsNues = RdDItemArme.corpsACorps(actor)
|
const pugilat = RdDItemArme.corpsACorps(actor)
|
||||||
mainsNues.name = 'Mains nues'
|
pugilat.name = 'Mains nues'
|
||||||
return mainsNues;
|
return pugilat;
|
||||||
}
|
}
|
||||||
|
|
||||||
static empoignade(actor) {
|
static empoignade(actor) {
|
||||||
|
@@ -3,7 +3,6 @@ import { RdDInitiative } from "../initiative.mjs";
|
|||||||
|
|
||||||
export class MappingCreatureArme {
|
export class MappingCreatureArme {
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static setRollDataCreature(rollData) {
|
static setRollDataCreature(rollData) {
|
||||||
const code = Grammar.toLowerCaseNoAccentNoSpace(rollData.competence.name);
|
const code = Grammar.toLowerCaseNoAccentNoSpace(rollData.competence.name);
|
||||||
@@ -26,7 +25,7 @@ export class MappingCreatureArme {
|
|||||||
competence: item.name,
|
competence: item.name,
|
||||||
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
|
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
|
||||||
niveau: item.system.niveau,
|
niveau: item.system.niveau,
|
||||||
initiative: RdDInitiative.calculInitiative(item.system.niveau, item.system.carac_value),
|
initiative: RdDInitiative.getRollInitiative(item.system.carac_value, item.system.niveau),
|
||||||
equipe: true,
|
equipe: true,
|
||||||
resistance: 100,
|
resistance: 100,
|
||||||
dommagesReels: item.system.dommages,
|
dommagesReels: item.system.dommages,
|
||||||
|
@@ -35,8 +35,12 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inRange(value, min, max) {
|
static inRange(value, min, max) {
|
||||||
|
if (min > max) {
|
||||||
|
return Misc.inRange(value, max, min)
|
||||||
|
}
|
||||||
return Math.max(min, Math.min(value, max))
|
return Math.max(min, Math.min(value, max))
|
||||||
}
|
}
|
||||||
|
|
||||||
static sum() {
|
static sum() {
|
||||||
return (a, b) => Number(a) + Number(b);
|
return (a, b) => Number(a) + Number(b);
|
||||||
}
|
}
|
||||||
@@ -111,6 +115,10 @@ export class Misc {
|
|||||||
list.forEach(it => addToObj(obj, it))
|
list.forEach(it => addToObj(obj, it))
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
static indexed(list, index = 'index') {
|
||||||
|
let i = 0;
|
||||||
|
return list.map(it => { it[index] = i++; return it })
|
||||||
|
}
|
||||||
|
|
||||||
static concat(lists) {
|
static concat(lists) {
|
||||||
return lists.reduce((a, b) => a.concat(b), []);
|
return lists.reduce((a, b) => a.concat(b), []);
|
||||||
|
@@ -56,9 +56,8 @@ export class RdDBonus {
|
|||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static dmgRollV2(rollData, current) {
|
static dmgRollV2(rollData, attaque) {
|
||||||
const actor = rollData.active.actor
|
const actor = rollData.active.actor
|
||||||
const attaque = current.attaque
|
|
||||||
const arme = attaque.arme
|
const arme = attaque.arme
|
||||||
const dmgArme = RdDBonus.dmgArme(arme, attaque.dommagesArme)
|
const dmgArme = RdDBonus.dmgArme(arme, attaque.dommagesArme)
|
||||||
const dmg = {
|
const dmg = {
|
||||||
@@ -66,10 +65,10 @@ export class RdDBonus {
|
|||||||
dmgArme: dmgArme,
|
dmgArme: dmgArme,
|
||||||
penetration: arme.penetration(),
|
penetration: arme.penetration(),
|
||||||
diff: attaque.diff,
|
diff: attaque.diff,
|
||||||
dmgTactique: current.tactique?.dmg ?? 0,
|
dmgTactique: attaque.tactique?.dmg ?? 0,
|
||||||
dmgParticuliere: 0, // TODO RdDBonus._dmgParticuliere(rollData),
|
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
|
||||||
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
|
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
|
||||||
mortalite: RdDBonus.mortalite(current.dmg?.mortalite, arme.system.mortalite, rollData.opponent?.actor?.isEntite()),
|
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme.system.mortalite, rollData.opponent?.actor?.isEntite()),
|
||||||
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise),
|
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise),
|
||||||
dmgForceInsuffisante: Math.min(0, actor.getForce() - attaque.forceRequise),
|
dmgForceInsuffisante: Math.min(0, actor.getForce() - attaque.forceRequise),
|
||||||
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
|
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
|
||||||
|
@@ -12,13 +12,14 @@ import { RdDEmpoignade } from "./rdd-empoignade.js";
|
|||||||
import { RdDRollResult } from "./rdd-roll-result.js";
|
import { RdDRollResult } from "./rdd-roll-result.js";
|
||||||
import { RdDItemArme } from "./item/arme.js";
|
import { RdDItemArme } from "./item/arme.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDInitiative } from "./initiative.mjs";
|
import { MAP_PHASE, RdDInitiative } from "./initiative.mjs";
|
||||||
import RollDialog from "./roll/roll-dialog.mjs";
|
import RollDialog from "./roll/roll-dialog.mjs";
|
||||||
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
|
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
|
||||||
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
|
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
|
||||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
|
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
|
||||||
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
|
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
|
||||||
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
|
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
|
||||||
|
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const premierRoundInit = [
|
const premierRoundInit = [
|
||||||
@@ -67,7 +68,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (Misc.isFirstConnectedGM()) {
|
if (Misc.isFirstConnectedGM()) {
|
||||||
await this.finDeRound({ terminer: true })
|
await this.finDeRound({ terminer: true })
|
||||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`)
|
ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`)
|
||||||
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
game.messages.filter(m => ChatUtility.getMessageData(m, 'rollData') != undefined && ChatUtility.getMessageData(m, 'rollData') != undefined)
|
||||||
.forEach(it => it.delete())
|
.forEach(it => it.delete())
|
||||||
RdDEmpoignade.deleteAllEmpoignades()
|
RdDEmpoignade.deleteAllEmpoignades()
|
||||||
}
|
}
|
||||||
@@ -106,13 +107,15 @@ export class RdDCombatManager extends Combat {
|
|||||||
return combatant.actor
|
return combatant.actor
|
||||||
}
|
}
|
||||||
|
|
||||||
static calculAjustementInit(actor, arme) {
|
static bonusArme(arme) {
|
||||||
const efficacite = (arme?.system.magique) ? arme.system.ecaille_efficacite : 0
|
return (arme?.system.magique) ? arme.system.ecaille_efficacite : 0
|
||||||
const etatGeneral = actor.getEtatGeneral() ?? 0
|
|
||||||
return efficacite + etatGeneral
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static etatGeneral(actor) {
|
||||||
|
return actor.getEtatGeneral() ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/************************************************************************************/
|
/************************************************************************************/
|
||||||
async rollInitiative(ids, messageOptions = {}) {
|
async rollInitiative(ids, messageOptions = {}) {
|
||||||
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, messageOptions)
|
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, messageOptions)
|
||||||
@@ -121,18 +124,17 @@ export class RdDCombatManager extends Combat {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
async rollInitRdD(id, formula, messageOptions = {}) {
|
async rollInitRdD(id, formule, messageOptions = {}) {
|
||||||
const combatant = this.combatants.get(id);
|
const combatant = this.combatants.get(id);
|
||||||
const actor = RdDCombatManager.getActorCombatant(combatant)
|
const actor = RdDCombatManager.getActorCombatant(combatant)
|
||||||
if (actor) {
|
if (actor) {
|
||||||
const rollFormula = formula ?? RdDCombatManager.getFirstInitRollFormula(actor)
|
formule = formule ?? RdDCombatManager.getFirstInitRollFormula(actor)
|
||||||
const roll = combatant.getInitiativeRoll(rollFormula);
|
const init = await RdDInitiative.roll(formule)
|
||||||
if (!roll.total) {
|
|
||||||
await roll.evaluate();
|
await this.updateEmbeddedDocuments("Combatant", [{
|
||||||
}
|
_id: combatant._id || combatant.id,
|
||||||
const total = Math.max(roll.total, 0.00);
|
initiative: init.init, 'system.init': init
|
||||||
console.log("Compute init for", rollFormula, roll, total, combatant);
|
}])
|
||||||
await this.updateEmbeddedDocuments("Combatant", [{ _id: combatant._id || combatant.id, initiative: total }]);
|
|
||||||
|
|
||||||
// Send a chat message
|
// Send a chat message
|
||||||
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
||||||
@@ -147,7 +149,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
flavor: `${combatant.token?.name} a fait son jet d'Initiative (${messageOptions.info})<br>`
|
flavor: `${combatant.token?.name} a fait son jet d'Initiative (${messageOptions.info})<br>`
|
||||||
},
|
},
|
||||||
messageOptions);
|
messageOptions);
|
||||||
roll.toMessage(messageData, { rollMode, create: true });
|
init.roll.toMessage(messageData, { rollMode, create: true });
|
||||||
|
|
||||||
RdDCombatManager.processPremierRoundInit();
|
RdDCombatManager.processPremierRoundInit();
|
||||||
}
|
}
|
||||||
@@ -159,16 +161,11 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (actions.length > 0) {
|
if (actions.length > 0) {
|
||||||
const action = actions[0]
|
const action = actions[0]
|
||||||
const init = RdDCombatManager.getInitData(actor, action)
|
const init = RdDCombatManager.getInitData(actor, action)
|
||||||
const ajustement = RdDCombatManager.calculAjustementInit(actor, action)
|
const ajustement = RdDCombatManager.bonusArme(action.arme) + RdDCombatManager.etatGeneral(actor)
|
||||||
return RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
|
return RdDInitiative.formule(init.phase, init.carac, init.niveau, ajustement);
|
||||||
}
|
}
|
||||||
|
|
||||||
let ajustement = RdDCombatManager.calculAjustementInit(actor, undefined);
|
return RdDInitiative.formule(MAP_PHASE['autre'], 10, 0, actor.getEtatGeneral() ?? 0);
|
||||||
return RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
|
|
||||||
}
|
|
||||||
|
|
||||||
static formuleInitiative(rang, carac, niveau, bonusMalus) {
|
|
||||||
return `${rang} +( (${RdDInitiative.calculInitiative(niveau, carac, bonusMalus)} )/100)`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -180,7 +177,6 @@ export class RdDCombatManager extends Combat {
|
|||||||
for (let combatant of game.combat.combatants) {
|
for (let combatant of game.combat.combatants) {
|
||||||
if (combatant.initiativeData?.arme?.type == "arme") {
|
if (combatant.initiativeData?.arme?.type == "arme") {
|
||||||
// TODO: get init data premier round
|
// TODO: get init data premier round
|
||||||
const initiativeData = combatant.initiativeData;
|
|
||||||
const action = combatant.initiativeData.arme;
|
const action = combatant.initiativeData.arme;
|
||||||
const fromArme = Grammar.toLowerCaseNoAccentNoSpace(action.system.initpremierround)
|
const fromArme = Grammar.toLowerCaseNoAccentNoSpace(action.system.initpremierround)
|
||||||
const initData = premierRoundInit.find(it => fromArme.includes(initData.pattern))
|
const initData = premierRoundInit.find(it => fromArme.includes(initData.pattern))
|
||||||
@@ -200,10 +196,27 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static incDecInit(combatantId, incDecValue) {
|
|
||||||
const combatant = game.combat.combatants.get(combatantId);
|
static applyInitiativeCommand(combatantId, command, commandValue) {
|
||||||
let initValue = combatant.initiative + incDecValue;
|
switch (command) {
|
||||||
game.combat.setInitiative(combatantId, initValue);
|
case 'delta': return RdDCombatManager.incDecInit(combatantId, commandValue);
|
||||||
|
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
|
||||||
|
{ name: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async incDecInit(combatantId, incDecValue) {
|
||||||
|
const combatant = game.combat.combatants.get(combatantId)
|
||||||
|
if (combatant?.initiative && incDecValue != 0) {
|
||||||
|
const value = combatant.system.init.value + incDecValue
|
||||||
|
const newInit = combatant.initiative + incDecValue / 100;
|
||||||
|
await game.combat.updateEmbeddedDocuments("Combatant", [{
|
||||||
|
_id: combatantId,
|
||||||
|
initiative: newInit,
|
||||||
|
'system.init.value': value,
|
||||||
|
'system.init.init': newInit,
|
||||||
|
}])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -220,56 +233,42 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
options = [
|
options = [
|
||||||
{ name: "Incrémenter initiative", condition: true, icon: '<i class="fa-solid fa-plus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), +0.01); } },
|
{ name: "Incrémenter initiative", condition: true, icon: '<i class="fa-solid fa-plus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), +1); } },
|
||||||
{ name: "Décrémenter initiative", condition: true, icon: '<i class="fa-solid fa-minus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), -0.01); } }
|
{ name: "Décrémenter initiative", condition: true, icon: '<i class="fa-solid fa-minus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), -1); } }
|
||||||
].concat(options);
|
].concat(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async rollInitiativeAction(combatantId, action) {
|
static async rollInitiativeAction(combatantId, action) {
|
||||||
const combatant = game.combat.combatants.get(combatantId)
|
const combatant = game.combat.combatants.get(combatantId)
|
||||||
const actor = RdDCombatManager.getActorCombatant(combatant)
|
const actor = RdDCombatManager.getActorCombatant(combatant)
|
||||||
if (actor == undefined) { return [] }
|
|
||||||
|
|
||||||
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
|
if (actor == undefined) { return }
|
||||||
|
|
||||||
const init = RdDCombatManager.getInitData(actor, action)
|
const init = RdDCombatManager.getInitData(actor, action)
|
||||||
const ajustement = RdDCombatManager.calculAjustementInit(actor, action.arme)
|
const ajustement = RdDCombatManager.bonusArme(actor, action.arme) + RdDCombatManager.etatGeneral(actor)
|
||||||
const rollFormula = RdDCombatManager.formuleInitiative(init.offset, init.carac, init.niveau, ajustement);
|
const formule = RdDInitiative.formule(init.phase, init.carac, init.niveau, ajustement);
|
||||||
|
|
||||||
await game.combat.rollInitRdD(combatantId, rollFormula, init);
|
await game.combat.rollInitRdD(combatantId, formule, init);
|
||||||
combatant.initiativeData
|
combatant.initiativeData = { action, formule } // pour reclasser l'init au round 0
|
||||||
}
|
}
|
||||||
|
|
||||||
static getInitData(actor, action) {
|
static getInitData(actor, action) {
|
||||||
if (actor.getSurprise() == "totale") { return { offset: -1, info: "Surprise Totale", carac: 0, niveau: 0 } }
|
if (actor.getSurprise() == "totale") { return { phase: MAP_PHASE['totale'], info: "Surprise Totale", carac: 0, niveau: 0 } }
|
||||||
if (actor.getSurprise() == "demi") { return { offset: 0, info: "Demi Surprise", carac: 0, niveau: 0 } }
|
if (actor.getSurprise() == "demi") { return { phase: MAP_PHASE['demi'], info: "Demi Surprise", carac: 0, niveau: 0 } }
|
||||||
if (action.action == 'autre') { return { offset: 2, info: "Autre Action", carac: 0, niveau: 0 } }
|
if (action.action == 'autre') { return { phase: MAP_PHASE['autre'], info: "Autre Action", carac: 0, niveau: 0 } }
|
||||||
if (action.action == 'possession') { return { offset: 10, info: "Possession", carac: actor.getReveActuel(), niveau: 0 } }
|
if (action.action == 'possession') { return { phase: MAP_PHASE['possession'], info: "Possession", carac: actor.getReveActuel(), niveau: 0 } }
|
||||||
if (action.action == 'haut-reve') { return { offset: 9, info: "Draconic", carac: actor.getReveActuel(), niveau: 0 } }
|
if (action.action == 'haut-reve') { return { phase: MAP_PHASE['draconic'], info: "Draconic", carac: actor.getReveActuel(), niveau: 0 } }
|
||||||
|
|
||||||
const comp = action.comp
|
const comp = action.comp
|
||||||
return {
|
return {
|
||||||
offset: RdDCombatManager.initOffset(comp?.system.categorie, action.arme),
|
phase: RdDInitiative.phaseArme(comp?.system.categorie, action.arme),
|
||||||
info: action.name + " / " + comp.name,
|
info: action.name + " / " + comp.name,
|
||||||
carac: actor.getCaracInit(comp),
|
carac: actor.getCaracInit(comp),
|
||||||
niveau: comp?.system.niveau ?? (['(lancer)', '(tir)'].includes(action.main) ? -8 : -6)
|
niveau: comp?.system.niveau ?? (['(lancer)', '(tir)'].includes(action.main) ? -8 : -6)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static initOffset(categorie, arme) {
|
|
||||||
switch (categorie) {
|
|
||||||
case "tir": return 8
|
|
||||||
case "lancer": return 7
|
|
||||||
default:
|
|
||||||
switch (arme.system.cac) {
|
|
||||||
case "empoignade": return 3
|
|
||||||
case "pugilat": return 4
|
|
||||||
case "naturelle": return 4
|
|
||||||
default: return 5
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static displayInitiativeMenu(html, combatantId) {
|
static displayInitiativeMenu(html, combatantId) {
|
||||||
const combatant = game.combat.combatants.get(combatantId)
|
const combatant = game.combat.combatants.get(combatantId)
|
||||||
@@ -297,13 +296,8 @@ export class RdDCombatManager extends Combat {
|
|||||||
? possessions
|
? possessions
|
||||||
: actor.listActions({ isEquipe: true })
|
: actor.listActions({ isEquipe: true })
|
||||||
|
|
||||||
for (let index = 0; index < actions.length; index++) {
|
return Misc.indexed(actions)
|
||||||
actions[index].index = index
|
|
||||||
}
|
}
|
||||||
return actions
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -383,10 +377,15 @@ export class RdDCombat {
|
|||||||
let defenderToken = canvas.tokens.get(msg.defenderToken.id)
|
let defenderToken = canvas.tokens.get(msg.defenderToken.id)
|
||||||
if (defenderToken && Misc.isFirstConnectedGM()) {
|
if (defenderToken && Misc.isFirstConnectedGM()) {
|
||||||
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
|
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
|
||||||
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme)
|
rddCombat?.removeChatMessageActionsPasseArme(msg.paramChatDefense.attackerRoll.passeArme)
|
||||||
|
if (msg.defenderRoll.ids) {/* TODO: delete roll V1 */
|
||||||
|
RollDialog.loadRollData(msg.paramChatDefense)
|
||||||
|
rddCombat?._chatMessageDefenseV2(msg.paramChatDefense)
|
||||||
|
} else {
|
||||||
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll)
|
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _callJetDeVie(event) {
|
static _callJetDeVie(event) {
|
||||||
@@ -464,8 +463,8 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onEvent(button, event) {
|
async onEvent(button, event) {
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
const defenderRoll = ChatUtility.getMessageData(chatMessage, 'defender-roll');
|
const defenderRoll = ChatUtility.getMessageData(chatMessage, 'rollData');
|
||||||
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'attacker-roll');
|
const attackerRoll = defenderRoll?.attackerRoll ?? ChatUtility.getMessageData(chatMessage, 'rollData');
|
||||||
console.log('RdDCombat', attackerRoll, defenderRoll);
|
console.log('RdDCombat', attackerRoll, defenderRoll);
|
||||||
|
|
||||||
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
|
const armeParadeId = event.currentTarget.attributes['data-armeid']?.value;
|
||||||
@@ -665,6 +664,92 @@ export class RdDCombat {
|
|||||||
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 };
|
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async attaqueV2() {
|
||||||
|
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await this.doRollAttaque({
|
||||||
|
ids: {
|
||||||
|
actorId: this.attackerId,
|
||||||
|
actorTokenId: this.attackerTokenId,
|
||||||
|
opponentId: this.defender.id,
|
||||||
|
opponentTokenId: this.defenderTokenId,
|
||||||
|
},
|
||||||
|
type: { allowed: ['attaque'], current: 'attaque' },
|
||||||
|
passeArme: foundry.utils.randomID(16),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async doRollAttaque(rollData, callbacks = []) {
|
||||||
|
// TODO V2 await this.proposerAjustementTirLancer(rollData)
|
||||||
|
await RollDialog.create(rollData, {
|
||||||
|
onRollDone: (dialog) => {
|
||||||
|
if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
|
||||||
|
dialog.close()
|
||||||
|
},
|
||||||
|
customChatMessage: true,
|
||||||
|
callbacks: [
|
||||||
|
async (roll) => await this.onAttaqueV2(roll),
|
||||||
|
...callbacks
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAttaqueV2(attackerRoll) {
|
||||||
|
if (!this.defender || !attackerRoll.rolled.isSuccess || attackerRoll.particulieres?.length > 1) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!await this.attacker.accorder(this.defender, 'avant-defense')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RollDialog.loadRollData(attackerRoll)
|
||||||
|
|
||||||
|
const surpriseDefender = this.defender.getSurprise(true);
|
||||||
|
const paramChatDefense = {
|
||||||
|
attackerRoll: attackerRoll,
|
||||||
|
isPossession: this.isPossession(attackerRoll),
|
||||||
|
defender: this.defender,
|
||||||
|
attacker: this.attacker,
|
||||||
|
attackerId: this.attackerId,
|
||||||
|
attackerToken: this.attackerToken,
|
||||||
|
defenderToken: this.defenderToken,
|
||||||
|
surprise: surpriseDefender,
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Misc.isFirstConnectedGM()) {
|
||||||
|
await this._chatMessageDefenseV2(paramChatDefense);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._socketSendMessageDefense(paramChatDefense, {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async _chatMessageDefenseV2(paramDemandeDefense) {
|
||||||
|
const attackerRoll = paramDemandeDefense.attackerRoll;
|
||||||
|
RollBasicParts.loadSurprises(attackerRoll)
|
||||||
|
attackerRoll.passeArme = attackerRoll.passeArme ?? foundry.utils.randomID(16)
|
||||||
|
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
|
||||||
|
// attackerRoll.current.attaque.dmg = attackerRoll.dmg
|
||||||
|
// attaque.dmg = attackerRoll.current.attaque.dmg
|
||||||
|
const attaque = RollDialog.saveParts(attackerRoll)
|
||||||
|
const defense = {
|
||||||
|
attackerRoll: attaque,
|
||||||
|
ids: RollBasicParts.reverseIds(attaque),
|
||||||
|
passeArme: attaque.passeArme ?? foundry.utils.randomID(16)
|
||||||
|
}
|
||||||
|
|
||||||
|
const choixDefense = await ChatMessage.create({
|
||||||
|
// message privé: du défenseur à lui même (et aux GMs)
|
||||||
|
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
||||||
|
alias: this.attacker?.getAlias(),
|
||||||
|
whisper: ChatUtility.getOwners(this.defender),
|
||||||
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', attackerRoll)
|
||||||
|
});
|
||||||
|
// flag pour garder les jets d'attaque/defense
|
||||||
|
ChatUtility.setMessageData(choixDefense, 'rollData', defense)
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async attaque(competence, arme) {
|
async attaque(competence, arme) {
|
||||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||||
@@ -725,7 +810,7 @@ export class RdDCombat {
|
|||||||
// sans armes: à mains nues
|
// sans armes: à mains nues
|
||||||
rollData.arme = RdDItemArme.corpsACorps(this.attacker)
|
rollData.arme = RdDItemArme.corpsACorps(this.attacker)
|
||||||
rollData.arme.system.niveau = competence.system.niveau
|
rollData.arme.system.niveau = competence.system.niveau
|
||||||
rollData.arme.system.initiative = RdDInitiative.calculInitiative(competence.system.niveau, this.attacker.system.carac['melee'].value);
|
rollData.arme.system.initiative = RdDInitiative.getRollInitiative(this.attacker.system.carac['melee'].value, competence.system.niveau);
|
||||||
}
|
}
|
||||||
return rollData;
|
return rollData;
|
||||||
}
|
}
|
||||||
@@ -776,7 +861,7 @@ export class RdDCombat {
|
|||||||
passeArme: rollData.passeArme
|
passeArme: rollData.passeArme
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
ChatUtility.setMessageData(choixParticuliere, 'attacker-roll', rollData);
|
ChatUtility.setMessageData(choixParticuliere, 'rollData', rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -852,10 +937,10 @@ export class RdDCombat {
|
|||||||
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
|
||||||
alias: this.attacker?.getAlias(),
|
alias: this.attacker?.getAlias(),
|
||||||
whisper: ChatUtility.getOwners(this.defender),
|
whisper: ChatUtility.getOwners(this.defender),
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', paramDemandeDefense),
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-v1.hbs', paramDemandeDefense),
|
||||||
});
|
});
|
||||||
// flag pour garder les jets d'attaque/defense
|
// flag pour garder les jets d'attaque/defense
|
||||||
ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll);
|
ChatUtility.setMessageData(choixDefense, 'rollData', defenderRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -869,7 +954,7 @@ export class RdDCombat {
|
|||||||
defenderToken: this.defenderToken,
|
defenderToken: this.defenderToken,
|
||||||
defenderRoll: defenderRoll,
|
defenderRoll: defenderRoll,
|
||||||
paramChatDefense: paramChatDefense,
|
paramChatDefense: paramChatDefense,
|
||||||
rollMode: true
|
rollMode: true,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -906,7 +991,7 @@ export class RdDCombat {
|
|||||||
essais: attackerRoll.essais
|
essais: attackerRoll.essais
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
ChatUtility.setMessageData(choixEchecTotal, 'attacker-roll', attackerRoll);
|
ChatUtility.setMessageData(choixEchecTotal, 'rollData', attackerRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -968,6 +1053,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
async defenseV2(attackerRoll) {
|
async defenseV2(attackerRoll) {
|
||||||
// this._prepareParade(attackerRoll, arme, competence);
|
// this._prepareParade(attackerRoll, arme, competence);
|
||||||
|
RollDialog.loadRollData(attackerRoll)
|
||||||
await this.doRollDefense({
|
await this.doRollDefense({
|
||||||
ids: {
|
ids: {
|
||||||
actorId: this.defender.id,
|
actorId: this.defender.id,
|
||||||
@@ -1034,22 +1120,17 @@ export class RdDCombat {
|
|||||||
if (RdDCombat.isReussite(rollData)) {
|
if (RdDCombat.isReussite(rollData)) {
|
||||||
if (isParade) {
|
if (isParade) {
|
||||||
await this.computeDeteriorationArme(rollData)
|
await this.computeDeteriorationArme(rollData)
|
||||||
|
if (RdDCombat.isParticuliere(rollData)) {
|
||||||
|
await this.infoAttaquantDesarme(rollData)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (RdDCombat.isParticuliere(rollData)) {
|
|
||||||
await this._onDefenseParticuliere(rollData, isEsquive)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.removeChatMessageActionsPasseArme(rollData.passeArme)
|
this.removeChatMessageActionsPasseArme(rollData.passeArme)
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onDefenseParticuliere(rollData, isEsquive) {
|
async infoAttaquantDesarme(rollData) {
|
||||||
if (isEsquive) {
|
if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) {
|
||||||
ChatUtility.createChatWithRollMode(
|
|
||||||
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
|
|
||||||
this.defender)
|
|
||||||
}
|
|
||||||
else if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) {
|
|
||||||
// TODO: attaquant doit jouer résistance et peut être désarmé p132
|
// TODO: attaquant doit jouer résistance et peut être désarmé p132
|
||||||
ChatUtility.createChatWithRollMode(
|
ChatUtility.createChatWithRollMode(
|
||||||
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
|
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
|
||||||
|
@@ -67,9 +67,9 @@ export class RdDResolutionTable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _computeCell(niveau, percentage) {
|
static _computeCell(level, percentage) {
|
||||||
return {
|
return {
|
||||||
niveau: niveau,
|
level: level,
|
||||||
score: percentage,
|
score: percentage,
|
||||||
norm: Math.min(99, percentage),
|
norm: Math.min(99, percentage),
|
||||||
sign: this._reussiteSignificative(percentage),
|
sign: this._reussiteSignificative(percentage),
|
||||||
@@ -189,7 +189,7 @@ export class RdDResolutionTable {
|
|||||||
static computeReussite(chances, roll, diviseur) {
|
static computeReussite(chances, roll, diviseur) {
|
||||||
const reussite = reussites.find(x => x.condition(chances, roll))
|
const reussite = reussites.find(x => x.condition(chances, roll))
|
||||||
if (diviseur > 1 && reussite.isSuccess) {
|
if (diviseur > 1 && reussite.isSuccess) {
|
||||||
if (chances > roll * diviseur) {
|
if (chances.norm < roll * diviseur) {
|
||||||
return reussiteInsuffisante
|
return reussiteInsuffisante
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "./constants.js";
|
import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "./constants.js";
|
||||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
import { RollDataAjustements } from "./rolldata-ajustements-v1.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { COORD_TMR_INCONNU, TMRUtility } from "./tmr-utility.js";
|
import { COORD_TMR_INCONNU, TMRUtility } from "./tmr-utility.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
|
@@ -1,7 +1,9 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
import { renderTemplate } from "./constants.js";
|
import { renderTemplate } from "./constants.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
||||||
import { Targets } from "./targets.js";
|
import { Targets } from "./targets.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -31,43 +33,86 @@ export class RdDTokenHud {
|
|||||||
const combatant = game.combat.combatants.find(c => c.tokenId == tokenId)
|
const combatant = game.combat.combatants.find(c => c.tokenId == tokenId)
|
||||||
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
|
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
|
||||||
if (actor) {
|
if (actor) {
|
||||||
|
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||||
|
await RdDTokenHud.addExtensionHudCombat(html, combatant, actor, token)
|
||||||
|
}
|
||||||
|
else {
|
||||||
const actions = RdDCombatManager.listActionsActorCombatant(actor)
|
const actions = RdDCombatManager.listActionsActorCombatant(actor)
|
||||||
// initiative
|
// initiative
|
||||||
await RdDTokenHud.addExtensionHudInit(html, combatant, actions)
|
await RdDTokenHud.addExtensionHudInit(html, combatant, actions)
|
||||||
// combat
|
// combat
|
||||||
await RdDTokenHud.addExtensionHudCombat(html, combatant, token, actions.filter(it => !it.initOnly))
|
await RdDTokenHud.addExtensionHudAttaques(html, combatant, token, actions.filter(it => !it.initOnly))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async addExtensionHudCombat(html, combatant, actor, token) {
|
||||||
|
const actionsActor = actor.listActionsCombat();
|
||||||
|
const ajustements = combatant?.initiative ?
|
||||||
|
[
|
||||||
|
{ label: 'Initiative +1', action: 'delta', value: 1 },
|
||||||
|
{ label: 'Initiative -1', action: 'delta', value: -1 }
|
||||||
|
] : []
|
||||||
|
const autres = [{ label: "Autre action", action: 'autre' }]
|
||||||
|
const actions = Misc.indexed(actionsActor.concat(ajustements).concat(autres))
|
||||||
|
|
||||||
|
const hudData = { combatant, token, actions };
|
||||||
|
const hud = $(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/hud-actor-combat.hbs', hudData))
|
||||||
|
$(html).find('div.col.left').append(hud)
|
||||||
|
|
||||||
|
const list = hud.find('div.rdd-hud-list')
|
||||||
|
RdDTokenHud.setupHudToggle(hud, list)
|
||||||
|
|
||||||
|
const selectInitiative = list.find('select[name="initiative"]');
|
||||||
|
selectInitiative.change(event => {
|
||||||
|
const action = actions.find(it => it.index == event.currentTarget.value)
|
||||||
|
console.log('select initiative', combatant.id, action)
|
||||||
|
if (action) {
|
||||||
|
switch (action.action) {
|
||||||
|
case 'delta':
|
||||||
|
RdDCombatManager.incDecInit(combatant.id, action.value);
|
||||||
|
break
|
||||||
|
case 'autre':
|
||||||
|
RdDCombatManager.rollInitiativeAction(combatant.id,
|
||||||
|
{ label: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
RdDCombatManager.rollInitiativeAction(combatant.id, action)
|
||||||
|
}
|
||||||
|
selectInitiative.select("")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
list.find('.rdd-attaque-v2').click(event => combatant.actor.rollAttaque(token))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async addExtensionHudInit(html, combatant, actions) {
|
static async addExtensionHudInit(html, combatant, actions) {
|
||||||
const hudData = {
|
const hudData = {
|
||||||
combatant, actions,
|
combatant, actions,
|
||||||
commandes: [
|
commandes: [
|
||||||
{ name: "Autre action", command: 'autre' },
|
{ label: "Autre action", command: 'autre' },
|
||||||
{ name: 'Initiative +1', command: 'inc', value: 0.01 },
|
{ label: 'Initiative +1', command: 'delta', value: 1 },
|
||||||
{ name: 'Initiative -1', command: 'dec', value: -0.01 }]
|
{ label: 'Initiative -1', command: 'deltac', value: -1 }]
|
||||||
};
|
};
|
||||||
const controlIconCombat = $(html).find('.control-icon[data-action=combat]');
|
const controlIconCombat = $(html).find('.control-icon[data-action=combat]');
|
||||||
await RdDTokenHud._configureSubMenu(it => controlIconCombat.after(it),
|
await RdDTokenHud._configureSubMenu(it => controlIconCombat.after(it),
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.hbs',
|
||||||
hudData,
|
hudData,
|
||||||
(event) => {
|
(event) => {
|
||||||
let initCommand = event.currentTarget.attributes['data-command']?.value;
|
let initCommand = event.currentTarget.attributes['data-command']?.value
|
||||||
let combatantId = event.currentTarget.attributes['data-combatant-id']?.value;
|
let initCommandValue = Number(event.currentTarget.attributes['data-command-value']?.value ?? 0)
|
||||||
|
let combatantId = event.currentTarget.attributes['data-combatant-id']?.value
|
||||||
if (initCommand) {
|
if (initCommand) {
|
||||||
RdDTokenHud._initiativeCommand(initCommand, combatantId);
|
RdDCombatManager.applyInitiativeCommand(combatantId, initCommand, initCommandValue)
|
||||||
} else {
|
} else {
|
||||||
let index = event.currentTarget.attributes['data-action-index'].value;
|
let index = event.currentTarget.attributes['data-action-index'].value
|
||||||
let action = hudData.actions[index];
|
let action = hudData.actions[index]
|
||||||
RdDCombatManager.rollInitiativeAction(combatantId, action);
|
RdDCombatManager.rollInitiativeAction(combatantId, action)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static async addExtensionHudCombat(html, combatant, token, actions) {
|
static async addExtensionHudAttaques(html, combatant, token, actions) {
|
||||||
|
|
||||||
const hudData = { combatant, token, actions, commandes: [] };
|
const hudData = { combatant, token, actions, commandes: [] };
|
||||||
const divColLeft = $(html).find('div.col.left');
|
const divColLeft = $(html).find('div.col.left');
|
||||||
@@ -104,15 +149,6 @@ export class RdDTokenHud {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static _initiativeCommand(initCommand, combatantId) {
|
|
||||||
switch (initCommand) {
|
|
||||||
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
|
||||||
case 'dec': return RdDCombatManager.incDecInit(combatantId, -0.01);
|
|
||||||
case 'autre': return RdDCombatManager.rollInitiativeAction(combatantId,
|
|
||||||
{ name: "Autre action", action: 'autre', system: { initOnly: true, competence: "Autre action" } });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async addTokenHudExtensions(app, html, tokenId) {
|
static async addTokenHudExtensions(app, html, tokenId) {
|
||||||
console.log(`Adding token HUD extensions for token ${tokenId}`);
|
console.log(`Adding token HUD extensions for token ${tokenId}`);
|
||||||
@@ -132,20 +168,24 @@ export class RdDTokenHud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async _configureSubMenu(insertMethod, template, hudData, onMenuItem) {
|
static async _configureSubMenu(callInsertion, template, hudData, onMenuItem) {
|
||||||
const hud = $(await renderTemplate(template, hudData));
|
const hud = $(await renderTemplate(template, hudData));
|
||||||
const list = hud.find('div.rdd-hud-list');
|
const list = hud.find('div.rdd-hud-list');
|
||||||
|
|
||||||
RdDTokenHud._toggleHudListActive(hud, list);
|
RdDTokenHud.setupHudToggle(hud, list)
|
||||||
|
|
||||||
hud.find('img.rdd-hud-togglebutton').click(event => RdDTokenHud._toggleHudListActive(hud, list));
|
|
||||||
list.find('.rdd-hud-menu').click(onMenuItem);
|
list.find('.rdd-hud-menu').click(onMenuItem);
|
||||||
|
|
||||||
insertMethod(hud);
|
callInsertion(hud);
|
||||||
}
|
}
|
||||||
|
|
||||||
static _toggleHudListActive(hud, list) {
|
static setupHudToggle(hud, list) {
|
||||||
hud.toggleClass('active');
|
function toggleHudList(hud, list) {
|
||||||
HtmlUtility.showControlWhen(list, hud.hasClass('active'));
|
hud.toggleClass('active')
|
||||||
|
HtmlUtility.showControlWhen(list, hud.hasClass('active'))
|
||||||
}
|
}
|
||||||
|
toggleHudList(hud, list)
|
||||||
|
$(hud).find('img.rdd-hud-togglebutton').click(event => toggleHudList(hud, list))
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -16,6 +16,7 @@ export default class ChatRollResult {
|
|||||||
static onReady() {
|
static onReady() {
|
||||||
foundry.applications.handlebars.loadTemplates({
|
foundry.applications.handlebars.loadTemplates({
|
||||||
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
|
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
|
||||||
|
'partial-attaque-particuliere': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-attaque-particuliere.hbs',
|
||||||
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
|
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
|
||||||
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
|
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
|
||||||
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
|
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
|
||||||
@@ -38,12 +39,12 @@ export default class ChatRollResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
prepareDisplay(roll) {
|
prepareDisplay(roll) {
|
||||||
roll.done = roll.done || {}
|
roll.done = roll.done ?? {}
|
||||||
roll.show = roll.show || {}
|
roll.show = roll.show ?? {}
|
||||||
roll.show.chance = this.isAppelChancePossible(roll)
|
roll.show.chance = this.isAppelChancePossible(roll)
|
||||||
roll.show.encaissement = this.isShowEncaissement(roll)
|
roll.show.encaissement = this.isShowEncaissement(roll)
|
||||||
roll.show.recul = this.getReculChoc(roll)
|
roll.show.recul = this.getRecul(roll)
|
||||||
|
roll.show.particuliere = roll.show.particuliere ?? []
|
||||||
}
|
}
|
||||||
|
|
||||||
isAppelChancePossible(roll) {
|
isAppelChancePossible(roll) {
|
||||||
@@ -57,7 +58,11 @@ export default class ChatRollResult {
|
|||||||
roll.attackerRoll?.dmg.mortalite != 'empoignade'
|
roll.attackerRoll?.dmg.mortalite != 'empoignade'
|
||||||
}
|
}
|
||||||
|
|
||||||
getReculChoc(roll, defender = roll.active.actor, attacker = roll.opponent.actor) {
|
|
||||||
|
getRecul(roll, defender = roll.active.actor, attacker = roll.opponent.actor) {
|
||||||
|
switch (roll.type.current) {
|
||||||
|
case ROLL_TYPE_DEFENSE:
|
||||||
|
{
|
||||||
const attaque = roll.attackerRoll
|
const attaque = roll.attackerRoll
|
||||||
if (attaque &&
|
if (attaque &&
|
||||||
(roll.rolled.isEchec || !roll.current.defense.isEsquive) &&
|
(roll.rolled.isEchec || !roll.current.defense.isEsquive) &&
|
||||||
@@ -72,6 +77,18 @@ export default class ChatRollResult {
|
|||||||
diff: taille - impact
|
diff: taille - impact
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ROLL_TYPE_ATTAQUE:
|
||||||
|
{
|
||||||
|
const attaque = roll
|
||||||
|
if (attaque.particuliere == 'force' || 'charge' == attaque.tactique?.key) {
|
||||||
|
return {
|
||||||
|
raison: 'charge' == attaque.tactique?.key ? 'charge' : 'particulière en force',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +102,7 @@ export default class ChatRollResult {
|
|||||||
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
|
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
|
||||||
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
|
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
|
||||||
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
|
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
|
||||||
|
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,4 +196,13 @@ export default class ChatRollResult {
|
|||||||
await this.updateChatMessage(chatMessage, savedRoll)
|
await this.updateChatMessage(chatMessage, savedRoll)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onClickChoixParticuliere(event) {
|
||||||
|
const choix = event.currentTarget.attributes['data-particuliere'].value
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event)
|
||||||
|
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||||
|
savedRoll.particuliere = choix
|
||||||
|
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
|
||||||
|
await this.updateChatMessage(chatMessage, savedRoll)
|
||||||
|
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll, callbacks)
|
||||||
|
}
|
||||||
}
|
}
|
@@ -4,9 +4,10 @@ import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
|
|||||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
||||||
import { PART_DEFENSE } from "./roll-part-defense.mjs"
|
import { PART_DEFENSE } from "./roll-part-defense.mjs"
|
||||||
|
|
||||||
|
|
||||||
export class RollBasicParts {
|
export class RollBasicParts {
|
||||||
|
|
||||||
restore(rollData) {
|
static restore(rollData) {
|
||||||
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
|
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
|
||||||
rollData.active = RollBasicParts.$getActor(rollData)
|
rollData.active = RollBasicParts.$getActor(rollData)
|
||||||
rollData.opponent = RollBasicParts.$getOpponent(rollData)
|
rollData.opponent = RollBasicParts.$getOpponent(rollData)
|
||||||
@@ -15,14 +16,14 @@ export class RollBasicParts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSurprises(rollData, type) {
|
static loadSurprises(rollData, type = rollData.type.current) {
|
||||||
if (!rollData.type.passif) {
|
if (!rollData.type.passif) {
|
||||||
this.loadSurprise(rollData.active, this.getForceRequiseActiveActor(rollData, type))
|
RollBasicParts.loadSurprise(rollData.active, RollBasicParts.getForceRequiseActiveActor(rollData, type))
|
||||||
this.loadSurprise(rollData.opponent, 0)
|
RollBasicParts.loadSurprise(rollData.opponent, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSurprise(who, forceRequise) {
|
static loadSurprise(who, forceRequise) {
|
||||||
if (who?.actor) {
|
if (who?.actor) {
|
||||||
foundry.utils.mergeObject(who,
|
foundry.utils.mergeObject(who,
|
||||||
StatusEffects.getActorEffetSurprise(who.actor, forceRequise),
|
StatusEffects.getActorEffetSurprise(who.actor, forceRequise),
|
||||||
@@ -30,15 +31,15 @@ export class RollBasicParts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getForceRequiseActiveActor(rollData, type) {
|
static getForceRequiseActiveActor(rollData, type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case ROLL_TYPE_ATTAQUE: return rollData.current[PART_ATTAQUE].attaque.forceRequise
|
case ROLL_TYPE_ATTAQUE: return rollData.current[PART_ATTAQUE].forceRequise
|
||||||
case ROLL_TYPE_DEFENSE: return rollData.current[PART_DEFENSE].forceRequise
|
case ROLL_TYPE_DEFENSE: return rollData.current[PART_DEFENSE].forceRequise
|
||||||
default: return 0
|
default: return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
initFrom(rollData) {
|
static initFrom(rollData) {
|
||||||
return {
|
return {
|
||||||
selected: {},
|
selected: {},
|
||||||
type: rollData.type,
|
type: rollData.type,
|
||||||
@@ -52,6 +53,16 @@ export class RollBasicParts {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static reverseIds(rollData) {
|
||||||
|
return {
|
||||||
|
sceneId: rollData.ids.sceneId,
|
||||||
|
actorId: rollData.ids.opponentId,
|
||||||
|
actorTokenId: rollData.ids.opponentTokenId,
|
||||||
|
opponentId: rollData.ids.actorId,
|
||||||
|
opponentTokenId: rollData.actorTokenId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static $getActor(rollData) {
|
static $getActor(rollData) {
|
||||||
if (rollData.ids.actorTokenId) {
|
if (rollData.ids.actorTokenId) {
|
||||||
return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
|
return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
|
||||||
|
@@ -6,6 +6,10 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
|||||||
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs";
|
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs";
|
||||||
import { RdDItemArme } from "../item/arme.js";
|
import { RdDItemArme } from "../item/arme.js";
|
||||||
import { RdDBonus } from "../rdd-bonus.js";
|
import { RdDBonus } from "../rdd-bonus.js";
|
||||||
|
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
|
||||||
|
import { CARACS } from "../rdd-carac.js";
|
||||||
|
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs";
|
||||||
|
import { PART_ATTAQUE } from "./roll-part-attaque.mjs";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RollDialogAdapter {
|
export class RollDialogAdapter {
|
||||||
@@ -15,21 +19,21 @@ export class RollDialogAdapter {
|
|||||||
carac: rollData.current.carac.value,
|
carac: rollData.current.carac.value,
|
||||||
diff: rollData.current.totaldiff,
|
diff: rollData.current.totaldiff,
|
||||||
bonus: rollData.current.bonus,
|
bonus: rollData.current.bonus,
|
||||||
sign: rollData.current.sign,
|
|
||||||
showDice: rollData.options.showDice,
|
showDice: rollData.options.showDice,
|
||||||
rollMode: rollData.current.rollmode.key
|
rollMode: rollData.current.rollmode.key
|
||||||
})
|
})
|
||||||
|
|
||||||
const rolled = await RollDialogAdapter.rollChances(rollData, chances)
|
const rolled = await RollDialogAdapter.rollChances(rollData, chances)
|
||||||
RollDialogAdapter.adjustRollDataForV1(rollData, rolled, rollTitle)
|
RollDialogAdapter.setRollDataRolled(rollData, rolled, rollTitle)
|
||||||
|
RollDialogAdapter.adjustRollDataForV1(rollData)
|
||||||
|
RollDialogAdapter.adjustAttaqueParticuliere(rollData)
|
||||||
|
|
||||||
return rolled
|
return rolled
|
||||||
}
|
}
|
||||||
|
|
||||||
static computeChances({ carac, diff, bonus, sign, showDice, rollMode }) {
|
static computeChances({ carac, diff, bonus, showDice, rollMode }) {
|
||||||
const chances = foundry.utils.duplicate(RdDResolutionTable.computeChances(carac, diff))
|
const chances = foundry.utils.duplicate(RdDResolutionTable.computeChances(carac, diff))
|
||||||
RdDResolutionTable._updateChancesWithBonus(chances, bonus, diff)
|
RdDResolutionTable._updateChancesWithBonus(chances, bonus, diff)
|
||||||
RdDResolutionTable._updateChancesFactor(chances, sign)
|
|
||||||
chances.showDice = showDice
|
chances.showDice = showDice
|
||||||
chances.rollMode = rollMode
|
chances.rollMode = rollMode
|
||||||
return chances
|
return chances
|
||||||
@@ -37,7 +41,7 @@ export class RollDialogAdapter {
|
|||||||
|
|
||||||
static async rollChances(rollData, chances) {
|
static async rollChances(rollData, chances) {
|
||||||
const rolled = await RdDResolutionTable.rollChances(chances,
|
const rolled = await RdDResolutionTable.rollChances(chances,
|
||||||
rollData.current.sign,
|
rollData.current.sign.diviseur,
|
||||||
rollData.current.resultat)
|
rollData.current.resultat)
|
||||||
rolled.caracValue = rollData.current.carac.value
|
rolled.caracValue = rollData.current.carac.value
|
||||||
rolled.finalLevel = rollData.current.totaldiff
|
rolled.finalLevel = rollData.current.totaldiff
|
||||||
@@ -46,13 +50,20 @@ export class RollDialogAdapter {
|
|||||||
return rolled
|
return rolled
|
||||||
}
|
}
|
||||||
|
|
||||||
static adjustRollDataForV1(rollData, rolled, rollTitle) {
|
static setRollDataRolled(rollData, rolled, rollTitle) {
|
||||||
|
rollData.rolled = rolled
|
||||||
|
rollData.choix = rollData.choix ?? {}
|
||||||
|
rollData.show = rollData.show ?? {}
|
||||||
|
rollData.show.title = rollTitle
|
||||||
|
}
|
||||||
|
|
||||||
|
static adjustRollDataForV1(rollData) {
|
||||||
|
const rolled = rollData.rolled
|
||||||
// temporaire pour être homogène roll v1
|
// temporaire pour être homogène roll v1
|
||||||
rollData.alias = rollData.active.actor.getAlias()
|
rollData.alias = rollData.active.actor.getAlias()
|
||||||
// pour experience
|
// pour experience
|
||||||
rollData.finalLevel = rollData.current.totaldiff
|
rollData.finalLevel = rollData.current.totaldiff
|
||||||
if (rollData.use == undefined) { rollData.use = {} }
|
if (rollData.use == undefined) { rollData.use = {} }
|
||||||
if (rollData.show == undefined) { rollData.show = {} }
|
|
||||||
if (rollData.ajustements == undefined) {
|
if (rollData.ajustements == undefined) {
|
||||||
rollData.ajustements = {}
|
rollData.ajustements = {}
|
||||||
}
|
}
|
||||||
@@ -75,7 +86,6 @@ export class RollDialogAdapter {
|
|||||||
if (rollData.current[PART_APPELMORAL]?.checked) {
|
if (rollData.current[PART_APPELMORAL]?.checked) {
|
||||||
rollData.use.moral = true
|
rollData.use.moral = true
|
||||||
}
|
}
|
||||||
rollData.rolled = rolled
|
|
||||||
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||||
rolled.niveauNecessaire = this.findNiveauNecessaire(carac, rolled.roll)
|
rolled.niveauNecessaire = this.findNiveauNecessaire(carac, rolled.roll)
|
||||||
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
|
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
|
||||||
@@ -88,7 +98,39 @@ export class RollDialogAdapter {
|
|||||||
descr: aj.diff == undefined ? aj.label : undefined
|
descr: aj.diff == undefined ? aj.label : undefined
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
rollData.show.title = rollTitle
|
}
|
||||||
|
|
||||||
|
static adjustAttaqueParticuliere(rollData) {
|
||||||
|
if (rollData.type.current != ROLL_TYPE_ATTAQUE || !rollData.rolled.isPart) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const attaque = rollData.current.attaque;
|
||||||
|
const choix = []
|
||||||
|
const isEmpoignade = attaque.dmg.mortalite == 'empoignade';
|
||||||
|
const isCharge = attaque.tactique == 'charge'
|
||||||
|
/* TODO: cas de créatures faisant des lancers, Glou, Glipzouk */
|
||||||
|
const isMeleeDiffNegative = (attaque.comp.type == ITEM_TYPES.competencecreature || rollData.current.carac.key == CARACS.MELEE)
|
||||||
|
&& rollData.current.diff.value < 0
|
||||||
|
|
||||||
|
// force toujours, sauf empoignade
|
||||||
|
if (!isEmpoignade) {
|
||||||
|
choix.push(RDD_CONFIG.particuliere.force)
|
||||||
|
}
|
||||||
|
|
||||||
|
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
|
||||||
|
if (!isCharge && (isEmpoignade || isMeleeDiffNegative)) {
|
||||||
|
choix.push(RDD_CONFIG.particuliere.finesse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
|
||||||
|
if (!isCharge && !isEmpoignade && isMeleeDiffNegative && attaque.arme.system.rapide) {
|
||||||
|
choix.push(RDD_CONFIG.particuliere.rapidite)
|
||||||
|
}
|
||||||
|
if (choix.length == 1) {
|
||||||
|
rollData.particuliere = choix[0].key
|
||||||
|
}
|
||||||
|
rollData.particulieres = choix
|
||||||
}
|
}
|
||||||
|
|
||||||
static mapActionAttaque(attackerRoll) {
|
static mapActionAttaque(attackerRoll) {
|
||||||
@@ -99,7 +141,6 @@ export class RollDialogAdapter {
|
|||||||
return {
|
return {
|
||||||
// correspond à l'attaque de RollPartAttaque (dans rollDta.current.attaque)
|
// correspond à l'attaque de RollPartAttaque (dans rollDta.current.attaque)
|
||||||
label: label,
|
label: label,
|
||||||
attaque: {
|
|
||||||
// correspond aux actions d'attaques dans RdDActor.listActionsAttaque
|
// correspond aux actions d'attaques dans RdDActor.listActionsAttaque
|
||||||
name: label,
|
name: label,
|
||||||
// action: 'attaque',
|
// action: 'attaque',
|
||||||
@@ -109,7 +150,6 @@ export class RollDialogAdapter {
|
|||||||
equipe: attackerRoll.arme.system.equipe,
|
equipe: attackerRoll.arme.system.equipe,
|
||||||
// carac: { key: caracCode, value: caracValue },
|
// carac: { key: caracCode, value: caracValue },
|
||||||
// dommagesArme: dommagesArme,
|
// dommagesArme: dommagesArme,
|
||||||
},
|
|
||||||
diff: attackerRoll.diffLibre,
|
diff: attackerRoll.diffLibre,
|
||||||
particuliere: attackerRoll.particuliere,
|
particuliere: attackerRoll.particuliere,
|
||||||
tactique: RdDBonus.find(attackerRoll.tactique),
|
tactique: RdDBonus.find(attackerRoll.tactique),
|
||||||
|
@@ -37,7 +37,7 @@ import { RollPartAttaque } from "./roll-part-attaque.mjs";
|
|||||||
import { RollPartDefense } from "./roll-part-defense.mjs";
|
import { RollPartDefense } from "./roll-part-defense.mjs";
|
||||||
import { RollDialogAdapter } from "./roll-dialog-adapter.mjs";
|
import { RollDialogAdapter } from "./roll-dialog-adapter.mjs";
|
||||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs";
|
import { ROLLDIALOG_SECTION } from "./roll-part.mjs";
|
||||||
import { ROLL_TYPE_COMP } from "./roll-constants.mjs";
|
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP } from "./roll-constants.mjs";
|
||||||
import ChatRollResult from "./chat-roll-result.mjs";
|
import ChatRollResult from "./chat-roll-result.mjs";
|
||||||
import { renderTemplate } from "../constants.js";
|
import { renderTemplate } from "../constants.js";
|
||||||
|
|
||||||
@@ -58,8 +58,6 @@ const ALL_ROLL_TYPES = [
|
|||||||
// new RollTypeFixedCarac ??
|
// new RollTypeFixedCarac ??
|
||||||
]
|
]
|
||||||
|
|
||||||
const BASIC_PARTS = new RollBasicParts()
|
|
||||||
|
|
||||||
const ROLL_PARTS = [
|
const ROLL_PARTS = [
|
||||||
new RollPartActor(),
|
new RollPartActor(),
|
||||||
new RollPartAction(),
|
new RollPartAction(),
|
||||||
@@ -257,7 +255,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
|||||||
rollData.selected = rollData.selected ?? {}
|
rollData.selected = rollData.selected ?? {}
|
||||||
rollData.type = rollData.type ?? {}
|
rollData.type = rollData.type ?? {}
|
||||||
rollData.type.retry = rollData.type.retry ?? false
|
rollData.type.retry = rollData.type.retry ?? false
|
||||||
BASIC_PARTS.restore(rollData)
|
RollBasicParts.restore(rollData)
|
||||||
|
|
||||||
const potential = ALL_ROLL_TYPES.find(m => m.code == rollData.type.current)?.code
|
const potential = ALL_ROLL_TYPES.find(m => m.code == rollData.type.current)?.code
|
||||||
const allowed = rollData.type.retry && potential
|
const allowed = rollData.type.retry && potential
|
||||||
@@ -283,13 +281,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
|||||||
}
|
}
|
||||||
|
|
||||||
static saveParts(rollData) {
|
static saveParts(rollData) {
|
||||||
const target = BASIC_PARTS.initFrom(rollData)
|
const target = RollBasicParts.initFrom(rollData)
|
||||||
ROLL_PARTS.filter(p => p.isActive(rollData))
|
ROLL_PARTS.filter(p => p.isActive(rollData))
|
||||||
.forEach(p => p.storeClean(rollData, target))
|
.forEach(p => p.storeClean(rollData, target))
|
||||||
target.attackerRoll = rollData.attackerRoll
|
target.attackerRoll = rollData.attackerRoll
|
||||||
target.rolled = rollData.rolled
|
target.rolled = rollData.rolled
|
||||||
target.result = rollData.result
|
target.result = rollData.result
|
||||||
target.done = target.done ?? {}
|
target.done = rollData.done ?? {}
|
||||||
|
target.dmg = rollData.dmg
|
||||||
return target
|
return target
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,7 +376,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
|||||||
|
|
||||||
const types = ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData))
|
const types = ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData))
|
||||||
.map(m => m.toTypeData(rollData))
|
.map(m => m.toTypeData(rollData))
|
||||||
BASIC_PARTS.loadSurprises(rollData, this.getSelectedType().code)
|
RollBasicParts.loadSurprises(rollData, this.getSelectedType().code)
|
||||||
rollData.type.label = this.getSelectedType()?.title(rollData)
|
rollData.type.label = this.getSelectedType()?.title(rollData)
|
||||||
//TOCHECK: set type.label ?
|
//TOCHECK: set type.label ?
|
||||||
const visibleRollParts = RollDialog.getActiveParts(rollData)
|
const visibleRollParts = RollDialog.getActiveParts(rollData)
|
||||||
@@ -423,18 +422,17 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
|||||||
}
|
}
|
||||||
|
|
||||||
async roll() {
|
async roll() {
|
||||||
// ROLL_PARTS.filter(p => p.isActive(this.rollData))
|
|
||||||
// .forEach(p => p.validate(this.rollData))
|
|
||||||
|
|
||||||
const roll = RollDialog.saveParts(this.rollData)
|
const roll = RollDialog.saveParts(this.rollData)
|
||||||
RollDialog.loadRollData(roll)
|
RollDialog.loadRollData(roll)
|
||||||
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
|
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
|
||||||
roll.rolled = await this.$rollDice(roll)
|
roll.choix = {}
|
||||||
|
roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll))
|
||||||
roll.result = this.getSelectedType(roll).getResult(roll)
|
roll.result = this.getSelectedType(roll).getResult(roll)
|
||||||
console.info('RollDialog.roll:', roll)
|
|
||||||
await Promise.all(this.rollOptions.callbacks.map(async callback => await callback(roll)))
|
|
||||||
await this.chatRollResult.display(roll)
|
|
||||||
|
|
||||||
|
console.info('RollDialog.roll:', roll)
|
||||||
|
await this.chatRollResult.display(roll)
|
||||||
|
await Promise.all(this.rollOptions.callbacks.map(async callback => await callback(roll)))
|
||||||
this.rollOptions.onRollDone(this)
|
this.rollOptions.onRollDone(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -444,12 +442,9 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
|||||||
roll.v2 = true
|
roll.v2 = true
|
||||||
}
|
}
|
||||||
|
|
||||||
async defaultCallback(rollData, rolled) {
|
async defaultCallback(roll, rolled) {
|
||||||
await rollData.active.actor.appliquerAjoutExperience(rollData)
|
await roll.active.actor.appliquerAjoutExperience(roll)
|
||||||
await rollData.active.actor.appliquerAppelMoral(rollData)
|
await roll.active.actor.appliquerAppelMoral(roll)
|
||||||
}
|
}
|
||||||
|
|
||||||
async $rollDice(rollData) {
|
|
||||||
return await RollDialogAdapter.rollDice(rollData, this.rollTitle(rollData))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { RdDBonus } from "../rdd-bonus.js"
|
import { RdDBonus } from "../rdd-bonus.js"
|
||||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
|
|
||||||
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
||||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||||
@@ -40,12 +39,12 @@ export class RollPartAttaque extends RollPartSelect {
|
|||||||
choices(refs) { return refs.attaques }
|
choices(refs) { return refs.attaques }
|
||||||
|
|
||||||
static $extractAttaque(attaque, actor) {
|
static $extractAttaque(attaque, actor) {
|
||||||
return {
|
return foundry.utils.mergeObject({
|
||||||
key: `${attaque.action}::${attaque.name}`,
|
key: `${attaque.action}::${attaque.label}`,
|
||||||
label: attaque.name,
|
tactique: TACTIQUES[0]
|
||||||
attaque: attaque,
|
},
|
||||||
tactique: TACTIQUES[0],
|
attaque
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareContext(rollData) {
|
prepareContext(rollData) {
|
||||||
@@ -100,8 +99,8 @@ export class RollPartAttaque extends RollPartSelect {
|
|||||||
if (this.visible(rollData)) {
|
if (this.visible(rollData)) {
|
||||||
const current = this.getCurrent(rollData)
|
const current = this.getCurrent(rollData)
|
||||||
switch (part.code) {
|
switch (part.code) {
|
||||||
case PART_CARAC: return part.filterCaracs(rollData, [current.attaque.carac.key])
|
case PART_CARAC: return part.filterCaracs(rollData, [current.carac.key])
|
||||||
case PART_COMP: return part.filterComps(rollData, [current.attaque.comp?.name])
|
case PART_COMP: return part.filterComps(rollData, [current.comp.name])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
|
@@ -34,7 +34,7 @@ export class RollPartDefense extends RollPartSelect {
|
|||||||
.map(it => RollPartDefense.$extractEsquive(it, defenseur))
|
.map(it => RollPartDefense.$extractEsquive(it, defenseur))
|
||||||
|
|
||||||
const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
|
const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
|
||||||
.map(it => RollPartDefense.$extractParade(it, attackerRoll?.attaque.arme, defenseur))
|
.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
|
||||||
|
|
||||||
refs.defenses = [...esquives, ...parades].filter(it => it != undefined)
|
refs.defenses = [...esquives, ...parades].filter(it => it != undefined)
|
||||||
this.$selectDefense(rollData)
|
this.$selectDefense(rollData)
|
||||||
@@ -113,17 +113,16 @@ export class RollPartDefense extends RollPartSelect {
|
|||||||
isArmeDisparate(rollData) {
|
isArmeDisparate(rollData) {
|
||||||
const armeDefense = this.getCurrent(rollData).arme
|
const armeDefense = this.getCurrent(rollData).arme
|
||||||
if (armeDefense) {
|
if (armeDefense) {
|
||||||
const armeAttaque = rollData.attackerRoll?.attaque.arme
|
const armeAttaque = rollData.attackerRoll?.arme
|
||||||
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
|
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
getDiffDefense(rollData) {
|
getDiffDefense(rollData) {
|
||||||
const current = this.getCurrent(rollData)
|
|
||||||
const refs = this.getRefs(rollData)
|
const refs = this.getRefs(rollData)
|
||||||
if (refs.isDistance || !rollData.attackerRoll) {
|
if (refs.isDistance || !rollData.attackerRoll) {
|
||||||
// Déterminer la difficulté de parade
|
// TODO: Déterminer la difficulté de parade
|
||||||
return { diff: 0, type: DIFF.LIBRE }
|
return { diff: 0, type: DIFF.LIBRE }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
|
||||||
|
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
|
||||||
import { RollType } from "./roll-type.mjs"
|
import { RollType } from "./roll-type.mjs"
|
||||||
|
|
||||||
export class RollTypeAttaque extends RollType {
|
export class RollTypeAttaque extends RollType {
|
||||||
@@ -10,4 +11,5 @@ export class RollTypeAttaque extends RollType {
|
|||||||
onSelect(rollData) {
|
onSelect(rollData) {
|
||||||
this.setDiffType(rollData, DIFF.ATTAQUE)
|
this.setDiffType(rollData, DIFF.ATTAQUE)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -37,7 +37,6 @@ export class RollType {
|
|||||||
this.setDiffType(rollData, type)
|
this.setDiffType(rollData, type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
typeFromOpponents(rollData) {
|
typeFromOpponents(rollData) {
|
||||||
if (rollData.type.opposed) {
|
if (rollData.type.opposed) {
|
||||||
if (rollData.type.resistance) {
|
if (rollData.type.resistance) {
|
||||||
|
@@ -8,16 +8,16 @@
|
|||||||
</li>
|
</li>
|
||||||
{{#each combat as |action key|}}
|
{{#each combat as |action key|}}
|
||||||
<li class="item flexrow list-item" data-item-id="{{action._id}}" data-arme-name="{{action.arme.name}}"
|
<li class="item flexrow list-item" data-item-id="{{action._id}}" data-arme-name="{{action.arme.name}}"
|
||||||
|
{{log 'action' action}}
|
||||||
data-competence-name="{{action.comp.name}}"
|
data-competence-name="{{action.comp.name}}"
|
||||||
data-tooltip="{{action.name}}: niveau {{plusMoins action.comp.system.niveau}}">
|
data-tooltip="{{action.label}}: niveau {{plusMoins action.comp.system.niveau}}">
|
||||||
<span class="list-item-label flexrow">
|
<span class="list-item-label flexrow">
|
||||||
<a class="roll-arme flexrow">
|
<a class="roll-arme flexrow">
|
||||||
{{#if action.arme.img}}
|
{{#if action.arme.img}}
|
||||||
<img class="sheet-competence-img" src="{{action.arme.img}}" data-tooltip="{{action.arme.name}}" />
|
<img class="sheet-competence-img" src="{{action.arme.img}}" data-tooltip="{{action.arme.name}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span>{{action.name}}</span>
|
<span>{{action.label}}</span>
|
||||||
</a>
|
</a>
|
||||||
({{action.comp.name}})
|
|
||||||
{{>"systems/foundryvtt-reve-de-dragon/templates/item/icon-arme-broken.hbs" action.arme}}
|
{{>"systems/foundryvtt-reve-de-dragon/templates/item/icon-arme-broken.hbs" action.arme}}
|
||||||
</span>
|
</span>
|
||||||
<span class="competence-value">{{plusMoins action.comp.system.niveau}}</span>
|
<span class="competence-value">{{plusMoins action.comp.system.niveau}}</span>
|
||||||
|
@@ -2,8 +2,8 @@
|
|||||||
data-item-id="{{attaque.arme._id}}"
|
data-item-id="{{attaque.arme._id}}"
|
||||||
data-arme-name="{{attaque.arme.name}}"
|
data-arme-name="{{attaque.arme.name}}"
|
||||||
data-competence-name="{{attaque.comp.name}}">
|
data-competence-name="{{attaque.comp.name}}">
|
||||||
{{#if attaque.name}}
|
{{#if attaque.label}}
|
||||||
<a class="roll-arme">{{upperFirst attaque.name}}</a>
|
<a class="roll-arme">{{upperFirst attaque.label}}</a>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div></div>
|
<div></div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
103
templates/chat-demande-defense-v1.hbs
Normal file
103
templates/chat-demande-defense-v1.hbs
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<div data-passearme="{{passeArme}}">
|
||||||
|
{{#if (eq surprise 'totale')}}
|
||||||
|
<span><strong>{{defenderToken.name}}</strong> est totalement surpris</span>
|
||||||
|
{{else if essais.defense}}
|
||||||
|
<span><strong>{{defenderToken.name}}</strong> doit :</span>
|
||||||
|
{{else}}
|
||||||
|
<span><strong>{{defenderToken.name}}</strong> doit se défendre
|
||||||
|
{{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque
|
||||||
|
{{~#if attaqueParticuliere}} <strong>particulière en
|
||||||
|
{{~#if (eq attaqueParticuliere 'finesse')}} finesse
|
||||||
|
{{else if (eq attaqueParticuliere 'force')}} force
|
||||||
|
{{else if (eq attaqueParticuliere 'rapidite')}} rapidité
|
||||||
|
{{/if~}}</strong>
|
||||||
|
{{/if}} de {{attackerToken.name}} ({{attaqueArme.name}}):
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
<span class='chat-card-button-area'>
|
||||||
|
<br>
|
||||||
|
{{#unless (eq surprise 'totale')}}
|
||||||
|
{{#if essais.defense}}
|
||||||
|
{{#unless essais.defenseChance}}
|
||||||
|
{{#if (eq defender.type 'personnage')}}
|
||||||
|
<a class='chat-card-button appel-chance-defense'
|
||||||
|
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||||
|
Faire appel à la chance
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}}
|
||||||
|
<a class='chat-card-button appel-destinee-defense'
|
||||||
|
data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'>
|
||||||
|
Utiliser la destinée
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
|
{{else}}
|
||||||
|
{{#if (settings-get 'rdd-advanced-roll-dialog-v2')}}
|
||||||
|
<a class='chat-card-button button-defense'
|
||||||
|
data-attackerId='{{attackerId}}'
|
||||||
|
data-attackerTokenId='{{attackerToken.id}}'
|
||||||
|
data-defenderTokenId='{{defenderToken.id}}'
|
||||||
|
>
|
||||||
|
Se défendre
|
||||||
|
{{#if (or (eq attaqueCategorie 'tir') (eq attaqueCategorie 'lancer'))}}
|
||||||
|
(difficulté à déterminer)
|
||||||
|
{{else}}
|
||||||
|
à {{diffLibre }}
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{else}}
|
||||||
|
{{#each armes as |arme key|}}
|
||||||
|
<a class='chat-card-button button-parade'
|
||||||
|
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
||||||
|
data-armeid='{{arme._id}}'>
|
||||||
|
Parer avec {{arme.name}}
|
||||||
|
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
|
||||||
|
(difficulté à déterminer)
|
||||||
|
{{else}}à {{../diffLibre }}
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq arme.typeParade 'sign')}}
|
||||||
|
<span class="rdd-diviseur">×½</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if arme.nbUsage}}(Utilisations : {{arme.nbUsage}}){{/if}}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{/each}}
|
||||||
|
{{#if mainsNues}}
|
||||||
|
<a class='chat-card-button button-parade'
|
||||||
|
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
|
||||||
|
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
|
||||||
|
Parer à mains nues à {{diffLibre}}{{#if arme.nbUsage}} (Utilisations : {{arme.nbUsage}}){{/if}}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (ne attaqueCategorie 'tir')}}
|
||||||
|
{{#each esquives as |esquive key|}}
|
||||||
|
<a class='chat-card-button button-esquive'
|
||||||
|
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
||||||
|
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
|
||||||
|
{{esquive.name}}
|
||||||
|
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
|
||||||
|
(difficulté à déterminer)
|
||||||
|
{{else}}à {{../diffLibre }}
|
||||||
|
{{/if}}
|
||||||
|
{{#if esquive.nbUsage}}(Utilisations : {{esquive.nbUsage}}){{/if}}
|
||||||
|
</a>
|
||||||
|
<br>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
{{/unless}}
|
||||||
|
<a class='chat-card-button button-encaisser'
|
||||||
|
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
||||||
|
Encaisser à {{plusMoins dmg.total}}
|
||||||
|
{{#if (eq dmg.mortalite 'non-mortel')~}}
|
||||||
|
(non-mortel) !
|
||||||
|
{{/if}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
@@ -1,103 +1,59 @@
|
|||||||
<div data-passearme="{{passeArme}}">
|
{{log this}}
|
||||||
{{#if (eq surprise 'totale')}}
|
<div class="roll-chat" data-passearme="{{passeArme}}">
|
||||||
<span><strong>{{defenderToken.name}}</strong> est totalement surpris</span>
|
<div class="chat-img">
|
||||||
{{else if essais.defense}}
|
<img src="{{opponent.img}}" data-tooltip="{{opponent.name}}" />
|
||||||
<span><strong>{{defenderToken.name}}</strong> doit :</span>
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-header">
|
||||||
|
<h4>Défense de {{opponent.name}}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-resume">
|
||||||
|
{{#if (eq opponent.surprise.key 'totale')}}
|
||||||
|
<span><strong>{{opponent.name}}</strong> est totalement surpris</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span><strong>{{defenderToken.name}}</strong> doit se défendre
|
<span><strong>{{opponent.name}}</strong> doit se défendre
|
||||||
{{~#if (eq surprise 'demi')}} avec une significative {{/if}} d'une attaque
|
{{~#if (eq opponent.surprise.key 'demi')}} avec une significative {{/if}} d'une attaque
|
||||||
{{~#if attaqueParticuliere}} <strong>particulière en
|
{{~#if particuliere}} <strong>particulière en
|
||||||
{{~#if (eq attaqueParticuliere 'finesse')}} finesse
|
{{~#if (eq particuliere 'finesse')}} finesse
|
||||||
{{else if (eq attaqueParticuliere 'force')}} force
|
{{else if (eq particuliere 'force')}} force
|
||||||
{{else if (eq attaqueParticuliere 'rapidite')}} rapidité
|
{{else if (eq particuliere 'rapidite')}} rapidité
|
||||||
{{/if~}}</strong>
|
{{/if~}}</strong>
|
||||||
{{/if}} de {{attackerToken.name}} ({{attaqueArme.name}}):
|
{{/if}} de {{active.name}} ({{current.attaque.label}}):
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<span class='chat-card-button-area'>
|
</div>
|
||||||
<br>
|
|
||||||
{{#unless (eq surprise 'totale')}}
|
<div class="chat-details">
|
||||||
{{#if essais.defense}}
|
</div>
|
||||||
{{#unless essais.defenseChance}}
|
|
||||||
{{#if (eq defender.type 'personnage')}}
|
<div class="chat-actions">
|
||||||
<a class='chat-card-button appel-chance-defense'
|
{{#unless (eq opponent.surprise.key 'totale')}}
|
||||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
|
||||||
Faire appel à la chance
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (and (eq defender.type 'personnage') (gt defender.system.compteurs.destinee.value 0))}}
|
|
||||||
<a class='chat-card-button appel-destinee-defense'
|
|
||||||
data-attackerId='{{attackerId}}' data-attackerTokenId='{{attackerToken.id}}' data-defenderTokenId='{{defenderToken.id}}'>
|
|
||||||
Utiliser la destinée
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{{/if}}
|
|
||||||
{{/unless}}
|
|
||||||
{{else}}
|
|
||||||
{{#if (settings-get 'rdd-advanced-roll-dialog-v2')}}
|
|
||||||
<a class='chat-card-button button-defense'
|
<a class='chat-card-button button-defense'
|
||||||
data-attackerId='{{attackerId}}'
|
data-attackerId='{{ids.actorId}}'
|
||||||
data-attackerTokenId='{{attackerToken.id}}'
|
data-attackerTokenId='{{ids.actorTokenId}}'
|
||||||
data-defenderTokenId='{{defenderToken.id}}'
|
data-defenderTokenId='{{ids.opponentTokenId}}'
|
||||||
>
|
>
|
||||||
|
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/defense.svg"/>
|
||||||
Se défendre
|
Se défendre
|
||||||
{{#if (or (eq attaqueCategorie 'tir') (eq attaqueCategorie 'lancer'))}}
|
{{#if (or (eq attaqueCategorie 'tir') (eq attaqueCategorie 'lancer'))}}
|
||||||
(difficulté à déterminer)
|
(difficulté à déterminer)
|
||||||
{{else}}
|
{{else}}
|
||||||
à {{diffLibre }}
|
à {{current.diff.value}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</a>
|
</a>
|
||||||
<br>
|
|
||||||
{{else}}
|
|
||||||
{{#each armes as |arme key|}}
|
|
||||||
<a class='chat-card-button button-parade'
|
|
||||||
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
|
||||||
data-armeid='{{arme._id}}'>
|
|
||||||
Parer avec {{arme.name}}
|
|
||||||
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
|
|
||||||
(difficulté à déterminer)
|
|
||||||
{{else}}à {{../diffLibre }}
|
|
||||||
{{/if}}
|
|
||||||
{{#if (eq arme.typeParade 'sign')}}
|
|
||||||
<span class="rdd-diviseur">×½</span>
|
|
||||||
{{/if}}
|
|
||||||
{{#if arme.nbUsage}}(Utilisations : {{arme.nbUsage}}){{/if}}
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{{/each}}
|
|
||||||
{{#if mainsNues}}
|
|
||||||
<a class='chat-card-button button-parade'
|
|
||||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'
|
|
||||||
data-armeid='{{arme._id}}' data-competence='{{arme.system.competence}}'>
|
|
||||||
Parer à mains nues à {{diffLibre}}{{#if arme.nbUsage}} (Utilisations : {{arme.nbUsage}}){{/if}}
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{{/if}}
|
|
||||||
{{#if (ne attaqueCategorie 'tir')}}
|
|
||||||
{{#each esquives as |esquive key|}}
|
|
||||||
<a class='chat-card-button button-esquive'
|
|
||||||
data-attackerId='{{../attackerId}}' data-defenderTokenId='{{../defenderToken.id}}' data-attackerTokenId='{{../attackerToken.id}}'
|
|
||||||
data-compid='{{esquive._id}}' data-competence='{{esquive.name}}'>
|
|
||||||
{{esquive.name}}
|
|
||||||
{{#if (or (eq ../attaqueCategorie 'tir') (eq ../attaqueCategorie 'lancer'))}}
|
|
||||||
(difficulté à déterminer)
|
|
||||||
{{else}}à {{../diffLibre }}
|
|
||||||
{{/if}}
|
|
||||||
{{#if esquive.nbUsage}}(Utilisations : {{esquive.nbUsage}}){{/if}}
|
|
||||||
</a>
|
|
||||||
<br>
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
<a class='chat-card-button button-encaisser'
|
{{#unless (eq dmg.mortalite 'empoignade')}}
|
||||||
data-attackerId='{{attackerId}}' data-defenderTokenId='{{defenderToken.id}}' data-attackerTokenId='{{attackerToken.id}}'>
|
<a class='chat-card-button encaissement'
|
||||||
|
data-tooltip="Encaisser à {{plusMoins dmg.total}} {{#if (eq dmg.mortalite 'non-mortel')~}}(non-mortel){{/if}}"
|
||||||
|
>
|
||||||
|
<img src="systems/foundryvtt-reve-de-dragon/assets/ui/encaisser.svg"/>
|
||||||
Encaisser à {{plusMoins dmg.total}}
|
Encaisser à {{plusMoins dmg.total}}
|
||||||
{{#if (eq dmg.mortalite 'non-mortel')~}}
|
{{#if (eq dmg.mortalite 'non-mortel')~}}(non-mortel){{/if}}
|
||||||
(non-mortel) !
|
|
||||||
{{/if}}
|
|
||||||
</a>
|
</a>
|
||||||
</span>
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-buttons">
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
@@ -1,13 +1,11 @@
|
|||||||
|
{{log rolled}}
|
||||||
<div>
|
<div>
|
||||||
<span {{#if ajustements}}class="tooltip-overflow tooltip-dotted" {{/if}}>
|
<span {{#if ajustements}}class="tooltip-overflow tooltip-dotted" {{/if}}>
|
||||||
<span>
|
<span>
|
||||||
<span>{{rolled.caracValue}} à {{plusMoins rolled.finalLevel}}</span>
|
<span>{{rolled.caracValue}} à {{plusMoins rolled.finalLevel}}</span>
|
||||||
{{#if (and rolled.factorHtml (gt rolled.factorHtml 1))}}
|
|
||||||
<span class="rdd-diviseur">×{{{rolled.factorHtml}}}</span>
|
|
||||||
<span>= {{rolled.score}}%</span>
|
<span>= {{rolled.score}}%</span>
|
||||||
|
{{#if (and rolled.factorHtml (ne rolled.factorHtml 1))}}
|
||||||
<span class="rdd-diviseur">×{{{rolled.factorHtml}}}</span>
|
<span class="rdd-diviseur">×{{{rolled.factorHtml}}}</span>
|
||||||
{{else}}
|
|
||||||
<span>= {{rolled.score}}%</span>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</span>
|
</span>
|
||||||
<div class="tooltiptext ttt-ajustements">
|
<div class="tooltiptext ttt-ajustements">
|
||||||
|
@@ -6,8 +6,8 @@
|
|||||||
<div class="control-icon token-hud-icon rdd-hud-menu rdd-attaque"
|
<div class="control-icon token-hud-icon rdd-hud-menu rdd-attaque"
|
||||||
data-combatant-id="{{../combatant.id}}"
|
data-combatant-id="{{../combatant.id}}"
|
||||||
data-action-index="{{action.index}}"
|
data-action-index="{{action.index}}"
|
||||||
data-tooltip="Attaque: {{action.name}}">
|
data-tooltip="Attaque: {{action.label}}">
|
||||||
<label><i class="fa-solid fa-sword"></i> {{action.name}} {{action.system.infoMain}}</label>
|
<label><i class="fa-solid fa-sword"></i> {{action.label}} {{action.system.infoMain}}</label>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
34
templates/hud-actor-combat.hbs
Normal file
34
templates/hud-actor-combat.hbs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{{log this}}
|
||||||
|
<div class="control-icon rdd-combat ">
|
||||||
|
<img class="rdd-hud-togglebutton"
|
||||||
|
src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" width="36" height="36"
|
||||||
|
data-tooltip="Combat"/>
|
||||||
|
<div class="rdd-hud-list token-hud-ext left">
|
||||||
|
<div class="control-icon token-hud-icon select-init-v2">
|
||||||
|
<i class="fa-solid fa-dice-d6"></i>
|
||||||
|
<select name="initiative">
|
||||||
|
{{log combatant}}
|
||||||
|
<option value="">{{#if combatant.system.init}}
|
||||||
|
{{combatant.system.init.value}} {{combatant.system.init.label}}
|
||||||
|
{{else}}Initiative...{{/if}}
|
||||||
|
</option>
|
||||||
|
{{selectOptions actions selected='' valueAttr='index' labelAttr='label'}}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{!-- <div class="control-icon token-hud-icon rdd-init-v2"
|
||||||
|
data-combatant-id="{{../combatant.id}}"
|
||||||
|
data-action="initiative"
|
||||||
|
data-tooltip="Choisir l'initiative">
|
||||||
|
<label><i class="fa-solid fa-dice-d6"></i><span> Initiative</span></label>
|
||||||
|
</div> --}}
|
||||||
|
|
||||||
|
<div class="control-icon token-hud-icon rdd-attaque-v2"
|
||||||
|
data-combatant-id="{{../combatant.id}}"
|
||||||
|
data-action="attaque"
|
||||||
|
data-tooltip="Attaquer la cible">
|
||||||
|
<label><i class="fa-solid fa-sword"></i> Attaquer</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -5,17 +5,17 @@
|
|||||||
<div class="control-icon token-hud-icon rdd-hud-menu"
|
<div class="control-icon token-hud-icon rdd-hud-menu"
|
||||||
data-combatant-id="{{../combatant.id}}"
|
data-combatant-id="{{../combatant.id}}"
|
||||||
data-action-index="{{action.index}}"
|
data-action-index="{{action.index}}"
|
||||||
data-tooltip="Initiative {{action.name}}">
|
data-tooltip="Initiative {{action.label}}">
|
||||||
<label><i class="fa-solid fa-dice-d6"></i><span> {{action.name}} {{action.system.infoMain}}</span></label>
|
<label><i class="fa-solid fa-dice-d6"></i><span> {{action.label}} {{action.system.infoMain}}</span></label>
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{#each commandes as |commande key|}}
|
{{#each commandes as |commande key|}}
|
||||||
<div class="control-icon token-hud-icon rdd-hud-menu"
|
<div class="control-icon token-hud-icon rdd-hud-menu"
|
||||||
data-command="{{commande.command}}"
|
data-command="{{commande.command}}"
|
||||||
|
data-command-value="{{commande.value}}"
|
||||||
data-combatant-id="{{../combatant.id}}"
|
data-combatant-id="{{../combatant.id}}"
|
||||||
data-action-index="{{commande.index}}"
|
data-tooltip="{{commande.label}}">
|
||||||
data-tooltip="{{commande.name}}">
|
<label>{{commande.label}}</label>
|
||||||
<label>{{commande.name}}</label>
|
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -0,0 +1,75 @@
|
|||||||
|
<div class="roll-chat">
|
||||||
|
<div class="chat-img">
|
||||||
|
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
|
||||||
|
<img src="{{competence.img}}" data-tooltip="{{competence.name}}" />
|
||||||
|
<img src="{{opponent.img}}" data-tooltip="{{opponent.name}}" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-header">
|
||||||
|
{{active.name}} attaque {{opponent.name}}: {{current.label}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-resume">
|
||||||
|
{{current.carac.label}} / {{current.comp.label}} à {{current.diff.value}}
|
||||||
|
<br>{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs"}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-details">
|
||||||
|
<hr>
|
||||||
|
{{#if rolled.isSuccess}}
|
||||||
|
<span>
|
||||||
|
<strong>{{opponent.name}}</strong> doit se défendre à <strong>{{current.diff.value}}</strong>,
|
||||||
|
{{#if (eq current.dmg.mortalite 'empoignade')}}
|
||||||
|
ou {{active.name}} marquera un point d'empoignade
|
||||||
|
{{else if (eq current.dmg.mortalite 'non-mortel')}}
|
||||||
|
ou encaisser à <span class="rdd-roll-norm">{{plusMoins current.dmg.total}} (non-mortel)</span>
|
||||||
|
{{else}}
|
||||||
|
{{!-- {{~#if (eq current.dmg.mortalite 'mortel')}} --}}
|
||||||
|
ou encaisser à <span class="rdd-roll-echec">{{plusMoins current.dmg.total}}</span>
|
||||||
|
{{!-- {{~#if (eq current.dmg.mortalite 'cauchemar')}} --}}
|
||||||
|
{{!-- {{else}}
|
||||||
|
<span class="rdd-roll-etotal">{{plusMoins dmg.total}}</span> (entités de cauchemar) --}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
</span>
|
||||||
|
{{#if show.recul}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
|
<img src="icons/svg/thrust.svg" data-tooltip="charge" />
|
||||||
|
Si votre adversaire n'esquive pas cette {{show.recul.raison}}, il devra résister à l'impact ou reculer sous le choc!
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq particuliere 'rapidite')}}
|
||||||
|
<span>
|
||||||
|
<br>Votre attaque rapide vous permet une deuxième attaque, ou une défense supplémentaire!
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
<span>Votre attaque a échoué!</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq current.tactique 'charge')}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
|
<img src="icons/svg/thrust.svg" data-tooltip="charge" />
|
||||||
|
C'est une charge, vos parades auront un -4 et vous ne pourrez pas esquiver!
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (and (eq current.tactique 'feinte') rolled.isSuccess)}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
|
<img src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" data-tooltip="feinte"/>
|
||||||
|
Votre feinte peut faire mouche!
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
<p>
|
||||||
|
{{> "systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.hbs"}}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-actions">
|
||||||
|
{{> 'partial-attaque-particuliere'}}
|
||||||
|
{{!-- TODO: maladresses --}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="chat-buttons">
|
||||||
|
{{> 'partial-appel-chance'}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
@@ -1,9 +1,8 @@
|
|||||||
|
|
||||||
{{log this}}
|
|
||||||
<div class="roll-chat">
|
<div class="roll-chat">
|
||||||
<div class="chat-img">
|
<div class="chat-img">
|
||||||
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
|
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
|
||||||
<img src="{{competence.img}}" data-tooltip="{{competence.name}}" />
|
<img src="{{competence.img}}" data-tooltip="{{competence.name}}" />
|
||||||
|
<img src="{{opponent.img}}" data-tooltip="{{opponent.name}}" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chat-header">
|
<div class="chat-header">
|
||||||
@@ -30,20 +29,22 @@
|
|||||||
{{!-- {{else}}
|
{{!-- {{else}}
|
||||||
<!-- TODO: cas de parade à mains nues, texte à modifier -->
|
<!-- TODO: cas de parade à mains nues, texte à modifier -->
|
||||||
{{/if}} --}}
|
{{/if}} --}}
|
||||||
{{#if attackerRoll.tactique}}
|
|
||||||
<p>
|
|
||||||
{{#if (eq attackerRoll.tactique.key 'charge')}}
|
{{#if (eq attackerRoll.tactique.key 'charge')}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
<img class="chat-icon" src="icons/svg/thrust.svg" data-tooltip="charge" height="32" width="32" />
|
<img class="chat-icon" src="icons/svg/thrust.svg" data-tooltip="charge" height="32" width="32" />
|
||||||
C'était une charge, les parades de {{opponent.name}} auront un -4 et il ne pourra pas esquiver!
|
C'était une charge, les parades de {{opponent.name}} auront un -4 et il ne pourra pas esquiver!
|
||||||
{{else if (eq attackerRoll.tactique.key 'feinte')}}
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if (eq attackerRoll.tactique.key 'feinte')}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
<img class="chat-icon" src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" data-tooltip="feinte" height="32" width="32" />
|
<img class="chat-icon" src="systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg" data-tooltip="feinte" height="32" width="32" />
|
||||||
C'était une feinte!
|
C'était une feinte!
|
||||||
{{/if}}
|
</span>
|
||||||
</p>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{> 'partial-info-appel-moral'}}
|
{{> 'partial-info-appel-moral'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="chat-actions">
|
<div class="chat-actions">
|
||||||
|
{{!-- TODO: maladresses --}}
|
||||||
{{> 'partial-recul-choc'}}
|
{{> 'partial-recul-choc'}}
|
||||||
{{> 'partial-encaissement'}}
|
{{> 'partial-encaissement'}}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
{{log this}}
|
|
||||||
<div class="roll-chat">
|
<div class="roll-chat">
|
||||||
<div class="chat-img">
|
<div class="chat-img">
|
||||||
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
|
<img src="{{active.img}}" data-tooltip="{{active.name}}" />
|
||||||
|
16
templates/roll/result/partial-attaque-particuliere.hbs
Normal file
16
templates/roll/result/partial-attaque-particuliere.hbs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{{#if particulieres.length}}
|
||||||
|
{{#if (eq particulieres.length 1)}}
|
||||||
|
{{#each particulieres as |part|}}
|
||||||
|
<span class='chat-card-info'>
|
||||||
|
<img src="{{part.img}}"/> Attaque particulière {{part.descr}}
|
||||||
|
</span>
|
||||||
|
{{/each}}
|
||||||
|
{{else}}
|
||||||
|
{{#each particulieres as |part|}}
|
||||||
|
<a class='chat-card-button choix-particuliere' data-particuliere='{{part.key}}'
|
||||||
|
data-tooltip="Choisir une particulière {{part.descr}}">
|
||||||
|
<img src="{{part.img}}"/> Choisir une particulière {{part.descr}}
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
@@ -4,8 +4,8 @@
|
|||||||
</select>
|
</select>
|
||||||
</subline>
|
</subline>
|
||||||
<roll-part-img>
|
<roll-part-img>
|
||||||
{{#if current.attaque.arme}}
|
{{#if current.arme}}
|
||||||
<img src="{{current.attaque.arme.img}}" data-tooltip="{{current.attaque.arme.name}}" />
|
<img src="{{current.arme.img}}" data-tooltip="{{current.arme.name}}" />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</roll-part-img>
|
</roll-part-img>
|
||||||
<roll-part-detail>
|
<roll-part-detail>
|
||||||
@@ -16,10 +16,10 @@
|
|||||||
</select>
|
</select>
|
||||||
</subline>
|
</subline>
|
||||||
<subline>
|
<subline>
|
||||||
{{#if (eq current.attaque.arme.system.mortalite 'empoignade')}}
|
{{#if (eq current.arme.system.mortalite 'empoignade')}}
|
||||||
Empoignade, pas de dommages directs
|
Empoignade, pas de dommages directs
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#if (and (ne current.attaque.arme.system.mortalite 'non-mortel') (eq current.dmg.penetration 0))}}
|
{{#if (and (ne current.arme.system.mortalite 'non-mortel') (eq current.dmg.penetration 0))}}
|
||||||
<input name="check-mortalite" type="checkbox" {{#if (eq current.dmg.mortalite 'mortel')}}checked{{/if}} />
|
<input name="check-mortalite" type="checkbox" {{#if (eq current.dmg.mortalite 'mortel')}}checked{{/if}} />
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<label for="check-mortalite">
|
<label for="check-mortalite">
|
||||||
|
Reference in New Issue
Block a user