diff --git a/src/module/actor/entity.js b/src/module/actor/entity.js
index 775bd2b..cbe9c96 100644
--- a/src/module/actor/entity.js
+++ b/src/module/actor/entity.js
@@ -298,6 +298,19 @@ export class OseActor extends Actor {
});
}
+ async applyDamage(amount=0, multiplier=1) {
+ amount = Math.floor(parseInt(amount) * multiplier);
+ const hp = this.data.data.hp;
+
+ // Remaining goes to health
+ const dh = Math.clamped(hp.value - amount, 0, hp.max);
+
+ // Update the Actor
+ return this.update({
+ "data.hp.value": dh
+ });
+ }
+
static _valueToMod(val) {
switch (val) {
case 3:
diff --git a/src/module/chat.js b/src/module/chat.js
new file mode 100644
index 0000000..47b7288
--- /dev/null
+++ b/src/module/chat.js
@@ -0,0 +1,47 @@
+/**
+ * This function is used to hook into the Chat Log context menu to add additional options to each message
+ * These options make it easy to conveniently apply damage to controlled tokens based on the value of a Roll
+ *
+ * @param {HTMLElement} html The Chat Message being rendered
+ * @param {Array} options The Array of Context Menu options
+ *
+ * @return {Array} The extended options Array including new context choices
+ */
+export const addChatMessageContextOptions = function(html, options) {
+ let canApply = li => canvas.tokens.controlled.length && li.find(".dice-roll").length;
+ options.push(
+ {
+ name: game.i18n.localize("OSE.ChatContextDamage"),
+ icon: '',
+ condition: canApply,
+ callback: li => applyChatCardDamage(li, 1)
+ },
+ {
+ name: game.i18n.localize("OSE.ChatContextHealing"),
+ icon: '',
+ condition: canApply,
+ callback: li => applyChatCardDamage(li, -1)
+ }
+ );
+ return options;
+};
+
+/* -------------------------------------------- */
+
+/**
+ * Apply rolled dice damage to the token or tokens which are currently controlled.
+ * This allows for damage to be scaled by a multiplier to account for healing, critical hits, or resistance
+ *
+ * @param {HTMLElement} roll The chat entry which contains the roll data
+ * @param {Number} multiplier A damage multiplier to apply to the rolled damage.
+ * @return {Promise}
+ */
+function applyChatCardDamage(roll, multiplier) {
+ const amount = roll.find('.dice-total').last().text();
+ return Promise.all(canvas.tokens.controlled.map(t => {
+ const a = t.actor;
+ return a.applyDamage(amount, multiplier);
+ }));
+}
+
+/* -------------------------------------------- */
diff --git a/src/ose.js b/src/ose.js
index 664ee2a..632448a 100644
--- a/src/ose.js
+++ b/src/ose.js
@@ -8,6 +8,7 @@ import { OseItem } from "./module/item/entity.js";
import { OSE } from "./module/config.js";
import { registerSettings } from './module/settings.js';
import { registerHelpers } from './module/helpers.js';
+import * as chat from "./module/chat.js";
/* -------------------------------------------- */
/* Foundry VTT Initialization */
@@ -64,5 +65,5 @@ Hooks.once("setup", function () {
}
});
-
-Hooks.on("renderChatLog", (app, html, data) => OseItem.chatListeners(html));
\ No newline at end of file
+Hooks.on("renderChatLog", (app, html, data) => OseItem.chatListeners(html));
+Hooks.on("getChatLogEntryContext", chat.addChatMessageContextOptions);
\ No newline at end of file