diff --git a/css/deltagreen.css b/css/deltagreen.css
index bcb0e59..ded1f8e 100644
--- a/css/deltagreen.css
+++ b/css/deltagreen.css
@@ -1235,4 +1235,36 @@ body:not(.no-theme) #interface:not(.theme-light) #action-bar .slot.full:hover {
.target-proficiency-mod {
color: #247c14;
-}
\ No newline at end of file
+}
+
+.rollback-section {
+ order: 99;
+ display: flex;
+ margin-top: 5px;
+ align-items: center;
+ justify-content: center;
+
+ > i {
+ margin: 5px;
+ }
+}
+
+[data-action="rollback-skill-failure-state"] {
+ align-items: center;
+ display: inline-flex;
+ justify-content: center;
+ min-height: unset;
+ width: 20px;
+ height: 20px;
+ margin-left: 5px;
+ font-size: 12px;
+}
+
+[data-tooltip] {
+ position: relative;
+ cursor: pointer;
+}
+
+.strike {
+ text-decoration: line-through;
+}
diff --git a/lang/ca.json b/lang/ca.json
index c358c52..53045db 100644
--- a/lang/ca.json
+++ b/lang/ca.json
@@ -271,5 +271,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Activation Time",
"DG.ItemWindow.Ritual.ActivationCosts": "Activation Costs",
"DG.ItemWindow.Ritual.StudyTime": "Study Time",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage",
+
+ "DG.Messages.Skillsmark.Marked": "Aquesta habilitat està marcada",
+ "DG.Messages.Skillsmark.Tooltip": "Vegeu la p. 29 del Manual de l'agent"
}
diff --git a/lang/cn.json b/lang/cn.json
index 935569d..a630732 100644
--- a/lang/cn.json
+++ b/lang/cn.json
@@ -309,5 +309,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "激活耗时",
"DG.ItemWindow.Ritual.ActivationCosts": "激活代价",
"DG.ItemWindow.Ritual.StudyTime": "学习时长",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "学习造成的理智损失"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "学习造成的理智损失",
+
+ "DG.Messages.Skillsmark.Marked": "此技能被标记",
+ "DG.Messages.Skillsmark.Tooltip": "参见第 29 页《代理人手册》"
}
diff --git a/lang/de.json b/lang/de.json
index a26da88..972e302 100644
--- a/lang/de.json
+++ b/lang/de.json
@@ -289,5 +289,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Activation Time",
"DG.ItemWindow.Ritual.ActivationCosts": "Activation Costs",
"DG.ItemWindow.Ritual.StudyTime": "Study Time",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage",
+
+ "DG.Messages.Skillsmark.Marked": "Diese Fähigkeit ist gekennzeichnet.",
+ "DG.Messages.Skillsmark.Tooltip": "Siehe S. 29 des Agentenhandbuchs"
}
diff --git a/lang/en.json b/lang/en.json
index 26a047a..f9bdbf7 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -391,4 +391,7 @@
"DG.Settings.hypergeometry.hint": "Always show Hypergeometry item section for players, even if they don't have any items of that type.",
"DG.Settings.landscapes.name": "Show Impossible Landscapes Content",
"DG.Settings.landscapes.hint": "Show Impossible Landscapes-specific fields from character sheets."
+
+ "DG.Messages.Skillsmark.Marked": "This skill is marked",
+ "DG.Messages.Skillsmark.Tooltip": "See p. 29 Agent's Handbook"
}
diff --git a/lang/es.json b/lang/es.json
index 0ae20b8..a976872 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -276,5 +276,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Activation Time",
"DG.ItemWindow.Ritual.ActivationCosts": "Activation Costs",
"DG.ItemWindow.Ritual.StudyTime": "Study Time",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage",
+
+ "DG.Messages.Skillsmark.Marked": "Esta habilidad está marcada.",
+ "DG.Messages.Skillsmark.Tooltip": "Ver pág. 29 del Manual del Agente."
}
diff --git a/lang/fr.json b/lang/fr.json
index 554a272..8e68ba9 100644
--- a/lang/fr.json
+++ b/lang/fr.json
@@ -313,5 +313,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Temp d'Activation",
"DG.ItemWindow.Ritual.ActivationCosts": "Coût d'Activation",
"DG.ItemWindow.Ritual.StudyTime": "Temps d'étude",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Dégâts SAN Étude"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Dégâts SAN Étude",
+
+ "DG.Messages.Skillsmark.Marked": "Cette compétence est marquée.",
+ "DG.Messages.Skillsmark.Tooltip": "Voir p. 29 du Manuel de l'agent."
}
diff --git a/lang/ja.json b/lang/ja.json
index 1936dc5..54107ca 100644
--- a/lang/ja.json
+++ b/lang/ja.json
@@ -352,5 +352,8 @@
"DG.Skills.ruby.swim": "すいえい",
"DG.Skills.ruby.unarmed_combat": "としゅかくとう",
"DG.Skills.ruby.unnatural": "ひしぜん",
- "DG.Skills.ruby.flight": "ひこう"
+ "DG.Skills.ruby.flight": "ひこう",
+
+ "DG.Messages.Skillsmark.Marked": "このスキルはマークされています",
+ "DG.Messages.Skillsmark.Tooltip": "エージェントハンドブック29ページ参照"
}
diff --git a/lang/pl.json b/lang/pl.json
index 2c04d39..9cd3841 100644
--- a/lang/pl.json
+++ b/lang/pl.json
@@ -313,5 +313,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Czas Aktywacji",
"DG.ItemWindow.Ritual.ActivationCosts": "Koszt Aktywacji",
"DG.ItemWindow.Ritual.StudyTime": "Czas Nauki",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Utrata PP po Nauce"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Utrata PP po Nauce",
+
+ "DG.Messages.Skillsmark.Marked": "Ta umiejętność jest oznaczona.",
+ "DG.Messages.Skillsmark.Tooltip": "Zobacz str. 29 Podręcznika Agenta."
}
diff --git a/lang/pt-BR.json b/lang/pt-BR.json
index 8bfea92..8ab62a1 100644
--- a/lang/pt-BR.json
+++ b/lang/pt-BR.json
@@ -311,5 +311,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Tempo de Ativação",
"DG.ItemWindow.Ritual.ActivationCosts": "Custos de Ativação",
"DG.ItemWindow.Ritual.StudyTime": "Tempo de Estudo",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Dano de SAN ao Aprender"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Dano de SAN ao Aprender",
+
+ "DG.Messages.Skillsmark.Marked": "Esta perícia é marcada",
+ "DG.Messages.Skillsmark.Tooltip": "Veja pág. 29 do Manual do Agente"
}
diff --git a/lang/sv.json b/lang/sv.json
index 033f7b0..c87f62a 100644
--- a/lang/sv.json
+++ b/lang/sv.json
@@ -311,5 +311,8 @@
"DG.ItemWindow.Ritual.ActivationTime": "Aktiveringstid",
"DG.ItemWindow.Ritual.ActivationCosts": "Aktiveringskostnader",
"DG.ItemWindow.Ritual.StudyTime": "Studietid",
- "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage"
+ "DG.ItemWindow.Ritual.LearnedSanityDamage": "Learn SAN Damage",
+
+ "DG.Messages.Skillsmark.Marked": "Denna färdighet är markerad",
+ "DG.Messages.Skillsmark.Tooltip": "Se s. 29 Agenthandbok"
}
diff --git a/module/deltagreen.js b/module/deltagreen.js
index 8f91de9..aecf462 100644
--- a/module/deltagreen.js
+++ b/module/deltagreen.js
@@ -15,6 +15,8 @@ import {
rollSkillMacro,
rollSkillTestAndDamageForOwnedItem,
} from "./other/macro-functions.js";
+import DGUtils from "./other/utility-functions.js";
+import { handleInlineActions } from "./other/inline.js";
Hooks.once("init", async () => {
game.deltagreen = {
@@ -197,3 +199,14 @@ Hooks.on("renderGamePause", function (_, html, options) {
html.querySelector("img").classList.remove("fa-spin"); // I don't like the logo spinning personally
} catch {}
});
+
+Hooks.on("renderChatLog", async (app, element, context, options) => {
+ element.addEventListener("click", (event) => {
+ let btnWithAction = DGUtils.htmlClosest(event.target, "button[data-action]");
+ let message = DGUtils.htmlClosest(event.target, "li[data-message-id]");
+
+ if (btnWithAction && message && message?.dataset?.messageId) {
+ handleInlineActions(btnWithAction, message?.dataset?.messageId);
+ }
+ });
+});
\ No newline at end of file
diff --git a/module/other/inline.js b/module/other/inline.js
new file mode 100644
index 0000000..aa6fe44
--- /dev/null
+++ b/module/other/inline.js
@@ -0,0 +1,36 @@
+export async function handleInlineActions(btnWithAction, messageId) {
+ let action = btnWithAction.dataset?.action;
+ let message = game.messages.get(messageId);
+ let actor = message?.speakerActor;
+ if (!action || !message || !actor) {
+ return;
+ }
+
+ if (action === 'rollback-skill-failure-state') {
+ let rollbackFlag = foundry.utils.deepClone(message.getFlag("deltagreen", "rollbacks"));
+ await actor.update(foundry.utils.deepClone(rollbackFlag));
+
+ toggleAllSkillFailures(rollbackFlag)
+
+ let label = btnWithAction
+ .closest(".rollback-section")
+ ?.querySelector("label");
+ let oldHtml = label.outerHTML;
+ label.classList.toggle('strike');
+
+ message.update({
+ [`flags.deltagreen.rollbacks`]: rollbackFlag,
+ content: message.content
+ .replace(oldHtml, label.outerHTML)
+ })
+ }
+}
+
+function toggleAllSkillFailures(data) {
+ for (const skill of Object.values(data.system?.skills || {})) {
+ skill.failure = !skill.failure;
+ }
+ for (const skill of Object.values(data.system?.typedSkills || {})) {
+ skill.failure = !skill.failure;
+ }
+}
\ No newline at end of file
diff --git a/module/other/utility-functions.js b/module/other/utility-functions.js
index dabf602..887bb30 100644
--- a/module/other/utility-functions.js
+++ b/module/other/utility-functions.js
@@ -33,4 +33,15 @@ export default class DGUtils {
static formatStringWithLeadingPlus(number) {
return number > 0 ? `+${number}` : number.toString();
}
+
+ static htmlClosest(element, selectors) {
+ if (element instanceof Element) {
+ return element.closest(selectors);
+ }
+ return null
+ }
+
+ static getValueByPath(obj, path) {
+ return path.split('.').reduce((acc, key) => acc?.[key], obj);
+ }
}
diff --git a/module/roll/roll.js b/module/roll/roll.js
index cb39c47..4648359 100644
--- a/module/roll/roll.js
+++ b/module/roll/roll.js
@@ -77,12 +77,13 @@ export class DGPercentileRoll extends DGRoll {
super("1D100", {}, options);
// Set roll info for Skill, Stat, Typed Skill, and non-custom Weapon Percentile rolls.
- const { target, localizedKey } = this.getRollInfoFromKey(
+ const { target, localizedKey, skillPath } = this.getRollInfoFromKey(
this.key,
this.actor.system,
);
this.target = target;
this.localizedKey = localizedKey;
+ this.skillPath = skillPath;
// Set roll info for other Percentile rolls
switch (this.type) {
@@ -272,50 +273,7 @@ export class DGPercentileRoll extends DGRoll {
this.options.rollMode = "blindroll";
}
- let label = `${game.i18n.localize("DG.Roll.Rolling")} ${
- this.localizedKey
- }
${game.i18n.localize("DG.Roll.Target")} ${this.effectiveTarget}%`;
- // "Inhuman" stat being rolled. See function for details.
- if (this.isInhuman) {
- label = `${game.i18n.localize("DG.Roll.Rolling")} ${
- this.localizedKey
- } [${game.i18n
- .localize("DG.Roll.Inhuman")
- .toUpperCase()}] ${game.i18n.localize("DG.Roll.Target")} ${
- this.effectiveTarget
- }`;
- }
-
- let isExhausted = false;
- let exhaustedCheckPenalty = -20;
-
- try {
- // I suspect (but am not entirely certain) that being tired doesn't make you less lucky)
- if (this.type !== "luck") {
- isExhausted = this.actor.system.physical.exhausted;
- exhaustedCheckPenalty = this.actor.system.physical.exhaustedPenalty;
- exhaustedCheckPenalty = -1 * Math.abs(exhaustedCheckPenalty);
- }
- } catch {
- isExhausted = false;
- exhaustedCheckPenalty = -20;
- }
-
- if (this.modifier || isExhausted) {
- label += ` (${this.target}%`;
-
- if (this.modifier) {
- label += `${DGUtils.formatStringWithLeadingPlus(this.modifier)}%`;
- }
-
- if (isExhausted) {
- label += `${DGUtils.formatStringWithLeadingPlus(
- exhaustedCheckPenalty,
- )}%`;
- }
-
- label += `)`;
- }
+ let label = this.createLabel();
let resultString = "";
let styleOverride = "";
@@ -338,31 +296,36 @@ export class DGPercentileRoll extends DGRoll {
}
}
- let html = "";
- html += `