Vincent Vandemeulebrouck
37c2b6432d
Les créatures peuvent avoir des compétences d'armes (lancer, mêlée, tir, armes naturelles), de parade, de possession, et générales. Les initiatives sont cohérentes. Les possessions sont en phase 10 d'initiative.
314 lines
13 KiB
JavaScript
314 lines
13 KiB
JavaScript
/* -------------------------------------------- */
|
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|
import { RdDRoll } from "./rdd-roll.js";
|
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
|
import { ChatUtility } from "./chat-utility.js";
|
|
import { STATUSES } from "./settings/status-effects.js";
|
|
|
|
/* -------------------------------------------- */
|
|
|
|
/* -------------------------------------------- */
|
|
export class RdDEmpoignade {
|
|
|
|
/* -------------------------------------------- */
|
|
static init() {
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static checkEmpoignadeEnCours(actor) {
|
|
// TODO: autoriser la perception? la comédie/séduction?
|
|
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
|
|
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static isEmpoignadeEnCours(actor) {
|
|
return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getEmpoignadeById(actor, id) {
|
|
let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id)
|
|
return emp && duplicate(emp) || undefined;
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static getEmpoignade(attacker, defender) {
|
|
let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id)
|
|
if (!emp) {
|
|
emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
|
}
|
|
if (emp) {
|
|
return duplicate(emp);
|
|
}
|
|
return undefined;
|
|
}
|
|
/* -------------------------------------------- */
|
|
static getMalusTaille(emp, attacker, defender) {
|
|
// Si pas empoigné, alors 0
|
|
if (emp.system.pointsemp == 0) {
|
|
return 0
|
|
}
|
|
// Malus de -1 si différence de taille de 2 ou plus (p 135)
|
|
if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) {
|
|
return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1)
|
|
}
|
|
return 0
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
|
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
|
const isNouvelle = empoignade == undefined;
|
|
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
|
|
|
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
|
|
|
let rollData = {
|
|
mode: mode,
|
|
isEmpoignade: true,
|
|
competence: attacker.getCompetence("Corps à corps").clone(),
|
|
selectedCarac: attacker.system.carac.melee,
|
|
empoignade: empoignade,
|
|
attackerId: attacker.id,
|
|
attackerName: attacker.name,
|
|
defenderName: defender.name,
|
|
defenderId: defender.id,
|
|
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
|
}
|
|
if (attacker.isCreatureEntite()) {
|
|
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
}
|
|
if (empoignade.system.pointsemp >= 2) {
|
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
} else {
|
|
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async onAttaqueEmpoignade(attacker, defender) {
|
|
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
|
const isNouvelle = empoignade == undefined;
|
|
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
|
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
|
|
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
|
|
ChatUtility.createChatWithRollMode(attacker.name, {
|
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.html`, { attacker: attacker, defender: defender })
|
|
})
|
|
} else {
|
|
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
|
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
|
const dialog = await RdDRoll.create(attacker, rollData,
|
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
|
{
|
|
name: 'jet-empoignade',
|
|
label: 'Empoigner',
|
|
callbacks: [
|
|
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, true, isNouvelle) },
|
|
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, false, isNouvelle) },
|
|
]
|
|
});
|
|
dialog.render(true);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) {
|
|
let attacker = game.actors.get(rollData.attackerId)
|
|
let defender = game.actors.get(rollData.defenderId)
|
|
|
|
let empoignade = rollData.empoignade
|
|
empoignade.isSuccess = isSuccess;
|
|
|
|
if (isSuccess && isNouvelle) {
|
|
// Creer l'empoignade sur attaquant/defenseur
|
|
await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
|
await defender.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
|
}
|
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") {
|
|
let attacker = game.actors.get(rollData.attackerId)
|
|
let defender = game.actors.get(rollData.defenderId)
|
|
let empoignade = this.getEmpoignade(attacker, defender)
|
|
|
|
if (!empoignade) {
|
|
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
|
return
|
|
}
|
|
|
|
empoignade = duplicate(empoignade)
|
|
rollData.mode = defenseMode
|
|
rollData.empoignade = empoignade
|
|
rollData.competence = defender.getCompetence(competenceName),
|
|
rollData.selectedCarac = defender.system.carac[carac],
|
|
rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker)
|
|
|
|
await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $rollDefenseEmpoignade(defender, rollData) {
|
|
const dialog = await RdDRoll.create(defender, rollData,
|
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
|
{
|
|
name: 'empoignade',
|
|
label: 'Contrer',
|
|
callbacks: [
|
|
{ action: async (r) => await RdDEmpoignade.$onRollContrerLiberer(r) }
|
|
]
|
|
}
|
|
);
|
|
dialog.render(true);
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $onRollContrerLiberer(rollData) {
|
|
let empoignade = rollData.empoignade
|
|
|
|
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
|
|
empoignade.system.pointsemp++
|
|
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
|
}
|
|
if (rollData.mode == "contrer-liberer" && !rollData.rolled.isSuccess) {
|
|
empoignade.system.pointsemp--
|
|
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
|
}
|
|
|
|
if (empoignade.system.pointsemp >= 2) {
|
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
}
|
|
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $updateEtatEmpoignade(empoignade) {
|
|
console.log("UPDATE Empoignade", empoignade)
|
|
|
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
|
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
|
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
|
await defender.updateEmbeddedDocuments('Item', [update])
|
|
|
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
|
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
|
await attacker.updateEmbeddedDocuments('Item', [update])
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async $deleteEmpoignade(empoignade) {
|
|
console.log("DELETE Empoignade", empoignade)
|
|
|
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
|
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
|
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
|
|
|
//let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
//emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
|
//await attacker.deleteEmbeddedDocuments('Item', [emp._id])
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async entrainerAuSol(rollData) {
|
|
let attacker = game.actors.get(rollData.attackerId)
|
|
let defender = game.actors.get(rollData.defenderId)
|
|
let empoignade = this.getEmpoignade(attacker, defender)
|
|
|
|
empoignade.system.ausol = true
|
|
await this.$updateEtatEmpoignade(empoignade)
|
|
|
|
await attacker.setEffect(STATUSES.StatusProne, true);
|
|
await defender.setEffect(STATUSES.StatusProne, true);
|
|
|
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async projeterAuSol(rollData) {
|
|
let attacker = game.actors.get(rollData.attackerId)
|
|
let defender = game.actors.get(rollData.defenderId)
|
|
let empoignade = this.getEmpoignade(attacker, defender)
|
|
|
|
await defender.setEffect(STATUSES.StatusProne, true);
|
|
await this.$deleteEmpoignade(empoignade)
|
|
|
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
}
|
|
/* -------------------------------------------- */
|
|
static async perteEndurance(rollData, perteMode) {
|
|
let attacker = game.actors.get(rollData.attackerId)
|
|
let defender = game.actors.get(rollData.defenderId)
|
|
let empoignade = this.getEmpoignade(attacker, defender)
|
|
|
|
//console.log("Perte d'endurance :!!!", perteMode)
|
|
let endValue = defender.system.sante.endurance.value
|
|
if (perteMode == "end0") {
|
|
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 RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async deleteAllEmpoignades() {
|
|
for (let actor of game.actors) {
|
|
let empIds = actor.itemTypes["empoignade"].map(it => it.id)
|
|
await actor.deleteEmbeddedDocuments('Item', empIds)
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async deleteLinkedEmpoignade(actorId, empoignade) {
|
|
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
|
|
let actor = game.actors.get(actorDeleteId)
|
|
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
|
|
if (emp) {
|
|
await actor.deleteEmbeddedDocuments('Item', [emp._id])
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------- */
|
|
static async createEmpoignade(attacker, defender) {
|
|
return await Item.create({
|
|
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
|
|
type: 'empoignade',
|
|
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
|
system: { description: "", empoignadeid: randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
|
|
},
|
|
{
|
|
temporary: true
|
|
})
|
|
}
|
|
} |