15 add duration to active effects (#50)

* Add Effect Duration & Rework Combat tracker

Changes:
 + rework combat tracker to display every uneven round as Movementphase
 + rework combat tracker to display every even round as actionphase
 + add possibility for effects durations
 + effects duration decreases with every actionphase
 + add enum for time Units
 + update localization
 + add display of remaining time on effects
 + add duration for spelleffect "Bärenwut"

* add LP AP Manipulation through effects

Changes:
 + add LimitHeal function
 + adjust LP AP Values if Mod exists in an effect

* Fix linked actor not being updated
This commit is contained in:
2023-12-11 17:36:12 +01:00
committed by GitHub
parent 30e94741bf
commit 1e27e135cf
10 changed files with 120 additions and 17 deletions
+71 -8
View File
@@ -2,7 +2,7 @@ import Logger from "./utils/Logger";
import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
import preloadTemplates from "./PreloadTemplates";
import { M5Character } from "./module/actors/M5Character";
import { M5Skill } from "./module/M5Base";
import { M5ItemMod, M5ModOperation, M5Skill, M5TimeUnit } from "./module/M5Base";
import { M5ItemSheet } from "./module/sheets/M5ItemSheet";
import { M5Item } from "./module/items/M5Item";
@@ -58,10 +58,10 @@ Hooks.once("init", async () => {
return `${obj}`;
});
Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string) => {
Handlebars.registerHelper("actorItemValue", (actorId: any, itemId: string, path: string, token?: boolean) => {
//console.log("actorItemValue", actorId, itemId, path)
const actor = (game as Game).actors.get(actorId);
let obj = actor.items.get(itemId).system;
let obj = actor.items.get(itemId)?.system;
path.split(".").forEach((p) => {
if (obj) obj = obj[p];
});
@@ -116,7 +116,6 @@ Hooks.on("getChatLogEntryContext", function (html, options) {
condition: (li) => {
// Only show this context menu if there are re-rollable dice in the message
const damageRolls = li.find(".apply-damage").length;
console.log(game["user"].isGm);
// All must be true to show the reroll dialogue
// The button doesn't work for the GM right now, so we don't need to show it
@@ -166,6 +165,70 @@ Hooks.on("getChatLogEntryContext", function (html, options) {
);
});
Hooks.on("updateCombat", function (combat: Combat, updateData: { round: number; turn: number }, updateOptions: { advanceTime: number; direction: number }) {
if (combat.round % 2 === 0 && combat.turn !== null) {
const tokenId = combat.current.tokenId;
const actorId = combat.combatant["actorId"];
let currentToken = game["actors"].tokens[tokenId];
if (!currentToken) {
currentToken = game["actors"].get(actorId);
}
let activeEffects = currentToken.items.filter((x) => x.type === "effect" && x.system.equipped) || [];
activeEffects.forEach((effect) => {
if (effect.system?.duration?.time > 0) {
if (effect.system.duration.unit === M5TimeUnit.ROUND) {
effect.system.duration.time -= 1;
}
}
if (effect.system?.duration.time === 0 && effect.system.duration.unit !== M5TimeUnit.LIMITLESS) {
effect.system.equipped = false;
}
for (const key in effect.system.mods) {
if (effect.system.mods[key].operation === M5ModOperation.SUBTRACT) {
switch (effect.system.mods[key].id) {
case "lp":
currentToken["system"].lp.value -= effect.system.mods[key].value;
break;
case "ap":
currentToken["system"].ap.value -= effect.system.mods[key].value;
break;
}
} else if (effect.system.mods[key].operation === M5ModOperation.ADD) {
switch (effect.system.mods[key].id) {
case "lp":
currentToken["system"].lp.value += limitHeal(effect.system.mods[key].value, currentToken["system"].lp.value, currentToken["system"].lp.max);
break;
case "ap":
currentToken["system"].ap.value += limitHeal(effect.system.mods[key].value, currentToken["system"].ap.value, currentToken["system"].ap.max);
break;
}
}
}
});
currentToken.render();
}
});
function limitHeal(heal: number, current: number, max: number): number {
if (current === max) {
return 0;
} else if (heal + current > max) {
return max - current;
}
return heal;
}
Hooks.on("renderCombatTracker", (combatTracker, html, context) => {
if (context.combat === null) {
html.find("h3.encounter-title")[0].innerHTML = game["i18n"].localize("midgard5.no-encounter");
} else if (Math.ceil(context.round / 2) === 0) {
html.find("h3.encounter-title")[0].innerHTML = game["i18n"].localize("midgard5.encounter-not-started");
} else {
html.find("h3.encounter-title")[0].innerHTML =
(context.round % 2 == 1 ? game["i18n"].localize("midgard5.phase-movement") : game["i18n"].localize("midgard5.phase-action")) + " " + Math.ceil(context.round / 2);
}
});
Hooks.once("ready", () => {
Logger.ok("Template module is now ready.");
});
@@ -187,9 +250,9 @@ async function applyDamage(roll, direction) {
token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value);
break;
case -1:
token["system"].lp.value += Math.min(damageValue, token["system"].lp.max - damageValue);
token["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max);
case -2:
token["system"].ap.value += Math.min(damageValue, token["system"].ap.max - damageValue);
token["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max);
}
token.render();
} else {
@@ -200,9 +263,9 @@ async function applyDamage(roll, direction) {
actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value);
break;
case -1:
actor["system"].lp.value += Math.min(damageValue, actor["system"].lp.max - damageValue);
actor["system"].lp.value += limitHeal(damageValue, token["system"].lp.value, token["system"].lp.max);
case -2:
actor["system"].ap.value += Math.min(damageValue, actor["system"].ap.max - damageValue);
actor["system"].ap.value += limitHeal(damageValue, token["system"].ap.value, token["system"].ap.max);
}
actor.render();
}
+7
View File
@@ -102,6 +102,13 @@ export enum M5ModOperation {
DIVISION = "division",
}
export enum M5TimeUnit {
ROUND = "round",
MINUTE = "minute",
HOUR = "hour",
LIMITLESS = "limitless",
}
export interface M5ItemMod {
type: M5ModType;
id: string;
+2 -1
View File
@@ -188,7 +188,8 @@ export class M5Character extends Actor {
label: label,
magic: item.system.magic,
calc: item.system.calc,
equipped: item.system?.equipped,
equipped: item.system?.equipped || false,
duration: item.system?.duration || { time: 0, unit: "" },
};
});
}
+9 -1
View File
@@ -201,6 +201,14 @@
"value": 0,
"magic": false
},
"durationSelection": {
"durationSelection": {
"round": "midgard5.time-round",
"minute": "midgard5.time-minute",
"hour": "midgard5.time-hour",
"limitless": "midgard5.time-limitless"
}
},
"spellSelection": {
"spellProcessSelection": {
"none": "midgard5.spell-process-none",
@@ -295,7 +303,7 @@
"calc": {}
},
"effect": {
"templates": ["itemDescription", "equippable", "physical"],
"templates": ["itemDescription", "equippable", "physical", "durationSelection"],
"rolls": {
"formulas": {},
"output": ""