Skip to content

Commit

Permalink
Update magichant support
Browse files Browse the repository at this point in the history
- Update magichant to refer to verse dialog
- Fix default volume
  • Loading branch information
Azurelol committed Feb 13, 2025
1 parent e1a6adf commit daa4eea
Show file tree
Hide file tree
Showing 29 changed files with 381 additions and 214 deletions.
1 change: 1 addition & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"InlineLoss": "Apply resource loss to selected tokens",
"InlineWeapon": "Apply effect to equipped weapon on character",
"InlineWeaponActiveEffectName": "Alter Damage Type ({damageType})",
"InlineAffinity": "Alter affinity {type} to {affinity} on character",
"Name": "Name",
"Roll": "Roll",
"Add": "Add",
Expand Down
39 changes: 19 additions & 20 deletions module/checks/common-sections.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -229,30 +229,29 @@ async function showFloatyText(targetData, localizedText) {
* @param {FUItem} item
* @param {TargetData[]} targets
* @param {Object} flags
* @param {ResourceExpense} expense
*/
const spendResource = (sections, actor, item, targets, flags) => {
/**
* @type ResourceExpense
*/
let expense;

// If using the newer cost data model
if (item.system.cost) {
if (item.system.cost.amount === 0) {
return;
const spendResource = (sections, actor, item, targets, flags, expense) => {
// Resolve the expense if not explicit
if (expense === undefined) {
// If using the newer cost data model
if (item.system.cost) {
if (item.system.cost.amount === 0) {
return;
}
expense = ResourcePipeline.calculateExpense(item, targets);
if (expense.amount === 0) {
return;
}
}
expense = ResourcePipeline.calculateExpense(item, targets);
if (expense.amount === 0) {
return;
// Support for consumables
else if (item.system instanceof ConsumableDataModel) {
expense = {
resource: 'ip',
amount: item.system.ipCost.value,
};
}
}
// Support for consumables
else if (item.system instanceof ConsumableDataModel) {
expense = {
resource: 'ip',
amount: item.system.ipCost.value,
};
}

if (expense) {
Pipeline.toggleFlag(flags, Flags.ChatMessage.ResourceLoss);
Expand Down
5 changes: 3 additions & 2 deletions module/documents/effects/active-effect.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -177,16 +177,17 @@ export class FUActiveEffect extends ActiveEffect {
* @param {EffectChangeData} change
* @returns {{}|*}
*/
apply(target, change) {
async apply(target, change) {
// Support expressions
if (change.value && typeof change.value === 'string') {
try {
// First, evaluate using built-in support
const expression = Roll.replaceFormulaData(change.value, this.parent);
// Second, evaluate with our custom expressions
const context = ExpressionContext.resolveTarget(target);
const value = Expressions.evaluate(expression, context);
const value = await Expressions.evaluate(expression, context);
change.value = String(value ?? 0);
console.debug(`Assigning ${change.key} = ${change.value}`);
} catch (e) {
console.error(e);
ui.notifications?.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class KeyDataModel extends RollableClassFeatureDataModel {
if (!actor) {
return;
}

const data = {
types: FU.damageTypes[model.type],
statuses: KeyDataModel.statuses[model.status],
Expand Down
83 changes: 2 additions & 81 deletions module/documents/items/classFeature/chanter/verse-data-model.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ async function getDescription(model, useAttributes = false) {
const keyData = key.system.data;
rollData.key = {
type: game.i18n.localize(FU.damageTypes[keyData.type]),
status: game.i18n.localize(KeyDataModel.statuses[keyData.status]),
status: `@EFFECT[${keyData.status}]`,
//status: game.i18n.localize(KeyDataModel.statuses[keyData.status]),
attribute: game.i18n.localize(FU.attributeAbbreviations[keyData.attribute]),
recovery: game.i18n.localize(KeyDataModel.recoveryOptions[keyData.recovery]),
};
Expand Down Expand Up @@ -105,86 +106,6 @@ export class VerseDataModel extends RollableClassFeatureDataModel {
new VersesApplication(model).render(true);
}

// static async roll(model, item) {
// if (!model.key || !model.tone) {
// return;
// }

// const keys = model.parent.parent?.actor?.itemTypes.classFeature.filter((item) => item.system.data instanceof KeyDataModel) ?? [];
// const tones = model.parent.parent?.actor?.itemTypes.classFeature.filter((item) => item.system.data instanceof ToneDataModel) ?? [];

// const volumeSelection = await Dialog.prompt({
// title: game.i18n.localize('FU.ClassFeatureVerseSingDialogTitle'),
// label: game.i18n.localize('FU.ClassFeatureVerseSingDialogLabel'),
// content: `
// <div>
// <label>${game.i18n.localize('FU.ClassFeatureVerseSelectVolume')}</label>
// <select name="volume">
// ${Object.entries(volumes)
// .map(([key, label]) => `<option value="${key}">${game.i18n.localize(label)}</option>`)
// .join('')}
// </select>
// </div>
// <div>
// <label>${game.i18n.localize('FU.ClassFeatureVerseChooseKey')}</label>
// <select name="key">
// ${keys.map((key) => `<option value="${key.id}">${key.name}</option>`).join('')}
// </select>
// </div>
// <div>
// <label>${game.i18n.localize('FU.ClassFeatureVerseSelectTone')}</label>
// <select name="tone">
// ${tones.map((tone) => `<option value="${tone.id}">${tone.name}</option>`).join('')}
// </select>
// </div>
// `,
// options: { classes: ['projectfu', 'unique-dialog', 'backgroundstyle'] },
// rejectClose: false,
// callback: (html) => ({
// volume: html.find('select[name=volume]').val(),
// key: html.find('select[name=key]').val(),
// tone: html.find('select[name=tone]').val(),
// }),
// });

// const actor = model.parent.parent.actor;
// if (!volumeSelection || !actor) {
// return;
// }

// // Get the selected key and tone
// const selectedKey = keys.find((key) => key.id === volumeSelection.key);
// const selectedTone = tones.find((tone) => tone.id === volumeSelection.tone);

// // Update the model's key and tone directly with FUItem instances
// if (selectedKey && selectedTone) {
// model.updateSource({
// key: selectedKey, // Use the FUItem instance directly
// tone: selectedTone, // Use the FUItem instance directly
// });
// }

// const data = {
// verse: model,
// volume: volumes[volumeSelection.volume],
// cost: model.config[volumeSelection.volume],
// targets: volumeTargets[volumeSelection.volume],
// key: model.key.name,
// tone: model.tone.name,
// description: await getDescription(model, true),
// };

// const speaker = ChatMessage.implementation.getSpeaker({ actor: actor });
// const chatMessage = {
// speaker,
// flavor: await renderTemplate('systems/projectfu/templates/chat/chat-check-flavor-item.hbs', model.parent.parent),
// content: await renderTemplate('systems/projectfu/templates/feature/chanter/feature-verse-chat-message.hbs', data),
// flags: { [SYSTEM]: { [Flags.ChatMessage.Item]: item } },
// };

// ChatMessage.create(chatMessage);
// }

static getTabConfigurations() {
return [
{
Expand Down
44 changes: 36 additions & 8 deletions module/documents/items/classFeature/chanter/verses-application.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@ import { KeyDataModel } from './key-data-model.mjs';
import { ToneDataModel } from './tone-data-model.mjs';
import { FU, SYSTEM } from '../../../../helpers/config.mjs';
import { Flags } from '../../../../helpers/flags.mjs';
import { CommonSections } from '../../../../checks/common-sections.mjs';
import { Targeting } from '../../../../helpers/targeting.mjs';

const SCALING_FORMULA = '($wlp*2)+&step(0,10,20)';

async function getDescription(model, useAttributes = false) {
const key = model.key;
const tone = model.tone;
Expand Down Expand Up @@ -31,9 +36,14 @@ async function getDescription(model, useAttributes = false) {
const keyData = key.system.data;
rollData.key = {
type: game.i18n.localize(FU.damageTypes[keyData.type]),
status: game.i18n.localize(KeyDataModel.statuses[keyData.status]),
damage: `@DMG[${SCALING_FORMULA} ${keyData.type}]`,
status: `@EFFECT[${keyData.status}]`,
attribute: game.i18n.localize(FU.attributeAbbreviations[keyData.attribute]),
recovery: game.i18n.localize(KeyDataModel.recoveryOptions[keyData.recovery]),
boost: `@EFFECT[${keyData.attribute}-up]`,
resistance: `@AFFINITY[${keyData.type} resistance]`,
normal: `@AFFINITY[${keyData.type} none]`,
vulnerability: `@AFFINITY[${keyData.type} vulnerability]`,
recovery: `@GAIN[${SCALING_FORMULA} ${keyData.recovery}]`,
};

const actor = model.parent?.parent?.actor;
Expand Down Expand Up @@ -99,6 +109,10 @@ export class VersesApplication extends FormApplication {
return 'systems/projectfu/templates/feature/chanter/feature-verse-application.hbs';
}

get defaultVolume() {
return 'low';
}

async getData(options = {}) {
// Prepare data for the form template
let keys = this.#verse.actor.itemTypes.classFeature
Expand Down Expand Up @@ -129,7 +143,7 @@ export class VersesApplication extends FormApplication {
let performance = {
key: this.#verse.key?.id || '',
tone: this.#verse.tone?.id || '',
volume: this.#verse.volume || 'low',
volume: this.#verse.volume || this.defaultVolume,
};

return {
Expand Down Expand Up @@ -172,7 +186,7 @@ export class VersesApplication extends FormApplication {
return;
}

const volumeSelection = this.#verse.volume || 'medium';
const volumeSelection = this.#verse.volume || this.defaultVolume;

const volumes = {
low: game.i18n.localize('FU.ClassFeatureVerseVolumeLow'),
Expand All @@ -187,24 +201,38 @@ export class VersesApplication extends FormApplication {
};

// Prepare the data object for the chat message
let flags = { [SYSTEM]: { [Flags.ChatMessage.Item]: this.#verse } };
const cost = this.#verse.config[volumeSelection];
const actor = this.#verse.actor;
const item = this.#verse.item;
const targets = Targeting.getSerializedTargetData();

// SpendResource
const sections = [];
const expense = {
resource: 'mp',
amount: cost,
};
CommonSections.spendResource(sections, actor, item, targets, flags, expense);

// Data for the template
const data = {
verse: this.#verse,
volume: volumes[volumeSelection],
cost: this.#verse.config[volumeSelection],
cost: cost,
targets: volumeTargets[volumeSelection],
key: this.#verse.key?.name || '',
tone: this.#verse.tone?.name || '',
description: await getDescription(this.#verse, true),
sections: sections,
};

const actor = this.#verse.actor;

// Prepare the chat message data
const chatMessage = {
speaker: ChatMessage.implementation.getSpeaker({ actor }),
flavor: await renderTemplate('systems/projectfu/templates/chat/chat-check-flavor-item.hbs', this.#verse.parent.parent),
content: await renderTemplate('systems/projectfu/templates/feature/chanter/feature-verse-chat-message.hbs', data),
flags: { [SYSTEM]: { [Flags.ChatMessage.Item]: this.#verse } },
flags: flags,
};

// Create the chat message
Expand Down
Loading

0 comments on commit daa4eea

Please sign in to comment.