Empoignade V2

Correction, de l'empoignade en mode jet V2

- le défenseur diminue le nombre de points d'empoignade
- amélioration des messages liés à l'empoignade
- ajout de choix de pertes d'endurance à infliger
This commit is contained in:
2025-11-24 18:04:43 +01:00
parent 3f19886342
commit e2ee73bc4e
13 changed files with 183 additions and 122 deletions
+7
View File
@@ -1,5 +1,12 @@
# 13.0 # 13.0
## 13.0.20 - L'immobilisme d'Illysis
- Fenêtre de jet v2
- correction du compteur empoignade
- amélioration des messages liés à l'empoignade
- amélioration des choix de perte d'endurance
## 13.0.19 - L'introspection d'Illysis ## 13.0.19 - L'introspection d'Illysis
- Ajout d'un bouton pour les jets de résistance sous rêve actuel - Ajout d'un bouton pour les jets de résistance sous rêve actuel
+3 -5
View File
@@ -157,11 +157,9 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
async $finDeRoundEmpoignade() { async $finDeRoundEmpoignade() {
const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); await Promise.all(this.itemTypes[ITEM_TYPES.empoignade]
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this, .filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id)
game.actors.get(emp.system.empoigneid), .map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
emp
))
} }
async setSonne(sonne = true) { } async setSonne(sonne = true) { }
+1 -1
View File
@@ -105,7 +105,7 @@ export class RdDCombatManager extends Combat {
} }
else if (!combatant.actor.isActorCombat()) { else if (!combatant.actor.isActorCombat()) {
if (options.warning) { if (options.warning) {
ui.notifications.warn(`${combatant.name} ne peut pas combattre!`) ui.notifications.warn(`L'acteur ${combatant.name} ne peut pas combattre!`)
} }
return undefined return undefined
} }
+91 -59
View File
@@ -21,14 +21,21 @@ export class RdDEmpoignade {
} }
static async ajustementEmpoignade(attacker, defender, adjust = 1) { static async ajustementEmpoignade(attacker, defender, adjust = 1) {
const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16) if (empoignade?.system.empoigneurid == defender.id) {
let empoignade = RdDEmpoignade.getEmpoignade(defender, attacker)
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, defender, attacker, - adjust);
}
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, attacker, defender, adjust);
}
static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) {
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16);
const empFin = (empoignade?.system.pointsemp ?? 0) + adjust
if (empoignade) { if (empoignade) {
if (empoignade.system.empoigneurid == defender.id) { empoignade.system.pointsemp = empFin;
adjust = - adjust await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender);
}
empoignade.system.pointsemp += adjust
await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender)
} }
else { else {
await RdDEmpoignade.$createEtatEmpoignade({ await RdDEmpoignade.$createEtatEmpoignade({
@@ -39,24 +46,26 @@ export class RdDEmpoignade {
empoignadeid: empId, empoignadeid: empId,
empoigneurid: attacker.id, empoigneurid: attacker.id,
empoigneid: defender.id, empoigneid: defender.id,
pointsemp: adjust, pointsemp: empFin,
empoigneurname: attacker.name, empoigneurname: attacker.name,
empoignename: defender.name empoignename: defender.name
} }
}, attacker, defender) }, attacker, defender);
}
if (adjust != 0 && empFin == 2) {
await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade);
} }
const result = RdDEmpoignade.getEmpoignadeById(defender, empId); const result = RdDEmpoignade.getEmpoignadeById(defender, empId);
const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2) const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2);
const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2) const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2);
const grappling = Math.abs(result.system.pointsemp) > 0 const grappling = Math.abs(result.system.pointsemp) > 0;
await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled) await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled);
await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled) await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled);
await defender.setEffect(STATUSES.StatusGrappled, defGrappled) await defender.setEffect(STATUSES.StatusGrappled, defGrappled);
await attacker.setEffect(STATUSES.StatusGrappled, attGrappled) await attacker.setEffect(STATUSES.StatusGrappled, attGrappled);
return result return result
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static registerChatCallbacks(html) { static registerChatCallbacks(html) {
$(html).on("click", '.defense-empoignade-cac', event => { $(html).on("click", '.defense-empoignade-cac', event => {
@@ -93,7 +102,7 @@ export class RdDEmpoignade {
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
if (event.currentTarget.value && event.currentTarget.value != "none") { if (event.currentTarget.value && event.currentTarget.value != "none") {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value) RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
ChatUtility.removeChatMessageId(chatMessage.id) //ChatUtility.removeChatMessageId(chatMessage.id)
} }
}); });
} }
@@ -138,8 +147,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id) return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && foundry.utils.duplicate(emp) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -233,12 +241,24 @@ export class RdDEmpoignade {
MappingCreatureArme.setRollDataCreature(rollData) MappingCreatureArme.setRollDataCreature(rollData)
} }
if (empoignade.system.pointsemp >= 2) { if (empoignade.system.pointsemp >= 2) {
if (!empoignade.system.ausol) { await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade)
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
} else { } else {
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle); await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle)
}
}
static async proposerEntrainerAuSol(attacker, defender, empoignade) {
if (!empoignade.system.ausol) {
const mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
const rollData = {
mode, empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps(),
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
const msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
} }
@@ -249,7 +269,14 @@ export class RdDEmpoignade {
await this.onAttaqueEmpoignadeValidee(attacker, defender) await this.onAttaqueEmpoignadeValidee(attacker, defender)
} }
static async onImmobilisation(attacker, defender, empoignade) { static async onImmobilisation(attacker, empoignade) {
const defender = game.actors.get(empoignade.system.empoigneid)
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{
_id: empDefenseur.id,
'system.immobilise': true
}])
const rollData = { const rollData = {
mode: "immobilise", mode: "immobilise",
empoignade, attacker, defender, empoignade, attacker, defender,
@@ -372,29 +399,35 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) { static async $updateEtatEmpoignade(empoignade, attacker, defender) {
console.log("UPDATE Empoignade", empoignade)
const belligerants = [ const belligerants = [
attacker ?? game.actors.get(empoignade.system.empoigneurid), attacker ?? game.actors.get(empoignade.system.empoigneurid),
defender ?? game.actors.get(empoignade.system.empoigneid)] defender ?? game.actors.get(empoignade.system.empoigneid)]
const removeEmp = empoignade.system.pointsemp == 0
await Promise.all( if (removeEmp) {
belligerants.map(async belligerant => { const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid) return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
return await belligerant.updateEmbeddedDocuments('Item', [{ }
_id: emp._id, else {
"system.pointsemp": empoignade.system.pointsemp, await Promise.all(
"system.ausol": empoignade.system.ausol belligerants.map(async belligerant => {
}]) const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
})) return await belligerant.updateEmbeddedDocuments('Item', [{
_id: emp.id,
"system.pointsemp": empoignade.system.pointsemp,
"system.ausol": empoignade.system.ausol
}])
}))
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $deleteEmpoignade(empoignade) { static async $deleteEmpoignade(empoignade) {
console.log("DELETE Empoignade", empoignade) console.log("DELETE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid) const defender = game.actors.get(empoignade.system.empoigneid)
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid) const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp._id]) await defender.deleteEmbeddedDocuments('Item', [emp.id])
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -436,29 +469,28 @@ export class RdDEmpoignade {
static async perteEndurance(rollData, perteMode) { static async perteEndurance(rollData, perteMode) {
let attacker = game.actors.get(rollData.attacker.id) let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id) let defender = game.actors.get(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) const perteEndurance = await RdDEmpoignade.$calcPerteEnd(perteMode, defender.system.sante.endurance.value)
await defender.santeIncDec("endurance", -perteEndurance)
//console.log("Perte d'endurance :!!!", perteMode) await RdDRollResult.displayRollData({ attacker, defender, perteEndurance },
let endValue = defender.system.sante.endurance.value attacker,
if (perteMode == "end0") { 'chat-empoignade-perte-endurance.hbs')
await defender.santeIncDec("endurance", -endValue);
}
if (perteMode == "end1") {
await defender.santeIncDec("endurance", -(endValue - 1));
}
if (perteMode == "endmoitie") {
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
}
if (perteMode == "endquart") {
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
}
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
static async $calcPerteEnd(perteMode, endValue) {
switch (perteMode) {
case "none": return 0
case "end0": return endValue
case "end1": return (endValue - 1)
case "3/4": return Math.floor(3 * endValue / 4)
case "1/2": return Math.floor(endValue / 2)
case "1/4": return Math.floor(endValue / 4)
}
const rolled = await (new Roll(perteMode).evaluate())
return rolled.total
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async deleteAllEmpoignades() { static async deleteAllEmpoignades() {
for (let actor of game.actors) { for (let actor of game.actors) {
@@ -473,7 +505,7 @@ export class RdDEmpoignade {
let actor = game.actors.get(actorDeleteId) let actor = game.actors.get(actorDeleteId)
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid) let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (emp) { if (emp) {
await actor.deleteEmbeddedDocuments('Item', [emp._id]) await actor.deleteEmbeddedDocuments('Item', [emp.id])
} }
} }
-1
View File
@@ -73,7 +73,6 @@ export class StatusEffects extends FormApplication {
CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddEffectIds.includes(it.id))) CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddEffectIds.includes(it.id)))
StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects()); StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects());
console.log('statusEffects', CONFIG.statusEffects);
} }
static isSurprise(effect) { static isSurprise(effect) {
+2 -1
View File
@@ -644,7 +644,8 @@
"pointsemp": 0, "pointsemp": 0,
"empoigneurname": "", "empoigneurname": "",
"empoignename": "", "empoignename": "",
"ausol": false "ausol": false,
"immobilise": false
}, },
"possession": { "possession": {
"templates": ["description"], "templates": ["description"],
+1 -1
View File
@@ -72,7 +72,7 @@
{{#if options.vueDetaillee}} {{#if options.vueDetaillee}}
     
{{#if @root.options.vueArchetype}} {{#if @root.options.vueArchetype}}
<a class="competence-archetype toggle-archetype chat-card-button-pushed" data-tooltip="Retour à la vue détaillée des compétences"> <a class="competence-archetype toggle-archetype chat-card-button-checked" data-tooltip="Retour à la vue détaillée des compétences">
<i class="fa-solid fa-up-right-from-square"></i>Incarnation <i class="fa-solid fa-up-right-from-square"></i>Incarnation
</a> </a>
{{else}} {{else}}
+18 -15
View File
@@ -1,15 +1,18 @@
<h4><img class="chat-icon" src="{{competence.img}}" /> <div class="roll-chat" data-passearme="{{passeArme}}">
{{attacker.name}} a empoigné {{defender.name}} <div class="chat-img">
</h4> <img src="{{active.img}}" data-tooltip="{{active.name}}" />
<hr> <img src="{{competence.img}}" data-tooltip="Empoignade" />
<p> </div>
<span class='chat-card-button-area'> <div class="chat-header">
{{attacker.name}} vient d'obtenir 2 points d'Emp, et peut <h4>{{attacker.name}} a empoigné {{defender.name}}</h4>
entraîner {{defender.name}} au sol. Les deux protagonistes </div>
restent empoignés.
<br> <div class="chat-resume">
<a class='empoignade-entrainer-sol chat-card-button'> {{attacker.name}} vient d'obtenir 2 points d'empoignade contre {{defender.name}}, et
Entraîner au sol peut l'<strong>entraîner au sol</strong>. Les deux protagonistes resteront empoignés.
</a> </div>
</span>
</p> <div class="chat-actions">
<a class='chat-card-button empoignade-entrainer-sol'>Entraîner au sol</a>
</div>
</div>
+43 -30
View File
@@ -1,31 +1,44 @@
<h4><img class="chat-icon" src="{{competence.img}}" /> <div class="roll-chat" data-passearme="{{passeArme}}">
{{attacker.name}} a empoigné {{defender.name}} <div class="chat-img">
</h4> <img src="{{attacker.img}}" data-tooltip="{{attacker.name}}" />
<hr> <img src="{{competence.img}}" data-tooltip="Empoignade" />
<p> </div>
<span class='chat-card-button-area'>
{{attacker.name}} a obtenu 2 points d'Emp à la fin du round précédent, et peut: <div class="chat-header">
<ul><li> <h4>{{attacker.name}} a empoigné {{defender.name}}</h4>
faire perdre des points d'Endurance à {{defender.name}} </div>
<br>
<a class='empoignade-perte-endurance chat-card-button'> <div class="chat-resume">
<select class='empoignade-perte-endurance'> {{attacker.name}} a 2 points d'empoignade contre {{defender.name}} à la fin du round,
<option value="none">Faire perdre de l'endurance (selectionnez)</option> et peut lui faire <strong>perdre des points d'endurance</strong>
<option value="end0">Endurance à 0</option> {{#unless empoignade.system.ausol}}
<option value="end1">Endurance à 1</option> ou le <strong>projeter au sol</strong>. Les deux protagonistes ne sont plus empoignés
<option value="endmoitie">La moitié de l'endurance</option> {{/unless}}.
<option value="endquart">Le quart de l'endurance</option> </div>
</select>
</a> <div class="chat-details">
{{#if empoignade.system.ausol}} </div>
{{else}}
</li><li> <div class="chat-actions">
projeter {{defender.name}} au sol. Les deux protagonistes ne sont plus empoignés. <select class='chat-card-select empoignade-perte-endurance'>
<br> <option value="none">Choisir la perte d'endurance:</option>
<a class='empoignade-projeter-sol chat-card-button'> <option value="end0">Endurance à 0</option>
Projeter au sol <option value="end1">Endurance à 1</option>
</a> <option value="3/4">&frac34; de l'endurance</option>
{{/if}} <option value="1/2">&frac12; de l'endurance</option>
</li></ul> <option value="1/4">&frac14; de l'endurance</option>
</span> <option value="1d4">1d4 d'endurance</option>
<option value="1d6">1d6 d'endurance</option>
<option value="2d6">2d6 d'endurance</option>
<option value="1">1 point d'endurance</option>
<option value="2">2 point d'endurance</option>
</select>
{{!-- <a class='chat-card-button empoignade-perte-endurance'>
</a> --}}
{{#unless empoignade.system.ausol}}
<a class='chat-card-button empoignade-projeter-sol'>
Projeter au sol
</a>
{{/unless}}
</div>
</p> </p>
+13 -7
View File
@@ -1,7 +1,13 @@
<h4><img class="chat-icon" src="{{competence.img}}" /> <div class="roll-chat" >
{{attacker.name}} a fait perdre de l'endurance à {{defender.name}} <div class="chat-img">
</h4> <img src="{{attacker.img}}" data-tooltip="{{attacker.name}}" />
<hr> </div>
<p>
{{defender.name}} reste immobilisé. L'empoignade peut continuer. <div class="chat-header">
</p> <h4>{{attacker.name}} a fait perdre {{perteEndurance}} points d'endurance à {{defender.name}}</h4>
</div>
<div class="chat-resume">
{{defender.name}} reste immobilisé. L'empoignade peut continuer.
</div>
</div>
+4
View File
@@ -6,6 +6,10 @@
<label for="system.pointsemp">Points d'Empoignade </label> <label for="system.pointsemp">Points d'Empoignade </label>
<input class="attribute-value" type="text" name="system.pointsemp" value="{{system.pointsemp}}" data-dtype="Number"/> <input class="attribute-value" type="text" name="system.pointsemp" value="{{system.pointsemp}}" data-dtype="Number"/>
</div> </div>
<div class="form-group">
<label for="system.immobilise">Immobilisé </label>
<input type="checkbox" name="system.immobilise" {{#if system.immobilise}}checked{{/if}}/>
</div>
{{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.hbs"}} {{>"systems/foundryvtt-reve-de-dragon/templates/partial-item-description.hbs"}}
</section> </section>
</form> </form>
-1
View File
@@ -61,7 +61,6 @@
<div class="chat-actions"> <div class="chat-actions">
{{> 'partial-choix-maladresse'}} {{> 'partial-choix-maladresse'}}
{{> 'partial-attaque-particuliere'}} {{> 'partial-attaque-particuliere'}}
{{!-- TODO: maladresses --}}
</div> </div>
<div class="chat-buttons"> <div class="chat-buttons">
@@ -1,4 +1,3 @@
{{log 'partial-encaissement' this}}
{{#if show.encaissement}} {{#if show.encaissement}}
{{#if done.encaissement}} {{#if done.encaissement}}
<span class='chat-card-info'> <span class='chat-card-info'>