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:
parent
30e94741bf
commit
1e27e135cf
15
lang/de.json
15
lang/de.json
|
|
@ -5,11 +5,22 @@
|
||||||
|
|
||||||
"TYPES.Item.item": "Gegenstand",
|
"TYPES.Item.item": "Gegenstand",
|
||||||
"TYPES.Item.weapon": "Waffe",
|
"TYPES.Item.weapon": "Waffe",
|
||||||
"ITEM.TypeDefensiveWeapon": "Verteidigungswaffe",
|
"TYPES.Item.defensiveWeapon": "Verteidigungswaffe",
|
||||||
"TYPES.Item.armor": "Rüstung",
|
"TYPES.Item.armor": "Rüstung",
|
||||||
"TYPES.Item.spell": "Zauber",
|
"TYPES.Item.spell": "Zauber",
|
||||||
"TYPES.Item.effect": "Aktive Effekte",
|
"TYPES.Item.effect": "Aktive Effekte",
|
||||||
"ITEM.type.kampfkunst": "Kampfkünste",
|
"TYPES.Item.kampfkunst": "Kampfkünste",
|
||||||
|
|
||||||
|
"midgard5.phase-action": "Handlungsphase",
|
||||||
|
"midgard5.phase-movement": "Bewegungsphase",
|
||||||
|
"midgard5.no-encounter": "Kein Kampf",
|
||||||
|
"midgard5.encounter-not-started": "Kein aktiver Kampf",
|
||||||
|
|
||||||
|
"midgard5.time-duration": "Dauer",
|
||||||
|
"midgard5.time-round": "Runde(n)",
|
||||||
|
"midgard5.time-minute": "Minute(n)",
|
||||||
|
"midgard5.time-hour": "Stunde(n)",
|
||||||
|
"midgard5.time-limitless": "Unbegrenzt",
|
||||||
|
|
||||||
"midgard5.doRoll": "Würfeln",
|
"midgard5.doRoll": "Würfeln",
|
||||||
"midgard5.learn": "Lernen",
|
"midgard5.learn": "Lernen",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"description": "<p>ARK S. 144</p>",
|
"description": "<p>ARK S. 144</p>",
|
||||||
"equippable": false,
|
"equippable": false,
|
||||||
"equipped": true,
|
"equipped": true,
|
||||||
|
"duration": { "time": 12, "unit": "round" },
|
||||||
"value": 0,
|
"value": 0,
|
||||||
"magic": true,
|
"magic": true,
|
||||||
"rolls": { "formulas": {}, "output": "" },
|
"rolls": { "formulas": {}, "output": "" },
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import Logger from "./utils/Logger";
|
||||||
import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
|
import M5CharacterSheet from "./module/sheets/M5CharacterSheet";
|
||||||
import preloadTemplates from "./PreloadTemplates";
|
import preloadTemplates from "./PreloadTemplates";
|
||||||
import { M5Character } from "./module/actors/M5Character";
|
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 { M5ItemSheet } from "./module/sheets/M5ItemSheet";
|
||||||
import { M5Item } from "./module/items/M5Item";
|
import { M5Item } from "./module/items/M5Item";
|
||||||
|
|
||||||
|
|
@ -58,10 +58,10 @@ Hooks.once("init", async () => {
|
||||||
return `${obj}`;
|
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)
|
//console.log("actorItemValue", actorId, itemId, path)
|
||||||
const actor = (game as Game).actors.get(actorId);
|
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) => {
|
path.split(".").forEach((p) => {
|
||||||
if (obj) obj = obj[p];
|
if (obj) obj = obj[p];
|
||||||
});
|
});
|
||||||
|
|
@ -116,7 +116,6 @@ Hooks.on("getChatLogEntryContext", function (html, options) {
|
||||||
condition: (li) => {
|
condition: (li) => {
|
||||||
// Only show this context menu if there are re-rollable dice in the message
|
// Only show this context menu if there are re-rollable dice in the message
|
||||||
const damageRolls = li.find(".apply-damage").length;
|
const damageRolls = li.find(".apply-damage").length;
|
||||||
console.log(game["user"].isGm);
|
|
||||||
|
|
||||||
// All must be true to show the reroll dialogue
|
// 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
|
// 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", () => {
|
Hooks.once("ready", () => {
|
||||||
Logger.ok("Template module is now 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);
|
token["system"].ap.value -= Math.max(0, damageValue - token["system"].calc.stats.apProtection.value);
|
||||||
break;
|
break;
|
||||||
case -1:
|
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:
|
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();
|
token.render();
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -200,9 +263,9 @@ async function applyDamage(roll, direction) {
|
||||||
actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value);
|
actor["system"].ap.value -= Math.max(0, damageValue - actor["system"].calc.stats.apProtection.value);
|
||||||
break;
|
break;
|
||||||
case -1:
|
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:
|
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();
|
actor.render();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,13 @@ export enum M5ModOperation {
|
||||||
DIVISION = "division",
|
DIVISION = "division",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum M5TimeUnit {
|
||||||
|
ROUND = "round",
|
||||||
|
MINUTE = "minute",
|
||||||
|
HOUR = "hour",
|
||||||
|
LIMITLESS = "limitless",
|
||||||
|
}
|
||||||
|
|
||||||
export interface M5ItemMod {
|
export interface M5ItemMod {
|
||||||
type: M5ModType;
|
type: M5ModType;
|
||||||
id: string;
|
id: string;
|
||||||
|
|
|
||||||
|
|
@ -188,7 +188,8 @@ export class M5Character extends Actor {
|
||||||
label: label,
|
label: label,
|
||||||
magic: item.system.magic,
|
magic: item.system.magic,
|
||||||
calc: item.system.calc,
|
calc: item.system.calc,
|
||||||
equipped: item.system?.equipped,
|
equipped: item.system?.equipped || false,
|
||||||
|
duration: item.system?.duration || { time: 0, unit: "" },
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,14 @@
|
||||||
"value": 0,
|
"value": 0,
|
||||||
"magic": false
|
"magic": false
|
||||||
},
|
},
|
||||||
|
"durationSelection": {
|
||||||
|
"durationSelection": {
|
||||||
|
"round": "midgard5.time-round",
|
||||||
|
"minute": "midgard5.time-minute",
|
||||||
|
"hour": "midgard5.time-hour",
|
||||||
|
"limitless": "midgard5.time-limitless"
|
||||||
|
}
|
||||||
|
},
|
||||||
"spellSelection": {
|
"spellSelection": {
|
||||||
"spellProcessSelection": {
|
"spellProcessSelection": {
|
||||||
"none": "midgard5.spell-process-none",
|
"none": "midgard5.spell-process-none",
|
||||||
|
|
@ -295,7 +303,7 @@
|
||||||
"calc": {}
|
"calc": {}
|
||||||
},
|
},
|
||||||
"effect": {
|
"effect": {
|
||||||
"templates": ["itemDescription", "equippable", "physical"],
|
"templates": ["itemDescription", "equippable", "physical", "durationSelection"],
|
||||||
"rolls": {
|
"rolls": {
|
||||||
"formulas": {},
|
"formulas": {},
|
||||||
"output": ""
|
"output": ""
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,9 @@
|
||||||
<span class="edit-item">{{item.label}}</span>
|
<span class="edit-item">{{item.label}}</span>
|
||||||
{{#if item.equipped}}
|
{{#if item.equipped}}
|
||||||
<span class="spell-process">{{localize "midgard5.active"}}</span>
|
<span class="spell-process">{{localize "midgard5.active"}}</span>
|
||||||
|
{{#unless (or (eq item.duration.unit "") (eq item.duration.unit "limitless"))}}
|
||||||
|
<span class="spell-process">{{item.duration.time}} {{localize (concat "midgard5.time-" item.duration.unit)}}</span>
|
||||||
|
{{/unless}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
|
<td class="fixed-value"><a class="item-delete" title="Delete Item"><i class="fas fa-trash"></i></a></td>
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="title">{{localize "ITEM.TypeDefensiveWeapon"}}</th>
|
<th class="title">{{localize "TYPES.Item.defensiveWeapon"}}</th>
|
||||||
<th class="title">{{localize "midgard5.ew"}}</th>
|
<th class="title">{{localize "midgard5.ew"}}</th>
|
||||||
<th class="title"></th>
|
<th class="title"></th>
|
||||||
<th class="title"></th>
|
<th class="title"></th>
|
||||||
|
|
@ -90,7 +90,7 @@
|
||||||
<span class="spell-process">{{localize "midgard5.equipped"}}</span>
|
<span class="spell-process">{{localize "midgard5.equipped"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
<td class="fixed-value">{{actorItemValue ../actor._id itemId "lpProtection"}}</td>
|
<td class="fixed-value">{{actorItemValue ../actor._id itemId "lpProtection" ../actor.isToken}}</td>
|
||||||
<td class="fixed-value">{{actorItemValue ../actor._id itemId "apProtection"}}</td>
|
<td class="fixed-value">{{actorItemValue ../actor._id itemId "apProtection"}}</td>
|
||||||
<td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.attackBonus"}}</td>
|
<td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.attackBonus"}}</td>
|
||||||
<td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.defenseBonus"}}</td>
|
<td class="fixed-value">{{actorItemValue ../actor._id itemId "stats.defenseBonus"}}</td>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="title">{{localize "ITEM.type.kampfkunst"}}</th>
|
<th class="title">{{localize "TYPES.Item.kampfkunst"}}</th>
|
||||||
<th class="title">{{localize "midgard5.ew"}}</th>
|
<th class="title">{{localize "midgard5.ew"}}</th>
|
||||||
<th class="title"></th>
|
<th class="title"></th>
|
||||||
<th class="title"></th>
|
<th class="title"></th>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,17 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<div class="flexrow">
|
<div class="flexrow">
|
||||||
<span>{{localize "midgard5.item-value"}}</span>
|
<span>{{localize "midgard5.time-duration"}}</span>
|
||||||
<input name="data.value" type="text" value="{{data.value}}" data-dtype="Number" />
|
<input name="data.duration.time" type="text" value="{{data.duration.time}}" data-dtype="Number" />
|
||||||
|
<select class="select-mod-operation" name="data.duration.unit" data-type="String">
|
||||||
|
{{#select data.duration.unit}}
|
||||||
|
<option value=""></option>
|
||||||
|
<option value="round">{{localize "midgard5.time-round"}}</option>
|
||||||
|
<option value="minute">{{localize "midgard5.time-minute"}}</option>
|
||||||
|
<option value="hour">{{localize "midgard5.time-hour"}}</option>
|
||||||
|
<option value="limitless">{{localize "midgard5.time-limitless"}}</option>
|
||||||
|
{{/select}}
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue