Skip to content
This repository has been archived by the owner on Sep 18, 2024. It is now read-only.

Commit

Permalink
Merge pull request #696 from death-save:v1.10.0
Browse files Browse the repository at this point in the history
V1.10.0
  • Loading branch information
eclarke12 authored Jul 28, 2022
2 parents f0f65a3 + a2a93b8 commit 6d052b2
Show file tree
Hide file tree
Showing 30 changed files with 1,025 additions and 322 deletions.
790 changes: 719 additions & 71 deletions API.md

Large diffs are not rendered by default.

20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@
2. Chat log may not re-render when Hide Names settings are changed. This may cause the old name to still show in the log for players. Advise players to reload Foundry if you change these settings mid-session.
3. The Default/Inferred Condition Lab Mappings for game systems may not correctly import all data. Importing the map from the CUB Condition Maps folder imports correctly.
4. **PF2e users**: PF2e is not currently supported by Enhanced Conditions due to the customisation of the effects framework implemented by the system.
## [1.10.0] - 2022-07-27
> This update adds compatibility for Foundry VTT v10.275 (v10-testing 1)
### ✨ Enhanced Conditions
- Macros executed by Conditions correctly pass the actor/token
- Added a shim for the deprecated API function `applyCondition` that points to the correct method: `addCondition`

### 💭 Concentrator
- Concentrator now fires when temporary HP is damaged

### 😷 Hide Names
- Added API access to Hide Names functionality (thanks @Autmor ! 🎉).
> Check [API Docs](./API.md) for more details
### 🕰️Temporary Combatants
- Temporary Combatants no longer require an actor or token
> The existing Temporary Combatants folder can safely be deleted from your Actor directory
### Misc Token
- Added a setting for Mighty Summoner that allows the GM to opt-out of receiving Mighty Summoner prompts

## [1.9.2] - 2022-06-25
### ✨ Enhanced Conditions
Expand Down
16 changes: 15 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
}
},
"ChatCard": {
"Heading": "Enhanced Conditions",
"Heading": "Enhanced Condition Changes",
"HeadingActive": "Active Enhanced Conditions",
"Title": {
"Added": "Added",
"Removed": "Removed",
Expand All @@ -42,6 +43,9 @@
"RemoveHeading": "Remove Trigger",
"Description": "Triggers that Apply or Remove this Condition",
"SelectNone": "--No Trigger--"
},
"Warnings": {
"ApplyCondition": "applyCondition was replaced with addCondition. Please update your code."
}
},
"CONCENTRATOR": {
Expand Down Expand Up @@ -94,8 +98,18 @@
"MigrationVersionH": "Version of CUB for which migration was last performed",
"ShowSortDirectionDialogN": "Show Condition Lab Sort Direction Save Dialog",
"ShowSortDirectionDialogH": "Whether or not to show the confirmation dialog for saving the sort direction."
},
"MIGHTY_SUMMONER": {
"PromptGMN": "Prompt GM For Mighty Summoner",
"PromptGMH": "Specify whether GMs should receive the Mighty Summoner prompt when tokens are placed. Note: due to the way permissions work in Foundry, any actor with the feat will cause the GM to be prompted for every token dropped if this setting is checked."
}
},
"TEMPORARY_COMBATANTS": {
"Form": {
"Title": "Create Temporary Combatant"
},
"AddTempCombatant": "Add Temporary Combatant"
},
"TRIGGLER": {
"ButtonTitle": "Open Triggler"
},
Expand Down
38 changes: 21 additions & 17 deletions module.json
Original file line number Diff line number Diff line change
@@ -1,30 +1,28 @@
{
"name": "combat-utility-belt",
"id": "combat-utility-belt",
"title": "Combat Utility Belt",
"description": "Adds various combat-focused features",
"version": "1.9.2",
"author": "Evan Clarke [errational#2007]",
"version": "1.10.0",
"authors": [
{
"name": "Evan Clarke",
"url": "https://patreon.com/deathsave",
"email": "[email protected]",
"discord": "errational#2007",
"twitter": "@death_save_dev",
"reddit": "u/etherboy12"
}
],
"minimumCoreVersion": "9.235",
"compatibleCoreVersion": "9.269",
"url": "https://github.com/death-save/combat-utility-belt",
"bugs": "https://github.com/death-save/combat-utility-belt/issues",
"readme": "https://github.com/death-save/combat-utility-belt/wiki",
"manifest": "https://github.com/death-save/combat-utility-belt/releases/latest/download/module.json",
"download": "https://github.com/death-save/combat-utility-belt/releases/latest/download/module.zip",
"scripts": [
"./library/typewriterjs/core.js"
"library/typewriterjs/core.js"
],
"esmodules": [
"./combat-utility-belt.js"
"combat-utility-belt.js"
],
"languages": [
{
Expand Down Expand Up @@ -67,27 +65,27 @@
"name": "Polski",
"path": "lang/pl.json"
}
],
],
"packs": [
{
"name": "conditionsdnd5e",
"label": "Conditions (D&D5e)",
"system": "dnd5e",
"module": "combat-utility-belt",
"path": "./packs/conditionsdnd5e.db",
"type": "JournalEntry"
"path": "packs/conditionsdnd5e.db",
"type": "JournalEntry",
"private": false
},
{
"name": "conditionsarchmage",
"label": "Conditions (13th Age)",
"system": "archmage",
"module": "combat-utility-belt",
"path": "./packs/conditionsarchmage.db",
"type": "JournalEntry"
"path": "packs/conditionsarchmage.db",
"type": "JournalEntry",
"private": false
}
],
"styles" : [
"./styles/combat-utility-belt.css"
"styles/combat-utility-belt.css"
],
"media": [
{
Expand All @@ -102,5 +100,11 @@
"flags": {
"allowBugReporter": true
},
"socket": true
}
"socket": true,
"compatibility": {
"minimum": "10.270",
"verified": "10.275"
},
"name": "combat-utility-belt",
"minimumCoreVersion": "10.270"
}
10 changes: 4 additions & 6 deletions modules/butler.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export const DEFAULT_CONFIG = {
macroConfig: `${PATH}/templates/enhanced-condition-macro-config.hbs`,
triggerConfig: `${PATH}/templates/enhanced-condition-trigger-config.hbs`
},
migrationVersion: null
migrationVersion: ""
},
giveXP: {
enable: false,
Expand Down Expand Up @@ -272,7 +272,8 @@ export const DEFAULT_CONFIG = {
},
mightySummoner: {
enable: false,
featName: "Mighty Summoner"
featName: "Mighty Summoner",
promptGm: false
},
panSelect: {
enablePan: false,
Expand Down Expand Up @@ -445,10 +446,6 @@ export const SETTING_KEYS = {
hideFooter: "hideFooter",
hideParts: "hideNameParts"
},
mightySummoner: {
enable: "enableMightySummoner",
featName: "mightySummonerFeatName"
},
panSelect: {
enablePan: "enablePan",
panGM: "panGM",
Expand All @@ -472,6 +469,7 @@ export const SETTING_KEYS = {
tokenUtility: {
mightySummoner: "enableMightySummoner",
mightySummonerFeat: "mightySummonerFeatName",
mightySummonerPromptGm: "mightySummonerPromptGm",
autoRollHP: "autoRollHP",
hideAutoRoll: "hideAutoRollHP",
effectSize: "effectSize"
Expand Down
49 changes: 29 additions & 20 deletions modules/concentrator.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class Concentrator {
*/
static async _onRenderChatMessage(app, html, data) {
const enableConcentrator = Sidekick.getSetting(SETTING_KEYS.concentrator.enable);
const actor = ChatMessage.getSpeakerActor(app.data?.speaker);
const actor = ChatMessage.getSpeakerActor(app.speaker);
const gmUser = Sidekick.getFirstGM();

if (!enableConcentrator || game.userId !== gmUser?.id || !actor) return;
Expand Down Expand Up @@ -68,7 +68,7 @@ export class Concentrator {
const isSpell = item ? item.type === "spell" : false;

// If it is, check if it requires concentration
const isConcentration = concentrationDiv.length ? true : (isSpell ? !!getProperty(item, `data.data.components.concentration`) : false);
const isConcentration = concentrationDiv.length ? true : (isSpell ? !!getProperty(item, `system.components.concentration`) : false);

if (!isConcentration) return;

Expand Down Expand Up @@ -108,16 +108,20 @@ export class Concentrator {

// Update handled in token hooks
if (actor.isToken) return true;

const newHealth = getProperty(update, `data.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const oldHealth = getProperty(actor, `data.data.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);


const newTempHealth = getProperty(update, `system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.temp`);
const oldTempHealth = getProperty(actor, `system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.temp`);
const tempDamageTaken = Concentrator._wasDamageTaken(newTempHealth, oldTempHealth);

const newHealth = getProperty(update, `system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const oldHealth = getProperty(actor, `system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const damageTaken = Concentrator._wasDamageTaken(newHealth, oldHealth);

options[NAME] = options[NAME] ?? {};

if (damageTaken) {
if (tempDamageTaken || damageTaken) {
options[NAME][FLAGS.concentrator.damageTaken] = true;
options[NAME][FLAGS.concentrator.damageAmount] = Concentrator._calculateDamage(newHealth, oldHealth);
options[NAME][FLAGS.concentrator.damageAmount] = tempDamageTaken ? Concentrator._calculateDamage(newTempHealth, oldTempHealth) : Concentrator._calculateDamage(newHealth, oldHealth);
options[NAME][FLAGS.concentrator.isDead] = newHealth <= 0;
}

Expand Down Expand Up @@ -153,21 +157,26 @@ export class Concentrator {
* @param {*} options
*/
static _onPreUpdateToken(token, update, options, userId){
if (token.data.actorLink) return true;
if (token.actorLink) return true;

const enableConcentrator = Sidekick.getSetting(SETTING_KEYS.concentrator.enable);

if (!enableConcentrator) return true;

const newHealth = getProperty(update, `actorData.data.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const oldHealth = getProperty(token, `actor.data.data.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const newTempHealth = getProperty(update, `actorData.system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.temp`);
const oldTempHealth = getProperty(token, `actor.system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.temp`);

const tempDamageTaken = Concentrator._wasDamageTaken(newTempHealth, oldTempHealth);

const newHealth = getProperty(update, `actorData.system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);
const oldHealth = getProperty(token, `actor.system.${Sidekick.getSetting(SETTING_KEYS.concentrator.healthAttribute)}.value`);

const damageTaken = Concentrator._wasDamageTaken(newHealth, oldHealth);

if (damageTaken) {
if (tempDamageTaken || damageTaken) {
const cubOption = options[NAME] = options[NAME] ?? {};
cubOption[FLAGS.concentrator.damageTaken] = true;
cubOption[FLAGS.concentrator.damageAmount] = Concentrator._calculateDamage(newHealth, oldHealth);
cubOption[FLAGS.concentrator.damageAmount] = tempDamageTaken ? Concentrator._calculateDamage(newTempHealth, oldTempHealth) : Concentrator._calculateDamage(newHealth, oldHealth);
cubOption[FLAGS.concentrator.isDead] = newHealth <= 0;
}

Expand Down Expand Up @@ -274,7 +283,7 @@ export class Concentrator {
* Processes a damage event for Concentration purposes
* @param {*} entity
* @param {*} options
* @returns
* @returns {Concentrator._processDeath | Concentrator._determinePromptedUsers}
*/
static _processDamage(entity, options) {
const isConcentrating = Concentrator._isConcentrating(entity);
Expand Down Expand Up @@ -417,9 +426,9 @@ export class Concentrator {
});

Hooks.once("createChatMessage", (message, options, userId) => {
const includesSaveText = message.data.flavor?.includes(game.i18n.format("DND5E.SavePromptTitle", {ability: CONFIG.DND5E.abilities[ability]}));
const includesSaveText = message.flavor?.includes(game.i18n.format("DND5E.SavePromptTitle", {ability: CONFIG.DND5E.abilities[ability]}));
// Support BetterRolls5e
const betterRoll = message.data?.flags?.betterrolls5e;
const betterRoll = message?.flags?.betterrolls5e;

if (!message.isRoll && (!includesSaveText || !betterRoll)) return;

Expand Down Expand Up @@ -514,7 +523,7 @@ export class Concentrator {
* @param {*} spell
* @param {*} conditionName
* @param {*} options
* @returns
* @returns {Actor.setFlag}
*/
static async _startConcentration(entity, spell, conditionName, {sendMessage=DEFAULT_CONFIG.concentrator.notifyConcentration.none}={}) {
const isActor = entity instanceof Actor;
Expand Down Expand Up @@ -542,7 +551,7 @@ export class Concentrator {
* Processes end of Concentration
* @param {*} entity
* @param {*} options
* @returns
* @returns {Actor.unsetFlag}
*/
static async _endConcentration(entity, {reason=null}={}) {
const isActor = entity instanceof Actor;
Expand Down Expand Up @@ -670,7 +679,7 @@ export class Concentrator {
/**
* Calculates a Concentration DC based on a damage amount
* @param {*} damage
* @returns
* @returns {Number}
*/
static _calculateDC(damage) {
const halfDamage = Math.floor(damage / 2);
Expand Down Expand Up @@ -769,7 +778,7 @@ export class Concentrator {
* Finds whisper recipients for given entity and desired visibility
* @param {*} entity
* @param {*} desiredVisibility
* @returns
* @returns {Array}
*/
static _getWhisperRecipients(entity, desiredVisibility) {
let whisperRecipients = [];
Expand Down
6 changes: 3 additions & 3 deletions modules/cub-puter.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class CUBPuter extends FormApplication {
* Passes data to the template on render
*/
getData() {
const moduleVersion = game.modules.get(NAME)?.data?.version;
const moduleVersion = game.modules.get(NAME)?.version;
const username = game.user.name;
const gadgets = GADGETS;
const config = Sidekick.getSetting(SETTING_KEYS.cubPuter.config);
Expand Down Expand Up @@ -362,7 +362,7 @@ export class CUBPuter extends FormApplication {
const header = html.find("header");
header.addClass("terminal");
const appTitle = header.find(`:contains("${app.title}")`);
appTitle.append(` -- cubOS v${game.modules.get(NAME).data.version}`);
appTitle.append(` -- cubOS v${game.modules.get(NAME).version}`);
const consoleDiv = html.find("div.console-panel");
const gadgetSelect = html.find("div.gadget-select");
const infoDiv = html.find("div.information-panel");
Expand All @@ -381,7 +381,7 @@ export class CUBPuter extends FormApplication {
`Salutations fleshy meat-bag who identifies as ${game.user.name}. I hope you are feeling cold and callous today because it's going to be a bloodbath!`
];

const startup = config.startup ? `> Starting cubOS v${game.modules.get(NAME).data.version}` : ``;
const startup = config.startup ? `> Starting cubOS v${game.modules.get(NAME).version}` : ``;
const loginPrompt = config.startup ? `> Login: ` : ``;
const loginInput = config.startup ? username : ``;
const passwordPrompt = config.startup ? `<br/> > Password: ` : ``;
Expand Down
Loading

0 comments on commit 6d052b2

Please sign in to comment.