forked from public/foundryvtt-reve-de-dragon
212 lines
8.2 KiB
JavaScript
212 lines
8.2 KiB
JavaScript
import { ChatUtility } from "../chat-utility.js"
|
|
import RollDialog from "./roll-dialog.mjs"
|
|
import { RdDCarac } from "../rdd-carac.js"
|
|
import { RdDCombat } from "../rdd-combat.js"
|
|
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
|
|
import { RdDResolutionTable } from "../rdd-resolution-table.js"
|
|
import { RDD_CONFIG, renderTemplate } from "../constants.js"
|
|
import { EMPOIGNADE } from "../item/arme.js"
|
|
|
|
export default class ChatRollResult {
|
|
static init() {
|
|
ChatRollResult.instance = new ChatRollResult()
|
|
|
|
Hooks.on('renderChatLog', (log, html, chatLog) => ChatRollResult.instance.chatListeners(html))
|
|
}
|
|
|
|
static onReady() {
|
|
foundry.applications.handlebars.loadTemplates({
|
|
'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-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',
|
|
})
|
|
}
|
|
|
|
async display(roll) {
|
|
this.prepareDisplay(roll)
|
|
|
|
const chatMessage = await ChatUtility.createChatWithRollMode(
|
|
{
|
|
content: await this.buildRollHtml(roll)
|
|
},
|
|
roll.active.actor,
|
|
roll.current?.rollmode?.key
|
|
)
|
|
const save = RollDialog.saveParts(roll)
|
|
ChatUtility.setMessageData(chatMessage, 'rollData', save)
|
|
return chatMessage
|
|
}
|
|
|
|
prepareDisplay(roll) {
|
|
roll.done = roll.done ?? {}
|
|
roll.show = roll.show ?? {}
|
|
roll.show.chance = this.isAppelChancePossible(roll)
|
|
roll.show.encaissement = this.isShowEncaissement(roll)
|
|
roll.show.recul = this.getRecul(roll)
|
|
//roll.show.particuliere = roll.show.particuliere ?? []
|
|
}
|
|
|
|
isAppelChancePossible(roll) {
|
|
return roll.active.actor.isPersonnage() &&
|
|
roll.rolled.isEchec &&
|
|
RdDCarac.isActionPhysique(roll.current.carac?.key)
|
|
}
|
|
|
|
isShowEncaissement(roll) {
|
|
switch (roll.type.current) {
|
|
case ROLL_TYPE_DEFENSE:
|
|
return roll.rolled.isEchec && roll.attackerRoll?.dmg.mortalite != EMPOIGNADE
|
|
}
|
|
return false
|
|
}
|
|
|
|
|
|
getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
|
|
switch (roll.type.current) {
|
|
case ROLL_TYPE_DEFENSE:
|
|
{
|
|
const attaque = roll.attackerRoll
|
|
if (attaque &&
|
|
(roll.rolled.isEchec || !roll.current.defense.isEsquive) &&
|
|
(attaque.particuliere == 'force' || 'charge' == attaque.tactique?.key)) {
|
|
const taille = defender.system.carac.taille.value
|
|
const impact = attacker.system.carac.force.value + roll.attackerRoll?.dmg.dmgArme
|
|
return {
|
|
raison: 'charge' == attaque.tactique?.key ? 'charge' : 'particulière en force',
|
|
taille: taille,
|
|
impact: impact,
|
|
chances: RdDResolutionTable.computeChances(10, taille - impact).norm,
|
|
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
|
|
}
|
|
|
|
async buildRollHtml(roll) {
|
|
const template = `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${roll.type.current}.hbs`
|
|
return await renderTemplate(template, roll)
|
|
}
|
|
|
|
async chatListeners(html) {
|
|
$(html).on("click", '.appel-chance', event => this.onClickAppelChance(event))
|
|
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
|
|
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
|
|
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
|
|
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
|
|
|
|
}
|
|
|
|
getCombat(roll) {
|
|
switch (roll.type.current) {
|
|
case ROLL_TYPE_DEFENSE:
|
|
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.opponentId, roll.ids.opponentTokenId, roll.ids.actorTokenId)
|
|
case ROLL_TYPE_ATTAQUE:
|
|
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.actorId, roll.ids.actorTokenId, roll.ids.opponentId)
|
|
}
|
|
return undefined
|
|
}
|
|
|
|
async updateChatMessage(chatMessage, savedRoll) {
|
|
ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
|
|
const copy = foundry.utils.duplicate(savedRoll)
|
|
RollDialog.loadRollData(copy)
|
|
this.prepareDisplay(copy)
|
|
chatMessage.update({ content: await this.buildRollHtml(copy) })
|
|
chatMessage.render(true)
|
|
}
|
|
|
|
onClickAppelChance(event) {
|
|
const chatMessage = ChatUtility.getChatMessage(event)
|
|
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
|
const actor = game.actors.get(savedRoll.ids.actorId)
|
|
actor.rollAppelChance(
|
|
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
|
|
() => this.onAppelChanceEchec(savedRoll, chatMessage))
|
|
event.preventDefault()
|
|
}
|
|
|
|
onAppelChanceSuccess(savedRoll, chatMessage) {
|
|
const reRoll = foundry.utils.duplicate(savedRoll)
|
|
reRoll.type.retry = true
|
|
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
|
|
// TODO: annuler les effets
|
|
switch (reRoll.type.current) {
|
|
case ROLL_TYPE_DEFENSE:
|
|
this.getCombat(reRoll)?.doRollDefense(reRoll, callbacks)
|
|
break
|
|
case ROLL_TYPE_ATTAQUE:
|
|
// TODO
|
|
this.getCombat(reRoll)?.doRollAttaque(reRoll, callbacks)
|
|
break
|
|
default: {
|
|
RollDialog.create(reRoll, { callbacks: callbacks })
|
|
}
|
|
}
|
|
}
|
|
|
|
async onAppelChanceEchec(savedRoll, chatMessage) {
|
|
savedRoll.type.retry = true
|
|
await this.updateChatMessage(chatMessage, savedRoll)
|
|
}
|
|
|
|
onClickAppelDestinee(event) {
|
|
const chatMessage = ChatUtility.getChatMessage(event)
|
|
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
|
const actor = game.actors.get(savedRoll.ids.actorId)
|
|
|
|
actor.appelDestinee(async () => {
|
|
const reRoll = foundry.utils.duplicate(savedRoll)
|
|
reRoll.type.retry = true
|
|
RdDResolutionTable.significativeRequise(reRoll.rolled)
|
|
await this.updateChatMessage(chatMessage, reRoll)
|
|
})
|
|
}
|
|
|
|
async onClickEncaissement(event) {
|
|
const chatMessage = ChatUtility.getChatMessage(event)
|
|
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
|
const attaque = savedRoll.attackerRoll
|
|
const defender = game.actors.get(savedRoll.ids.actorId)
|
|
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
|
const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined
|
|
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
|
|
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
|
|
|
|
savedRoll.done.encaissement = true
|
|
await this.updateChatMessage(chatMessage, savedRoll)
|
|
}
|
|
|
|
async onClickRecul(event) {
|
|
const chatMessage = ChatUtility.getChatMessage(event)
|
|
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
|
const defender = game.actors.get(savedRoll.ids.actorId)
|
|
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
|
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
|
|
// const reculChoc = this.getReculChoc(savedRoll, defender, attacker)
|
|
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)
|
|
}
|
|
} |