Skip to content

Commit 52e71e8

Browse files
authored
Merge pull request #52 from orffen/chat-rolls
r12
2 parents 84cbafe + 285d8e4 commit 52e71e8

File tree

13 files changed

+116
-36
lines changed

13 files changed

+116
-36
lines changed

lang/en.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"BASICFANTASYRPG.Duration": "Duration",
6464
"BASICFANTASYRPG.ExperiencePoints": "Experience Points",
6565
"BASICFANTASYRPG.ExperiencePointsAbbr": "XP",
66+
"BASICFANTASYRPG.Failure": "Failure",
6667
"BASICFANTASYRPG.Formula": "Roll Formula",
6768
"BASICFANTASYRPG.HitDice": "Hit Dice",
6869
"BASICFANTASYRPG.HitDiceAbbr": "HD",
@@ -82,13 +83,18 @@
8283
"BASICFANTASYRPG.Race": "Race",
8384
"BASICFANTASYRPG.Range": "Range",
8485
"BASICFANTASYRPG.Ranged": "Ranged",
86+
"BASICFANTASYRPG.Roll": "Roll",
8587
"BASICFANTASYRPG.Sex": "Gender",
8688
"BASICFANTASYRPG.Size": "Size",
8789
"BASICFANTASYRPG.SpecialAbility": "Special Abilities",
8890
"BASICFANTASYRPG.Spells": "Spells",
8991
"BASICFANTASYRPG.SpellLevel": "Level",
9092
"BASICFANTASYRPG.SpellsPerLevel": "Spells",
93+
"BASICFANTASYRPG.Success": "Success",
94+
"BASICFANTASYRPG.TargetNumber": "Target Number",
9195
"BASICFANTASYRPG.TreasureType": "Treasure Type",
96+
"BASICFANTASYRPG.Versus": "Versus",
97+
"BASICFANTASYRPG.VersusAbbr": "vs.",
9298
"BASICFANTASYRPG.Weight": "Weight",
9399

94100
"BASICFANTASYRPG.EffectCreate": "Create Effect",

module/basicfantasyrpg.mjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ Handlebars.registerHelper('localizeLowerCase', function(str) {
7171
return game.i18n.localize(str).toLowerCase();
7272
});
7373

74+
Handlebars.registerHelper('calculateAbilityTargetNumber', function(lvl) {
75+
return Math.floor(17 - (lvl / 2 - lvl % 2));
76+
})
77+
7478
/* -------------------------------------------- */
7579
/* Ready Hook */
7680
/* -------------------------------------------- */

module/documents/item.mjs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import {successChatMessage} from "../helpers/chat.mjs";
2+
13
/**
24
* Extend the basic Item with some very simple modifications.
35
* @extends {Item}
@@ -34,26 +36,28 @@ export class BasicFantasyRPGItem extends Item {
3436
const item = this;
3537

3638
// Initialize chat data.
37-
const speaker = ChatMessage.getSpeaker({ actor: this.actor });
39+
const speaker = ChatMessage.getSpeaker({ actor: item.actor });
3840
const rollMode = game.settings.get('core', 'rollMode');
39-
const label = `Roll: ${game.i18n.localize('ITEM.Type' + item.type.capitalize())} - ${item.name}`;
4041

41-
// If there's no roll data, or the formula is empty, send a chat message.
42-
if (!this.system.formula || !this.system.formula.value) {
42+
// If there's no roll data, or the formula is empty, just send a chat message.
43+
if (!item.system.formula || !item.system.formula.value) {
4344
ChatMessage.create({
4445
speaker: speaker,
4546
rollMode: rollMode,
46-
flavor: label,
47-
content: item.description ?? ''
47+
flavor: `<span class="chat-item-name">${game.i18n.localize('ITEM.Type' + item.type.capitalize())} - ${item.name}</span>`,
48+
content: item.system.description ? `<span class="chat-item-description">${item.system.description}</span>` : ''
4849
});
4950
} else { // Otherwise, create a roll and send a chat message from it.
50-
// Retrieve roll data.
51-
const rollData = this.getRollData();
51+
let label = `<span class="chat-item-name">${game.i18n.localize('BASICFANTASYRPG.Roll')}: ${game.i18n.localize('ITEM.Type' + item.type.capitalize())} - ${item.name}</span>`;
52+
if (item.type == 'feature' && item.system.description) {
53+
label += `<span class="chat-item-description">${item.system.description}</span>`;
54+
}
5255

53-
// Invoke the roll and submit it to chat.
56+
// Retrieve roll data and invoke the roll
57+
const rollData = item.getRollData();
5458
const roll = new Roll(rollData.item.formula.value, rollData);
55-
// If you need to store the value first, uncomment the next line.
56-
// let result = await roll.roll({async: true});
59+
await roll.roll();
60+
label += successChatMessage(roll.total, rollData.item.targetNumber.value, true);
5761
roll.toMessage({
5862
speaker: speaker,
5963
rollMode: rollMode,

module/helpers/chat.mjs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Check if a roll was successful and format a success/failure message.
3+
*
4+
* @param {Number} result The result of the roll
5+
* @param {Number} targetNumber The target number to beat for the roll to be successful
6+
* @param {Boolean} percentile Whether to check for rolling under on percentile dice instead of a d20 roll (defaults to false)
7+
*
8+
* @return {String}
9+
*/
10+
export function successChatMessage(result, targetNumber, percentile=false) {
11+
let msg = '';
12+
let success = false;
13+
if (result && !isNaN(result) && targetNumber && !isNaN(targetNumber)) {
14+
if (percentile) {
15+
success = (Number(result) <= Number(targetNumber));
16+
} else {
17+
success = (Number(result) == 20 || (Number(result) > 1 && Number(result) >= Number(targetNumber)));
18+
}
19+
msg += `<span class="chat-item-description">`;
20+
if (success) {
21+
msg += `<span class="chat-roll-success">&#9989;&nbsp;${game.i18n.localize('BASICFANTASYRPG.Success')}</span>`;
22+
} else {
23+
msg += `<span class="chat-roll-failure">&#9940;&nbsp;${game.i18n.localize('BASICFANTASYRPG.Failure')}</span>`;
24+
}
25+
msg += ` ${game.i18n.localize('BASICFANTASYRPG.VersusAbbr')} ${game.i18n.localize('BASICFANTASYRPG.TargetNumber').toLowerCase()} <span class="chat-roll-target-number">${targetNumber}</span></span>`;
26+
}
27+
return msg;
28+
}

module/sheets/actor-sheet.mjs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {successChatMessage} from "../helpers/chat.mjs";
12
import {onManageActiveEffect, prepareActiveEffectCategories} from "../helpers/effects.mjs";
23

34
/**
@@ -270,17 +271,17 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
270271
* @param {Event} event The originating click event
271272
* @private
272273
*/
273-
_onRoll(event) {
274+
async _onRoll(event) {
274275
event.preventDefault();
275276
const element = event.currentTarget;
276277
const dataset = element.dataset;
277278

278279
if (dataset.rollType) {
279-
// Handle weapon rolls. TODO: this could be moved into the item.roll() function instead
280+
// Handle weapon rolls.
280281
if (dataset.rollType == 'weapon') {
281282
const itemId = element.closest('.item').dataset.itemId;
282283
const item = this.actor.items.get(itemId);
283-
let label = dataset.label ? `Roll: ${dataset.label}` : `Roll: ${dataset.attack.capitalize()} attack with ${item.name}`;
284+
let label = dataset.label ? `<span class="chat-item-name">${game.i18n.localize('BASICFANTASYRPG.Roll')}: ${dataset.label}</span>` : `<span class="chat-item-name">${game.i18n.localize('BASICFANTASYRPG.Roll')}: ${dataset.attack.capitalize()} attack with ${item.name}</span>`;
284285
let rollFormula = 'd20+@ab';
285286
if (this.actor.type == 'character') {
286287
if (dataset.attack == 'melee') {
@@ -309,8 +310,10 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
309310

310311
// Handle rolls that supply the formula directly.
311312
if (dataset.roll) {
312-
let label = dataset.label ? `Roll: ${dataset.label}` : '';
313+
let label = dataset.label ? `<span class="chat-item-name">${game.i18n.localize('BASICFANTASYRPG.Roll')}: ${dataset.label}</span>` : '';
313314
let roll = new Roll(dataset.roll, this.actor.getRollData());
315+
await roll.roll();
316+
label += successChatMessage(roll.total, dataset.targetNumber);
314317
roll.toMessage({
315318
speaker: ChatMessage.getSpeaker({ actor: this.actor }),
316319
flavor: label,
@@ -319,5 +322,4 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
319322
return roll;
320323
}
321324
}
322-
323325
}

styles/basicfantasyrpg.css

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,42 @@
109109
cursor: pointer;
110110
}
111111

112+
.chat-message {
113+
font-family: "Century Gothic", "TeX Gyre Adventor", var(--font-primary);
114+
}
115+
116+
.chat-message .chat-item-name {
117+
color: black;
118+
display: block;
119+
font-size: 14px;
120+
font-weight: bold;
121+
text-shadow: 1px 1px 2px #aaa;
122+
}
123+
124+
.chat-message .chat-item-description {
125+
font-family: "Soutane", "Century Gothic", "TeX Gyre Adventor", var(--font-primary);
126+
font-size: 14px;
127+
}
128+
129+
.chat-message .chat-item-description .chat-roll-success {
130+
color: green;
131+
font-variant: small-caps;
132+
font-weight: bold;
133+
text-shadow: 0 0 2px;
134+
}
135+
136+
.chat-message .chat-item-description .chat-roll-failure {
137+
color: darkred;
138+
font-variant: small-caps;
139+
font-weight: bold;
140+
text-shadow: 0 0 2px;
141+
}
142+
143+
.chat-message .chat-item-description .chat-roll-target-number {
144+
font-weight: bold;
145+
text-shadow: 0 0 2px;
146+
}
147+
112148
.grid,
113149
.grid-2col {
114150
display: grid;
@@ -441,14 +477,6 @@
441477
display: flex;
442478
}
443479

444-
/*.basicfantasyrpg .items-header .item-detail {
445-
font-weight: bold;
446-
text-align: left;
447-
display: -webkit-box;
448-
display: -ms-flexbox;
449-
display: flex;
450-
}*/
451-
452480
.basicfantasyrpg .items-list {
453481
list-style: none;
454482
margin: 0;

system.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"id": "basicfantasyrpg",
33
"title": "Basic Fantasy RPG",
44
"description": "The Basic Fantasy RPG system for FoundryVTT!",
5-
"version": "r11",
5+
"version": "r12",
66
"compatibility": {
77
"minimum": "11",
88
"verified": "11"
@@ -30,7 +30,7 @@
3030
"primaryTokenAttribute": "hitPoints",
3131
"secondaryTokenAttribute": null,
3232
"url": "https://github.com/orffen/basicfantasyrpg",
33-
"manifest": "https://raw.githubusercontent.com/orffen/basicfantasyrpg/r11/system.json",
34-
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r11.zip",
33+
"manifest": "https://raw.githubusercontent.com/orffen/basicfantasyrpg/r12/system.json",
34+
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r12.zip",
3535
"license": "LICENSE.txt"
3636
}

template.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,10 @@
236236
"formula": {
237237
"value": "d100",
238238
"label": "BASICFANTASYRPG.Formula"
239+
},
240+
"targetNumber": {
241+
"value": "",
242+
"label": "BASICFANTASYRPG.TargetNumber"
239243
}
240244
}
241245
}

templates/actor/actor-character-sheet.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@ <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" place
5959
<div class="abilities flexcol">
6060
{{#each data.abilities as |ability key|}}
6161
<div class="ability flexrow flex-group-center">
62-
<label for="data.abilities.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20+@abilities.{{key}}.bonus" data-label="{{ability.label}}">{{ability.label}}</label>
62+
<label for="data.abilities.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20+@abilities.{{key}}.bonus" data-label="{{ability.label}}" data-target-number="{{calculateAbilityTargetNumber ../data.level.value}}">{{ability.label}}</label>
6363
<input type="text" name="data.abilities.{{key}}.value" value="{{ability.value}}" data-dtype="Number"/>
64-
<span class="ability-mod rollable" data-roll="d20+@abilities.{{key}}.bonus" data-label="{{ability.label}}">{{numberFormat ability.bonus decimals=0 sign=true}}</span>
64+
<span class="ability-mod rollable" data-roll="d20+@abilities.{{key}}.bonus" data-label="{{ability.label}}" data-target-number="{{calculateAbilityTargetNumber ../data.level.value}}">{{numberFormat ability.bonus decimals=0 sign=true}}</span>
6565
</div>
6666
{{/each}}
6767

6868
<hr>
6969

7070
{{#each data.saves as |save key|}}
7171
<div class="ability flexrow flex-group-center">
72-
<label for="data.saves.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20" data-label="Saving Throw - {{save.label}}">{{save.label}}</label>
72+
<label for="data.saves.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20" data-label="Saving Throw - {{save.label}}" data-target-number="{{save.value}}">{{save.label}}</label>
7373
<input type="text" name="data.saves.{{key}}.value" value="{{save.value}}" data-dtype="Number"/>
7474
</div>
7575
{{/each}}

templates/actor/actor-monster-sheet.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" place
8282
<div class="abilities flexcol">
8383
{{#each data.saves as |save key|}}
8484
<div class="ability flexrow flex-group-center">
85-
<label for="data.saves.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20" data-label="Saving Throw - {{save.label}}">{{save.label}}</label>
85+
<label for="data.saves.{{key}}.value" class="resource-label rollable flexlarge align-left" data-roll="d20" data-label="Saving Throw - {{save.label}}" data-target-number="{{save.value}}">{{save.label}}</label>
8686
<input type="text" name="data.saves.{{key}}.value" value="{{save.value}}" data-dtype="Number"/>
8787
</div>
8888
{{/each}}

0 commit comments

Comments
 (0)