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) {
armeData = Misc.data(armeData);
if (armeData) {
if (armeData && !armeData.data.cac) {
armeData.data.unemain = 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("/");
@ -171,11 +171,12 @@ export class RdDItemArme extends Item {
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { data: { niveau: -6 } };
let init = RdDCombatManager.calculInitiative(corpsACorps.data.niveau, carac['melee'].value);
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.data.niveau, initiative: init }));
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.data.niveau, initiative: init }));
}
static mainsNues(actorData = {}) {
const mainsNues = {
name: 'Mains nues',
static corpsACorps(actorData) {
const corpsACorps = {
name: 'Corps à corps',
data: {
equipe: true,
rapide: true,
@ -187,9 +188,24 @@ export class RdDItemArme extends Item {
categorie_parade: 'sans-armes'
}
};
if (actorData) {
mergeObject(mainsNues.data, actorData, { overwrite: false });
}
mergeObject(corpsACorps.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;
}
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 = [
{ pattern: 'hast', init: 3.90 },
{ pattern: 'lance', init: 3.85 },
{ pattern: 'baton', init: 3.80 },
{ pattern: 'doubledragonne', init: 3.75 },
{ pattern: 'esparlongue', init: 3.70 },
{ pattern: 'epeedragonne', init: 3.65 },
{ pattern: 'epeebatarde', init: 3.60 },
{ pattern: 'epeecyane', init: 3.55 },
{ pattern: 'epeesorde', init: 3.50 },
{ pattern: 'grandehache', init: 3.45 },
{ pattern: 'bataille', init: 3.40 },
{ pattern: 'epeegnome', init: 3.35 },
{ pattern: 'masse', init: 3.30 },
{ pattern: 'gourdin', init: 3.25 },
{ pattern: 'fléau', init: 3.20 },
{ pattern: 'dague', init: 3.15 },
{ pattern: 'autre', init: 3.10 },
{ pattern: 'hast', init: 5.90 },
{ pattern: 'lance', init: 5.85 },
{ pattern: 'baton', init: 5.80 },
{ pattern: 'doubledragonne', init: 5.75 },
{ pattern: 'esparlongue', init: 5.70 },
{ pattern: 'epeedragonne', init: 5.65 },
{ pattern: 'epeebatarde', init: 5.60 },
{ pattern: 'epeecyane', init: 5.55 },
{ pattern: 'epeesorde', init: 5.50 },
{ pattern: 'grandehache', init: 5.45 },
{ pattern: 'bataille', init: 5.40 },
{ pattern: 'epeegnome', init: 5.35 },
{ pattern: 'masse', init: 5.30 },
{ pattern: 'gourdin', init: 5.25 },
{ pattern: 'fléau', init: 5.20 },
{ pattern: 'dague', init: 5.15 },
{ 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);
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
if (armeData.data.unemain && !armeData.data.deuxmains) {
armeData.data.mainInfo = "(1m)";
@ -185,7 +186,8 @@ export class RdDCombatManager extends Combat {
} else {
// Recupération des items 'arme'
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');
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
@ -277,30 +279,23 @@ export class RdDCombatManager extends Combat {
initOffset = 2;
initInfo = "Autre Action"
} else if (arme.name == "Draconic") {
initOffset = 7;
initOffset = 9;
initInfo = "Draconic"
} else {
initOffset = 3; // Melée = 3.XX
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence));
compNiveau = compData.data.niveau;
initInfo = arme.name + " / " + arme.data.competence;
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
caracForInit = compData.data.carac_value;
if (compData.data.categorie == "lancer") {
initOffset = 7;
}
else {
initOffset = 5;
}
} else {
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 = 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;
}
initOffset = RdDCombatManager._baseInitOffset(compData.data.categorie, arme);
}
}
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 });
}
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) {
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')) {
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);
console.log("RdDCombat.attaque >>>", rollData);
@ -742,6 +763,7 @@ export class RdDCombat {
_prepareAttaque(competence, arme) {
let rollData = {
passeArme: randomID(16),
mortalite: arme?.data.mortalite,
coupsNonMortels: false,
competence: competence,
surprise: this.attacker.getSurprise(true),
@ -758,7 +780,9 @@ export class RdDCombat {
}
else {
// 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;
}
@ -767,8 +791,24 @@ export class RdDCombat {
async _onAttaqueParticuliere(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;
// 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({
alias: this.attacker.name,
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
@ -776,8 +816,9 @@ export class RdDCombat {
alias: this.attacker.name,
attackerId: this.attackerId,
defenderTokenId: this.defenderTokenId,
isFinesse: isMeleeDiffNegative,
isRapide: isMeleeDiffNegative && rollData.arme.data.rapide,
isForce: isForce,
isFinesse: isFinesse,
isRapide: isRapide,
passeArme: rollData.passeArme
})
});

View File

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

View File

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

View File

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