Skip to content

Commit

Permalink
add regeneration, fix localisation
Browse files Browse the repository at this point in the history
  • Loading branch information
Werner committed Oct 16, 2022
1 parent 001fc26 commit 2353a5a
Show file tree
Hide file tree
Showing 9 changed files with 246 additions and 1,454 deletions.
256 changes: 11 additions & 245 deletions lang/en.json

Large diffs are not rendered by default.

253 changes: 13 additions & 240 deletions lang/es.json

Large diffs are not rendered by default.

254 changes: 13 additions & 241 deletions lang/fr.json

Large diffs are not rendered by default.

253 changes: 13 additions & 240 deletions lang/ja.json

Large diffs are not rendered by default.

253 changes: 13 additions & 240 deletions lang/ko.json

Large diffs are not rendered by default.

253 changes: 13 additions & 240 deletions lang/pt-BR.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion scripts/creature-aide.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ import { logger } from './logger.js';
import { AbilityRecharge } from './modules/AbilityRecharge.js';
import { LegendaryActionManagement } from './modules/LegendaryActionManagement.js';
import { LairActionManagement } from './modules/LairActionManagement.js';
import { Regeneration } from './modules/Regeneration.js';

const SUB_MODULES = {
MODULE,
logger,
AbilityRecharge,
LegendaryActionManagement,
LairActionManagement
LairActionManagement,
Regeneration
};

/*
Expand Down
14 changes: 7 additions & 7 deletions scripts/modules/LegendaryActionManagement.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ export class LegendaryActionManagement {
static settings(){
const config = true;
const settingsData = {
legendaryActionRecharge : {
scope : "world", config, group: "npc-features", default: false, type: Boolean,
},
legendaryActionHelper : {
scope : "world", config, group: "npc-features", default: false, type: Boolean,
}
legendaryActionRecharge : {
scope : "world", config, group: "npc-features", default: false, type: Boolean,
},
legendaryActionHelper : {
scope : "world", config, group: "npc-features", default: false, type: Boolean,
}
};

MODULE.applySettings(settingsData);
Expand Down Expand Up @@ -147,7 +147,7 @@ export class LegendaryActionManagement {
if (!!legact && legact.value !== null) {
/* only reset if needed */
if (legact.value < legact.max) {
ui.notifications.info(game.i18n.format("DND5EH.CombatLegendary_notification", {max: legact.max, tokenName: combatant.token.name}))
ui.notifications.info(game.i18n.format("SCA.CombatLegendary_notification", {max: legact.max, tokenName: combatant.token.name}))

/* send the reset update and sheet refresh */
queueUpdate( async () => {
Expand Down
160 changes: 160 additions & 0 deletions scripts/modules/Regeneration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
import { logger } from '../logger.js';
import { MODULE } from '../module.js';
import { queueUpdate } from './update-queue.js';

const NAME = "Regeneration";

export class Regeneration {

static register() {
logger.info("Registering Automatic Regeneration");
Regeneration.settings();
Regeneration.hooks();
}

static settings() {
const config = true;
const settingsData = {
autoRegen : {
scope : "world", config, group: "npc-features", default: 0, type: Boolean,
},
regenBlock : {
scope : "world", config, group: "npc-features", default: MODULE.localize('SCA.regenBlock_default'), type: String,
}
};

MODULE.applySettings(settingsData);

}

static hooks() {
Hooks.on("updateCombat", Regeneration._updateCombat);
}

static _updateCombat(combat, changed) {

const setting = MODULE.setting('autoRegen');

/** bail out if disabled */
if( setting == 0 ) return;

/** only want the GM to operate and only on a legitimate turn change */
if (!MODULE.isTurnChange(combat, changed) || !MODULE.isFirstGM()) return;

/** get the actor whose turn it just changed to */
const next = combat.combatants.get(combat.current.combatantId);
const token = next.token?.object;

if(!token) {
logger.debug('Could not find a valid token in the upcoming turn.');
return;
}

/** does the current actor have a regeneration feature? */
const feature = Regeneration._getRegenFeature(token.actor);

/** if we have a valid feature, and the token's HP is less than max run the regen process */
var currentHP = token.document.actor.system.attributes.hp.value;
var maxHP = token.document.actor.system.attributes.hp.max;
if (feature && currentHP < maxHP) {
Regeneration._executeRegen(token, feature);
}

}

static _getRegenFeature(actor) {
if(!actor) {
logger.debug('Cannot regenerate a null actor');
return null;
}

/** before we check anything else, is regen blocked on this actor? */
const regenBlockName = MODULE.setting("regenBlock");
const blockEffect = actor.effects?.find(e => e.label === regenBlockName );
const enabledBlockEffect = !(getProperty(blockEffect ?? {}, 'disabled') ?? true);

if (enabledBlockEffect) {
logger.debug(`${actor.name}'s regeneration blocked by ${blockEffect.label}`);
return null;
}

/** Get the supported names of the regeneration feature */
const regenName = game.i18n.format("SCA.AutoRegen_Regneration")
const selfRepairName = game.i18n.format("SCA.AutoRegen_SelfRepair")

/** search for this item in the actor */
const regen = actor.items.find(i => i.name === regenName || i.name === selfRepairName);

return regen;
}

static _getActorHP(actor) {
const actorHP = getProperty(actor, 'system.attributes.hp');
return actorHP;
}

/* @private */
static _parseRegenFeature(item) {

/* @todo localize 'hit points'! */
const hitPointsString = MODULE.localize("SCA.AutoRegen_HP");
const regenRegExp = new RegExp(`([0-9]+|[0-9]*d0*[1-9][0-9]*) ${hitPointsString}`);
let match = item.system.description.value.match(regenRegExp);

if (!match) {
logger.debug(`Could not parse ${item.name}'s description for a regeneration value containing ${hitPointsString}`);
return null;
}

return match[1];
}

static _executeRegen(token, feature) {

const regen = Regeneration._parseRegenFeature(feature);

if (!regen) return;

const hp = Regeneration._getActorHP(token.actor);

const rollRegenCallback = () => queueUpdate( async () => {

/** roll the regen expression */
const rollObject = await new Roll(regen).evaluate({async: true});
let regenRoll = rollObject.total;

/** apply the damage to the token */
await token.actor.applyDamage(- regenRoll);

/** echo results to chat */
await ChatMessage.create({
content: game.i18n.format("SCA.AutoRegenDialog_healingmessage",
{tokenName: token.name, regenRoll: regenRoll}),
whisper: ChatMessage.getWhisperRecipients('gm').map(o => o.id)
});

});


//dialog choice to heal or not
if (regen !== null) {
new Dialog({
title: game.i18n.format("SCA.AutoRegenDialog_name", {tokenName: token.name}),
content: game.i18n.format("SCA.AutoRegenDialog_content", {tokenName: token.name, tokenHP: hp.value, actorMax: hp.max}),
buttons: {
one: {
// @todo need to correct the type in 'regenAmout'
label: game.i18n.format("SCA.AutoRegenDialog_healingprompt", {regenAmout: regen}),
callback: rollRegenCallback
},
two: {
label: game.i18n.format("SCA.AutoRegenDialog_stopprompt"),
}
}
}).render(true);

return;
}

}
}

0 comments on commit 2353a5a

Please sign in to comment.