Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Expose API for roll formula and resolver #73

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions litm.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ SuperCheckbox.Register();
Hooks.once("init", () => {
info("Initializing Legend in the Mist...");
game.litm = {
config: LitmConfig.createConfig(),
data: {
TagData,
},
methods: {
calculatePower: LitmRollDialog.calculatePower,
},
importCharacter,
LitmRollDialog,
LitmRoll,
Expand All @@ -60,7 +62,7 @@ Hooks.once("init", () => {
CONFIG.Item.dataModels.backpack = BackpackData;
CONFIG.Item.dataModels.theme = ThemeData;
CONFIG.Item.dataModels.threat = ThreatData;
CONFIG.litm = game.litm.config;
CONFIG.litm = new LitmConfig();

info("Registering Sheets...");
// Unregister the default sheets
Expand Down
78 changes: 46 additions & 32 deletions scripts/apps/roll-dialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,17 +51,34 @@ export class LitmRollDialog extends FormApplication {
positiveStatusValue,
negativeStatusValue,
totalPower,
} = LitmRollDialog.#calculateTotalPower({
} = game.litm.methods.calculatePower({
burnedTags,
powerTags,
weaknessTags,
positiveStatuses,
negativeStatuses,
});

const formula = typeof CONFIG.litm.roll.formula === "function" ? CONFIG.litm.roll.formula({
burnedTags,
powerTags,
weaknessTags,
positiveStatuses,
negativeStatuses,
burnedValue,
powerValue,
weaknessValue,
positiveStatusValue,
negativeStatusValue,
totalPower,
actorId,
type,
title,
}) : CONFIG.litm.roll.formula || "2d6 + (@burnedValue + @powerValue + @positiveStatusValue - @weaknessValue - @negativeStatusValue)";

// Roll
const roll = new game.litm.LitmRoll(
"2d6 + @burnedValue + @powerValue + @positiveStatusValue - @weaknessValue - @negativeStatusValue",
formula,
{
burnedValue,
powerValue,
Expand Down Expand Up @@ -96,31 +113,7 @@ export class LitmRollDialog extends FormApplication {
});
}

static #filterTags(tags) {
const burnedTags = tags.filter((t) => t.state === "burned");
const powerTags = tags.filter(
(t) => t.type !== "status" && t.state === "positive",
);
const weaknessTags = tags.filter(
(t) => t.type !== "status" && t.state === "negative",
);
const positiveStatuses = tags.filter(
(t) => t.type === "status" && t.state === "positive",
);
const negativeStatuses = tags.filter(
(t) => t.type === "status" && t.state === "negative",
);

return {
burnedTags,
powerTags,
weaknessTags,
positiveStatuses,
negativeStatuses,
};
}

static #calculateTotalPower(tags) {
static calculatePower(tags) {
const burnedValue = tags.burnedTags.length * 3;

const powerValue = tags.powerTags.length;
Expand Down Expand Up @@ -154,7 +147,30 @@ export class LitmRollDialog extends FormApplication {
};
}

#rollId = null;
static #filterTags(tags) {
const burnedTags = tags.filter((t) => t.state === "burned");
const powerTags = tags.filter(
(t) => t.type !== "status" && t.state === "positive",
);
const weaknessTags = tags.filter(
(t) => t.type !== "status" && t.state === "negative",
);
const positiveStatuses = tags.filter(
(t) => t.type === "status" && t.state === "positive",
);
const negativeStatuses = tags.filter(
(t) => t.type === "status" && t.state === "negative",
);

return {
burnedTags,
powerTags,
weaknessTags,
positiveStatuses,
negativeStatuses,
};
}

#tagState = [];
#shouldRoll = () => false;

Expand All @@ -170,7 +186,6 @@ export class LitmRollDialog extends FormApplication {
options.speaker || ChatMessage.getSpeaker({ actor: this.actor });
this.rollName = options.title || LitmRollDialog.defaultOptions.title;
this.type = options.type || "tracked";
this.#rollId = options.id;
}

get actor() {
Expand Down Expand Up @@ -219,7 +234,7 @@ export class LitmRollDialog extends FormApplication {
get totalPower() {
const state = [...this.#tagState, ...this.characterTags];
const tags = LitmRollDialog.#filterTags(state);
const { totalPower } = LitmRollDialog.#calculateTotalPower(tags);
const { totalPower } = LitmRollDialog.calculatePower(tags);
return totalPower;
}

Expand Down Expand Up @@ -366,10 +381,9 @@ export class LitmRollDialog extends FormApplication {

async #createModerationRequest(data) {
const id = foundry.utils.randomID();
this.#rollId = id;
const userId = game.user.id;
const tags = LitmRollDialog.#filterTags(data.tags);
const { totalPower } = LitmRollDialog.#calculateTotalPower(tags);
const { totalPower } = game.litm.methods.calculatePower(tags);
const recipients = Object.entries(this.actor.ownership)
.filter((u) => u[1] === 3 && u[0] !== "default")
.map((u) => u[0]);
Expand Down
32 changes: 24 additions & 8 deletions scripts/apps/roll.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,30 +37,45 @@ export class LitmRoll extends Roll {
}

get power() {
const { label: outcome } = this.outcome;

// Quick outcomes don't need to track power
if (this.litm.type === "quick") return null;
if (this.total < 7) return 0;
if (outcome === 'failure') return 0;

// Minimum of 1 power
let totalPower = Math.max(this.litm.totalPower, 1);
if (this.total < 10) return totalPower;
if (this.litm.type === "mitigate") totalPower += 1;

// If it's not a strong success, return the total power
if (outcome === "consequence") return totalPower;

// Mitigate outcomes add 1 power on a strong success
if (this.litm.type === "mitigate") totalPower += 1;
return totalPower;
}

get outcome() {
const total = this.total;
if (total >= 10)
const { resolver } = CONFIG.litm.roll;

if (typeof resolver === "function")
return resolver(this);

if (this.total > 9)
return { label: "success", description: "Litm.ui.roll-success" };
if (total >= 7)

if (this.total > 6)
return { label: "consequence", description: "Litm.ui.roll-consequence" };

return { label: "failure", description: "Litm.ui.roll-failure" };
}

async render({
template = this.constructor.CHAT_TEMPLATE,
isPrivate = false,
} = {}) {

if (!this._evaluated) await this.evaluate({ async: true });

const chatData = {
actor: this.actor,
formula: isPrivate ? "???" : this._formula.replace(/\s\+0/, ""),
Expand All @@ -79,7 +94,7 @@ export class LitmRoll extends Roll {
hasWeaknessTags:
!this.litm.gainedExp &&
this.litm.weaknessTags.filter((t) => t.type === "weaknessTag").length >
0,
0,
};

return renderTemplate(template, chatData);
Expand All @@ -92,8 +107,9 @@ export class LitmRoll extends Roll {
}

getTooltipData() {
const { label: outcome } = this.outcome
return {
mitigate: this.litm.type === "mitigate" && this.total > 9,
mitigate: this.litm.type === "mitigate" && outcome === 'success',
burnedTags: this.litm.burnedTags,
powerTags: this.litm.powerTags,
weaknessTags: this.litm.weaknessTags,
Expand Down
16 changes: 12 additions & 4 deletions scripts/system/config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export class LitmConfig {

challenge_types = [
"attacker",
"barrier-hazard",
Expand Down Expand Up @@ -94,6 +95,17 @@ export class LitmConfig {
},
};

/**
* You can use this to completely override the default effects.
* formula: ({ totalPower }) => `${1 + Math.max(Math.abs(totalPower))}d6${totalPower < 1 ? `kl1` : "kh1"}`,
* resolver: (roll) => {
* if (roll.dice[0].results.every(d => d.active && d.result === 1)) return { label: "failure", description: "Litm.ui.roll-failure" };
* }
* @link scripts/apps/roll-dialog.js
* @link scripts/apps/roll.js
*/
roll = { formula: null, resolver: null }

theme_levels = {
origin: [
"circumstance",
Expand Down Expand Up @@ -131,8 +143,4 @@ export class LitmConfig {

tagStringRe = /(?!\b|\s)(?:\[|\{)([^\d\[\]{}]+)(?:[\s\-\:](\d+))?(?:\}|\])/gi;
sceneLinkRe = /@ActivateScene\[([^\]]+)\](?:\{([^\}]+)\})?/gi;

static createConfig() {
return new LitmConfig();
}
}
4 changes: 2 additions & 2 deletions templates/chat/message.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ <h4 class="dice-total {{outcome.label}}">
{{localize 'Litm.tags.power'}}</span>{{/unless}}
</h4>
{{#if (eq type 'tracked')}}
{{#if (gt total 6)}}
{{#if (eq outcome.label 'consequence')}}
<p class="litm--dice-roll-subtle">
{{{localize "Litm.ui.roll-tracked-hint"}}}
</p>
{{/if}}
{{#if (gt total 9)}}
{{#if (eq outcome.label 'success')}}
<p class="litm--dice-roll-subtle">
{{localize 'Litm.ui.roll-tracked-success'}}
</p>
Expand Down