Roll V2: cuisine

This commit is contained in:
2025-10-07 01:49:53 +02:00
parent 293af5ab83
commit edf920b340
34 changed files with 574 additions and 143 deletions

View File

@@ -51,6 +51,7 @@ import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION } from "./roll/roll-constants.mjs";
import { PART_TACHE } from "./roll/roll-part-tache.mjs";
import { PART_COMP } from "./roll/roll-part-comp.mjs";
import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@@ -1937,10 +1938,11 @@ export class RdDActor extends RdDBaseActorSang {
type: { allowed: [PART_COMP], current: PART_COMP },
selected: {
carac: { key: caracName },
comp: { key: compName, forced: options.forced }
comp: { key: compName, forced: options.forced },
diff: { value: diff ?? 0 }
}
}
RollDialog.create(rollData, options)
RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose }))
return
}
@@ -2064,7 +2066,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { meditation: { key: id } },
type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION }
}
await RollDialog.create(rollData)
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
@@ -3210,14 +3212,26 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async rollRecetteCuisine(id) {
const oeuvre = this.getRecetteCuisine(id);
const recette = this.getRecetteCuisine(id);
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE },
selected: {
cuisine: { key: recette.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
const artData = {
verbe: 'Cuisiner',
compName: 'cuisine',
proportions: 1,
ajouterEquipement: false
};
await this._rollArtV1(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r));
await this._rollArtV1(artData, 'odoratgout', recette, r => this._resultRecetteCuisine(r));
}
/* -------------------------------------------- */
@@ -3250,6 +3264,18 @@ export class RdDActor extends RdDBaseActorSang {
}
async preparerNourriture(item) {
if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE },
selected: {
cuisine: { key: item.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
if (item.getUtilisationCuisine() == 'brut') {
const nourriture = {
name: 'Plat de ' + item.name,
@@ -3260,7 +3286,7 @@ export class RdDActor extends RdDBaseActorSang {
exotisme: item.system.exotisme,
ingredients: item.name
}
};
}
const artData = {
verbe: 'Préparer',
compName: 'cuisine',

View File

@@ -191,7 +191,7 @@ export class ChatUtility {
const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
$(html).find('header.message-header .message-sender').after(dateHeure)
$(html).find('header.message-header .message-timestamp').after(dateHeure)
}
}

View File

@@ -7,6 +7,7 @@ import { RdDResolutionTable } from "../rdd-resolution-table.js"
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"
export default class ChatRollResult {
static init() {
@@ -25,7 +26,7 @@ export default class ChatRollResult {
})
}
async display(roll) {
async display(roll, impacts) {
this.prepareDisplay(roll)
const chatMessage = await ChatUtility.createChatWithRollMode(
@@ -35,7 +36,8 @@ export default class ChatRollResult {
roll.active.actor,
roll.current?.rollmode?.key
)
const save = RollDialog.saveParts(roll)
const save = RollDialog.saveParts(roll, impacts)
ChatUtility.setMessageData(chatMessage, 'rollData', save)
return chatMessage
}
@@ -109,6 +111,7 @@ export default class ChatRollResult {
$(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))
$(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event))
}
@@ -143,6 +146,7 @@ export default class ChatRollResult {
onAppelChanceSuccess(savedRoll, chatMessage) {
const reRoll = foundry.utils.duplicate(savedRoll)
console.log('onAppelChanceSuccess savedRoll', savedRoll)
reRoll.type.retry = true
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
// TODO: annuler les effets
@@ -211,4 +215,9 @@ export default class ChatRollResult {
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')
await new RollTypeCuisine().onFaireGouter(savedRoll)
}
}

View File

@@ -1,4 +1,4 @@
import { ActorToken } from "../actor-token.mjs"
import { TokenActor } from "../technical/actor-token.mjs"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
@@ -9,8 +9,8 @@ export class RollBasicParts {
static restore(rollData) {
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
rollData.active = RollBasicParts.$getActor(rollData)
rollData.opponent = RollBasicParts.$getOpponent(rollData)
rollData.active = RollBasicParts.getTokenActor(rollData)
rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
if (rollData.type.opposed == undefined) {
rollData.type.opposed = rollData.opponent != null
}
@@ -64,30 +64,30 @@ export class RollBasicParts {
}
}
static $getActor(rollData) {
static getTokenActor(rollData) {
if (rollData.ids.actorTokenId) {
return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
return TokenActor.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
}
else {
const actorId = rollData.ids.actorId ?? (canvas.tokens.controlled.length == 1
/** TODO: jets de plusieurs personnages??? */
? canvas.tokens.controlled[0]
: undefined)
return ActorToken.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") })
return TokenActor.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") })
}
}
static $getOpponent(rollData) {
static getTokenActorOpponent(rollData) {
if (rollData.ids.opponentTokenId) {
return ActorToken.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId)
return TokenActor.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId)
}
else if (rollData.ids.opponentId) {
return ActorToken.fromActorId(rollData.ids.opponentId)
return TokenActor.fromActorId(rollData.ids.opponentId)
}
else {
const targets = Array.from(game.user.targets)
if (targets.length == 1) {
return ActorToken.fromToken(targets[0])
return TokenActor.fromToken(targets[0])
}
else {
return undefined

View File

@@ -43,6 +43,7 @@ import { renderTemplate } from "../constants.js";
import { RollTypeCuisine } from "./roll-type-cuisine.mjs";
import { RollPartCuisine } from "./roll-part-cuisine.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js";
import { ActorImpacts } from "../technical/actor-impacts.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
@@ -292,7 +293,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData
}
static saveParts(rollData) {
static saveParts(rollData, impacts) {
const target = RollBasicParts.initFrom(rollData)
ROLL_PARTS.filter(p => p.isActive(rollData))
.forEach(p => p.storeClean(rollData, target))
@@ -301,6 +302,12 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
target.result = rollData.result
target.done = rollData.done ?? {}
target.dmg = rollData.dmg
if (impacts) {
target.reverse = {
active: impacts.active?.reverseImpacts(),
opponent: impacts.opponent?.reverseImpacts()
}
}
return target
}
@@ -442,18 +449,29 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
roll.choix = {}
roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll))
roll.result = selectedRollType.getResult(roll)
const impacts = {
active: new ActorImpacts(roll.active),
opponent: roll.opponent ? new ActorImpacts(roll.opponent) : undefined
}
roll.result = selectedRollType.getResult(roll, impacts)
console.info('RollDialog.roll:', roll)
const callbacks = [
...this.rollOptions.callbacks,
...selectedRollType.callbacks(this.rollOptions),
]
await Promise.all(callbacks.map(async callback => await callback(roll)))
await this.chatRollResult.display(roll)
await impacts.active?.applyImpacts()
await impacts.opponent?.applyImpacts()
selectedRollType.onApplyImpacts(roll, impacts)
await this.chatRollResult.display(roll, impacts)
this.rollOptions.onRollDone(this)
}
loadRollData(roll) {
RollDialog.$prepareRollData(roll)
RollDialog.calculAjustements(roll)

View File

@@ -19,55 +19,153 @@ export class RollPartCuisine extends RollPartSelect {
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_CUISINE) }
restore(rollData) {
super.restore(rollData)
this.$restoreSavedOptions(rollData)
}
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
key: current.key,
fabriquer: current.fabriquer,
proportions: current.proportions,
value: current.value,
})
}
loadRefs(rollData) {
const refs = this.getRefs(rollData)
refs.recettes = rollData.active.actor.items
const actor = rollData.active.actor
refs.cuisine = actor.getCompetence('Cuisine')
const recettes = actor.items
.filter(it => it.type == ITEM_TYPES.recettecuisine)
.map(it => RollPartCuisine.$extractRecette(it, rollData.active.actor))
if (refs.recettes.length > 0) {
this.$selectRecette(rollData)
.map(RollPartCuisine.$extractPreparationRecette)
const ingredientsBruts = actor.items
.filter(it => it.getUtilisationCuisine() == 'brut')
.map(RollPartCuisine.$extractPreparationBrut)
refs.preparations = [RollPartCuisine.$preparationBasique(), ...recettes, ...ingredientsBruts]
refs.preparations.forEach(p => p.comp = refs.cuisine)
if (refs.preparations.length > 0) {
this.$selectPreparation(rollData)
this.$restoreSavedOptions(rollData)
}
}
choices(refs) { return refs.recettes }
$restoreSavedOptions(rollData) {
const saved = this.getSaved(rollData)
const current = this.getCurrent(rollData)
if (saved.fabriquer != undefined) {
current.fabriquer = saved.fabriquer
}
if (saved.proportions != undefined) {
current.proportions = saved.proportions
}
if (saved.value != undefined) {
current.value = saved.value
}
}
static $extractRecette(recette, actor) {
choices(refs) { return refs.preparations }
static $preparationBasique() {
return {
key: '',
label: "Improvisation du moment",
img: RollPartCuisine.$getImgIngredient(),
sust: 1,
exotisme: 0,
ingredients: "Ce qu'il y a sous la main",
proportions: 8,
proportionsMax: 50,
value: 0,
fabriquer: false,
}
}
static $extractPreparationRecette(recette) {
const proportions = recette.system.sust ?? 1
return {
key: recette.id,
label: recette.name,
caracs: RollPartCuisine.getCaracs(recette),
qualite: recette.system.niveau,
img: 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg',
sust: 1,
exotisme: recette.system.exotisme,
ingredients: recette.system.ingredients,
proportions: proportions,
proportionsMax: proportions * 10,
value: -recette.system.niveau,
recette: recette,
comp: actor.getCompetence('Cuisine')
fabriquer: true,
}
}
static getCaracs(recette){
// TODO: permettre différentes caractéristiques pour la cuisine?
return [CARACS.ODORATGOUT, CARACS.EMPATHIE, CARACS.DEXTERITE]
static $extractPreparationBrut(ingredient) {
return {
key: ingredient.id,
label: ingredient.name + ' cuisiné',
img: RollPartCuisine.$getImgIngredient(ingredient.type),
sust: ingredient.system.sust ?? 1,
exotisme: ingredient.system.exotisme,
ingredients: ingredient.name,
proportions: Math.min(10, ingredient.system.quantite),
proportionsMax: Math.min(50, ingredient.system.quantite),
value: 0,
ingredient: ingredient,
fabriquer: true,
}
}
$selectRecette(rollData, key) {
static $getImgIngredient(type = ITEM_TYPES.ingredient) {
switch (type) {
case ITEM_TYPES.herbe:
case ITEM_TYPES.plante:
return `systems/foundryvtt-reve-de-dragon/icons/cuisine/${type}.svg`
case ITEM_TYPES.faune:
return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/gibier.svg'
}
return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg'
}
$selectPreparation(rollData, key) {
this.selectByKey(rollData, key, 0)
}
async _onRender(rollDialog, context, options) {
const selectRecette = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-recette"]`)
const current = this.getCurrent(rollDialog.rollData)
selectRecette.addEventListener("change", e => {
const selectPreparation = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-preparation"]`)
const inputDiff = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="diff-var"]`)
const checkboxFabriquer = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="fabriquer"]`)
const inputProportions = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="proportions"]`)
selectPreparation.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectRecette(rollDialog.rollData, selectOptions[index]?.value)
this.$selectPreparation(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render()
})
checkboxFabriquer?.addEventListener("change", e => {
current.fabriquer = e.currentTarget.checked
})
inputDiff?.addEventListener("change", e => {
current.value = parseInt(e.currentTarget.value)
})
inputProportions?.addEventListener("change", e => {
current.proportions = parseInt(e.currentTarget.value)
})
}
impactOtherPart(part, rollData) {
if (this.visible(rollData)) {
const current = this.getCurrent(rollData)
switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, current.caracs)
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
case PART_CARAC: return part.filterCaracs(rollData, [CARACS.ODORATGOUT])
case PART_COMP: return part.filterComps(rollData, [this.getRefs(rollData).cuisine.name])
}
}
return undefined

View File

@@ -1,3 +1,5 @@
import { ITEM_TYPES } from "../constants.js"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { DIFF, ROLL_TYPE_CUISINE } from "./roll-constants.mjs"
import { PART_CUISINE } from "./roll-part-cuisine.mjs"
import { RollType } from "./roll-type.mjs"
@@ -9,19 +11,73 @@ export class RollTypeCuisine extends RollType {
visible(rollData) { return rollData.active.actor.isPersonnage() }
title(rollData) {
const current = rollData.current[PART_CUISINE]
return `prépare une recette: ${current.label}`
return current.recette ? `prépare une recette: ${current.label}` : `prépare: ${current.label}`
}
onSelect(rollData) {
this.setDiffType(rollData, DIFF.AUCUN)
}
getResult(rollData){
getResult(rollData, impacts) {
const current = rollData.current[PART_CUISINE]
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau)
return {
qualite: qualite + rollData.rolled.ptQualite
const diff = -current.value
const cuisine = rollData.refs[PART_CUISINE].cuisine
const qualite = rollData.rolled.ptQualite + (rollData.rolled.isSuccess ? diff : Math.min(diff, cuisine.system.niveau))
const result = {
qualite: qualite,
exotisme: Math.min(Math.min(qualite, current.exotisme ?? 0), 0),
messages: []
}
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)
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)
result.messages.push(`Il n'y a plus de ${ingredient.name}`)
}
else {
impacts.active.addItemDelta(current.ingredient, 'system.quantite', -current.proportions)
result.messages.push(`${current.proportions} ${current.ingredient.name} ont été utilisés`)
}
}
return result
}
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
}
}
$prepareNourriture(cuisinier, current, result) {
return {
id: foundry.utils.randomID(16),
name: current.label,
img: current.img,
type: ITEM_TYPES.nourritureboisson,
system: {
sust: current.sust,
cuisinier: cuisinier,
exotisme: result.exotisme,
encombrement: 0.1,
quantite: current.proportions,
qualite: result.qualite,
cout: result.qualite > 0 ? (result.qualite * 0.01) : 0.01,
}
}
}
async onFaireGouter(savedRoll) {
const actor = RollBasicParts.getTokenActor(savedRoll).actor
const platId = savedRoll.result.plat.id
const plat = actor.items.get(platId)
await plat?.proposerVente()
}
}

View File

@@ -16,11 +16,12 @@ export class RollTypeOeuvre extends RollType {
this.setDiffType(rollData, DIFF.AUCUN)
}
getResult(rollData){
getResult(rollData, impacts) {
const current = rollData.current[PART_OEUVRE]
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau)
return {
qualite: qualite + rollData.rolled.ptQualite
qualite: qualite + rollData.rolled.ptQualite,
messages: []
}
}

View File

@@ -53,5 +53,14 @@ export class RollType {
callbacks(rollOptions) { return [] }
getResult(rollData) { return undefined }
/**
* Préparation des résultats d'un jet pour ce type de jet
*
* @param {*} rollData les données du jet, incluans la partie rolled
* @param {*} impacts une structure composée de deux ActorImpacts {active, opponent}
* pour stocker les effets sur ces deux participants au jey
* @returns undefined ou une structure contenant les informations requise pour afficher
*/
getResult(rollData, impacts) { return { messages: [] } }
onApplyImpacts(roll, impacts) { }
}

View File

@@ -0,0 +1,128 @@
/**
* class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these
*/
export class ActorImpacts {
constructor(actorToken) {
this.actorToken = actorToken
this.updates = []
this.deltas = []
this.itemCreates = []
this.itemUpdates = []
this.itemDeletes = []
}
addActorUpdate(path, value) {
this.updates.push([path, value])
}
addActorDelta(path, value) {
const intValue = Number.parseInt(value)
if (Number.isInteger(intValue) && intValue != 0) {
const delta = [path, intValue]
this.deltas.push(delta)
}
else {
console.error('Cannot use non integer value {} for delta update', value)
}
}
addDeletedItem(item) {
this.itemDeletes.push(item)
}
addCreatedItem(item) {
this.itemCreates.push(item)
}
addItemUpdate(item, path, value) {
const existing = this.itemUpdates.find(it => it.id == item.id)
const update = [path, value]
if (existing) {
existing.updates.push(update)
}
else {
this.itemUpdates.push({ id: item.id, updates: [update], deltas: [] })
}
}
addItemDelta(item, path, value) {
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)
if (existing) {
existing.deltas.push(delta)
}
else {
this.itemUpdates.push({ id: item.id, updates: [], deltas: [delta] })
}
}
else {
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)))
return reverse
}
toStorable() {
delete this.actorToken
return this
}
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
if (isItemsDelete) {
const deletes = this.itemDeletes.map(it => it.id)
await actor.deleteEmbeddedDocuments('Item', deletes, { render: !(isItemsCreate || isItemsUpdate || isActorUpdate) })
}
if (isItemsCreate) {
const creates = this.itemCreates
const created = await actor.createEmbeddedDocuments('Item', creates, { render: !(isItemsUpdate || isActorUpdate)})
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 })
}
}
$getActorItem(id) {
return this.actorToken.actor.items.get(id)
}
static $computeUpdates(u, getSource) {
const source = getSource(u.id)
const instruction = { _id: u.id }
u.updates.forEach(u => instruction[u[0]] = u[1])
u.deltas.forEach(u => instruction[u[0]] = foundry.utils.getProperty(source, u[0]) + u[1])
return instruction
}
static $computeReverts(target, u, getSource) {
const source = getSource(u.id)
target.updates = u.updates.map(u => [u[0], foundry.utils.getProperty(source, u[0])])
target.deltas = u.deltas.map(d => [d[0], -d[1]])
return target
}
}

View File

@@ -1,9 +1,9 @@
/**
* class providing the actor and token, and choosing the name and image from the token if available.
*/
export class ActorToken {
export class TokenActor {
static fromTokenActor(token, actor){
return token ? ActorToken.fromToken(token) : ActorToken.fromActor(actor)
return token ? TokenActor.fromToken(token) : TokenActor.fromActor(actor)
}
static fromActorId(actorId, onError = () => undefined) {
@@ -19,17 +19,17 @@ export class ActorToken {
static fromActor(actor) {
const token = actor.isToken ? actor.token : actor.prototypeToken
return ActorToken.fromToken(token)
return TokenActor.fromToken(token)
}
static fromTokenId(tokenId, sceneId = undefined) {
const tokensList = sceneId ? game.scenes.get(sceneId).tokens : canvas.tokens.placeables
const token = tokensList.get(tokenId)
return ActorToken.fromToken(token)
return TokenActor.fromToken(token)
}
static fromToken(token) {
return new ActorToken(token)
return new TokenActor(token)
}
constructor(token) {