Skip to content
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
1 change: 1 addition & 0 deletions src/lang/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ GRIMWILD:
SheetLabels:
Actor: Grimwild Actor Sheet
Item: Grimwild Item Sheet
RollTable: Grimwild Crucible Sheet
Actor:
Plural:
character: Characters
Expand Down
2 changes: 1 addition & 1 deletion src/module/controls/suspense.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class SuspenseTracker {
const quickPoolHtml = isGM || quickPoolsVisibleToPlayers ? getScenePools() : "";
susControl.innerHTML = `${susControlInnerHTML}${quickPoolHtml}`;
const susElement = document.querySelector("#sus-control");
const poolElement = document.querySelector('.quick-pool-inner');
const poolElement = document.querySelector(".quick-pool-inner");

if (isGM && susElement) {
susElement.querySelector("#js-sus-up").onclick = () => setSuspense(getSuspense() + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/module/data/actor-character.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ export default class GrimwildCharacter extends GrimwildActorBase {
// Update the active turn.
const combatantTurn = combat.turns.findIndex((c) => c.id === combatant.id);
if (combatantTurn !== undefined) {
combat.update({'turn': combatantTurn});
combat.update({ turn: combatantTurn });
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/module/data/item-arcana.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default class GrimwildArcana extends GrimwildItemBase {

// Arcana type.
schema.tier = new fields.StringField({
initial: 'minor',
initial: "minor"
});

// Arbitrary notes.
Expand Down
14 changes: 14 additions & 0 deletions src/module/data/item-talent.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,23 @@ export default class GrimwildTalent extends GrimwildItemBase {
})
}));

// @TODO refactor this to use roll tables.
// Crucible.
// schema.crucible = new CrucibleTableField();

return schema;
}

// async rollCrucible(options = {}) {
// const result = new grimwild.rollCrucible('{2d6}', {}, {crucible: this.crucible});
// await result.roll();
// if (options.toMessage) {
// result.toMessage();
// }

// return result;
// }

/**
* Migrate source data from prior format to the new specification.
*
Expand Down
1 change: 1 addition & 0 deletions src/module/dice/_module.mjs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as GrimwildRoll } from "./rolls.mjs";
export { default as GrimwildCrucibleRoll } from "./crucible-rolls.mjs";
export { default as GrimwildDiePoolRoll } from "./die-pools.mjs";
39 changes: 39 additions & 0 deletions src/module/dice/crucible-rolls.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// @TODO make this actually work.
export default class GrimwildCrucibleRoll extends Roll {
static CHAT_TEMPLATE = "systems/grimwild/templates/chat/roll-crucible.hbs";

constructor(formula, data, options) {
super(formula, data, options);
if (game.dice3d && game.settings.get("grimwild", "diceSoNiceOverride")) {
if (!this.options.appearance) this.options.appearance = {};
this.options.appearance.system = "grimwild";
this.options.appearance.colorset = "grimwild-dark";
}

if (!this.options.crucible) {
throw new Error("A crucible object must be supplied in options.crucible for this roll.");
}
}

async render({ flavor, template=this.constructor.CHAT_TEMPLATE, isPrivate=false }={}) {
if (!this._evaluated) await this.evaluate();
const dice = this.dice[0].results;

const chatData = {
formula: isPrivate ? "???" : this._formula,
flavor: isPrivate ? null : flavor ?? this.options.flavor,
user: game.user.id,
tooltip: isPrivate ? "" : await this.getTooltip(),
stat: this.options.stat,
dice: dice,
name: this.options.crucible?.name ?? "Crucible",
crucible: {
0: this.options.crucible.table[dice[0].result][dice[1].result],
1: this.options.crucible.table[dice[1].result][dice[0].result]
},
isPrivate: isPrivate
};

return foundry.applications.handlebars.renderTemplate(template, chatData);
}
}
2 changes: 1 addition & 1 deletion src/module/dice/rolls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default class GrimwildRoll extends Roll {
chatData.result = successToResult(chatData.success);
chatData.rawResult = successToResult(chatData.rawSuccess);
chatData.isCut = chatData.success !== chatData.rawSuccess;
chatData.isFail = ['disaster', 'grim', 'messy'].includes(chatData.result);
chatData.isFail = ["disaster", "grim", "messy"].includes(chatData.result);

// Separate assist dice from other dice
if (this.options?.assists) {
Expand Down
34 changes: 14 additions & 20 deletions src/module/documents/chat-message.mjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { GrimwildActor } from "./actor.mjs";

export class GrimwildChatMessage extends ChatMessage {
/** @inheritDoc */
async renderHTML(...args) {
Expand Down Expand Up @@ -88,7 +86,7 @@ export class GrimwildChatMessage extends ChatMessage {
return;
}
}
else if (['applyMark', 'applyHarm'].includes(action)) {
else if (["applyMark", "applyHarm"].includes(action)) {
if (damageTaken) {
element.setAttribute("disabled", true);
return;
Expand All @@ -107,7 +105,7 @@ export class GrimwildChatMessage extends ChatMessage {
return {
updateSpark: this._updateSpark,
applyMark: this._applyHarm,
applyHarm: this._applyHarm,
applyHarm: this._applyHarm
};
}

Expand Down Expand Up @@ -199,25 +197,23 @@ export class GrimwildChatMessage extends ChatMessage {
let harmUpdate = {};
// Handle marks.
if (stat) {
if (['bra', 'agi', 'wit', 'pre'].includes(stat)) {
if (["bra", "agi", "wit", "pre"].includes(stat)) {
const isMarked = actor.system.stats[stat].marked;
if (!isMarked) {
update[`system.stats.${stat}.marked`] = true;
}
else if (["bra", "agi"].includes(stat)) {
harmUpdate = this.calculateHarm(actor, "bloodied");
}
else {
if (['bra', 'agi'].includes(stat)) {
harmUpdate = this.calculateHarm(actor, 'bloodied');
}
else {
harmUpdate = this.calculateHarm(actor, 'rattled');
}
harmUpdate = this.calculateHarm(actor, "rattled");
}
}
}

// Handle harm.
if (harm) {
if (['bloodied', 'rattled'].includes(harm)) {
if (["bloodied", "rattled"].includes(harm)) {
harmUpdate = this.calculateHarm(actor, harm);
}
}
Expand Down Expand Up @@ -255,21 +251,19 @@ export class GrimwildChatMessage extends ChatMessage {
*/
calculateHarm(actor, harm) {
const harmPools = game.settings.get("grimwild", "enableHarmPools");
const maxHarm = game.settings.get("grimwild", `max${harm === 'bloodied' ? 'Bloodied' : 'Rattled'}`) ?? 1;
const maxHarm = game.settings.get("grimwild", `max${harm === "bloodied" ? "Bloodied" : "Rattled"}`) ?? 1;
const update = {};
if (!actor.system[harm == 'bloodied' ? 'isBloodied' : 'isRattled']) {
if (!actor.system[harm === "bloodied" ? "isBloodied" : "isRattled"]) {
update[`system.${harm}.marked`] = true;
if (harmPools) {
update[`system.${harm}.pool.diceNum`] = 1;
}
}
else if (!harmPools || actor.system[harm].pool.diceNum >= maxHarm) {
update["system.dropped"] = true;
}
else {
if (!harmPools || actor.system[harm].pool.diceNum >= maxHarm) {
update[`system.dropped`] = true;
}
else {
update[`system.${harm}.pool.diceNum`] = actor.system[harm].pool.diceNum + 1;
}
update[`system.${harm}.pool.diceNum`] = actor.system[harm].pool.diceNum + 1;
}

return update;
Expand Down
80 changes: 80 additions & 0 deletions src/module/documents/roll-table.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
export class GrimwildRollTable extends foundry.documents.RollTable {
async _preUpdate(changes, options, user) {
await super._preUpdate(changes, options, user);

if (changes?.flags?.core?.sheetClass === "grimwild.GrimwildRollTableCrucibleSheet") {
if (this.results && this.results.size < 36) {
const results = Array.fromRange(36 - this.results.size, 1).map((result) => {
return {
name: "",
range: [result, result],
weight: 1,
_id: foundry.utils.randomID()
};
});
changes.formula = "1d36";
changes.results = results;
}
}
}

async roll({ roll, recursive=true, _depth=0 }={}) {
if (this.isCrucible()) {
// @todo tie this to the rollCrucible() method.
return super.roll({ roll, recursive, _depth });
}

return super.roll({ roll, recursive, _depth });

}

isCrucible() {
return this.getFlag("core", "sheetClass") === "grimwild.GrimwildRollTableCrucibleSheet";
}

getCrucibleTable() {
if (this.isCrucible()) {
const grid = {
1: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" },
2: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" },
3: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" },
4: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" },
5: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" },
6: { 1: "", 2: "", 3: "", 4: "", 5: "", 6: "" }
};
let row = 1;
let col = 1;
let count = 0;
this.results.forEach((result) => {
if (count < 36) {
grid[row][col] = result.name;
col++;
if (col === 7) {
row++;
col = 1;
}
count++;
}
});

return grid;
}
}

async rollCrucible({ toMessage=true }={}) {
const crucibleRoll = new grimwild.rollCrucible("{2d6}", {}, {
crucible: {
name: this.name,
instructions: "",
table: this.getCrucibleTable()
}
});

await crucibleRoll.roll();
if (toMessage) {
crucibleRoll.toMessage();
}

return crucibleRoll;
}
}
Loading
Loading