forked from public/foundryvtt-reve-de-dragon
Montée TMR sur méditation
ajout d'un bouton pour aller dans les TMR lors d'une méditation réussie
This commit is contained in:
@@ -8,6 +8,7 @@ import { RDD_CONFIG, renderTemplate } from "../constants.js"
|
||||
import { EMPOIGNADE } from "../item/arme.js"
|
||||
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"
|
||||
import { RollTypeCuisine } from "./roll-type-cuisine.mjs"
|
||||
import { RollTypeMeditation } from "./roll-type-meditation.mjs"
|
||||
|
||||
export default class ChatRollResult {
|
||||
static init() {
|
||||
@@ -38,7 +39,7 @@ export default class ChatRollResult {
|
||||
)
|
||||
const save = RollDialog.saveParts(roll, impacts)
|
||||
|
||||
ChatUtility.setMessageData(chatMessage, 'rollData', save)
|
||||
await this.saveChatMessageRoll(chatMessage, save)
|
||||
return chatMessage
|
||||
}
|
||||
|
||||
@@ -112,6 +113,8 @@ export default class ChatRollResult {
|
||||
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
|
||||
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
|
||||
$(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event))
|
||||
$(html).on("click", '.monter-tmr-normale', event => this.onClickMonteeTMR(event, 'normal'))
|
||||
$(html).on("click", '.monter-tmr-rapide', event => this.onClickMonteeTMR(event, 'rapide'))
|
||||
|
||||
}
|
||||
|
||||
@@ -125,8 +128,16 @@ export default class ChatRollResult {
|
||||
return undefined
|
||||
}
|
||||
|
||||
async saveChatMessageRoll(chatMessage, savedRoll) {
|
||||
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
|
||||
}
|
||||
|
||||
loadChatMessageRoll(chatMessage) {
|
||||
return ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
}
|
||||
|
||||
async updateChatMessage(chatMessage, savedRoll) {
|
||||
ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
|
||||
await this.saveChatMessageRoll(chatMessage, savedRoll)
|
||||
const copy = foundry.utils.duplicate(savedRoll)
|
||||
RollDialog.loadRollData(copy)
|
||||
this.prepareDisplay(copy)
|
||||
@@ -136,7 +147,7 @@ export default class ChatRollResult {
|
||||
|
||||
onClickAppelChance(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const actor = game.actors.get(savedRoll.ids.actorId)
|
||||
actor.rollAppelChance(
|
||||
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
|
||||
@@ -144,11 +155,13 @@ export default class ChatRollResult {
|
||||
event.preventDefault()
|
||||
}
|
||||
|
||||
onAppelChanceSuccess(savedRoll, chatMessage) {
|
||||
async onAppelChanceSuccess(savedRoll, chatMessage) {
|
||||
const reRoll = foundry.utils.duplicate(savedRoll)
|
||||
console.log('onAppelChanceSuccess savedRoll', savedRoll)
|
||||
reRoll.type.retry = true
|
||||
await this.updateChatMessage(chatMessage, reRoll)
|
||||
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
|
||||
|
||||
// TODO: annuler les effets
|
||||
switch (reRoll.type.current) {
|
||||
case ROLL_TYPE_DEFENSE:
|
||||
@@ -171,7 +184,7 @@ export default class ChatRollResult {
|
||||
|
||||
onClickAppelDestinee(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const actor = game.actors.get(savedRoll.ids.actorId)
|
||||
|
||||
actor.appelDestinee(async () => {
|
||||
@@ -184,7 +197,7 @@ export default class ChatRollResult {
|
||||
|
||||
async onClickEncaissement(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
const attaque = savedRoll.attackerRoll
|
||||
const defender = game.actors.get(savedRoll.ids.actorId)
|
||||
const attacker = game.actors.get(savedRoll.ids.opponentId)
|
||||
@@ -198,7 +211,7 @@ export default class ChatRollResult {
|
||||
|
||||
async onClickRecul(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
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)
|
||||
@@ -209,15 +222,29 @@ export default class ChatRollResult {
|
||||
async onClickChoixParticuliere(event) {
|
||||
const choix = event.currentTarget.attributes['data-particuliere'].value
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
savedRoll.particuliere = choix
|
||||
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll, callbacks)
|
||||
}
|
||||
|
||||
async onClickFaireGouter(event) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
if (!savedRoll.type.retry) {
|
||||
savedRoll.type.retry = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
await new RollTypeCuisine().onFaireGouter(savedRoll)
|
||||
}
|
||||
|
||||
async onClickMonteeTMR(event, mode) {
|
||||
const chatMessage = ChatUtility.getChatMessage(event)
|
||||
const savedRoll = this.loadChatMessageRoll(chatMessage)
|
||||
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
|
||||
savedRoll.done.meditation = true
|
||||
await this.updateChatMessage(chatMessage, savedRoll)
|
||||
}
|
||||
}
|
||||
}
|
@@ -443,7 +443,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
async roll() {
|
||||
|
||||
const roll = RollDialog.saveParts(this.rollData)
|
||||
this.loadRollData(roll)
|
||||
RollDialog.loadRollData(roll)
|
||||
const selectedRollType = this.getSelectedType(roll);
|
||||
selectedRollType.onSelect(roll)
|
||||
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
|
||||
@@ -472,7 +472,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
|
||||
this.rollOptions.onRollDone(this)
|
||||
}
|
||||
|
||||
loadRollData(roll) {
|
||||
static loadRollData(roll) {
|
||||
RollDialog.$prepareRollData(roll)
|
||||
RollDialog.calculAjustements(roll)
|
||||
roll.v2 = true
|
||||
|
@@ -32,17 +32,17 @@ export class RollTypeCuisine extends RollType {
|
||||
if (current.fabriquer) {
|
||||
const plat = this.$prepareNourriture(rollData.active.name, current, result)
|
||||
result.messages.push(`${plat.system.quantite} ${plat.name} ont été préparés dans l'équipement`)
|
||||
impacts.active.addCreatedItem(plat)
|
||||
impacts.active.addCreated('Item', plat)
|
||||
result.plat = { id: plat.id }
|
||||
}
|
||||
if (current.ingredient) {
|
||||
const quantite = Math.min(current.proportions, current.ingredient.system.quantite)
|
||||
if (quantite == current.ingredient.system.quantite) {
|
||||
impacts.active.addDeletedItem(current.ingredient)
|
||||
impacts.active.addDeleted('Item', current.ingredient)
|
||||
result.messages.push(`Il n'y a plus de ${ingredient.name}`)
|
||||
}
|
||||
else {
|
||||
impacts.active.addItemDelta(current.ingredient, 'system.quantite', -current.proportions)
|
||||
impacts.active.addDelta('Item', current.ingredient, 'system.quantite', -current.proportions)
|
||||
result.messages.push(`${current.proportions} ${current.ingredient.name} ont été utilisés`)
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ export class RollTypeCuisine extends RollType {
|
||||
onApplyImpacts(roll, impacts) {
|
||||
if (roll.result.plat) {
|
||||
// le plat n'est pas créé immédiatement, il faut donc retrouver l'id
|
||||
roll.result.plat.id = impacts.active.itemCreates.find(it => it.id = roll.result.plat.id)?.createdId
|
||||
roll.result.plat.id = impacts.active.findCreatedId('Item', roll.result.plat.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { RdDItemSigneDraconique } from "../item/signedraconique.js"
|
||||
import { RollBasicParts } from "./roll-basic-parts.mjs"
|
||||
import { DIFF, ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
|
||||
import { PART_MEDITATION } from "./roll-part-meditation.mjs"
|
||||
import { RollType } from "./roll-type.mjs"
|
||||
@@ -26,7 +27,7 @@ export class RollTypeMeditation extends RollType {
|
||||
const rolled = rollData.rolled
|
||||
if (meditation && rolled) {
|
||||
if (rolled.isSuccess) {
|
||||
await actor.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)])
|
||||
await actor.createEmbeddedDocuments('Item', [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)])
|
||||
}
|
||||
if (rolled.isEPart) {
|
||||
await actor.updateEmbeddedDocuments('Item', [{ _id: meditation._id, 'system.malus': meditation.system.malus - 1 }])
|
||||
@@ -34,4 +35,9 @@ export class RollTypeMeditation extends RollType {
|
||||
await actor.santeIncDec("fatigue", 2)
|
||||
}
|
||||
}
|
||||
|
||||
async onMonteeTMR(savedRoll, mode){
|
||||
const actor = RollBasicParts.getTokenActor(savedRoll).actor
|
||||
return actor?.displayTMR(mode)
|
||||
}
|
||||
}
|
@@ -1,15 +1,25 @@
|
||||
|
||||
const ACTOR_EMBEDDED_DOCTYPES = ['Item', 'ActiveEffect']
|
||||
/**
|
||||
* class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these
|
||||
*/
|
||||
export class ActorImpacts {
|
||||
static $newDocumentImpacts(docType) {
|
||||
return { creates: [], deletes: [], updates: [], docType: docType }
|
||||
}
|
||||
static $checkDocType(docType) {
|
||||
if (!ACTOR_EMBEDDED_DOCTYPES.includes(docType)) {
|
||||
throw `Unsupported document type ${docType}`
|
||||
}
|
||||
}
|
||||
|
||||
constructor(actorToken) {
|
||||
this.actorToken = actorToken
|
||||
this.updates = []
|
||||
this.deltas = []
|
||||
this.itemCreates = []
|
||||
this.itemUpdates = []
|
||||
this.itemDeletes = []
|
||||
ACTOR_EMBEDDED_DOCTYPES.forEach(
|
||||
docType => this[docType] = ActorImpacts.$newDocumentImpacts(docType)
|
||||
)
|
||||
}
|
||||
|
||||
addActorUpdate(path, value) {
|
||||
@@ -27,46 +37,55 @@ export class ActorImpacts {
|
||||
}
|
||||
}
|
||||
|
||||
addDeletedItem(item) {
|
||||
this.itemDeletes.push(item)
|
||||
}
|
||||
addCreatedItem(item) {
|
||||
this.itemCreates.push(item)
|
||||
addDeleted(docType, document) {
|
||||
ActorImpacts.$checkDocType(docType)
|
||||
this[docType].deletes.push(document)
|
||||
}
|
||||
|
||||
addItemUpdate(item, path, value) {
|
||||
const existing = this.itemUpdates.find(it => it.id == item.id)
|
||||
addCreated(docType, document) {
|
||||
ActorImpacts.$checkDocType(docType)
|
||||
this[docType].creates.push(document)
|
||||
}
|
||||
|
||||
addUpdate(docType, document, path, value) {
|
||||
ActorImpacts.$checkDocType(docType)
|
||||
const update = [path, value]
|
||||
const existing = this[docType].updates.find(it => it.id == document.id)
|
||||
if (existing) {
|
||||
existing.updates.push(update)
|
||||
}
|
||||
else {
|
||||
this.itemUpdates.push({ id: item.id, updates: [update], deltas: [] })
|
||||
this[docType].updates.push({ id: document.id, updates: [update], deltas: [] })
|
||||
}
|
||||
}
|
||||
|
||||
addItemDelta(item, path, value) {
|
||||
addDelta(document, path, value) {
|
||||
ActorImpacts.$checkDocType(document)
|
||||
const intValue = Number.parseInt(value)
|
||||
if (Number.isInteger(intValue) && intValue != 0) {
|
||||
const delta = [path, intValue]
|
||||
const existing = this.itemUpdates.find(it => it.id == item.id)
|
||||
const existing = this[docType].updates.find(it => it.id == document.id)
|
||||
if (existing) {
|
||||
existing.deltas.push(delta)
|
||||
}
|
||||
else {
|
||||
this.itemUpdates.push({ id: item.id, updates: [], deltas: [delta] })
|
||||
this[docType].updates.push({ id: document.id, updates: [], deltas: [delta] })
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error('Cannot use non integer value {} for delta update', value)
|
||||
console.error('Cannot use non-integer value {} for delta update', value)
|
||||
}
|
||||
}
|
||||
|
||||
reverseImpacts() {
|
||||
const reverse = ActorImpacts.$computeReverts(new ActorImpacts(this.actorToken), this, __ => this.actorToken.actor)
|
||||
reverse.itemCreates = this.itemDeletes.map(it => foundry.utils.duplicate(it))
|
||||
reverse.itemDeletes = this.itemCreates.map(it => { return { id: it.id } })
|
||||
reverse.itemUpdates = this.itemUpdates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getActorItem(id)))
|
||||
ACTOR_EMBEDDED_DOCTYPES.forEach(
|
||||
docType => {
|
||||
reverse[docType].creates = this[docType].deletes.map(it => foundry.utils.duplicate(it))
|
||||
reverse[docType].deletes = this[docType].creates.map(it => { return { id: it.id } })
|
||||
reverse[docType].updates = this[docType].updates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getEmbeddedDocument(docType, id)))
|
||||
}
|
||||
)
|
||||
return reverse
|
||||
}
|
||||
|
||||
@@ -77,40 +96,44 @@ export class ActorImpacts {
|
||||
|
||||
async applyImpacts() {
|
||||
const actor = this.actorToken.actor
|
||||
const isItemsDelete = this.itemDeletes.length > 0
|
||||
const isItemsCreate = this.itemCreates.length > 0
|
||||
const isItemsUpdate = this.itemUpdates.length > 0
|
||||
const isActorUpdate = this.updates.length > 0 || this.deltas.length > 0
|
||||
await Promise.all(ACTOR_EMBEDDED_DOCTYPES.map(async docType => await this.$applyDocumentsImpacts(actor, docType)))
|
||||
const updates = ActorImpacts.$computeUpdates(this, id => actor)
|
||||
await actor.update(updates, { render: true })
|
||||
}
|
||||
|
||||
if (isItemsDelete) {
|
||||
const deletes = this.itemDeletes.map(it => it.id)
|
||||
await actor.deleteEmbeddedDocuments('Item', deletes, { render: !(isItemsCreate || isItemsUpdate || isActorUpdate) })
|
||||
|
||||
async $applyDocumentsImpacts(actor, docType) {
|
||||
if (this[docType].deletes.length > 0) {
|
||||
const deletes = this[docType].deletes.map(it => it.id)
|
||||
await actor.deleteEmbeddedDocuments(docType, deletes, { render: false })
|
||||
}
|
||||
|
||||
if (isItemsCreate) {
|
||||
const creates = this.itemCreates
|
||||
const created = await actor.createEmbeddedDocuments('Item', creates, { render: !(isItemsUpdate || isActorUpdate)})
|
||||
for (let i=0; i<creates.length; i++){
|
||||
if (this[docType].creates.length > 0) {
|
||||
const creates = this[docType].creates
|
||||
const created = await actor.createEmbeddedDocuments(docType, creates, { render: false })
|
||||
for (let i = 0; i < creates.length; i++) {
|
||||
creates[i].createdId = created[i].id
|
||||
}
|
||||
}
|
||||
|
||||
if (isItemsUpdate) {
|
||||
const updates = this.itemUpdates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getActorItem(id)))
|
||||
await actor.updateEmbeddedDocuments('Item', updates, { render: !isActorUpdate })
|
||||
}
|
||||
|
||||
if (isActorUpdate) {
|
||||
const updates = ActorImpacts.$computeUpdates(this, id => actor)
|
||||
await actor.update(updates, { render: true })
|
||||
if (this[docType].updates.length > 0) {
|
||||
const updates = this[docType].updates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getEmbeddedDocument(docType, id)))
|
||||
await actor.updateEmbeddedDocuments(docType, updates, { render: false })
|
||||
}
|
||||
}
|
||||
|
||||
$getActorItem(id) {
|
||||
return this.actorToken.actor.items.get(id)
|
||||
findCreatedId(docType, origId){
|
||||
return this[docType].creates.find(it => it.id = origId)?.createdId
|
||||
}
|
||||
|
||||
$getEmbeddedDocument(docType, id) {
|
||||
return this.actorToken.actor.getEmbeddedDocument(docType, id)
|
||||
}
|
||||
|
||||
static $computeUpdates(u, getSource) {
|
||||
if (u.updates.length == 0 && u.deltas.length == 0) {
|
||||
return {}
|
||||
}
|
||||
const source = getSource(u.id)
|
||||
const instruction = { _id: u.id }
|
||||
u.updates.forEach(u => instruction[u[0]] = u[1])
|
||||
@@ -124,5 +147,4 @@ export class ActorImpacts {
|
||||
target.deltas = u.deltas.map(d => [d[0], -d[1]])
|
||||
return target
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,12 +21,12 @@
|
||||
<p>
|
||||
{{active.name}}
|
||||
{{#if rolled.isSuccess}}
|
||||
réussit la recette, pour un plat de qualité {{result.qualite~}}
|
||||
{{#if (lt result.exotisme 0)}}et d'exotisme {{result.exotisme}}{{/if~}}
|
||||
réussit la recette, pour un plat de qualité {{result.qualite}}
|
||||
{{#if (lt result.exotisme 0)}}et d'exotisme {{result.exotisme}}{{/if}}
|
||||
{{else}}
|
||||
fait un piètre cuisinier, et obtient un plat de qualité {{result.qualite~}}
|
||||
{{#if (lt result.exotisme 0)}}à l'exotisme certain ({{result.exotisme}}){{/if~}}
|
||||
{{/if~}}.
|
||||
fait un piètre cuisinier, et obtient un plat de qualité {{result.qualite}}
|
||||
{{#if (lt result.exotisme 0)}}à l'exotisme certain ({{result.exotisme}}){{/if}}
|
||||
{{~/if~}}.
|
||||
{{#if (lt result.exotisme 0)}}
|
||||
<br>Au vu de l'exotisme du plat, les convives devront réussir un jet de @roll[Volonté/Cuisine/{{result.exotisme}}].
|
||||
En cas d'échec, ils peuvent se forcer à faire plaisir à {{active.name}}, mais devront faire un jet de moral Malheureux.
|
||||
|
@@ -39,6 +39,19 @@
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="chat-actions">
|
||||
{{#if rolled.isSuccess}}
|
||||
{{#unless done.meditation}}
|
||||
<a class='chat-card-button monter-tmr-normale' data-tooltip="Montée rapide dans les TMR" >
|
||||
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg"/> Montée normale dans les TMR
|
||||
</a>
|
||||
<a class='chat-card-button monter-tmr-rapide' data-tooltip="Montée rapide dans les TMR" >
|
||||
<img src="systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg"/> Montée rapide dans les TMR
|
||||
</a>
|
||||
{{/unless}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="chat-buttons">
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user