commit
8cf10371c2
|
@ -83,9 +83,33 @@
|
|||
</div>
|
||||
</div>
|
||||
<div id="demo" class="row" style="text-align: center;">
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/xKFuPXfyMoE" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
|
||||
<iframe width="560" height="315"
|
||||
src="https://www.youtube.com/embed/xKFuPXfyMoE" frameborder="0"
|
||||
allow="accelerometer; autoplay; encrypted-media; gyroscope;
|
||||
picture-in-picture" allowfullscreen></iframe>
|
||||
</div>
|
||||
<div id="setup" class="row">
|
||||
<h4>Installation</h4>
|
||||
<p>
|
||||
You'll need a Foundry VTT License or GM access to a Foundry VTT
|
||||
server.
|
||||
</p>
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
Launch Foundry VTT.
|
||||
</li>
|
||||
<li>
|
||||
Go to Game Systems, Install System.
|
||||
</li>
|
||||
<li>
|
||||
Find 'Old-School Essentials' and click Install.
|
||||
</li>
|
||||
<li>
|
||||
Create a new World using the Old-School Essentials system.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
<h4>Setup</h4>
|
||||
<p>You can find System settings in the Configure Settings dialog you
|
||||
open from the sidebar</p>
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
13
src/acks.js
13
src/acks.js
|
@ -125,15 +125,22 @@ Hooks.on("renderCombatTracker", (object, html, data) => {
|
|||
|
||||
Hooks.on("preUpdateCombat", async (combat, data, diff, id) => {
|
||||
let init = game.settings.get("acks", "initiative");
|
||||
let reroll = game.settings.get("acks", "rerollInitiative");
|
||||
if (!data.round) {
|
||||
return;
|
||||
}
|
||||
if (data.round !== 1) {
|
||||
if (reroll === "reset") {
|
||||
OseCombat.resetInitiative(combat, data, diff, id);
|
||||
return;
|
||||
} else if (reroll === "keep") {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (init === "group") {
|
||||
AcksCombat.rollInitiative(combat, data, diff, id);
|
||||
} else if (init === "rerolled") {
|
||||
} else if (init === "individual") {
|
||||
AcksCombat.individualInitiative(combat, data, diff, id);
|
||||
} else if (init === "reset") {
|
||||
AcksCombat.resetInitiative(combat, data, diff, id);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@
|
|||
"ACKS.saves.spell.short": "S",
|
||||
"ACKS.saves.spell.long": "Spells",
|
||||
"ACKS.saves.magic.long": "Bonus vs Magic",
|
||||
"ACKS.saves.magic.short": "vs Magic",
|
||||
|
||||
"ACKS.Health": "Hit Points",
|
||||
"ACKS.HealthMax": "Maximum Hit Points",
|
||||
|
@ -160,11 +161,14 @@
|
|||
"ACKS.category.equipment": "Equipment",
|
||||
|
||||
"ACKS.Setting.Initiative": "Initiative",
|
||||
"ACKS.Setting.InitiativeHint": "Grouped or individual initiative. Unique individual is only rolled at the start of the combat",
|
||||
"ACKS.Setting.InitiativeOnce": "Unique individual Initiative",
|
||||
"ACKS.Setting.InitiativeReroll": "Roll individual Initiative each Round",
|
||||
"ACKS.Setting.InitiativeReset": "Reset individual Initiative each Round",
|
||||
"ACKS.Setting.InitiativeHint": "Grouped or individual initiative.",
|
||||
"ACKS.Setting.InitiativeIndividual": "Individual initiative",
|
||||
"ACKS.Setting.InitiativeGroup": "Grouped Initiative",
|
||||
"ACKS.Setting.RerollInitiative": "Initiative persistence",
|
||||
"ACKS.Setting.RerollInitiativeHint": "Keeps, resets or rerolls initiative each round",
|
||||
"ACKS.Setting.InitiativeKeep": "Keep for each round",
|
||||
"ACKS.Setting.InitiativeReroll": "Reroll each round",
|
||||
"ACKS.Setting.InitiativeReset": "Reset each round",
|
||||
"ACKS.Setting.AscendingAC": "Ascending Armor Class",
|
||||
"ACKS.Setting.AscendingACHint": "The more the better",
|
||||
"ACKS.Setting.Morale": "Enable monsters Morale Rating",
|
||||
|
|
|
@ -13,8 +13,7 @@ export class AcksActorSheet extends ActorSheet {
|
|||
data.config = CONFIG.ACKS;
|
||||
// Settings
|
||||
data.config.ascendingAC = game.settings.get("acks", "ascendingAC");
|
||||
data.config.encumbranceBasic =
|
||||
game.settings.get("acks", "encumbranceOption") == "basic";
|
||||
data.config.encumbrance = game.settings.get("acks", "encumbranceOption");
|
||||
|
||||
// Prepare owned items
|
||||
this._prepareItems(data);
|
||||
|
@ -120,11 +119,20 @@ export class AcksActorSheet extends ActorSheet {
|
|||
}
|
||||
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
|
||||
// Item summaries
|
||||
html
|
||||
.find(".item .item-name h4")
|
||||
.click((event) => this._onItemSummary(event));
|
||||
|
||||
html.find(".item .item-controls .item-show").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
item.show();
|
||||
});
|
||||
|
||||
html.find(".saving-throw .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
|
@ -132,12 +140,6 @@ export class AcksActorSheet extends ActorSheet {
|
|||
actorObject.rollSave(save, { event: event });
|
||||
});
|
||||
|
||||
html.find(".item .item-controls .item-show").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
item.show();
|
||||
});
|
||||
|
||||
html.find(".item .item-rollable .item-image").click(async (ev) => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
|
@ -166,21 +168,35 @@ export class AcksActorSheet extends ActorSheet {
|
|||
let attack = element.parentElement.parentElement.dataset.attack;
|
||||
const rollData = {
|
||||
actor: this.data,
|
||||
roll: {}
|
||||
}
|
||||
actorObject.targetAttack(rollData, attack, {type: attack, skipDialog: ev.ctrlKey});
|
||||
});
|
||||
roll: {},
|
||||
};
|
||||
actorObject.targetAttack(rollData, attack, {
|
||||
type: attack,
|
||||
skipDialog: ev.ctrlKey,
|
||||
});
|
||||
|
||||
html.find(".spells .item-reset").click((ev) => {
|
||||
this._resetSpells(ev);
|
||||
});
|
||||
});
|
||||
|
||||
html.find(".hit-dice .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollHitDice({ event: event });
|
||||
});
|
||||
|
||||
super.activateListeners(html);
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
html
|
||||
.find(".memorize input")
|
||||
.click((ev) => ev.target.select())
|
||||
.change(this._onSpellChange.bind(this));
|
||||
|
||||
|
||||
html.find(".spells .item-reset").click((ev) => {
|
||||
this._resetSpells(ev);
|
||||
});
|
||||
}
|
||||
|
||||
// Override to set resizable initial size
|
||||
|
@ -221,7 +237,7 @@ export class AcksActorSheet extends ActorSheet {
|
|||
let heightDelta = this.position.height - this.options.height;
|
||||
editor.style.height = `${
|
||||
heightDelta + parseInt(container.dataset.editorSize)
|
||||
}px`;
|
||||
}px`;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ export class AcksActorSheetCharacter extends AcksActorSheet {
|
|||
resizable: true,
|
||||
tabs: [
|
||||
{
|
||||
navSelector: ".tabs",
|
||||
navSelector: ".sheet-tabs",
|
||||
contentSelector: ".sheet-body",
|
||||
initial: "attributes",
|
||||
},
|
||||
|
@ -136,6 +136,50 @@ export class AcksActorSheetCharacter extends AcksActorSheet {
|
|||
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||
*/
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
html.find(".ability-score .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let score = element.parentElement.parentElement.dataset.score;
|
||||
let stat = element.parentElement.parentElement.dataset.stat;
|
||||
if (!score) {
|
||||
if (stat == "lr") {
|
||||
actorObject.rollLoyalty(score, { event: event });
|
||||
}
|
||||
} else {
|
||||
actorObject.rollCheck(score, { event: event });
|
||||
}
|
||||
});
|
||||
|
||||
html.find(".exploration .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let expl = element.parentElement.parentElement.dataset.exploration;
|
||||
actorObject.rollExploration(expl, { event: event });
|
||||
});
|
||||
|
||||
html.find(".inventory .item-titles .item-caret").click((ev) => {
|
||||
let items = $(event.currentTarget.parentElement.parentElement).children(
|
||||
".item-list"
|
||||
);
|
||||
if (items.css("display") == "none") {
|
||||
let el = $(event.currentTarget).find(".fas.fa-caret-right");
|
||||
el.removeClass("fa-caret-right");
|
||||
el.addClass("fa-caret-down");
|
||||
items.slideDown(200);
|
||||
} else {
|
||||
let el = $(event.currentTarget).find(".fas.fa-caret-down");
|
||||
el.removeClass("fa-caret-down");
|
||||
el.addClass("fa-caret-right");
|
||||
items.slideUp(200);
|
||||
}
|
||||
});
|
||||
|
||||
html.find("a[data-action='modifiers']").click((ev) => {
|
||||
this._onShowModifiers(ev);
|
||||
});
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
|
@ -200,53 +244,8 @@ export class AcksActorSheetCharacter extends AcksActorSheet {
|
|||
.click((ev) => ev.target.select())
|
||||
.change(this._onQtChange.bind(this));
|
||||
|
||||
html.find(".ability-score .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let score = element.parentElement.parentElement.dataset.score;
|
||||
let stat = element.parentElement.parentElement.dataset.stat;
|
||||
if (!score) {
|
||||
if (stat == "lr") {
|
||||
actorObject.rollLoyalty(score, { event: event });
|
||||
}
|
||||
} else {
|
||||
actorObject.rollCheck(score, { event: event });
|
||||
}
|
||||
});
|
||||
|
||||
html.find(".exploration .attribute-name a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let element = event.currentTarget;
|
||||
let expl = element.parentElement.parentElement.dataset.exploration;
|
||||
actorObject.rollExploration(expl, { event: event });
|
||||
});
|
||||
|
||||
html.find(".inventory .item-titles .item-caret").click((ev) => {
|
||||
let items = $(event.currentTarget.parentElement.parentElement).children(
|
||||
".item-list"
|
||||
);
|
||||
if (items.css("display") == "none") {
|
||||
let el = $(event.currentTarget).find(".fas.fa-caret-right");
|
||||
el.removeClass("fa-caret-right");
|
||||
el.addClass("fa-caret-down");
|
||||
items.slideDown(200);
|
||||
} else {
|
||||
let el = $(event.currentTarget).find(".fas.fa-caret-down");
|
||||
el.removeClass("fa-caret-down");
|
||||
el.addClass("fa-caret-right");
|
||||
items.slideUp(200);
|
||||
}
|
||||
});
|
||||
|
||||
html.find("a[data-action='modifiers']").click((ev) => {
|
||||
this._onShowModifiers(ev);
|
||||
});
|
||||
|
||||
html.find("a[data-action='generate-scores']").click((ev) => {
|
||||
this.generateScores(ev);
|
||||
});
|
||||
|
||||
// Handle default listeners last so system listeners are triggered first
|
||||
super.activateListeners(html);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,12 +123,15 @@ export class AcksActor extends Actor {
|
|||
roll: {
|
||||
type: "above",
|
||||
target: this.data.data.saves[save].value,
|
||||
magic: this.data.data.scores.wis.mod
|
||||
},
|
||||
details: game.i18n.format("ACKS.roll.details.save", { save: label }),
|
||||
};
|
||||
|
||||
let skip = options.event && options.event.ctrlKey;
|
||||
|
||||
const rollMethod = this.data.type == "character" ? OseDice.RollSave : OseDice.Roll;
|
||||
|
||||
// Roll and return
|
||||
return AcksDice.Roll({
|
||||
event: options.event,
|
||||
|
@ -384,7 +387,10 @@ export class AcksActor extends Actor {
|
|||
if (game.user.targets.size > 0) {
|
||||
for (let t of game.user.targets.values()) {
|
||||
data.roll.target = t;
|
||||
await this.rollAttack(data, { type: type, skipDialog: options.skipDialog });
|
||||
await this.rollAttack(data, {
|
||||
type: type,
|
||||
skipDialog: options.skipDialog,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.rollAttack(data, { type: type, skipDialog: options.skipDialog });
|
||||
|
@ -437,7 +443,7 @@ export class AcksActor extends Actor {
|
|||
thac0: thac0,
|
||||
dmg: dmgParts,
|
||||
save: attData.roll.save,
|
||||
target: attData.roll.target
|
||||
target: attData.roll.target,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -500,14 +506,20 @@ export class AcksActor extends Actor {
|
|||
let totalWeight = 0;
|
||||
let hasItems = false;
|
||||
Object.values(this.data.items).forEach((item) => {
|
||||
if (item.type == "item" && (['complete', 'disabled'].includes(option) || item.data.treasure)) {
|
||||
totalWeight += item.data.quantity.value * item.data.weight;
|
||||
if (item.type == "item" && !item.data.treasure) {
|
||||
|
||||
hasItems = true;
|
||||
} else if (option != 'basic' && ['weapon', 'armor'].includes(item.type)) {
|
||||
}
|
||||
if (
|
||||
item.type == "item" &&
|
||||
(["complete", "disabled"].includes(option) || item.data.treasure)
|
||||
) {
|
||||
totalWeight += item.data.quantity.value * item.data.weight;
|
||||
} else if (option != "basic" && ["weapon", "armor"].includes(item.type)) {
|
||||
totalWeight += item.data.weight;
|
||||
}
|
||||
});
|
||||
if (option === 'detailed' && hasItems) totalWeight += 80;
|
||||
if (option === "detailed" && hasItems) totalWeight += 80;
|
||||
|
||||
data.encumbrance = {
|
||||
pct: Math.clamped(
|
||||
|
|
|
@ -170,6 +170,24 @@ export class AcksActorSheetMonster extends AcksActorSheet {
|
|||
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||
*/
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
html.find(".morale-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollMorale({ event: event });
|
||||
});
|
||||
|
||||
html.find(".reaction-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollReaction({ event: event });
|
||||
});
|
||||
|
||||
html.find(".appearing-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let check = $(ev.currentTarget).closest('.check-field').data('check');
|
||||
actorObject.rollAppearing({ event: event, check: check });
|
||||
});
|
||||
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
|
@ -220,22 +238,6 @@ export class AcksActorSheetMonster extends AcksActorSheet {
|
|||
this._resetCounters(ev);
|
||||
});
|
||||
|
||||
html.find(".morale-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollMorale({ event: event });
|
||||
});
|
||||
|
||||
html.find(".reaction-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
actorObject.rollReaction({ event: event });
|
||||
});
|
||||
|
||||
html.find(".appearing-check a").click((ev) => {
|
||||
let actorObject = this.actor;
|
||||
let check = $(ev.currentTarget).closest('.check-field').data('check');
|
||||
actorObject.rollAppearing({ event: event, check: check });
|
||||
});
|
||||
|
||||
html
|
||||
.find(".counter input")
|
||||
.click((ev) => ev.target.select())
|
||||
|
@ -263,7 +265,5 @@ export class AcksActorSheetMonster extends AcksActorSheet {
|
|||
});
|
||||
|
||||
html.find('button[data-action="generate-saves"]').click(() => this.generateSave());
|
||||
// Handle default listeners last so system listeners are triggered first
|
||||
super.activateListeners(html);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,14 +29,15 @@ export class AcksCombat {
|
|||
groups[data.combatants[i].flags.acks.group].initiative;
|
||||
}
|
||||
}
|
||||
combat.setupTurns();
|
||||
}
|
||||
|
||||
static async resetInitiative(combat, data) {
|
||||
let updates = [];
|
||||
combat.data.combatants.forEach((c, i) => {
|
||||
updates.push({_id: c._id, initiative: ""});
|
||||
});
|
||||
await combat.updateEmbeddedEntity("Combatant", updates);
|
||||
let reroll = game.settings.get("acks", "rerollInitiative");
|
||||
if (!["reset", "reroll"].includes(reroll)) {
|
||||
return;
|
||||
}
|
||||
combat.resetAll();
|
||||
}
|
||||
|
||||
static async individualInitiative(combat, data) {
|
||||
|
@ -171,7 +172,9 @@ export class AcksCombat {
|
|||
}
|
||||
let data = {};
|
||||
AcksCombat.rollInitiative(game.combat, data);
|
||||
game.combat.update({ data: data });
|
||||
game.combat.update({ data: data }).then(() => {
|
||||
game.combat.setupTurns();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -128,16 +128,23 @@ export class AcksDice {
|
|||
};
|
||||
result.target = data.roll.thac0;
|
||||
|
||||
const targetAc = data.roll.target ? data.roll.target.actor.data.data.ac.value : 9;
|
||||
const targetAac = data.roll.target ? data.roll.target.actor.data.data.aac.value : 0;
|
||||
result.victim = data.roll.target ? data.roll.target.actor.name : null;
|
||||
const targetAc = data.roll.target
|
||||
? data.roll.target.actor.data.data.ac.value
|
||||
: 9;
|
||||
const targetAac = data.roll.target
|
||||
? data.roll.target.actor.data.data.aac.value
|
||||
: 0;
|
||||
result.victim = data.roll.target ? data.roll.target.data.name : null;
|
||||
|
||||
if (game.settings.get("acks", "ascendingAC")) {
|
||||
if (roll.total < targetAac + 10) {
|
||||
result.details = game.i18n.format("ACKS.messages.AttackAscendingFailure", {
|
||||
result: roll.total - 10,
|
||||
bonus: result.target,
|
||||
});
|
||||
result.details = game.i18n.format(
|
||||
"ACKS.messages.AttackAscendingFailure",
|
||||
{
|
||||
result: roll.total - 10,
|
||||
bonus: result.target,
|
||||
}
|
||||
);
|
||||
return result;
|
||||
}
|
||||
result.details = game.i18n.format("ACKS.messages.AttackAscendingSuccess", {
|
||||
|
@ -257,6 +264,77 @@ export class AcksDice {
|
|||
});
|
||||
}
|
||||
|
||||
static async RollSave({
|
||||
parts = [],
|
||||
data = {},
|
||||
skipDialog = false,
|
||||
speaker = null,
|
||||
flavor = null,
|
||||
title = null,
|
||||
} = {}) {
|
||||
let rolled = false;
|
||||
const template = "systems/acks/templates/chat/roll-dialog.html";
|
||||
let dialogData = {
|
||||
formula: parts.join(" "),
|
||||
data: data,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
rollModes: CONFIG.Dice.rollModes,
|
||||
};
|
||||
|
||||
let rollData = {
|
||||
parts: parts,
|
||||
data: data,
|
||||
title: title,
|
||||
flavor: flavor,
|
||||
speaker: speaker,
|
||||
};
|
||||
if (skipDialog) { AcksDice.sendRoll(rollData); }
|
||||
|
||||
let buttons = {
|
||||
ok: {
|
||||
label: game.i18n.localize("ACKS.Roll"),
|
||||
icon: '<i class="fas fa-dice-d20"></i>',
|
||||
callback: (html) => {
|
||||
rolled = true;
|
||||
rollData.form = html[0].children[0];
|
||||
roll = AcksDice.sendRoll(rollData);
|
||||
},
|
||||
},
|
||||
magic: {
|
||||
label: game.i18n.localize("ACKS.saves.magic.short"),
|
||||
icon: '<i class="fas fa-magic"></i>',
|
||||
callback: (html) => {
|
||||
rolled = true;
|
||||
rollData.form = html[0].children[0];
|
||||
rollData.data.roll.target = parseInt(rollData.data.roll.target) + parseInt(rollData.data.roll.magic);
|
||||
rollData.title += ` ${game.i18n.localize("ACKS.saves.magic.short")} (${rollData.data.roll.magic})`;
|
||||
roll = AcksDice.sendRoll(rollData);
|
||||
},
|
||||
},
|
||||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("ACKS.Cancel"),
|
||||
callback: (html) => { },
|
||||
},
|
||||
};
|
||||
|
||||
const html = await renderTemplate(template, dialogData);
|
||||
let roll;
|
||||
|
||||
//Create Dialog window
|
||||
return new Promise((resolve) => {
|
||||
new Dialog({
|
||||
title: title,
|
||||
content: html,
|
||||
buttons: buttons,
|
||||
default: "ok",
|
||||
close: () => {
|
||||
resolve(rolled ? roll : false);
|
||||
},
|
||||
}).render(true);
|
||||
});
|
||||
}
|
||||
|
||||
static async Roll({
|
||||
parts = [],
|
||||
data = {},
|
||||
|
@ -302,7 +380,7 @@ export class AcksDice {
|
|||
cancel: {
|
||||
icon: '<i class="fas fa-times"></i>',
|
||||
label: game.i18n.localize("ACKS.Cancel"),
|
||||
callback: (html) => {},
|
||||
callback: (html) => { },
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
@ -16,6 +16,20 @@ export const registerSettings = function () {
|
|||
onChange: _ => window.location.reload()
|
||||
});
|
||||
|
||||
game.settings.register("acks", "ascendingAC", {
|
||||
name: game.i18n.localize("ACKS.Setting.RerollInitiative"),
|
||||
hint: game.i18n.localize("ACKS.Setting.RerollInitiativeHint"),
|
||||
default: "reset",
|
||||
scope: "world",
|
||||
type: String,
|
||||
config: true,
|
||||
choices: {
|
||||
keep: "ACKS.Setting.InitiativeKeep",
|
||||
reset: "ACKS.Setting.InitiativeReset",
|
||||
reroll: "ACKS.Setting.InitiativeReroll",
|
||||
}
|
||||
});
|
||||
|
||||
game.settings.register("acks", "ascendingAC", {
|
||||
name: game.i18n.localize("ACKS.Setting.AscendingAC"),
|
||||
hint: game.i18n.localize("ACKS.Setting.AscendingACHint"),
|
||||
|
|
|
@ -30,38 +30,44 @@ export const augmentTable = (table, html, data) => {
|
|||
});
|
||||
};
|
||||
|
||||
async function rollTreasure(table, options = {}) {
|
||||
let percent = (chance) => {
|
||||
let roll = new Roll("1d100").roll();
|
||||
function drawTreasure(table, data) {
|
||||
const percent = (chance) => {
|
||||
const roll = new Roll("1d100").roll();
|
||||
return roll.total <= chance;
|
||||
};
|
||||
data.treasure = {};
|
||||
if (table.getFlag('ose', 'treasure')) {
|
||||
table.results.forEach((r) => {
|
||||
if (percent(r.weight)) {
|
||||
const text = table._getResultChatText(r);
|
||||
data.treasure[r._id] = ({
|
||||
img: r.img,
|
||||
text: TextEditor.enrichHTML(text),
|
||||
});
|
||||
if ((r.type === CONST.TABLE_RESULT_TYPES.ENTITY) && (r.collection === "RollTable")) {
|
||||
const embeddedTable = game.tables.get(r.resultId);
|
||||
drawTreasure(embeddedTable, data.treasure[r._id]);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
const results = table.roll().results;
|
||||
results.forEach((s) => {
|
||||
const text = TextEditor.enrichHTML(table._getResultChatText(s));
|
||||
data.treasure[s._id] = {img: s.img, text: text};
|
||||
});
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
async function rollTreasure(table, options = {}) {
|
||||
// Draw treasure
|
||||
const data = drawTreasure(table, {});
|
||||
let templateData = {
|
||||
treasure: [],
|
||||
treasure: data.treasure,
|
||||
table: table,
|
||||
};
|
||||
let ids = [];
|
||||
table.results.forEach((r) => {
|
||||
if (percent(r.weight)) {
|
||||
let text = "";
|
||||
switch (r.type) {
|
||||
case 0:
|
||||
text = r.text;
|
||||
break;
|
||||
case 1:
|
||||
text = `@${r.collection}[${r.resultId}]{${r.text}}`;
|
||||
break;
|
||||
case 2:
|
||||
text = `@Compendium[${r.collection}.${r.resultId}]{${r.text}}`;
|
||||
}
|
||||
templateData.treasure.push({
|
||||
id: r._id,
|
||||
img: r.img,
|
||||
text: TextEditor.enrichHTML(text),
|
||||
});
|
||||
ids.push(r._id);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Animation
|
||||
if (options.event) {
|
||||
let results = $(event.currentTarget.parentElement)
|
||||
|
@ -69,7 +75,7 @@ async function rollTreasure(table, options = {}) {
|
|||
.find(".table-result");
|
||||
results.each((_, item) => {
|
||||
item.classList.remove("active");
|
||||
if (ids.includes(item.dataset.resultId)) {
|
||||
if (data.treasure[item.dataset.resultId]) {
|
||||
item.classList.add("active");
|
||||
}
|
||||
});
|
||||
|
@ -82,7 +88,7 @@ async function rollTreasure(table, options = {}) {
|
|||
|
||||
let chatData = {
|
||||
content: html,
|
||||
sound: "/systems/acks/assets/coins.mp3"
|
||||
// sound: "/systems/acks/assets/coins.mp3"
|
||||
}
|
||||
|
||||
let rollMode = game.settings.get("core", "rollMode");
|
||||
|
|
|
@ -306,6 +306,18 @@
|
|||
}
|
||||
line-height: 36px;
|
||||
}
|
||||
.sub {
|
||||
padding-left: 25px;
|
||||
line-height: 28px;
|
||||
img {
|
||||
flex: 0 0 28px;
|
||||
border: none;
|
||||
}
|
||||
div {
|
||||
text-indent: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
h3 {
|
||||
font-size: 12px;
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
"description": "Play B/X OSR modules with ACKS on Foundry VTT",
|
||||
"version": "0.1.0",
|
||||
"minimumCoreVersion": "0.6.2",
|
||||
"compatibleCoreVersion": "0.6.5",
|
||||
"compatibleCoreVersion": "0.6.6",
|
||||
"templateVersion": 2,
|
||||
"author": "The Happy Anarchist",
|
||||
"esmodules": ["acks.js"],
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
</header>
|
||||
|
||||
{{! Sheet Tab Navigation }}
|
||||
<nav class="sheet-tabs tabs flexrow" data-group="primary">
|
||||
<nav class="sheet-tabs tabs" data-group="primary">
|
||||
<a class="item" data-tab="attributes">
|
||||
{{localize "ACKS.category.attributes"}}
|
||||
</a>
|
||||
|
|
|
@ -31,12 +31,13 @@
|
|||
{{#each item.data.tags as |tag|}}
|
||||
{{#unless (getTagIcon tag.value)}}
|
||||
<span title="{{tag.title}}">{{tag.value}}{{#unless @last}},{{/unless}}</span>
|
||||
|
||||
|
||||
{{/unless}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{#if @root.config.encumbranceBasic}}_{{else}}{{item.data.weight}}{{/if}}
|
||||
{{#if (eq @root.config.encumbrance "basic")}}_{{else}}{{item.data.weight}}{{/if}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
|
@ -88,7 +89,7 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{#if @root.config.encumbranceBasic}}_{{else}}{{item.data.weight}}{{/if}}
|
||||
{{#if (eq @root.config.encumbrance "basic")}}_{{else}}{{item.data.weight}}{{/if}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
|
@ -135,7 +136,7 @@
|
|||
placeholder="0" />{{#if item.data.quantity.max}}<span>/{{item.data.quantity.max}}</span>{{/if}}
|
||||
</div>
|
||||
<div class="field-short">
|
||||
{{#if @root.config.encumbranceBasic}}_{{else}}{{mult item.data.quantity.value item.data.weight}}{{/if}}
|
||||
{{#if (eq @root.config.encumbrance "basic")}}_{{else if (eq @root.config.encumbrance "detailed")}}_{{else}}{{item.data.weight}}{{/if}}
|
||||
</div>
|
||||
<div class="item-controls">
|
||||
{{#if ../owner}}
|
||||
|
@ -158,7 +159,7 @@
|
|||
<div class="field-short"><i class="fas fa-hashtag"></i></div>
|
||||
<div class="field-short"><i class="fas fa-weight-hanging"></i></div>
|
||||
<div class="item-controls">
|
||||
<a class="item-control item-create" data-type="item" title="{{localize 'ACKS.Add'}}"><i
|
||||
<a class="item-control item-create" data-type="item" data-treasure="true" title="{{localize 'ACKS.Add'}}"><i
|
||||
class="fa fa-plus"></i></a>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -7,8 +7,18 @@
|
|||
<ol class="treasure-list">
|
||||
{{#each treasure as |t|}}
|
||||
<li class="treasure flexrow">
|
||||
<img src="{{t.img}}" width="36" height="36" />
|
||||
<div>{{{t.text}}}</div>
|
||||
{{#if t.img}}<img src="{{t.img}}" width="36" height="36" />{{/if}}
|
||||
<div>
|
||||
<div>{{{t.text}}}</div>
|
||||
{{#each t.treasure}}
|
||||
<li class="sub flexrow">
|
||||
{{#if img}}<img src="{{img}}" width="28" height="28">{{/if}}
|
||||
<div>
|
||||
{{{text}}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</div>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ol>
|
||||
|
|
Loading…
Reference in New Issue