Ajout compétence empoignade

This commit is contained in:
Vincent Vandemeulebrouck 2021-06-28 16:08:45 +02:00
parent ca4cf66b1b
commit 3edc740d8c
5 changed files with 115 additions and 54 deletions

View File

@ -138,7 +138,7 @@ export class RdDItemArme extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static armeUneOuDeuxMains(armeData, aUneMain) { static armeUneOuDeuxMains(armeData, aUneMain) {
armeData = Misc.data(armeData); armeData = Misc.data(armeData);
if (armeData) { if (armeData && !armeData.data.cac) {
armeData.data.unemain = armeData.data.unemain || !armeData.data.deuxmains; armeData.data.unemain = armeData.data.unemain || !armeData.data.deuxmains;
const uneOuDeuxMains = armeData.data.unemain && armeData.data.deuxmains; const uneOuDeuxMains = armeData.data.unemain && armeData.data.deuxmains;
const containsSlash = !Number.isInteger(armeData.data.dommages) && armeData.data.dommages.includes("/"); const containsSlash = !Number.isInteger(armeData.data.dommages) && armeData.data.dommages.includes("/");
@ -171,11 +171,12 @@ export class RdDItemArme extends Item {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } }; let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value); let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init })); armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
} }
static mainsNues(actorData = {}) { static corpsACorps(actorData) {
const mainsNues = { const corpsACorps = {
name: 'Mains nues', name: 'Corps à corps',
data: { data: {
equipe: true, equipe: true,
rapide: true, rapide: true,
@ -187,9 +188,24 @@ export class RdDItemArme extends Item {
categorie_parade: 'sans-armes' categorie_parade: 'sans-armes'
} }
}; };
if (actorData) { mergeObject(corpsACorps.data, actorData ??{}, { overwrite: false });
mergeObject(mainsNues.data, actorData, { overwrite: false }); return corpsACorps;
} }
static mainsNues(actorData) {
const mainsNues = RdDItemArme.corpsACorps(actorData);
mainsNues.name = 'Mains nues';
mainsNues.data.cac = 'pugilat';
mainsNues.data.baseInit = 4;
return mainsNues; return mainsNues;
} }
static empoignade(actorData) {
const empoignade = RdDItemArme.corpsACorps(actorData);
empoignade.name = 'Empoignade';
empoignade.data.cac = 'empoignade';
empoignade.data.baseInit = 3;
empoignade.data.mortalite = 'empoignade';
return empoignade;
}
} }

View File

@ -11,23 +11,23 @@ import { ReglesOptionelles } from "./regles-optionelles.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const premierRoundInit = [ const premierRoundInit = [
{ pattern: 'hast', init: 3.90 }, { pattern: 'hast', init: 5.90 },
{ pattern: 'lance', init: 3.85 }, { pattern: 'lance', init: 5.85 },
{ pattern: 'baton', init: 3.80 }, { pattern: 'baton', init: 5.80 },
{ pattern: 'doubledragonne', init: 3.75 }, { pattern: 'doubledragonne', init: 5.75 },
{ pattern: 'esparlongue', init: 3.70 }, { pattern: 'esparlongue', init: 5.70 },
{ pattern: 'epeedragonne', init: 3.65 }, { pattern: 'epeedragonne', init: 5.65 },
{ pattern: 'epeebatarde', init: 3.60 }, { pattern: 'epeebatarde', init: 5.60 },
{ pattern: 'epeecyane', init: 3.55 }, { pattern: 'epeecyane', init: 5.55 },
{ pattern: 'epeesorde', init: 3.50 }, { pattern: 'epeesorde', init: 5.50 },
{ pattern: 'grandehache', init: 3.45 }, { pattern: 'grandehache', init: 5.45 },
{ pattern: 'bataille', init: 3.40 }, { pattern: 'bataille', init: 5.40 },
{ pattern: 'epeegnome', init: 3.35 }, { pattern: 'epeegnome', init: 5.35 },
{ pattern: 'masse', init: 3.30 }, { pattern: 'masse', init: 5.30 },
{ pattern: 'gourdin', init: 3.25 }, { pattern: 'gourdin', init: 5.25 },
{ pattern: 'fléau', init: 3.20 }, { pattern: 'fléau', init: 5.20 },
{ pattern: 'dague', init: 3.15 }, { pattern: 'dague', init: 5.15 },
{ pattern: 'autre', init: 3.10 }, { pattern: 'autre', init: 5.10 },
]; ];
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -148,7 +148,8 @@ export class RdDCombatManager extends Combat {
let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence); let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence);
armesEquipe.push(armeData); armesEquipe.push(armeData);
armeData.data.initiative = RdDCombatManager.calculInitiative(armeData.data.niveau, carac[compData.data.defaut_carac].value); armeData.data.niveau = compData.data.niveau;
armeData.data.initiative = RdDCombatManager.calculInitiative(compData.data.niveau, carac[compData.data.defaut_carac].value);
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence // Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
if (armeData.data.unemain && !armeData.data.deuxmains) { if (armeData.data.unemain && !armeData.data.deuxmains) {
armeData.data.mainInfo = "(1m)"; armeData.data.mainInfo = "(1m)";
@ -185,7 +186,8 @@ export class RdDCombatManager extends Combat {
} else { } else {
// Recupération des items 'arme' // Recupération des items 'arme'
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it)) let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
.concat(RdDItemArme.mainsNues()); .concat(RdDItemArme.mainsNues())
.concat(RdDItemArme.empoignade());
let competences = items.filter(it => it.type == 'competence'); let competences = items.filter(it => it.type == 'competence');
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac)); actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
@ -277,30 +279,23 @@ export class RdDCombatManager extends Combat {
initOffset = 2; initOffset = 2;
initInfo = "Autre Action" initInfo = "Autre Action"
} else if (arme.name == "Draconic") { } else if (arme.name == "Draconic") {
initOffset = 7; initOffset = 9;
initInfo = "Draconic" initInfo = "Draconic"
} else { } else {
initOffset = 3; // Melée = 3.XX
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence)); compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence));
compNiveau = compData.data.niveau; compNiveau = compData.data.niveau;
initInfo = arme.name + " / " + arme.data.competence; initInfo = arme.name + " / " + arme.data.competence;
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
caracForInit = compData.data.carac_value; caracForInit = compData.data.carac_value;
if (compData.data.categorie == "lancer") { if (compData.data.categorie == "lancer") {
initOffset = 7;
}
else {
initOffset = 5; initOffset = 5;
} }
} else { } else {
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value; caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value;
if (compData.data.categorie == "lancer") { // Offset de principe pour les armes de jet initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, arme);
initOffset = 4;
}
if (compData.data.categorie == "tir") { // Offset de principe pour les armes de jet
initOffset = 5;
}
if (compData.data.categorie == "melee") { // Offset de principe pour les armes de jet
initOffset = 3;
}
} }
} }
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
@ -311,6 +306,21 @@ export class RdDCombatManager extends Combat {
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo }); game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
} }
static _baseInitOffset(categorie, arme) {
if (categorie == "tir") { // Offset de principe pour les armes de jet
return 8;
}
if (categorie == "lancer") { // Offset de principe pour les armes de jet
return 7;
}
// Offset de principe pour les armes de jet
switch (arme.data.cac) {
case "empoignade": return 3;
case "pugilat": return 4;
}
return 5;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static displayInitiativeMenu(html, combatantId) { static displayInitiativeMenu(html, combatantId) {
console.log("Combatant ; ", combatantId); console.log("Combatant ; ", combatantId);
@ -706,10 +716,21 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async attaque(competence, arme = undefined) { async attaque(competence, arme) {
if (!await this.accorderEntite('avant-attaque')) { if (!await this.accorderEntite('avant-attaque')) {
return; return;
} }
if (arme.data.cac =='empoignade' && this.attacker.isCombatTouche()){
ChatMessage.create({
alias: this.attacker.name,
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-actor-perte-empoignade.html', {
attacker: this.attacker,
competence: competence
})
});
return;
}
let rollData = this._prepareAttaque(competence, arme); let rollData = this._prepareAttaque(competence, arme);
console.log("RdDCombat.attaque >>>", rollData); console.log("RdDCombat.attaque >>>", rollData);
@ -742,6 +763,7 @@ export class RdDCombat {
_prepareAttaque(competence, arme) { _prepareAttaque(competence, arme) {
let rollData = { let rollData = {
passeArme: randomID(16), passeArme: randomID(16),
mortalite: arme?.data.mortalite,
coupsNonMortels: false, coupsNonMortels: false,
competence: competence, competence: competence,
surprise: this.attacker.getSurprise(true), surprise: this.attacker.getSurprise(true),
@ -758,7 +780,9 @@ export class RdDCombat {
} }
else { else {
// sans armes: à mains nues // sans armes: à mains nues
rollData.arme = RdDItemArme.mainsNues({ niveau: competence.data.niveau }); const niveau = competence.data.niveau;
const init = RdDCombatManager.calculInitiative(niveau, Misc.templateData(this.attacker).carac['melee'].value);
rollData.arme = RdDItemArme.mainsNues({ niveau: niveau, initiative: init });
} }
return rollData; return rollData;
} }
@ -767,8 +791,24 @@ export class RdDCombat {
async _onAttaqueParticuliere(rollData) { async _onAttaqueParticuliere(rollData) {
RdDCombat._storeAttaque(this.attackerId, rollData); RdDCombat._storeAttaque(this.attackerId, rollData);
// Finesse et Rapidité seulement en mêlée et si la difficulté libre est de -1 minimum
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
// force toujours, sauf empoignade
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
const isForce = !rollData.arme.data.empoignade;
const isFinesse = rollData.arme.data.empoignade || isMeleeDiffNegative;
const isRapide = !rollData.arme.data.empoignade && isMeleeDiffNegative && rollData.arme.data.rapide;
// si un seul choix possible, le prendre
if (isForce && !isFinesse && !isRapide) {
return await this.choixParticuliere(rollData, "force");
}
else if (!isForce && isFinesse && !isRapide) {
return await this.choixParticuliere(rollData, "finesse");
}
else if (!isForce && !isFinesse && isRapide) {
return await this.choixParticuliere(rollData, "rapidite");
}
ChatMessage.create({ ChatMessage.create({
alias: this.attacker.name, alias: this.attacker.name,
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
@ -776,8 +816,9 @@ export class RdDCombat {
alias: this.attacker.name, alias: this.attacker.name,
attackerId: this.attackerId, attackerId: this.attackerId,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
isFinesse: isMeleeDiffNegative, isForce: isForce,
isRapide: isMeleeDiffNegative && rollData.arme.data.rapide, isFinesse: isFinesse,
isRapide: isRapide,
passeArme: rollData.passeArme passeArme: rollData.passeArme
}) })
}); });

View File

@ -221,7 +221,7 @@ export class RdDRoll extends Dialog {
console.log("RdDRollSelectDialog - Cout reve", ptreve); console.log("RdDRollSelectDialog - Cout reve", ptreve);
this.updateRollResult(); this.updateRollResult();
}); });
html.find('#coupsNonMortels').change((event) => { html.find("[name='coupsNonMortels']").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel"; this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.updateRollResult(); this.updateRollResult();
}); });
@ -300,12 +300,14 @@ export class RdDRoll extends Dialog {
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat()); rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat());
rollData.caracValue = parseInt(rollData.selectedCarac.value); rollData.caracValue = parseInt(rollData.selectedCarac.value);
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? 'mortel';
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel'; rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac); rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
let dmgText = Misc.toSignedString(rollData.dmg.total); let dmgText = Misc.toSignedString(rollData.dmg.total);
if (rollData.coupsNonMortels) { switch (rollData.mortalite){
dmgText = `(${dmgText}) non-mortel` case 'non-mortel': dmgText = `(${dmgText}) non-mortel`; break;
case 'empoignade': dmgText = `empoignade`; break;
} }
RollDataAjustements.calcul(rollData, this.actor); RollDataAjustements.calcul(rollData, this.actor);
@ -318,7 +320,7 @@ export class RdDRoll extends Dialog {
// Mise à jour valeurs // Mise à jour valeurs
$(".dialog-roll-title").text(this._getTitle(rollData)); $(".dialog-roll-title").text(this._getTitle(rollData));
$('#coupsNonMortels').prop('checked', rollData.coupsNonMortels); $("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel');
$(".dmg-arme-actor").text(dmgText); $(".dmg-arme-actor").text(dmgText);
$('.table-ajustement').remove(); $('.table-ajustement').remove();
$(".table-resolution").remove(); $(".table-resolution").remove();

View File

@ -1,9 +1,11 @@
<div data-passearme="{{passeArme}}"> <div data-passearme="{{passeArme}}">
<h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4> <h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4>
{{#if isForce}}
<br> <br>
<a class="chat-card-button" id="particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}"> <a class="chat-card-button" id="particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}">
Attaquer en Force Attaquer en Force
</a> </a>
{{/if}}
{{#if isRapide}} {{#if isRapide}}
<br> <br>
<a class="chat-card-button" id="particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}"> <a class="chat-card-button" id="particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}">

View File

@ -45,13 +45,13 @@
<div class="flexrow"> <div class="flexrow">
{{#if (eq arme.data.mortalite 'non-mortel')}} {{#if (eq arme.data.mortalite 'non-mortel')}}
<label>D&eacute;gats:</label><label class="dmg-arme-actor"></label> <label>D&eacute;gats:</label><label class="dmg-arme-actor"></label>
{{else if (eq arme.data.mortalite 'empoignade')}}
<label>D&eacute;gats:</label><label>Empoignade</label>
{{else}} {{else}}
<label>D&eacute;gats: <label>D&eacute;gats:</label>
</label>
<span> <span>
<input class="attribute-value" type="checkbox" id="coupsNonMortels" name="coupsNonMortels" {{#if coupsNonMortels}}checked{{/if}}/> <input class="attribute-value" type="checkbox" name="coupsNonMortels" {{#unless (eq mortalite 'mortel')}}checked{{/unless}} />
<label class="dmg-arme-actor"> <label class="dmg-arme-actor"></label>
</label>
</span> </span>
{{/if}} {{/if}}
</div> </div>