Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[#3156] Add setting to show attack roll result (AC check) card to players #3157

Merged
merged 3 commits into from
Jul 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2119,6 +2119,13 @@
"SETTINGS.5eAutoCollapseCardN": "Collapse Item Cards in Chat",
"SETTINGS.5eAutoSpellTemplateL": "When a spell is cast, defaults to begin the process to create the corresponding Measured Template if any (requires TRUSTED or higher player role)",
"SETTINGS.5eAutoSpellTemplateN": "Always place Spell Template",
"SETTINGS.5eAttackRollVisibility": {
"Name": "Attack Result Visibility",
"Hint": "Control visibility of attack roll results in chat cards for players.",
"All": "Show results & target ACs",
"HideAC": "Show only results",
"None": "Hide all"
},
"SETTINGS.5eChallengeVisibility": {
"Name": "Challenge Visibility",
"Hint": "Control what roll DCs are visible to the players and whether successes/failures are highlighted.",
Expand Down
12 changes: 10 additions & 2 deletions module/documents/chat-message.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export default class ChatMessage5e extends ChatMessage {
if ( !this.isContentVisible || !this.rolls.length ) return;
const originatingMessage = game.messages.get(this.getFlag("dnd5e", "originatingMessage")) ?? this;
const displayChallenge = originatingMessage?.shouldDisplayChallenge;
const displayAttackResult = game.user.isGM || (game.settings.get("dnd5e", "attackRollVisibility") !== "none");

/**
* Create an icon to indicate success or failure.
Expand Down Expand Up @@ -202,7 +203,9 @@ export default class ChatMessage5e extends ChatMessage {
if ( !total ) continue;
// Only attack rolls and death saves can crit or fumble.
const canCrit = ["attack", "death"].includes(this.getFlag("dnd5e", "roll.type"));
if ( d.options.target && displayChallenge ) {
const isAttack = this.getFlag("dnd5e", "roll.type") === "attack";
const showResult = isAttack ? displayAttackResult : displayChallenge;
if ( d.options.target && showResult ) {
if ( d20Roll.total >= d.options.target ) total.classList.add("success");
else total.classList.add("failure");
}
Expand Down Expand Up @@ -359,7 +362,9 @@ export default class ChatMessage5e extends ChatMessage {
_enrichAttackTargets(html) {
const attackRoll = this.rolls[0];
const targets = this.getFlag("dnd5e", "targets");
if ( !game.user.isGM || !(attackRoll instanceof dnd5e.dice.D20Roll) || !targets?.length ) return;
const visibility = game.settings.get("dnd5e", "attackRollVisibility");
const isVisible = game.user.isGM || (visibility !== "none");
if ( !isVisible || !(attackRoll instanceof dnd5e.dice.D20Roll) || !targets?.length ) return;
const tray = document.createElement("div");
tray.classList.add("dnd5e2");
tray.innerHTML = `
Expand All @@ -376,15 +381,18 @@ export default class ChatMessage5e extends ChatMessage {
`;
const evaluation = tray.querySelector("ul");
evaluation.innerHTML = targets.map(({ name, ac, uuid }) => {
if ( !game.user.isGM && (visibility !== "all") ) ac = "";
const isMiss = !attackRoll.isCritical && ((attackRoll.total < ac) || attackRoll.isFumble);
return [`
<li data-uuid="${uuid}" class="target ${isMiss ? "miss" : "hit"}">
<i class="fas ${isMiss ? "fa-times" : "fa-check"}"></i>
<div class="name">${name}</div>
${ac ? `
<div class="ac">
<i class="fas fa-shield-halved"></i>
<span>${ac}</span>
</div>
` : ""}
</li>
`, isMiss];
}).sort((a, b) => (a[1] === b[1]) ? 0 : a[1] ? 1 : -1).reduce((str, [li]) => str + li, "");
Expand Down
14 changes: 14 additions & 0 deletions module/settings.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ export function registerSystemSettings() {
}
});

game.settings.register("dnd5e", "attackRollVisibility", {
name: "SETTINGS.5eAttackRollVisibility.Name",
hint: "SETTINGS.5eAttackRollVisibility.Hint",
scope: "world",
config: true,
default: "none",
type: String,
choices: {
all: "SETTINGS.5eAttackRollVisibility.All",
hideAC: "SETTINGS.5eAttackRollVisibility.HideAC",
none: "SETTINGS.5eAttackRollVisibility.None"
}
});

// Encumbrance tracking
game.settings.register("dnd5e", "encumbrance", {
name: "SETTINGS.5eEncumbrance.Name",
Expand Down