Skip to content

Commit

Permalink
10.6 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
ironmonk88 committed Jan 5, 2023
1 parent 4162e78 commit fd50990
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 43 deletions.
26 changes: 26 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,29 @@
## Version 10.6

Added a check to make sure adding XP only adds to tokens that are linked to an Actor.

Fixed issues calculating XP values from Actors that didn't have a max or value for xp.

Removed 'melee', 'condition' and 'spellcastEntry' from items lootable will collect.

Fixed issues collecting currency from Actors in PF2E.

Fixed issue changing if you want the loot entry to be automatically opened.

Fixed issue with Lootable name

Fixed issue with getting the default Loot Entry name.

Fixed issue with the loot being added to loot entries not correct, and not able to be assigned to players.

Fixed issues with saving throws when a token with tools is addded or removed from the Dialog.

Added option to use handlebars in flavor field when requesting rolls in MATT.

Added the option to select lore rolls in PF2E.

Fixed resizing issues with the saving throw dialog.

## Version 10.5

Fixed issue with Contested Rolls not responding to the ctrl or alt keys.
Expand Down
4 changes: 2 additions & 2 deletions apps/assignxp.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class AssignXPApp extends Application {
//get the actors
let monsters = [];
for (let combatant of entity.combatants) {
if (combatant.token?.disposition == 1 && combatant.actor && combatant.actor.hasPlayerOwner) {
if (combatant.token?.disposition == 1 && combatant.token?.actorLink && combatant.actor && combatant.actor.hasPlayerOwner) {
let actor = (combatant.actor.isPolymorphed ? game.actors.find(a => a.id == combatant.actor.getFlag(game.system.id, 'originalActor')) : combatant.actor);
this.actors.push({
actor: actor,
Expand Down Expand Up @@ -110,7 +110,7 @@ export class AssignXPApp extends Application {
const aXP = MonksTokenBar.system.getXP(a.actor);
const bXP = MonksTokenBar.system.getXP(b.actor);

let value = (MonksTokenBar.system.getLevel(a.actor) + (aXP.value / aXP.max)) - (MonksTokenBar.system.getLevel(b.actor) + (bXP.value / bXP.max));
let value = (MonksTokenBar.system.getLevel(a.actor) + ((aXP?.value ?? 0) / (aXP?.max ?? 1))) - (MonksTokenBar.system.getLevel(b.actor) + ((bXP?.value ?? 0) / (bXP?.max ?? 1)));
log(a.actor.name, b.actor.name, value);
return value;
});
Expand Down
55 changes: 33 additions & 22 deletions apps/lootables.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class LootablesApp extends Application {
else
result = item.system.armor.type != 'natural';
} else
result = !(['class', 'spell', 'feat', 'action', 'lore'].includes(item.type));
result = !(['class', 'spell', 'feat', 'action', 'lore', 'melee', 'condition', 'spellcastingEntry'].includes(item.type));

return result;
}).map(i => {
Expand Down Expand Up @@ -103,8 +103,12 @@ export class LootablesApp extends Application {
entry.items = entry.items.sort((a, b) => { return a.name.localeCompare(b.name); });

let actorCurrency = (document.actorData.currency || document.actor.system.currency);
for (let [key, value] of Object.entries(actorCurrency)) {
this.currency[key] = (this.currency[key] ?? 0) + value;
if (actorCurrency) {
for (let [key, value] of Object.entries(actorCurrency)) {
let val = (value.value ?? value);
if (isNaN(val)) val = 0;
this.currency[key] = (this.currency[key] ?? 0) + val;
}
}
};
this.entries = this.entries.sort((a, b) => { return a.name.localeCompare(b.name); });
Expand Down Expand Up @@ -207,7 +211,7 @@ export class LootablesApp extends Application {
$('.delete-entry', html).click(this.deleteEntry.bind(this));

$('[name="create-canvas-object"]', html).click(() => { this.createCanvasObject = $('[name="create-canvas-object"]', html).prop("checked"); });
$('[name="open-loot"]', html).click(() => { this.openLoot = $('[name="open-loot"]', html).prop("checked"); });
$('[name="open-loot"]', html).change(() => { this.openLoot = $('[name="open-loot"]', html).val(); });
$('[name="clear-items"]', html).click(() => { this.clearItems = $('[name="clear-items"]', html).prop("checked"); });
$('[name="entity-name"]', html).blur(() => { this.entityName = $('[name="entity-name"]', html).val(); });
$('[name="loot-entity"]', html).on("change", this.changeEntity.bind(this));
Expand Down Expand Up @@ -475,7 +479,7 @@ export class LootablesApp extends Application {
else if (entity == "convert")
return "Convert tokens";
else if (entity)
return `Creating ${entity.documentClass.documentName == "JournalEntry" ? "Journal Entry" : "Actor"} in the root folder`;
return `Creating ${(entity?.documentClass?.documentName || entity?.parent?.documentClass?.documentName) == "JournalEntry" ? "Journal Entry" : "Actor"} in the root folder`;
else
return "Unknown";
}
Expand All @@ -485,11 +489,15 @@ export class LootablesApp extends Application {
let lootSheet = setting('loot-sheet');
let collection = (this.isLootActor(lootSheet) ? game.actors : game.journal);

let documents = (entity == undefined ? collection.filter(e => e.folder == undefined) : entity.contents || entity.pages);
let previous = documents.map((e, i) =>
parseInt(e.name.replace('Loot Entry ', '').replace('(', '').replace(')', '')) || (i + 1)
).sort((a, b) => { return b - a; });
let num = (previous.length ? previous[0] + 1 : 1);
let num = 0;

let documents = (entity == undefined ? collection.filter(e => e.folder == undefined) : entity.contents || entity.pages || entity.parent.contents || entity.parent.pages);
if (documents && documents.length) {
let previous = documents.map((e, i) =>
parseInt(e.name.replace('Loot Entry ', '').replace('(', '').replace(')', '')) || (i + 1)
).sort((a, b) => { return b - a; });
num = (previous.length ? previous[0] + 1 : 1);
}

name = `${i18n("MonksTokenBar.LootEntry")}${(num > 1 ? ` (${num})` : '')}`;
return name;
Expand Down Expand Up @@ -697,30 +705,33 @@ export class LootablesApp extends Application {
ptAvg.y += entry.token.y;
ptAvg.count++;

let loot = entry.items.filter(i => i.quantity != "0");
for (let item of loot) {
let loots = entry.items.filter(i => i.quantity != "0");
for (let loot of loots) {
let item = loot.data;
let sysPrice = game.MonksEnhancedJournal.getSystemPrice(item);
let price = game.MonksEnhancedJournal.getPrice(sysPrice);

if (typeof item.quantity == "string" && item.quantity.indexOf("d") != -1) {
let r = new Roll(item.quantity);
if (typeof loot.quantity == "string" && loot.quantity.indexOf("d") != -1) {
let r = new Roll(loot.quantity);
await r.evaluate({ async: true });
item.quantity = r.total;
loot.quantity = r.total;
} else
item.quantity = parseInt(item.quantity);
loot.quantity = parseInt(loot.quantity);

if (isNaN(item.quantity))
item.quantity = 1;
if (isNaN(loot.quantity))
loot.quantity = 1;

item._id = randomID();
setProperty(item, "flags.monks-enhanced-journal.quantity", item.quantity);
setProperty(item, "flags.monks-enhanced-journal.quantity", loot.quantity);
setProperty(item, "flags.monks-enhanced-journal.price", price.value + " " + price.currency);
setProperty(item, "flags.monks-enhanced-journal.from", item.from);
setProperty(item, "flags.monks-enhanced-journal.from", loot.from);
if (lootSheet !== 'monks-enhanced-journal') {
setProperty(item, "system.quantity", item.quantity);
//+++ Need to set to correct system quantity
setProperty(item, "system.quantity", loot.quantity);
}

items.push(item);
}
items = items.concat(loot);
}

if (this.isLootActor(lootSheet)) {
Expand Down
4 changes: 3 additions & 1 deletion apps/savingthrow.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class SavingThrowApp extends Application {
this.entries = this.entries.concat(MonksTokenBar.getTokenEntries(tokens));

this.render(true);
window.setTimeout(() => { this.setPosition({ height: 'auto' }); }, 100);
}
changeTokens(e) {
let type = e.target.dataset.type;
Expand Down Expand Up @@ -143,7 +144,8 @@ export class SavingThrowApp extends Application {
this.entries.splice(idx, 1);
}
$(`li[data-item-id="${id}"]`, this.element).remove();
//this.render(true);
this.render(true); // Need this in case the token has tools
window.setTimeout(() => { this.setPosition({ height: 'auto' }); }, 100);
}

async requestRoll(roll) {
Expand Down
3 changes: 2 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"MonksTokenBar.TokenNoActorAttrs": "token has no actor to use for additional attributes",
"MonksTokenBar.ActorNoRollFunction": ": Could not find function to roll",
"MonksTokenBar.ActorNoTool": ": Does not have that tool",
"MonksTokenBar.ActorNoLore": ": Does not know that Lore",
"MonksTokenBar.UnknownSystem": "You're not using a system that Monk's Tokenbar supports.",
"MonksTokenBar.ActorNotCombatant": "Actor is not part of combat to roll initiative",

Expand Down Expand Up @@ -156,7 +157,7 @@
"MonksTokenBar.auto-gold-cr.hint": "Automatically calculate the gold by CR whenever the loot sheet is shown",
"MonksTokenBar.add-advantage-buttons.name": "Add Advantage Buttons",
"MonksTokenBar.add-advantage-buttons.hint": "Add advantage and disadvantage buttons to the token roll button",
"MonksTokenBar.minimum-ownership.name": "Minimum PLayer Permission",
"MonksTokenBar.minimum-ownership.name": "Minimum Player Permission",
"MonksTokenBar.minimum-ownership.hint": "The minimum permission a player needs to see a token",

"MonksTokenBar.XP": "XP",
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.5",
"version": "10.6",
"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.5.zip",
"download": "https://github.com/ironmonk88/monks-tokenbar/archive/10.6.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
58 changes: 50 additions & 8 deletions monks-tokenbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,10 @@ export class MonksTokenBar {
let message = game.messages.get(data.msgid);
const revealDice = game.dice3d ? game.settings.get("dice-so-nice", "immediatelyDisplayChatMessages") : true;
for (let response of data.response) {
let r = Roll.fromData(response.roll);
response.roll = r;
if (response.roll) {
let r = Roll.fromData(response.roll);
response.roll = r;
}
}
if (data.type == 'savingthrow')
SavingThrow.updateMessage(data.response, message, revealDice);
Expand Down Expand Up @@ -499,7 +501,7 @@ export class MonksTokenBar {
let curPermission = entry.actor?.ownership ?? {};
let tokPermission = token.actor?.ownership ?? {};
let ownedUsers = Object.keys(curPermission).filter(k => curPermission[k] === 3);
allowNpc = ownedUsers.some(u => tokPermission[u] === 3 && !game.users.get(u).isGM)
allowNpc = ownedUsers.some(u => tokPermission[u] === 3 && !game.users?.get(u).isGM)
&& curCombat.turns.every(t => { return t.tokenId !== token.id; });
}

Expand Down Expand Up @@ -604,7 +606,7 @@ export class MonksTokenBar {
return o.id == (request.type || request.key);
});
let req = (rt?.groups && rt?.groups[request.key]);
let flavor = i18n(req || rt?.text);
let flavor = i18n(req?.label || req || rt?.text);
switch (game.i18n.lang) {
case "pt-BR":
case "es":
Expand Down Expand Up @@ -1227,7 +1229,7 @@ Hooks.on("setupTileActions", (app) => {
},
group: 'monks-tokenbar',
fn: async (args = {}) => {
const { action, tile } = args;
const { action, tile, tokens, userid, value, method, change } = args;
let entities = await game.MonksActiveTiles.getEntities(args);

//if (entities.length == 0)
Expand All @@ -1239,7 +1241,27 @@ Hooks.on("setupTileActions", (app) => {
let type = (parts.length > 1 ? parts[0] : '');
let key = (parts.length > 1 ? parts[1] : parts[0]);

let savingthrow = new SavingThrowApp(MonksTokenBar.getTokenEntries(entities), { rollmode: action.data.rollmode, request: [{ type, key }], dc: action.data.dc, flavor: action.data.flavor });
let flavor = action.data.flavor;

if (flavor && flavor.includes("{{")) {
let context = {
actor: tokens[0]?.actor?.toObject(false),
token: tokens[0]?.toObject(false),
speaker: tokens[0],
tile: tile.toObject(false),
entities: entities,
user: game.users.get(userid),
value: value,
scene: canvas.scene,
method: method,
change: change
};

const compiled = Handlebars.compile(flavor);
flavor = compiled(context, { allowProtoMethodsByDefault: true, allowProtoPropertiesByDefault: true }).trim();
}

let savingthrow = new SavingThrowApp(MonksTokenBar.getTokenEntries(entities), { rollmode: action.data.rollmode, request: [{ type, key }], dc: action.data.dc, flavor:flavor });
savingthrow['active-tiles'] = { id: args._id, tile: args.tile.uuid, action: action };
if (action.data.silent === true) {
let msg = await savingthrow.requestRoll();
Expand Down Expand Up @@ -1348,7 +1370,7 @@ Hooks.on("setupTileActions", (app) => {
},
group: 'monks-tokenbar',
fn: async (args = {}) => {
const { action, tile } = args;
const { action, tile, tokens, userid, value, method, change } = args;
let entities1 = await game.MonksActiveTiles.getEntities(args, "tokens", action.data.entity1);
let entities2 = await game.MonksActiveTiles.getEntities(args, "tokens", action.data.entity2);

Expand All @@ -1366,9 +1388,29 @@ Hooks.on("setupTileActions", (app) => {
let request1 = mergeObject((MonksTokenBar.getTokenEntries([entity1])[0] || {}), { request: action.data.request1 });
let request2 = mergeObject((MonksTokenBar.getTokenEntries([entity2])[0] || {}), { request: action.data.request2 });

let flavor = action.data.flavor;

if (flavor && flavor.includes("{{")) {
let context = {
actor: tokens[0]?.actor?.toObject(false),
token: tokens[0]?.toObject(false),
speaker: tokens[0],
tile: tile.toObject(false),
entities: [entity1, entity2],
user: game.users.get(userid),
value: value,
scene: canvas.scene,
method: method,
change: change
};

const compiled = Handlebars.compile(flavor);
flavor = compiled(context, { allowProtoMethodsByDefault: true, allowProtoPropertiesByDefault: true }).trim();
}

let contested = new ContestedRollApp(
[request1, request2],
{ rollmode: action.data.rollmode, request: action.data.request, flavor: action.data.flavor });
{ rollmode: action.data.rollmode, request: action.data.request, flavor: flavor });
contested['active-tiles'] = { id: args._id, tile: args.tile.uuid, action: action };
if (action.data.silent === true) {
let msg = await contested.requestRoll();
Expand Down
41 changes: 40 additions & 1 deletion systems/pf2e-rolls.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,35 @@ export class PF2eRolls extends BaseRolls {
return 'ability:str';
}

dynamicRequest(entries) {
let lore = {};
//get the first token's tools
for (let item of entries[0].token.actor?.items) {
if (item.type == 'lore') {
let sourceID = item.id;
//let toolid = item.name.toLowerCase().replace(/[^a-z]/gi, '');
lore[sourceID] = item.name;
}
}
//see if the other tokens have these tools
if (Object.keys(lore).length > 0) {
for (let i = 1; i < entries.length; i++) {
for (let [k, v] of Object.entries(lore)) {
let _lore = entries[i].token.actor.items.find(l => {
return l.type == 'lore' && l.id == k;
});
if (_lore == undefined)
delete lore[k];
}
}
}

if (Object.keys(lore).length == 0)
return;

return [{ id: 'lore', text: 'Lore', groups: lore }];
}

getXP(actor) {
return actor?.system.details.xp;
}
Expand Down Expand Up @@ -145,10 +174,20 @@ export class PF2eRolls extends BaseRolls {
} else
rollfn = actor.rollSkill;
}
else if (request.type == 'lore') {
let lore = actor.items.find(i => { return i.id == request.key; });
if (lore != undefined) {
let slug = lore.name.slugify();
opts = actor.getRollOptions(["all", "skill-check", slug]);
rollfn = actor.skills[slug].check.roll;
actor = actor.skills[slug].check;
} else
return { id: id, error: true, msg: i18n("MonksTokenBar.ActorNoLore") };
}

if (rollfn != undefined) {
try {
if (request.type != 'skill')
if (request.type != 'skill' && request.type != 'lore')
return rollfn.call(actor, e, opts).then((roll) => { return callback(roll); }).catch(() => { return { id: id, error: true, msg: i18n("MonksTokenBar.UnknownError") } });
else {
return new Promise(function (resolve, reject) {
Expand Down
Loading

0 comments on commit fd50990

Please sign in to comment.