Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for exhaustion to be configurable #2959

Merged
merged 13 commits into from
Feb 9, 2024
13 changes: 9 additions & 4 deletions module/applications/actor/character-sheet-2.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -200,14 +200,19 @@ export default class ActorSheet5eCharacter2 extends ActorSheet5eCharacter {
};

// Exhaustion
context.exhaustion = Array.fromRange(6, 1).map(n => {
const max = CONFIG.DND5E.conditionTypes.exhaustion.levels;
context.exhaustion = Array.fromRange(max, 1).reduce((acc, n) => {
const label = game.i18n.format("DND5E.ExhaustionLevel", { n });
const classes = ["pip"];
const filled = attributes.exhaustion >= n;
if ( filled ) classes.push("filled");
if ( n === 6 ) classes.push("death");
return { n, label, filled, tooltip: label, classes: classes.join(" ") };
});
if ( n === max ) classes.push("death");
const pip = { n, label, filled, tooltip: label, classes: classes.join(" ") };

if ( n <= max / 2 ) acc.left.push(pip);
else acc.right.push(pip);
return acc;
}, { left: [], right: [] });

// Speed
context.speed = Object.entries(CONFIG.DND5E.movementTypes).reduce((obj, [k, label]) => {
Expand Down
14 changes: 9 additions & 5 deletions module/config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2355,6 +2355,7 @@ DND5E.consumableResources = [
* @property {string} [icon] Icon used to represent the condition on the token.
* @property {string} [reference] UUID of a journal entry with details on this condition.
* @property {string} [special] Set this condition as a special status effect under this name.
* @property {number} [levels] The number of levels of exhaustion an actor can obtain.
*/

/**
Expand Down Expand Up @@ -2385,7 +2386,8 @@ DND5E.conditionTypes = {
exhaustion: {
label: "DND5E.ConExhaustion",
icon: "systems/dnd5e/icons/svg/statuses/exhaustion.svg",
reference: "Compendium.dnd5e.rules.JournalEntry.w7eitkpD7QQTB6j0.JournalEntryPage.cspWveykstnu3Zcv"
reference: "Compendium.dnd5e.rules.JournalEntry.w7eitkpD7QQTB6j0.JournalEntryPage.cspWveykstnu3Zcv",
levels: 6
},
frightened: {
label: "DND5E.ConFrightened",
Expand Down Expand Up @@ -2453,14 +2455,16 @@ patchConfig("conditionTypes", "label", { since: "DnD5e 3.0", until: "DnD5e 3.2"
/* -------------------------------------------- */

/**
* Various effects of conditions and which conditions apply it.
* Various effects of conditions and which conditions apply it. Either keys for the conditions,
* and with a number appended for a level of exhaustion.
* @enum {object}
*/
DND5E.conditionEffects = {
noMovement: new Set(["grappled", "paralyzed", "petrified", "restrained", "stunned", "unconscious"]),
halfMovement: new Set(["prone"]),
noMovement: new Set(["exhaustion-5", "grappled", "paralyzed", "petrified", "restrained", "stunned", "unconscious"]),
halfMovement: new Set(["exhaustion-2", "prone"]),
crawl: new Set(["prone", "exceedingCarryingCapacity"]),
petrification: new Set(["petrified"])
petrification: new Set(["petrified"]),
halfHealth: new Set(["exhaustion-4"])
};

/* -------------------------------------------- */
Expand Down
4 changes: 2 additions & 2 deletions module/data/actor/templates/attributes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,8 @@ export default class AttributesFields {
*/
static prepareMovement() {
const statuses = this.parent.statuses;
const noMovement = this.parent.hasConditionEffect("noMovement") || (this.attributes.exhaustion >= 5);
const halfMovement = this.parent.hasConditionEffect("halfMovement") || (this.attributes.exhaustion >= 2);
const noMovement = this.parent.hasConditionEffect("noMovement");
const halfMovement = this.parent.hasConditionEffect("halfMovement");
const reduction = statuses.has("heavilyEncumbered")
? CONFIG.DND5E.encumbrance.speedReduction.heavilyEncumbered
: statuses.has("encumbered") ? CONFIG.DND5E.encumbrance.speedReduction.encumbered : 0;
Expand Down
25 changes: 21 additions & 4 deletions module/documents/active-effect.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -285,11 +285,12 @@ export default class ActiveEffect5e extends ActiveEffect {
* @protected
*/
_prepareExhaustionLevel() {
const config = CONFIG.DND5E.conditionTypes.exhaustion;
let level = this.getFlag("dnd5e", "exhaustionLevel");
if ( !Number.isFinite(level) ) level = 1;
this.icon = `systems/dnd5e/icons/svg/statuses/exhaustion-${level}.svg`;
this.icon = this.constructor._getExhaustionImage(level);
this.name = `${game.i18n.localize("DND5E.Exhaustion")} ${level}`;
if ( level >= 6 ) this.statuses.add("dead");
if ( level >= config.levels ) this.statuses.add("dead");
}

/* -------------------------------------------- */
Expand Down Expand Up @@ -364,15 +365,30 @@ export default class ActiveEffect5e extends ActiveEffect {
const actor = app.object.actor;
const level = foundry.utils.getProperty(actor, "system.attributes.exhaustion");
if ( Number.isFinite(level) && (level > 0) ) {
const img = this._getExhaustionImage(level);
arbron marked this conversation as resolved.
Show resolved Hide resolved
html.find('[data-status-id="exhaustion"]').css({
objectPosition: "-100px",
background: `url('systems/dnd5e/icons/svg/statuses/exhaustion-${level}.svg') no-repeat center / contain`
background: `url('${img}') no-repeat center / contain`
});
}
}

/* -------------------------------------------- */

/**
* Get the image used to represent exhaustion at this level.
* @param {number} level
* @returns {string}
*/
static _getExhaustionImage(level) {
const split = CONFIG.DND5E.conditionTypes.exhaustion.icon.split(".");
const ext = split.pop();
const path = split.join(".");
return `${path}-${level}.${ext}`;
}

/* -------------------------------------------- */

/**
* Implement custom exhaustion cycling when interacting with the Token HUD.
* @param {PointerEvent} event The triggering event.
Expand All @@ -387,7 +403,8 @@ export default class ActiveEffect5e extends ActiveEffect {
event.stopPropagation();
if ( event.button === 0 ) level++;
else level--;
actor.update({ "system.attributes.exhaustion": Math.clamped(level, 0, 6) });
const max = CONFIG.DND5E.conditionTypes.exhaustion.levels;
actor.update({ "system.attributes.exhaustion": Math.clamped(level, 0, max) });
}

/* -------------------------------------------- */
Expand Down
11 changes: 8 additions & 3 deletions module/documents/actor/actor.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -212,15 +212,20 @@ export default class Actor5e extends SystemDocumentMixin(Actor) {
/* -------------------------------------------- */

/**
* Is this actor under the effect of this property from some status?
* Is this actor under the effect of this property from some status or due to its level of exhaustion?
* @param {string} key A key in `DND5E.conditionEffects`.
* @returns {boolean} Whether the actor is affected.
*/
hasConditionEffect(key) {
const props = CONFIG.DND5E.conditionEffects[key] ?? new Set();
const level = this.system.attributes?.exhaustion ?? null;
const imms = this.system.traits?.ci?.value ?? new Set();
const statuses = this.statuses;
return statuses.difference(imms).intersects(props);
return props.some(k => {
const l = Number(k.split("-").pop());
return (statuses.has(k) && !imms.has(k))
|| (!imms.has("exhaustion") && (level !== null) && Number.isInteger(l) && (level >= l));
});
}

/* -------------------------------------------- */
Expand Down Expand Up @@ -664,7 +669,7 @@ export default class Actor5e extends SystemDocumentMixin(Actor) {

hp.max = base + levelBonus + overallBonus;

if ( this.system.attributes.exhaustion >= 4 ) hp.max = Math.floor(hp.max * 0.5);
if ( this.hasConditionEffect("halfHealth") ) hp.max = Math.floor(hp.max * 0.5);
}

hp.value = Math.min(hp.value, hp.max + (hp.tempmax ?? 0));
Expand Down
8 changes: 2 additions & 6 deletions templates/actors/character-sheet-2.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,8 @@
<div class="top">

<div class="pips" data-prop="system.attributes.exhaustion">
{{#each exhaustion}}
{{#if (lt @index 3)}}
{{#each exhaustion.left}}
{{> pip }}
{{/if}}
{{/each}}
</div>

Expand All @@ -171,10 +169,8 @@
</div>

<div class="pips" data-prop="system.attributes.exhaustion">
{{#each exhaustion}}
{{#if (gt @index 2)}}
{{#each exhaustion.right}}
{{> pip }}
{{/if}}
{{/each}}
</div>
</div>
Expand Down