commit
8cf10371c2
|
@ -83,9 +83,33 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="demo" class="row" style="text-align: center;">
|
<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>
|
||||||
<div id="setup" class="row">
|
<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>
|
<h4>Setup</h4>
|
||||||
<p>You can find System settings in the Configure Settings dialog you
|
<p>You can find System settings in the Configure Settings dialog you
|
||||||
open from the sidebar</p>
|
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) => {
|
Hooks.on("preUpdateCombat", async (combat, data, diff, id) => {
|
||||||
let init = game.settings.get("acks", "initiative");
|
let init = game.settings.get("acks", "initiative");
|
||||||
|
let reroll = game.settings.get("acks", "rerollInitiative");
|
||||||
if (!data.round) {
|
if (!data.round) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (data.round !== 1) {
|
||||||
|
if (reroll === "reset") {
|
||||||
|
OseCombat.resetInitiative(combat, data, diff, id);
|
||||||
|
return;
|
||||||
|
} else if (reroll === "keep") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (init === "group") {
|
if (init === "group") {
|
||||||
AcksCombat.rollInitiative(combat, data, diff, id);
|
AcksCombat.rollInitiative(combat, data, diff, id);
|
||||||
} else if (init === "rerolled") {
|
} else if (init === "individual") {
|
||||||
AcksCombat.individualInitiative(combat, data, diff, id);
|
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.short": "S",
|
||||||
"ACKS.saves.spell.long": "Spells",
|
"ACKS.saves.spell.long": "Spells",
|
||||||
"ACKS.saves.magic.long": "Bonus vs Magic",
|
"ACKS.saves.magic.long": "Bonus vs Magic",
|
||||||
|
"ACKS.saves.magic.short": "vs Magic",
|
||||||
|
|
||||||
"ACKS.Health": "Hit Points",
|
"ACKS.Health": "Hit Points",
|
||||||
"ACKS.HealthMax": "Maximum Hit Points",
|
"ACKS.HealthMax": "Maximum Hit Points",
|
||||||
|
@ -160,11 +161,14 @@
|
||||||
"ACKS.category.equipment": "Equipment",
|
"ACKS.category.equipment": "Equipment",
|
||||||
|
|
||||||
"ACKS.Setting.Initiative": "Initiative",
|
"ACKS.Setting.Initiative": "Initiative",
|
||||||
"ACKS.Setting.InitiativeHint": "Grouped or individual initiative. Unique individual is only rolled at the start of the combat",
|
"ACKS.Setting.InitiativeHint": "Grouped or individual initiative.",
|
||||||
"ACKS.Setting.InitiativeOnce": "Unique individual Initiative",
|
"ACKS.Setting.InitiativeIndividual": "Individual initiative",
|
||||||
"ACKS.Setting.InitiativeReroll": "Roll individual Initiative each Round",
|
|
||||||
"ACKS.Setting.InitiativeReset": "Reset individual Initiative each Round",
|
|
||||||
"ACKS.Setting.InitiativeGroup": "Grouped 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.AscendingAC": "Ascending Armor Class",
|
||||||
"ACKS.Setting.AscendingACHint": "The more the better",
|
"ACKS.Setting.AscendingACHint": "The more the better",
|
||||||
"ACKS.Setting.Morale": "Enable monsters Morale Rating",
|
"ACKS.Setting.Morale": "Enable monsters Morale Rating",
|
||||||
|
|
|
@ -13,8 +13,7 @@ export class AcksActorSheet extends ActorSheet {
|
||||||
data.config = CONFIG.ACKS;
|
data.config = CONFIG.ACKS;
|
||||||
// Settings
|
// Settings
|
||||||
data.config.ascendingAC = game.settings.get("acks", "ascendingAC");
|
data.config.ascendingAC = game.settings.get("acks", "ascendingAC");
|
||||||
data.config.encumbranceBasic =
|
data.config.encumbrance = game.settings.get("acks", "encumbranceOption");
|
||||||
game.settings.get("acks", "encumbranceOption") == "basic";
|
|
||||||
|
|
||||||
// Prepare owned items
|
// Prepare owned items
|
||||||
this._prepareItems(data);
|
this._prepareItems(data);
|
||||||
|
@ -120,11 +119,20 @@ export class AcksActorSheet extends ActorSheet {
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
|
||||||
// Item summaries
|
// Item summaries
|
||||||
html
|
html
|
||||||
.find(".item .item-name h4")
|
.find(".item .item-name h4")
|
||||||
.click((event) => this._onItemSummary(event));
|
.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) => {
|
html.find(".saving-throw .attribute-name a").click((ev) => {
|
||||||
let actorObject = this.actor;
|
let actorObject = this.actor;
|
||||||
let element = event.currentTarget;
|
let element = event.currentTarget;
|
||||||
|
@ -132,12 +140,6 @@ export class AcksActorSheet extends ActorSheet {
|
||||||
actorObject.rollSave(save, { event: event });
|
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) => {
|
html.find(".item .item-rollable .item-image").click(async (ev) => {
|
||||||
const li = $(ev.currentTarget).parents(".item");
|
const li = $(ev.currentTarget).parents(".item");
|
||||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||||
|
@ -166,21 +168,35 @@ export class AcksActorSheet extends ActorSheet {
|
||||||
let attack = element.parentElement.parentElement.dataset.attack;
|
let attack = element.parentElement.parentElement.dataset.attack;
|
||||||
const rollData = {
|
const rollData = {
|
||||||
actor: this.data,
|
actor: this.data,
|
||||||
roll: {}
|
roll: {},
|
||||||
}
|
};
|
||||||
actorObject.targetAttack(rollData, attack, {type: attack, skipDialog: ev.ctrlKey});
|
actorObject.targetAttack(rollData, attack, {
|
||||||
});
|
type: attack,
|
||||||
|
skipDialog: ev.ctrlKey,
|
||||||
|
});
|
||||||
|
|
||||||
html.find(".spells .item-reset").click((ev) => {
|
html.find(".spells .item-reset").click((ev) => {
|
||||||
this._resetSpells(ev);
|
this._resetSpells(ev);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
html.find(".hit-dice .attribute-name a").click((ev) => {
|
html.find(".hit-dice .attribute-name a").click((ev) => {
|
||||||
let actorObject = this.actor;
|
let actorObject = this.actor;
|
||||||
actorObject.rollHitDice({ event: event });
|
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
|
// Override to set resizable initial size
|
||||||
|
@ -221,7 +237,7 @@ export class AcksActorSheet extends ActorSheet {
|
||||||
let heightDelta = this.position.height - this.options.height;
|
let heightDelta = this.position.height - this.options.height;
|
||||||
editor.style.height = `${
|
editor.style.height = `${
|
||||||
heightDelta + parseInt(container.dataset.editorSize)
|
heightDelta + parseInt(container.dataset.editorSize)
|
||||||
}px`;
|
}px`;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ export class AcksActorSheetCharacter extends AcksActorSheet {
|
||||||
resizable: true,
|
resizable: true,
|
||||||
tabs: [
|
tabs: [
|
||||||
{
|
{
|
||||||
navSelector: ".tabs",
|
navSelector: ".sheet-tabs",
|
||||||
contentSelector: ".sheet-body",
|
contentSelector: ".sheet-body",
|
||||||
initial: "attributes",
|
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
|
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||||
*/
|
*/
|
||||||
activateListeners(html) {
|
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
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
@ -200,53 +244,8 @@ export class AcksActorSheetCharacter extends AcksActorSheet {
|
||||||
.click((ev) => ev.target.select())
|
.click((ev) => ev.target.select())
|
||||||
.change(this._onQtChange.bind(this));
|
.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) => {
|
html.find("a[data-action='generate-scores']").click((ev) => {
|
||||||
this.generateScores(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: {
|
roll: {
|
||||||
type: "above",
|
type: "above",
|
||||||
target: this.data.data.saves[save].value,
|
target: this.data.data.saves[save].value,
|
||||||
|
magic: this.data.data.scores.wis.mod
|
||||||
},
|
},
|
||||||
details: game.i18n.format("ACKS.roll.details.save", { save: label }),
|
details: game.i18n.format("ACKS.roll.details.save", { save: label }),
|
||||||
};
|
};
|
||||||
|
|
||||||
let skip = options.event && options.event.ctrlKey;
|
let skip = options.event && options.event.ctrlKey;
|
||||||
|
|
||||||
|
const rollMethod = this.data.type == "character" ? OseDice.RollSave : OseDice.Roll;
|
||||||
|
|
||||||
// Roll and return
|
// Roll and return
|
||||||
return AcksDice.Roll({
|
return AcksDice.Roll({
|
||||||
event: options.event,
|
event: options.event,
|
||||||
|
@ -384,7 +387,10 @@ export class AcksActor extends Actor {
|
||||||
if (game.user.targets.size > 0) {
|
if (game.user.targets.size > 0) {
|
||||||
for (let t of game.user.targets.values()) {
|
for (let t of game.user.targets.values()) {
|
||||||
data.roll.target = t;
|
data.roll.target = t;
|
||||||
await this.rollAttack(data, { type: type, skipDialog: options.skipDialog });
|
await this.rollAttack(data, {
|
||||||
|
type: type,
|
||||||
|
skipDialog: options.skipDialog,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.rollAttack(data, { type: type, skipDialog: options.skipDialog });
|
this.rollAttack(data, { type: type, skipDialog: options.skipDialog });
|
||||||
|
@ -437,7 +443,7 @@ export class AcksActor extends Actor {
|
||||||
thac0: thac0,
|
thac0: thac0,
|
||||||
dmg: dmgParts,
|
dmg: dmgParts,
|
||||||
save: attData.roll.save,
|
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 totalWeight = 0;
|
||||||
let hasItems = false;
|
let hasItems = false;
|
||||||
Object.values(this.data.items).forEach((item) => {
|
Object.values(this.data.items).forEach((item) => {
|
||||||
if (item.type == "item" && (['complete', 'disabled'].includes(option) || item.data.treasure)) {
|
if (item.type == "item" && !item.data.treasure) {
|
||||||
totalWeight += item.data.quantity.value * item.data.weight;
|
|
||||||
hasItems = true;
|
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;
|
totalWeight += item.data.weight;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (option === 'detailed' && hasItems) totalWeight += 80;
|
if (option === "detailed" && hasItems) totalWeight += 80;
|
||||||
|
|
||||||
data.encumbrance = {
|
data.encumbrance = {
|
||||||
pct: Math.clamped(
|
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
|
* @param html {HTML} The prepared HTML object ready to be rendered into the DOM
|
||||||
*/
|
*/
|
||||||
activateListeners(html) {
|
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
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
@ -220,22 +238,6 @@ export class AcksActorSheetMonster extends AcksActorSheet {
|
||||||
this._resetCounters(ev);
|
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
|
html
|
||||||
.find(".counter input")
|
.find(".counter input")
|
||||||
.click((ev) => ev.target.select())
|
.click((ev) => ev.target.select())
|
||||||
|
@ -263,7 +265,5 @@ export class AcksActorSheetMonster extends AcksActorSheet {
|
||||||
});
|
});
|
||||||
|
|
||||||
html.find('button[data-action="generate-saves"]').click(() => this.generateSave());
|
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;
|
groups[data.combatants[i].flags.acks.group].initiative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
combat.setupTurns();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async resetInitiative(combat, data) {
|
static async resetInitiative(combat, data) {
|
||||||
let updates = [];
|
let reroll = game.settings.get("acks", "rerollInitiative");
|
||||||
combat.data.combatants.forEach((c, i) => {
|
if (!["reset", "reroll"].includes(reroll)) {
|
||||||
updates.push({_id: c._id, initiative: ""});
|
return;
|
||||||
});
|
}
|
||||||
await combat.updateEmbeddedEntity("Combatant", updates);
|
combat.resetAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
static async individualInitiative(combat, data) {
|
static async individualInitiative(combat, data) {
|
||||||
|
@ -171,7 +172,9 @@ export class AcksCombat {
|
||||||
}
|
}
|
||||||
let data = {};
|
let data = {};
|
||||||
AcksCombat.rollInitiative(game.combat, 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;
|
result.target = data.roll.thac0;
|
||||||
|
|
||||||
const targetAc = data.roll.target ? data.roll.target.actor.data.data.ac.value : 9;
|
const targetAc = data.roll.target
|
||||||
const targetAac = data.roll.target ? data.roll.target.actor.data.data.aac.value : 0;
|
? data.roll.target.actor.data.data.ac.value
|
||||||
result.victim = data.roll.target ? data.roll.target.actor.name : null;
|
: 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 (game.settings.get("acks", "ascendingAC")) {
|
||||||
if (roll.total < targetAac + 10) {
|
if (roll.total < targetAac + 10) {
|
||||||
result.details = game.i18n.format("ACKS.messages.AttackAscendingFailure", {
|
result.details = game.i18n.format(
|
||||||
result: roll.total - 10,
|
"ACKS.messages.AttackAscendingFailure",
|
||||||
bonus: result.target,
|
{
|
||||||
});
|
result: roll.total - 10,
|
||||||
|
bonus: result.target,
|
||||||
|
}
|
||||||
|
);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
result.details = game.i18n.format("ACKS.messages.AttackAscendingSuccess", {
|
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({
|
static async Roll({
|
||||||
parts = [],
|
parts = [],
|
||||||
data = {},
|
data = {},
|
||||||
|
@ -302,7 +380,7 @@ export class AcksDice {
|
||||||
cancel: {
|
cancel: {
|
||||||
icon: '<i class="fas fa-times"></i>',
|
icon: '<i class="fas fa-times"></i>',
|
||||||
label: game.i18n.localize("ACKS.Cancel"),
|
label: game.i18n.localize("ACKS.Cancel"),
|
||||||
callback: (html) => {},
|
callback: (html) => { },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,20 @@ export const registerSettings = function () {
|
||||||
onChange: _ => window.location.reload()
|
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", {
|
game.settings.register("acks", "ascendingAC", {
|
||||||
name: game.i18n.localize("ACKS.Setting.AscendingAC"),
|
name: game.i18n.localize("ACKS.Setting.AscendingAC"),
|
||||||
hint: game.i18n.localize("ACKS.Setting.AscendingACHint"),
|
hint: game.i18n.localize("ACKS.Setting.AscendingACHint"),
|
||||||
|
|
|
@ -30,37 +30,43 @@ export const augmentTable = (table, html, data) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
async function rollTreasure(table, options = {}) {
|
function drawTreasure(table, data) {
|
||||||
let percent = (chance) => {
|
const percent = (chance) => {
|
||||||
let roll = new Roll("1d100").roll();
|
const roll = new Roll("1d100").roll();
|
||||||
return roll.total <= chance;
|
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 = {
|
let templateData = {
|
||||||
treasure: [],
|
treasure: data.treasure,
|
||||||
table: table,
|
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
|
// Animation
|
||||||
if (options.event) {
|
if (options.event) {
|
||||||
|
@ -69,7 +75,7 @@ async function rollTreasure(table, options = {}) {
|
||||||
.find(".table-result");
|
.find(".table-result");
|
||||||
results.each((_, item) => {
|
results.each((_, item) => {
|
||||||
item.classList.remove("active");
|
item.classList.remove("active");
|
||||||
if (ids.includes(item.dataset.resultId)) {
|
if (data.treasure[item.dataset.resultId]) {
|
||||||
item.classList.add("active");
|
item.classList.add("active");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -82,7 +88,7 @@ async function rollTreasure(table, options = {}) {
|
||||||
|
|
||||||
let chatData = {
|
let chatData = {
|
||||||
content: html,
|
content: html,
|
||||||
sound: "/systems/acks/assets/coins.mp3"
|
// sound: "/systems/acks/assets/coins.mp3"
|
||||||
}
|
}
|
||||||
|
|
||||||
let rollMode = game.settings.get("core", "rollMode");
|
let rollMode = game.settings.get("core", "rollMode");
|
||||||
|
|
|
@ -306,6 +306,18 @@
|
||||||
}
|
}
|
||||||
line-height: 36px;
|
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 {
|
h3 {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"description": "Play B/X OSR modules with ACKS on Foundry VTT",
|
"description": "Play B/X OSR modules with ACKS on Foundry VTT",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"minimumCoreVersion": "0.6.2",
|
"minimumCoreVersion": "0.6.2",
|
||||||
"compatibleCoreVersion": "0.6.5",
|
"compatibleCoreVersion": "0.6.6",
|
||||||
"templateVersion": 2,
|
"templateVersion": 2,
|
||||||
"author": "The Happy Anarchist",
|
"author": "The Happy Anarchist",
|
||||||
"esmodules": ["acks.js"],
|
"esmodules": ["acks.js"],
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{{! Sheet Tab Navigation }}
|
{{! 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">
|
<a class="item" data-tab="attributes">
|
||||||
{{localize "ACKS.category.attributes"}}
|
{{localize "ACKS.category.attributes"}}
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -32,11 +32,12 @@
|
||||||
{{#unless (getTagIcon tag.value)}}
|
{{#unless (getTagIcon tag.value)}}
|
||||||
<span title="{{tag.title}}">{{tag.value}}{{#unless @last}},{{/unless}}</span>
|
<span title="{{tag.title}}">{{tag.value}}{{#unless @last}},{{/unless}}</span>
|
||||||
|
|
||||||
|
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-short">
|
<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>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
{{#if ../owner}}
|
{{#if ../owner}}
|
||||||
|
@ -88,7 +89,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-short">
|
<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>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
{{#if ../owner}}
|
{{#if ../owner}}
|
||||||
|
@ -135,7 +136,7 @@
|
||||||
placeholder="0" />{{#if item.data.quantity.max}}<span>/{{item.data.quantity.max}}</span>{{/if}}
|
placeholder="0" />{{#if item.data.quantity.max}}<span>/{{item.data.quantity.max}}</span>{{/if}}
|
||||||
</div>
|
</div>
|
||||||
<div class="field-short">
|
<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>
|
||||||
<div class="item-controls">
|
<div class="item-controls">
|
||||||
{{#if ../owner}}
|
{{#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-hashtag"></i></div>
|
||||||
<div class="field-short"><i class="fas fa-weight-hanging"></i></div>
|
<div class="field-short"><i class="fas fa-weight-hanging"></i></div>
|
||||||
<div class="item-controls">
|
<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>
|
class="fa fa-plus"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -7,8 +7,18 @@
|
||||||
<ol class="treasure-list">
|
<ol class="treasure-list">
|
||||||
{{#each treasure as |t|}}
|
{{#each treasure as |t|}}
|
||||||
<li class="treasure flexrow">
|
<li class="treasure flexrow">
|
||||||
<img src="{{t.img}}" width="36" height="36" />
|
{{#if t.img}}<img src="{{t.img}}" width="36" height="36" />{{/if}}
|
||||||
<div>{{{t.text}}}</div>
|
<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>
|
</li>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ol>
|
</ol>
|
||||||
|
|
Loading…
Reference in New Issue