Skip to content

Commit

Permalink
10.3 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ironmonk88 committed Oct 24, 2022
1 parent 8d2b056 commit 3fbb8ab
Show file tree
Hide file tree
Showing 14 changed files with 414 additions and 62 deletions.
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
## Version 10.3

Fixed issues with calculating xp in pf2e

Fixed issue with assigning xp that's not a number

Fixed issue with contested rolls not getting the correct request value.

Fixed issue with getting currency when compiling lootables after a combat

Fixed issue with lootable generated for Monk's Enhanced Journal deleting after the first item is updated.

Added the option to start a combat if initiative is requested and no combat is available.

Fixed issue with finding the owner of a token.

Fixed issue where rolling initiative was throwing an error in pf1.

Fixed issue with Saving Throw when no default request has been determined.

Fixed issue where active effects aren't updating the token bar values

Remove tokens added by multilevel tokens.

Only notifying once on movement change if there's more than one GM logged in.

Added the option to use tagger when selecting tokens for a roll request

Fixed issue with pf1 when skipping the dialog is requested.

## Version 10.2

Updated the assign XP dialog to allow you to customise the actors that are being assigned XP. It will remember the last tokens to assigned XP to, can use the current combats tokens, or you can drag and drop and actor onto the dialog to add them to the list.
Expand Down
6 changes: 4 additions & 2 deletions apps/assignxp.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export class AssignXPApp extends Application {
for (let combatant of monsters) {
if (combatant.token?.disposition != 1 && combatant.actor && !combatant.actor.hasPlayerOwner) {
if (game.system.id == 'pf2e') {
let monstLevel = parseInt(MonksTokenBar.system.getLevel(combatant?.actor)?.value);
let monstLevel = parseInt(MonksTokenBar.system.getLevel(combatant?.actor));
let monstXP = this.xpchart[Math.clamped(4 + (monstLevel - calcAPL), 0, this.xpchart.length - 1)];
combatxp += monstXP;
}else
Expand Down Expand Up @@ -218,7 +218,9 @@ export class AssignXPApp extends Application {
});

$('#assign-xp-value', html).blur(function () {
that.xp = parseInt($(this).val());
that.xp = parseInt($(this).val() || '0');
if (isNaN(that.xp))
that.xp = 0;
that.changeXP.call(that, that.xp);
that.render(true);
});
Expand Down
2 changes: 1 addition & 1 deletion apps/contestedroll.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class ContestedRollApp extends Application {
if (index > 1)
return null;

let requests = this.request instanceof Array ? item.request : [item.request];
let requests = item.request instanceof Array ? item.request : [item.request];
requests = requests.map(r => {
r.name = MonksTokenBar.getRequestName(this.requestoptions, r);
return r;
Expand Down
33 changes: 27 additions & 6 deletions apps/lootables.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MonksTokenBar, log, i18n, warn, setting } from "../monks-tokenbar.js";
import { i18n, log, MonksTokenBar, setting, warn } from "../monks-tokenbar.js";

export class LootablesApp extends FormApplication {
constructor(entity, options) {
Expand All @@ -12,6 +12,7 @@ export class LootablesApp extends FormApplication {
}).map(c => {
return c.token;
});
this.combat = entity;
} else {
tokens = entity || canvas.tokens.controlled.filter(t => t.actor != undefined);
if (tokens != undefined && !$.isArray(tokens))
Expand Down Expand Up @@ -155,6 +156,16 @@ export class LootablesApp extends FormApplication {
$('.item-row', html).on('click', this.toggleTooltip.bind(this));
};

async _render(force, options = {}) {
let result = await super._render(force, options);

if (this.element && this.combat) {
$(this.element).attr("data-combat-id", this.combat.id);
}

return result;
}

toggleTooltip(ev) {
$(ev.currentTarget).next().toggle();
}
Expand All @@ -172,7 +183,7 @@ export class LootablesApp extends FormApplication {
this.usecr = $('#assign-gold-by-cr').is(':checked');
for (let token of this.entries) {
let hasGold = false;
for (const [k, v] in Object.entries(token.actor.system.currency)) {
for (let [k, v] of Object.entries(token.actor.system.currency)) {
hasGold = (hasGold && parseInt(v.value || v) > 0);
}
// If the actor has no gold, assign gold by CR: gold = 0.6e(0.15*CR)
Expand Down Expand Up @@ -464,6 +475,15 @@ export class LootablesApp extends FormApplication {
ptAvg.count++;

let loot = entry.items.filter(i => i.included);
for (let item of loot) {
let sysPrice = game.MonksEnhancedJournal.getSystemPrice(item);
let price = game.MonksEnhancedJournal.getPrice(sysPrice);

item._id = randomID();
setProperty(item, "flags.monks-enhanced-journal.quantity", 1);
setProperty(item, "flags.monks-enhanced-journal.price", price.value + " " + price.currency);
setProperty(item, "flags.monks-enhanced-journal.from", entry.actor.name);
}
items = items.concat(loot);

let entryCurr = entry.currency;
Expand Down Expand Up @@ -497,9 +517,9 @@ export class LootablesApp extends FormApplication {

let entityCurr = entity.getFlag("monks-enhanced-journal", "currency") || {};
for (let curr of Object.keys(CONFIG[game.system.id.toUpperCase()]?.currencies || {})) {
entityCurr[curr] = parseInt(currency[curr] || 0) + parseInt(entityCurr[curr] || 0);
entityCurr[curr] = parseInt(entityCurr[curr] || 0) + parseInt(currency[curr] || 0);
}
await entity.setFlag('monks-enhanced-journal', 'currency', currency);
await entity.setFlag('monks-enhanced-journal', 'currency', entityCurr);
}

msg = (created ?
Expand Down Expand Up @@ -534,7 +554,7 @@ export class LootablesApp extends FormApplication {
}
}

msg += `and a ${this.isLootActor(lootSheet) ? "Token" : "Note"} has been added to the canvas`
msg += ` and a ${this.isLootActor(lootSheet) ? "Token" : "Note"} has been added to the canvas`
}

if (setting('open-loot') != "none" && entity) {
Expand All @@ -553,7 +573,8 @@ export class LootablesApp extends FormApplication {

if(msg != "")
ui.notifications.info(msg);

if (this.combat)
MonksTokenBar.emit("closeLootable", { id: this.combat.id });
this.close();
}

Expand Down
98 changes: 81 additions & 17 deletions apps/savingthrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export class SavingThrowApp extends Application {

if (this.request == undefined || !this.request.length) {
log('Invalid request');
ui.notifications.error("Invalid value sent as a request");
ui.notifications.error("Please select a request to roll");
return;
}

Expand All @@ -179,6 +179,30 @@ export class SavingThrowApp extends Application {
});
let flavor = this.flavor;
let name = this.opts?.name || MonksTokenBar.getRequestName(this.requestoptions, requests[0]);

if (requests[0].type == 'misc' && requests[0].key == 'init') {
if (!game.combats.active) {
await Dialog.confirm({
title: "No Combat",
content: "You're asking for an initiative roll but there's no combat. <br />Would you like to start a combat with these tokens?<br />",
yes: async () => {
const cls = getDocumentClass("Combat")
await cls.create({ scene: canvas.scene.id, active: true });
}
});
}

let combat = game.combats.active;
if (combat) {
let combatants = []
for (let token of this.entries) {
if (!combat.combatants.find(c => c.token?.id == token.token.id))
combatants.push({ tokenId: token.token.id, actorId: token.token.actor?.id });
}
if (combatants.length)
await Combatant.createDocuments(combatants, { parent: combat });
}
}

let requestdata = {
dc: this.dc || (this.request[0].key == 'death' && ['dnd5e', 'sw5e'].includes(game.system.id) ? '10' : ''),
Expand All @@ -203,7 +227,7 @@ export class SavingThrowApp extends Application {
for (let i = 0; i < this.entries.length; i++) {
let token = this.entries[i].token;
if (token.actor != undefined) {
for (var key in Object.keys(token.actor.ownership)) {
for (let key of Object.keys(token.actor.ownership)) {
if (key != 'default' && token.actor.ownership[key] >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
if (whisper.find(t => t == key) == undefined)
whisper.push(key);
Expand Down Expand Up @@ -281,7 +305,7 @@ export class SavingThrowApp extends Application {
if (this.request.length > 1 && this.request.some(r => r.type == type && r.key == key)) {
this.request.findSplice(r => r.type == type && r.key == key);
target.removeClass('selected');
} else {
} else if (!this.request.some(r => r.type == type && r.key == key)){
this.request.push({ type, key });
target.addClass('selected');
}
Expand Down Expand Up @@ -325,8 +349,7 @@ export class SavingThrow {

static async rollDice(dice) {
let r = new Roll(dice);
r.evaluate();
return r;
return r.evaluate({ async: true });
}

static async returnRoll (id, roll, actor, rollmode, msgId) {
Expand All @@ -336,8 +359,45 @@ export class SavingThrow {
let combatant = roll.combatants.find(c => { return c?.actor?.id == actor.id });
if (combatant != undefined) {
let initTotal = combatant.actor.system.attributes.init.total;
let jsonRoll = '{ "class": "Roll", "dice": [], "formula": "1d20 + ' + initTotal + '", "terms": [{ "class": "Die", "number": 1, "faces": 20, "modifiers": [], "options": { "critical": 20, "fumble": 1 }, "results": [{ "result": ' + (combatant.initiative - initTotal) + ', "active": true }] }, " + ", ' + initTotal + '], "results": [' + (combatant.initiative - initTotal) + ', " + ", ' + initTotal + '], "total": ' + combatant.initiative + ' }';
let fakeroll = Roll.fromJSON(jsonRoll);
let jsonRoll = {
"class": "Roll",
"dice": [],
"formula": `1d20 + ${initTotal}`,
"terms": [
{
"class": "Die",
"options": {
"critical": 20,
"fumble": 1
},
"evaluated": true,
"number": 1,
"faces": 20,
"modifiers": [],
"results": [
{
"result": (combatant.initiative - initTotal),
"active": true
}
]
},
{
"class": "OperatorTerm",
"options": {},
"evaluated": true,
"operator": "+"
},
{
"class": "NumericTerm",
"options": {},
"evaluated": true,
"number": initTotal
}
],
"total": combatant.initiative,
"evaluated": true
};
let fakeroll = Roll.fromData(jsonRoll);
return { id: id, roll: fakeroll, finish: null, reveal: true };
} else {
log('Actor is not part of combat to roll initiative', actor, roll);
Expand All @@ -347,8 +407,10 @@ export class SavingThrow {
let finishroll;
if (roll instanceof ChatMessage) {
let msg = roll;
roll = msg.roll;
roll = msg.roll || msg.rolls[0];
msg.delete();
if (!(roll instanceof Roll))
roll = Roll.fromJSON(roll);
}

let whisper = (rollmode == 'roll' ? null : ChatMessage.getWhisperRecipients("GM").map(w => { return w.id }));
Expand Down Expand Up @@ -741,22 +803,24 @@ Hooks.on("diceSoNiceRollComplete", (messageid) => {
Hooks.on("renderSavingThrowApp", (app, html) => {
if (app.request == undefined) {
let request = MonksTokenBar.system.defaultRequest(app) || SavingThrow.lastRequest;
if (!request) {
/*if (!request) {
request = [];
$('.request-roll .request-option', html).each(function () {
request.push({ type: this.data.type, key: this.data.key });
$('.request-roll .request-option:first', html).each(function () {
request.push({ type: this.dataset.type, key: this.dataset.key });
});
}
}*/
// confirm that the requests are on the list
request = request instanceof Array ? request : [request];
request = request.filter(r => {
return $(`.request-roll .request-option[data-type="${r.type}"][data-key="${r.key}"]`, html).length;
})
if (request) {
request = request instanceof Array ? request : [request];
request = request.filter(r => {
return $(`.request-roll .request-option[data-type="${r.type}"][data-key="${r.key}"]`, html).length;
});
}

app.request = request;
}

for (let r of app.request) {
for (let r of app.request || []) {
$(`.request-roll .request-option[data-type="${r.type}"][data-key="${r.key}"]`, html).addClass('selected');
}

Expand Down
22 changes: 20 additions & 2 deletions apps/tokenbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ export class TokenBar extends Application {
}
});

Hooks.on("updateActiveEffect", (effect) => {
if (((game.user.isGM || setting("allow-player")) && !setting("disable-tokenbar"))) {
let actor = effect.parent;
if (actor instanceof Actor) {
let tkn = this.tokens.find(t => t.token.actor.id == actor.id);
if (tkn != undefined) {
this.updateToken(tkn)
} else if (data.ownership != undefined) {
this.refresh();
}
}
}
});

//updateActiveEffect

this.buttons = MonksTokenBar.system.getButtons();
}

Expand Down Expand Up @@ -186,9 +202,11 @@ export class TokenBar extends Application {

let hasActor = (t.actor != undefined);
let canView = (game.user.isGM || t.actor?.isOwner || t.actor?.testUserPermission(game.user, "OBSERVER"));
let disp = ((t.actor?.hasPlayerOwner && t.disposition == 1 && include != 'exclude') || include === 'include')
let disp = ((t.actor?.hasPlayerOwner && t.disposition == 1 && include != 'exclude') || include === 'include');

let mlt = !!getProperty(t, "flags.multilevel-tokens.stoken");

let addToken = hasActor && canView && disp;
let addToken = hasActor && canView && disp && !mlt;
debug("Checking token", t, "addToken", addToken, "Has Actor", hasActor, "Can View", canView, "Disposition", disp, "Included", include);

return addToken;
Expand Down
9 changes: 9 additions & 0 deletions css/tokenbar.css
Original file line number Diff line number Diff line change
Expand Up @@ -1038,3 +1038,12 @@ li.chat-message.message .message-content .monks-tokenbar *.noselect * {
height: 20px;
line-height: 21px;
}

a.inline-request-roll {
background: #DDD;
padding: 1px 4px;
border: 1px solid #4b4a44;
border-radius: 2px;
white-space: nowrap;
word-break: break-all;
}
11 changes: 11 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,17 @@
"MonksTokenBar.LootEntry": "Loot Entry",
"MonksTokenBar.FromCombat": "Actors from combat",
"MonksTokenBar.Combat": "Combat",
"MonksTokenBar.TransferLoot": "Transfer loot from selected token(s)",
"MonksTokenBar.RequestRollConfig": "Request Roll Config",
"MonksTokenBar.Silent": "Silent",
"MonksTokenBar.FastForward": "Fast Forward",
"MonksTokenBar.DC": "DC",
"MonksTokenBar.FlavorText": "Flavor Text",
"MonksTokenBar.PublicHiddenRoll": "Public Msg, Private Roll",
"MonksTokenBar.PrivateHiddenRoll": "Private Msg, Hidden Roll",
"MonksTokenBar.GMOnlyRoll": "GM Only Roll",
"MonksTokenBar.Close": "Close",
"MonksTokenBar.Save": "Save",

"MonksTokenBar.None": "No one",
"MonksTokenBar.GMOnly": "GM Only",
Expand Down
4 changes: 2 additions & 2 deletions module.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "Monk's TokenBar",
"description": "Add a bar with all the current player tokens. Limit movement, roll saving throws, assign XP.",
"version": "10.2",
"version": "10.3",
"authors": [
{
"name": "IronMonk",
Expand Down Expand Up @@ -64,7 +64,7 @@
"css/tokenbar.css"
],
"url": "https://github.com/ironmonk88/monks-tokenbar",
"download": "https://github.com/ironmonk88/monks-tokenbar/archive/10.2.zip",
"download": "https://github.com/ironmonk88/monks-tokenbar/archive/10.3.zip",
"manifest": "https://github.com/ironmonk88/monks-tokenbar/releases/latest/download/module.json",
"bugs": "https://github.com/ironmonk88/monks-tokenbar/issues",
"allowBugReporter": true,
Expand Down
Loading

0 comments on commit 3fbb8ab

Please sign in to comment.