Skip to content

Commit

Permalink
Merge pull request #52 from orffen/chat-rolls
Browse files Browse the repository at this point in the history
r12
  • Loading branch information
orffen committed Jul 21, 2023
2 parents 84cbafe + 285d8e4 commit 52e71e8
Show file tree
Hide file tree
Showing 13 changed files with 116 additions and 36 deletions.
6 changes: 6 additions & 0 deletions lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"BASICFANTASYRPG.Duration": "Duration",
"BASICFANTASYRPG.ExperiencePoints": "Experience Points",
"BASICFANTASYRPG.ExperiencePointsAbbr": "XP",
"BASICFANTASYRPG.Failure": "Failure",
"BASICFANTASYRPG.Formula": "Roll Formula",
"BASICFANTASYRPG.HitDice": "Hit Dice",
"BASICFANTASYRPG.HitDiceAbbr": "HD",
Expand All @@ -82,13 +83,18 @@
"BASICFANTASYRPG.Race": "Race",
"BASICFANTASYRPG.Range": "Range",
"BASICFANTASYRPG.Ranged": "Ranged",
"BASICFANTASYRPG.Roll": "Roll",
"BASICFANTASYRPG.Sex": "Gender",
"BASICFANTASYRPG.Size": "Size",
"BASICFANTASYRPG.SpecialAbility": "Special Abilities",
"BASICFANTASYRPG.Spells": "Spells",
"BASICFANTASYRPG.SpellLevel": "Level",
"BASICFANTASYRPG.SpellsPerLevel": "Spells",
"BASICFANTASYRPG.Success": "Success",
"BASICFANTASYRPG.TargetNumber": "Target Number",
"BASICFANTASYRPG.TreasureType": "Treasure Type",
"BASICFANTASYRPG.Versus": "Versus",
"BASICFANTASYRPG.VersusAbbr": "vs.",
"BASICFANTASYRPG.Weight": "Weight",

"BASICFANTASYRPG.EffectCreate": "Create Effect",
Expand Down
4 changes: 4 additions & 0 deletions module/basicfantasyrpg.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ Handlebars.registerHelper('localizeLowerCase', function(str) {
return game.i18n.localize(str).toLowerCase();
});

Handlebars.registerHelper('calculateAbilityTargetNumber', function(lvl) {
return Math.floor(17 - (lvl / 2 - lvl % 2));
})

/* -------------------------------------------- */
/* Ready Hook */
/* -------------------------------------------- */
Expand Down
26 changes: 15 additions & 11 deletions module/documents/item.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {successChatMessage} from "../helpers/chat.mjs";

/**
* Extend the basic Item with some very simple modifications.
* @extends {Item}
Expand Down Expand Up @@ -34,26 +36,28 @@ export class BasicFantasyRPGItem extends Item {
const item = this;

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

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

// Invoke the roll and submit it to chat.
// Retrieve roll data and invoke the roll
const rollData = item.getRollData();
const roll = new Roll(rollData.item.formula.value, rollData);
// If you need to store the value first, uncomment the next line.
// let result = await roll.roll({async: true});
await roll.roll();
label += successChatMessage(roll.total, rollData.item.targetNumber.value, true);
roll.toMessage({
speaker: speaker,
rollMode: rollMode,
Expand Down
28 changes: 28 additions & 0 deletions module/helpers/chat.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Check if a roll was successful and format a success/failure message.
*
* @param {Number} result The result of the roll
* @param {Number} targetNumber The target number to beat for the roll to be successful
* @param {Boolean} percentile Whether to check for rolling under on percentile dice instead of a d20 roll (defaults to false)
*
* @return {String}
*/
export function successChatMessage(result, targetNumber, percentile=false) {
let msg = '';
let success = false;
if (result && !isNaN(result) && targetNumber && !isNaN(targetNumber)) {
if (percentile) {
success = (Number(result) <= Number(targetNumber));
} else {
success = (Number(result) == 20 || (Number(result) > 1 && Number(result) >= Number(targetNumber)));
}
msg += `<span class="chat-item-description">`;
if (success) {
msg += `<span class="chat-roll-success">&#9989;&nbsp;${game.i18n.localize('BASICFANTASYRPG.Success')}</span>`;
} else {
msg += `<span class="chat-roll-failure">&#9940;&nbsp;${game.i18n.localize('BASICFANTASYRPG.Failure')}</span>`;
}
msg += ` ${game.i18n.localize('BASICFANTASYRPG.VersusAbbr')} ${game.i18n.localize('BASICFANTASYRPG.TargetNumber').toLowerCase()} <span class="chat-roll-target-number">${targetNumber}</span></span>`;
}
return msg;
}
12 changes: 7 additions & 5 deletions module/sheets/actor-sheet.mjs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {successChatMessage} from "../helpers/chat.mjs";
import {onManageActiveEffect, prepareActiveEffectCategories} from "../helpers/effects.mjs";

/**
Expand Down Expand Up @@ -270,17 +271,17 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {
* @param {Event} event The originating click event
* @private
*/
_onRoll(event) {
async _onRoll(event) {
event.preventDefault();
const element = event.currentTarget;
const dataset = element.dataset;

if (dataset.rollType) {
// Handle weapon rolls. TODO: this could be moved into the item.roll() function instead
// Handle weapon rolls.
if (dataset.rollType == 'weapon') {
const itemId = element.closest('.item').dataset.itemId;
const item = this.actor.items.get(itemId);
let label = dataset.label ? `Roll: ${dataset.label}` : `Roll: ${dataset.attack.capitalize()} attack with ${item.name}`;
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>`;
let rollFormula = 'd20+@ab';
if (this.actor.type == 'character') {
if (dataset.attack == 'melee') {
Expand Down Expand Up @@ -309,8 +310,10 @@ export class BasicFantasyRPGActorSheet extends ActorSheet {

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

}
44 changes: 36 additions & 8 deletions styles/basicfantasyrpg.css
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,42 @@
cursor: pointer;
}

.chat-message {
font-family: "Century Gothic", "TeX Gyre Adventor", var(--font-primary);
}

.chat-message .chat-item-name {
color: black;
display: block;
font-size: 14px;
font-weight: bold;
text-shadow: 1px 1px 2px #aaa;
}

.chat-message .chat-item-description {
font-family: "Soutane", "Century Gothic", "TeX Gyre Adventor", var(--font-primary);
font-size: 14px;
}

.chat-message .chat-item-description .chat-roll-success {
color: green;
font-variant: small-caps;
font-weight: bold;
text-shadow: 0 0 2px;
}

.chat-message .chat-item-description .chat-roll-failure {
color: darkred;
font-variant: small-caps;
font-weight: bold;
text-shadow: 0 0 2px;
}

.chat-message .chat-item-description .chat-roll-target-number {
font-weight: bold;
text-shadow: 0 0 2px;
}

.grid,
.grid-2col {
display: grid;
Expand Down Expand Up @@ -441,14 +477,6 @@
display: flex;
}

/*.basicfantasyrpg .items-header .item-detail {
font-weight: bold;
text-align: left;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
}*/

.basicfantasyrpg .items-list {
list-style: none;
margin: 0;
Expand Down
6 changes: 3 additions & 3 deletions system.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"id": "basicfantasyrpg",
"title": "Basic Fantasy RPG",
"description": "The Basic Fantasy RPG system for FoundryVTT!",
"version": "r11",
"version": "r12",
"compatibility": {
"minimum": "11",
"verified": "11"
Expand Down Expand Up @@ -30,7 +30,7 @@
"primaryTokenAttribute": "hitPoints",
"secondaryTokenAttribute": null,
"url": "https://github.com/orffen/basicfantasyrpg",
"manifest": "https://raw.githubusercontent.com/orffen/basicfantasyrpg/r11/system.json",
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r11.zip",
"manifest": "https://raw.githubusercontent.com/orffen/basicfantasyrpg/r12/system.json",
"download": "https://github.com/orffen/basicfantasyrpg/archive/refs/tags/r12.zip",
"license": "LICENSE.txt"
}
4 changes: 4 additions & 0 deletions template.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@
"formula": {
"value": "d100",
"label": "BASICFANTASYRPG.Formula"
},
"targetNumber": {
"value": "",
"label": "BASICFANTASYRPG.TargetNumber"
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions templates/actor/actor-character-sheet.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" place
<div class="abilities flexcol">
{{#each data.abilities as |ability key|}}
<div class="ability flexrow flex-group-center">
<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>
<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>
<input type="text" name="data.abilities.{{key}}.value" value="{{ability.value}}" data-dtype="Number"/>
<span class="ability-mod rollable" data-roll="d20+@abilities.{{key}}.bonus" data-label="{{ability.label}}">{{numberFormat ability.bonus decimals=0 sign=true}}</span>
<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>
</div>
{{/each}}

<hr>

{{#each data.saves as |save key|}}
<div class="ability flexrow flex-group-center">
<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>
<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>
<input type="text" name="data.saves.{{key}}.value" value="{{save.value}}" data-dtype="Number"/>
</div>
{{/each}}
Expand Down
2 changes: 1 addition & 1 deletion templates/actor/actor-monster-sheet.html
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" place
<div class="abilities flexcol">
{{#each data.saves as |save key|}}
<div class="ability flexrow flex-group-center">
<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>
<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>
<input type="text" name="data.saves.{{key}}.value" value="{{save.value}}" data-dtype="Number"/>
</div>
{{/each}}
Expand Down
4 changes: 2 additions & 2 deletions templates/actor/parts/actor-combat.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<li class="item flexrow" data-item-id="{{weapon._id}}">
<div class="item-name">
<div class="item-image">
<img src="{{weapon.img}}" title="{{weapon.name}}" width="24" height="24"/>
<a class="rollable" data-roll-type="item"><img src="{{weapon.img}}" title="{{weapon.name}}" width="24" height="24"/></a>
</div>
<h4>{{weapon.name}}</h4>
</div>
Expand Down Expand Up @@ -72,7 +72,7 @@ <h4>{{weapon.name}}</h4>
<li class="item flexrow" data-item-id="{{armor._id}}">
<div class="item-name">
<div class="item-image">
<img src="{{armor.img}}" title="{{armor.name}}" width="24" height="24"/>
<a class="rollable" data-roll-type="item"><img src="{{armor.img}}" title="{{armor.name}}" width="24" height="24"/></a>
</div>
<h4>{{armor.name}}</h4>
</div>
Expand Down
4 changes: 2 additions & 2 deletions templates/actor/parts/actor-features.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@
<li class="item flexrow" data-item-id="{{item._id}}">
<div class="item-name">
<div class="item-image">
<a class="rollable" data-roll-type="item"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/></a>
<a class="rollable" data-roll-type="item" data-target-number="{{item.system.targetNumber.value}}"><img src="{{item.img}}" title="{{item.name}}" width="24" height="24"/></a>
</div>
<h4>{{item.name}}</h4>
</div>
<div class="item-formula item-prop rollable" data-roll-type="item">{{item.system.formula.value}}</div>
<div class="item-formula item-prop rollable" data-roll-type="item" data-target-number="{{item.system.targetNumber.value}}">{{item.system.formula.value}}{{#if item.system.targetNumber.value}}&nbsp;(&le;&nbsp;{{item.system.targetNumber.value}}){{/if}}</div>
<div class="item-controls">
<a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
<a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
Expand Down
6 changes: 5 additions & 1 deletion templates/item/item-feature-sheet.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
<img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}"/>
<div class="header-fields">
<h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="{{localize 'BASICFANTASYRPG.Name'}}"/></h1>
<div class="grid grid-1col">
<div class="grid grid-2col">
<div class="resource">
<label for="data.formula.value" class="resource-label">{{localize data.formula.label}}</label>
<input type="text" name="data.formula.value" value="{{data.formula.value}}" data-dtype="String"/>
</div>
<div class="resource">
<label for="data.targetNumber.value" class="resource-label">{{localize data.targetNumber.label}}</label>
<input type="text" name="data.targetNumber.value" value="{{data.targetNumber.value}}" data-dtype="Number"/>
</div>
</div>
</div>
</header>
Expand Down

0 comments on commit 52e71e8

Please sign in to comment.