Compare commits
7 Commits
Author | SHA1 | Date | |
---|---|---|---|
1f2558b680 | |||
e25c51a570 | |||
3ba8fdd641 | |||
41a9769945 | |||
895ab67602 | |||
dc4a58a5c6 | |||
af8b2eeaba |
15
README.md
15
README.md
@ -1,16 +1,15 @@
|
||||
# Rolemaster Standard System for Foundry VTT
|
||||
|
||||
## Introduction
|
||||
This is an in-development implementation of the Rolemaster Standard System for FoundryVTT. All rights to the system remain property of Iron Crown Enterprises (http://ironcrown.com/). This system will not include any of the book content and aims to provide only what is on the character sheet.
|
||||
|
||||
If you need access to the Rolemaster Standard System you may be out of luck as the system has been out of print for some time. However it's successor Rolemaster Fantasy Roleplaying is broadly compatible and can be purchased as a PDF via Drive Thru RPG here: https://www.drivethrurpg.com/product/91995/Rolemaster-Fantasy-Role-Playing?cPath=1361_6495
|
||||
This repo is an independant fork from https://github.com/Cynicide/RMSS-FoundryVTT from Cynicide, in order to implement a fully playable Rolemaster FRP system in FoundryVTT.
|
||||
|
||||
All rights to the system remain property of Iron Crown Enterprises (http://ironcrown.com/). This system will not include any of the book content and aims to provide only what is on the character sheet.
|
||||
|
||||
## How to Use
|
||||
Download the latest release from this repository and then extract the rmss folder. Drag it into the systems folder of your FoundryVTT Data Directory. More detailed instructions can be found [here](docs/INSTALL.md) in the docs directory.
|
||||
Download the latest release from this repository and then extract the rmss folder. Drag it into the systems folder of your FoundryVTT Data Directory. More detailed instructions can be found [here](docs/INSTALL.md) in the docs directory (to be updated).
|
||||
|
||||
If you are using this system I highly recommend the "Simple Dice Roller" module which will allow you to roll dice easily while this feature is in development. You can install it in the Foundry Modules section or you can visit the following link for more instructions: https://foundryvtt.com/packages/simple-dice-roller/
|
||||
|
||||
Further information on how the system works can be found [here](docs/USAGE.md)
|
||||
Further information on how the system works can be found [here](docs/USAGE.md) (to be updated)
|
||||
|
||||
## Goals/ToDo
|
||||
Project goals include:
|
||||
@ -20,13 +19,11 @@ Project goals include:
|
||||
|
||||
I maintain a public Trello board here where I log my work items: https://trello.com/b/JkXd5EGx/rmss-for-foundryvtt-features
|
||||
|
||||
## About Me
|
||||
My name is Anthony, I'm a DevOps Engineer who has been playing Roleplaying Games since the mid 80's. I've been involved in numerous small programming projects. This system is by far the largest thing I've done. If the code here is awful it's because I'm learning CSS/Javascript as I go.
|
||||
|
||||
## Credits
|
||||
This system is based on:
|
||||
- The Foundry VTT Boilerplate system by Asacolips. (https://gitlab.com/asacolips-projects/foundry-mods/boilerplate)
|
||||
- The video tutorials by Cédric Hauteville you can watch them here: https://www.youtube.com/playlist?list=PLFV9z59nkHDccUbRXVt623UdloPTclIrz
|
||||
- The Rolemaster FRP is derivated from the RMSS system from Cynicide, available here https://github.com/Cynicide/RMSS-FoundryVTT
|
||||
|
||||
Icons used in this system have been sourced from https://game-icons.net
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
|
||||
"rmss": {
|
||||
"player_character": {
|
||||
"name": "Name:",
|
||||
@ -43,7 +44,8 @@
|
||||
"equipment": "Equipment",
|
||||
"spells": "Spells",
|
||||
"status_record": "Status Record",
|
||||
"experience_points": "Experience Points"
|
||||
"experience_points": "Experience Points",
|
||||
"background": "Background"
|
||||
},
|
||||
"pc_sheet_fixed_info": {
|
||||
"race": "Race:",
|
||||
|
@ -47,3 +47,7 @@
|
||||
border-bottom: 1px solid;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
|
||||
}
|
||||
.skill-box {
|
||||
margin-left: 1.2rem;
|
||||
background-color: lightgrey;
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
padding-bottom: 3px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
//flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
@ -36,7 +36,7 @@
|
||||
padding-bottom: 3px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
//flex-direction: column;
|
||||
justify-content: center;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
|
||||
}
|
||||
|
@ -15,6 +15,11 @@
|
||||
|
||||
.roll-button-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.roll-button {
|
||||
margin-top: 2px;
|
||||
width: 96px;
|
||||
max-width: 96px;
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
export const rmss = {};
|
||||
|
||||
rmss.curreny_type = {
|
||||
rmss.currency_type = {
|
||||
mp: "rmss.curreny_type.mp",
|
||||
pp: "rmss.curreny_type.pp",
|
||||
gp: "rmss.curreny_type.gp",
|
||||
@ -9,6 +9,59 @@ rmss.curreny_type = {
|
||||
cp: "rmss.curreny_type.cp"
|
||||
};
|
||||
|
||||
rmss.difficulties = {
|
||||
routine: {key: "routine", label:"Routine (+30)", value: 30},
|
||||
easy: {key: "easy", label:"Easy (+20)", value: 20},
|
||||
light: {key: "light", label:"Light (+10)", value: 10},
|
||||
medium: {key: "medium", label:"Medium (0)", value: 0},
|
||||
hard: {key: "hard", label:"Hard (-10)", value: -10},
|
||||
very_hard: {key: "very_hard", label:"Very Hard (-20)", value: -20},
|
||||
extremely_hard: {key: "extremely_hard", label:"Extremely Hard (-30)", value: -30},
|
||||
sheer_folly: {key: "sheer_folly", label:"Sheer Folly (-50)", value: -50},
|
||||
absurd: {key: "absurd", label:"Absurd (-70)", value: -70},
|
||||
};
|
||||
|
||||
rmss.combatSituations = [
|
||||
{key: "none", label:"None (0)", modifier: 0},
|
||||
{key: "melee", label:"Melee environment (-20)", modifier: -20},
|
||||
{key: "missile", label:"Under missile fire (-10)", modifier: -10},
|
||||
];
|
||||
|
||||
rmss.rankBonusProgressionList = [
|
||||
{key: "standard", label:"Standard"},
|
||||
{key: "limited", label:"Limited"},
|
||||
{key: "combined", label:"Combined"},
|
||||
]
|
||||
|
||||
rmss.lightOrDarknessModifiers = [
|
||||
{key: "none", label:"None", modifierLight: 0, modifierDark: 0},
|
||||
{key: "noshadows", label:"No shadows", modifierLight: 10, modifierDark: -30},
|
||||
{key: "lightshadows", label:"Light shadows", modifierLight: 5, modifierDark: -20},
|
||||
{key: "mediumshadows", label:"Medium shadows", modifierLight: 0, modifierDark: 0},
|
||||
{key: "heavyshadows", label:"Heavy shadows", modifierLight: -10, modifierDark: 10},
|
||||
{key: "dark", label:"Darkness", modifierLight: -25, modifierDark: 30},
|
||||
{key: "pitchblack", label:"Pitch black", modifierLight: -40, modifierDark: 40},
|
||||
]
|
||||
|
||||
rmss.hitsPerRound = [
|
||||
{key: "none", label:"None", modifier: 0},
|
||||
{key: "one", label:"One", modifier: -5},
|
||||
{key: "two", label:"Two", modifier: -10},
|
||||
{key: "three", label:"Three", modifier: -20},
|
||||
{key: "four", label:"Four", modifier: -25},
|
||||
{key: "five", label:"Five", modifier: -30},
|
||||
{key: "six", label:"Six", modifier: -35},
|
||||
{key: "seven", label:"Seven", modifier: -40},
|
||||
{key: "eight", label:"Eight", modifier: -45},
|
||||
{key: "nine", label:"Nine", modifier: -50},
|
||||
{key: "ten", label:"Ten", modifier: -55},
|
||||
{key: "eleven", label:"Eleven", modifier: -60},
|
||||
{key: "twelve", label:"Twelve", modifier: -65},
|
||||
{key: "thirteen", label:"Thirteen", modifier: -70},
|
||||
{key: "fourteen", label:"Fourteen", modifier: -75},
|
||||
{key: "fifteen", label:"Fifteen", modifier: -80}
|
||||
];
|
||||
|
||||
rmss.stats = {
|
||||
agility: {
|
||||
fullname: "Agility",
|
||||
|
@ -40,6 +40,31 @@ export class RMSSActor extends Actor {
|
||||
|
||||
// Iterate through and apply Skill Category Bonuses for Skill items
|
||||
this.calculateSkillBonuses();
|
||||
|
||||
this.computeWoundsMalus();
|
||||
}
|
||||
|
||||
getStunnedModifier() {
|
||||
if (this.system.state.stunned) {
|
||||
return Math.min(-50 + (3*this.system.stats.self_discipline.stat_bonus), 0)
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
computeWoundsMalus() {
|
||||
// Compute % of wounds
|
||||
let percent = 100 - (this.system.attributes.hits.current*100/this.system.attributes.hits.max);
|
||||
let modifier = 0;
|
||||
if (percent > 25 && percent < 50) {
|
||||
modifier = -10;
|
||||
} else if (percent >= 51 && percent < 75) {
|
||||
modifier = -20;
|
||||
} else if (percent >= 76) {
|
||||
modifier = -30;
|
||||
}
|
||||
this.system.modifiers.woundsModifier = modifier;
|
||||
console.log(`rmss | actor.js | Wounds Malus: ${this.system.modifiers.woundsModifier} ${percent}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,52 +258,36 @@ export class RMSSActor extends Actor {
|
||||
}
|
||||
else
|
||||
{
|
||||
let applicable_stat_bonus = 0;
|
||||
|
||||
let app_stat_1_found = false;
|
||||
let app_stat_2_found = false;
|
||||
let app_stat_3_found = false;
|
||||
let applicable_stat_bonuses = [];
|
||||
|
||||
// Iterate through the applicable stats and find their full names
|
||||
for (const stat in CONFIG.rmss.stats) {
|
||||
// If the configured App Stat matches the one of the stats in config
|
||||
if (app_stat_1 === CONFIG.rmss.stats[stat].shortname) {
|
||||
app_stat_1_found = true;
|
||||
// Get the Stat Bonus
|
||||
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus;
|
||||
// Add the Stat Bonus to the array
|
||||
applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
|
||||
}
|
||||
if (app_stat_2 === CONFIG.rmss.stats[stat].shortname) {
|
||||
app_stat_2_found = true;
|
||||
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus;
|
||||
// Add the Stat Bonus to the array
|
||||
applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
|
||||
}
|
||||
if (app_stat_3 === CONFIG.rmss.stats[stat].shortname) {
|
||||
app_stat_3_found = true;
|
||||
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus;
|
||||
// Add the Stat Bonus to the array
|
||||
applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
|
||||
}
|
||||
}
|
||||
|
||||
if (app_stat_1_found === true && app_stat_2_found === true && app_stat_3_found === true) {
|
||||
// Compute the total bonus for the applicable stats
|
||||
let applicable_stat_bonus = 0;
|
||||
for (const bonus of applicable_stat_bonuses) {
|
||||
applicable_stat_bonus += bonus;
|
||||
}
|
||||
// Apply the update if we found stat bonuses for every applicable stat
|
||||
if ( item.system.stat_bonus != applicable_stat_bonus ) {
|
||||
item.system.stat_bonus = applicable_stat_bonus;
|
||||
|
||||
}
|
||||
// Update the total in the Item
|
||||
item.calculateSkillCategoryTotalBonus(item);
|
||||
}
|
||||
else if (app_stat_1_found === true && app_stat_2_found === true && app_stat_3_found === false) {
|
||||
// Apply the update if we found stat bonuses for the first two applicable stats
|
||||
item.system.stat_bonus = applicable_stat_bonus;
|
||||
|
||||
// Update the total in the Item
|
||||
item.calculateSkillCategoryTotalBonus(item);
|
||||
}
|
||||
else if (app_stat_1_found === true && app_stat_2_found === false && app_stat_3_found === false) {
|
||||
// Apply the update if we found stat bonuses for the first applicable stat
|
||||
item.system.stat_bonus = applicable_stat_bonus;
|
||||
|
||||
// Update the total in the Item
|
||||
item.calculateSkillCategoryTotalBonus(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,7 +167,15 @@ export default class RMSSPlayerSheet extends ActorSheet {
|
||||
spells.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Parse skill categories and re+levant skills
|
||||
for (let s of skillcat) {
|
||||
s.skills = [];
|
||||
for (let sk of playerskill) {
|
||||
if (sk.system.category === s._id) {
|
||||
s.skills.push(sk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sort Skill/Skillcat Arrays
|
||||
skillcat.sort(function(a, b) {
|
||||
@ -198,6 +206,10 @@ export default class RMSSPlayerSheet extends ActorSheet {
|
||||
context.armor = armor;
|
||||
context.herbs = herbs;
|
||||
context.spells = spells;
|
||||
|
||||
// Dump context to console
|
||||
console.log(context);
|
||||
|
||||
}
|
||||
|
||||
async renderCharacterSettings(data) {
|
||||
@ -217,7 +229,7 @@ export default class RMSSPlayerSheet extends ActorSheet {
|
||||
|
||||
html.find(".item-roll").click(ev => {
|
||||
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
|
||||
new game.rmss.applications.RMSSToolsDiceRoller(item.name, item.system.total_bonus).render(true);
|
||||
new game.rmss.applications.RMSSToolsDiceRoller(item, this.actor).render(true);
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------
|
||||
|
@ -1,27 +1,17 @@
|
||||
import {
|
||||
roll_one_to_onehundred,
|
||||
roll_low_open_ended,
|
||||
roll_high_open_ended,
|
||||
roll_open_ended
|
||||
} from "./rmss_dice_roller_rolls.js";
|
||||
import {
|
||||
getOpenEndedRollModifier,
|
||||
processOpenEndedSixtySixRoll,
|
||||
processOpenEndedRoll,
|
||||
processHighOpenEndedRoll,
|
||||
processLowOpenEndedRoll
|
||||
} from "./rmss_dice_roller_processing.js";
|
||||
|
||||
export default class RMSSToolsDiceRoller extends FormApplication {
|
||||
constructor(itemName, characterBonus) {
|
||||
constructor(item, actor) {
|
||||
super();
|
||||
this.itemName = itemName;
|
||||
this.characterBonus = characterBonus;
|
||||
this.item = foundry.utils.duplicate(item);
|
||||
this.actor = actor;
|
||||
this.itemName = item.name;
|
||||
this.characterBonus = Number(item.system.total_bonus);
|
||||
this.stunnedModifier = actor.getStunnedModifier()
|
||||
this.rollType = [
|
||||
{value: "one_to_onehundred", text: "1-100", selected: false},
|
||||
{value: "open_ended", text: "Open-Ended", selected: true},
|
||||
{value: "high_open_ended", text: "High Open-Ended", selected: false},
|
||||
{value: "low_open_ended", text: "Low Open-Ended", selected: false}
|
||||
{ value: "one_to_onehundred", text: "1-100", selected: false },
|
||||
{ value: "open_ended", text: "Open-Ended", selected: true },
|
||||
{ value: "high_open_ended", text: "High Open-Ended", selected: false },
|
||||
{ value: "low_open_ended", text: "Low Open-Ended", selected: false }
|
||||
];
|
||||
}
|
||||
|
||||
@ -30,8 +20,8 @@ export default class RMSSToolsDiceRoller extends FormApplication {
|
||||
classes: ["form"],
|
||||
title: "Rolemaster Dice Roller",
|
||||
popOut: true,
|
||||
width: 380,
|
||||
height: 210,
|
||||
width: 480,
|
||||
height: 440,
|
||||
template: "systems/fvtt-rolemaster-frp/templates/sheets/apps/app_dice_roller.html"
|
||||
});
|
||||
}
|
||||
@ -42,6 +32,15 @@ export default class RMSSToolsDiceRoller extends FormApplication {
|
||||
itemName: this.itemName,
|
||||
characterBonus: this.characterBonus,
|
||||
selectOptions: this.rollType,
|
||||
woundsModifier: this.actor.system.modifiers.woundsModifier,
|
||||
config: CONFIG.rmss,
|
||||
difficulty: 0,
|
||||
combatSituation: 0,
|
||||
lightningModifier: 0,
|
||||
darknessModifier: 0,
|
||||
hitsPerRound: 0,
|
||||
isStunned: this.actor.system.state.stunned,
|
||||
stunnedModifier: this.stunnedModifier
|
||||
};
|
||||
}
|
||||
|
||||
@ -53,33 +52,112 @@ export default class RMSSToolsDiceRoller extends FormApplication {
|
||||
console.log("Rolling Dice");
|
||||
console.log(formData);
|
||||
console.log(event);
|
||||
switch (formData.rollType) {
|
||||
case "one_to_onehundred":
|
||||
this.roll_one_to_onehundred();
|
||||
this.roll(event.submitter?.dataset?.value, formData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async showDiceSoNice(roll, rollMode) {
|
||||
if (game.modules.get("dice-so-nice")?.active) {
|
||||
if (game.dice3d) {
|
||||
let whisper = null;
|
||||
let blind = false;
|
||||
rollMode = rollMode ?? game.settings.get("core", "rollMode");
|
||||
switch (rollMode) {
|
||||
case "blindroll": //GM only
|
||||
blind = true;
|
||||
case "gmroll": //GM + rolling player
|
||||
whisper = this.getUsers(user => user.isGM);
|
||||
break;
|
||||
case "open_ended":
|
||||
this.roll_open_ended();
|
||||
case "roll": //everybody
|
||||
whisper = this.getUsers(user => user.active);
|
||||
break;
|
||||
case "high_open_ended":
|
||||
this.roll_high_open_ended();
|
||||
break;
|
||||
case "low_open_ended":
|
||||
this.roll_low_open_ended();
|
||||
case "selfroll":
|
||||
whisper = [game.user.id];
|
||||
break;
|
||||
}
|
||||
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async roll(rollKey, formData) {
|
||||
let baseRoll = await new Roll("1d100").roll();
|
||||
await this.showDiceSoNice(baseRoll, game.settings.get("core", "rollMode"))
|
||||
let rollType = this.rollType.find(r => r.value == rollKey)?.text;
|
||||
let rollData = {
|
||||
name: this.itemName,
|
||||
rollKey: rollKey,
|
||||
rollType: rollType,
|
||||
difficulty: Number(formData.difficulty),
|
||||
combatSituation: Number(formData?.combatSituation || 0),
|
||||
lightningModifier: Number(formData?.lightningModifier || 0),
|
||||
darknessModifier: Number(formData?.darknessModifier || 0),
|
||||
characterBonus: Number(this.characterBonus),
|
||||
woundsModifier: Number(this.actor.system.modifiers.woundsModifier),
|
||||
hitsPerRound: Number(formData.hitsPerRound),
|
||||
isStunned: this.actor.system.state.stunned,
|
||||
stunnedModifier: this.stunnedModifier,
|
||||
rolls: [baseRoll],
|
||||
}
|
||||
if (baseRoll.result == 66) {
|
||||
rollData.content = "You rolled a 66!";
|
||||
}
|
||||
// Process the for low open ended rolls
|
||||
if (rollKey === "open_ended" || rollKey === "low_open_ended") {
|
||||
if (baseRoll.result < 6) {
|
||||
rollData.lowopen = true
|
||||
let newRoll = await new Roll("-1d100").roll();
|
||||
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.rolls.push(newRoll);
|
||||
while (newRoll.result > 95) {
|
||||
newRoll = await new Roll("-1d100").roll();
|
||||
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.rolls.push(newRoll);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Process the for high open ended rolls
|
||||
if (rollKey === "open_ended" || rollKey === "high_open_ended") {
|
||||
if (baseRoll.result > 95) {
|
||||
rollData.highopen = true
|
||||
let newRoll = await new Roll("1d100").roll();
|
||||
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.rolls.push(newRoll);
|
||||
while (newRoll.result > 95) {
|
||||
newRoll = await new Roll("1d100").roll();
|
||||
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
|
||||
rollData.rolls.push(newRoll);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Compute total of rolls
|
||||
rollData.totalRolls = rollData.rolls.reduce((acc, roll) => Number(acc) + Number(roll.result), 0);
|
||||
rollData.totalFinal = rollData.totalRolls + Number(rollData.combatSituation) +
|
||||
Number(rollData.lightningModifier) +
|
||||
Number(rollData.darknessModifier) +
|
||||
Number(this.actor.system.modifiers.woundsModifier) +
|
||||
Number(formData.difficulty) +
|
||||
Number(rollData.hitsPerRound) +
|
||||
Number(rollData.stunnedModifier) +
|
||||
Number(this.characterBonus);
|
||||
console.log(">>> Roll Data: ", rollData);
|
||||
|
||||
// Define the Chat Message Template
|
||||
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
|
||||
|
||||
// Pass the Data through to be used in the Chat Message
|
||||
let chatData = rollData
|
||||
// Render the Rolls to the Chat Window
|
||||
renderTemplate(chatTemplate, chatData).then((html) => {
|
||||
let chatOptions = {
|
||||
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
|
||||
flavor: rollType,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: html,
|
||||
};
|
||||
ChatMessage.create(chatOptions);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RMSSToolsDiceRoller.prototype.roll_one_to_onehundred = roll_one_to_onehundred;
|
||||
RMSSToolsDiceRoller.prototype.roll_low_open_ended = roll_low_open_ended;
|
||||
RMSSToolsDiceRoller.prototype.roll_high_open_ended = roll_high_open_ended;
|
||||
RMSSToolsDiceRoller.prototype.roll_open_ended = roll_open_ended;
|
||||
|
||||
RMSSToolsDiceRoller.prototype.getOpenEndedRollModifier =
|
||||
getOpenEndedRollModifier;
|
||||
RMSSToolsDiceRoller.prototype.processOpenEndedSixtySixRoll =
|
||||
processOpenEndedSixtySixRoll;
|
||||
RMSSToolsDiceRoller.prototype.processOpenEndedRoll = processOpenEndedRoll;
|
||||
RMSSToolsDiceRoller.prototype.processHighOpenEndedRoll =
|
||||
processHighOpenEndedRoll;
|
||||
RMSSToolsDiceRoller.prototype.processLowOpenEndedRoll = processLowOpenEndedRoll;
|
||||
|
@ -1,131 +0,0 @@
|
||||
export async function getOpenEndedRollModifier() {
|
||||
return await new Roll("1d100x>95").roll();
|
||||
}
|
||||
|
||||
export function processOpenEndedSixtySixRoll(baseroll, rolltype) {
|
||||
// Log the Roll to Chat
|
||||
let chatOptions = {
|
||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
||||
rolls: [baseroll],
|
||||
flavor: rolltype,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: "You rolled a 66!",
|
||||
};
|
||||
|
||||
ChatMessage.create(chatOptions);
|
||||
}
|
||||
|
||||
export function processOpenEndedRoll(baseroll, rolltype) {
|
||||
// Define the Chat Message Template
|
||||
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
|
||||
|
||||
// Pass the Data through to be used in the Chat Message
|
||||
let chatData = {
|
||||
baseroll: baseroll,
|
||||
total: baseroll.result,
|
||||
highopen: false,
|
||||
lowopen: false,
|
||||
};
|
||||
|
||||
// Render the Rolls to the Chat Window
|
||||
renderTemplate(chatTemplate, chatData).then((html) => {
|
||||
let chatOptions = {
|
||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
||||
rolls: [baseroll],
|
||||
flavor: rolltype,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: html,
|
||||
};
|
||||
|
||||
ChatMessage.create(chatOptions);
|
||||
});
|
||||
}
|
||||
|
||||
export async function processHighOpenEndedRoll(baseroll, rolltype) {
|
||||
// Get the Base Roll followed by the High Open Ended Roll
|
||||
let originalRoll = baseroll;
|
||||
let openendedRoll = await this.getOpenEndedRollModifier();
|
||||
|
||||
// Create a rolls array for Dice So Nice integration.
|
||||
let rolls = [originalRoll, openendedRoll];
|
||||
|
||||
// Create an Array to hold the High Open Ended Roll Results and set the total to base roll
|
||||
let openendedResults = [];
|
||||
let total = Number(originalRoll.result);
|
||||
|
||||
// Each time the High Open Ended Roll is triggered add the result to an array and add it to the total.
|
||||
for (const rollResult of openendedRoll.dice[0].results) {
|
||||
openendedResults.push(rollResult.result);
|
||||
total = total + Number(rollResult.result);
|
||||
}
|
||||
|
||||
// Define the Chat Message Template
|
||||
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
|
||||
|
||||
// Pass the Data through to be used in the Chat Message
|
||||
let chatData = {
|
||||
baseroll: baseroll,
|
||||
opeendedresults: [openendedResults],
|
||||
highopen: true,
|
||||
lowopen: false,
|
||||
total: total,
|
||||
};
|
||||
|
||||
// Render the Rolls to the Chat Window
|
||||
renderTemplate(chatTemplate, chatData).then((html) => {
|
||||
let chatOptions = {
|
||||
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
|
||||
rolls: rolls,
|
||||
flavor: rolltype,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: html,
|
||||
};
|
||||
|
||||
ChatMessage.create(chatOptions);
|
||||
});
|
||||
}
|
||||
|
||||
export async function processLowOpenEndedRoll(baseroll, rolltype) {
|
||||
// Get the Base Roll followed by the Low Open Ended Roll
|
||||
let originalRoll = baseroll;
|
||||
let openendedRoll = await this.getOpenEndedRollModifier();
|
||||
|
||||
// Create a rolls array for Dice So Nice integration.
|
||||
let rolls = [originalRoll, openendedRoll];
|
||||
|
||||
// Create an Array to hold the Low Open Ended Roll Results and set the total to base roll
|
||||
let openendedResults = [];
|
||||
let total = Number(originalRoll.result);
|
||||
|
||||
// Each time the Low Open Ended Roll is triggered add the result to an array and subtract it from the total.
|
||||
for (const rollResult of openendedRoll.dice[0].results) {
|
||||
openendedResults.push(rollResult.result);
|
||||
total = total - Number(rollResult.result);
|
||||
}
|
||||
|
||||
// Define the Chat Message Template
|
||||
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
|
||||
|
||||
// Pass the Data through to be used in the Chat Message
|
||||
let chatData = {
|
||||
baseroll: baseroll,
|
||||
rolls: rolls,
|
||||
opeendedresults: [openendedResults],
|
||||
highopen: false,
|
||||
lowopen: true,
|
||||
total: total,
|
||||
};
|
||||
|
||||
// Render the Rolls to the Chat Window
|
||||
renderTemplate(chatTemplate, chatData).then((html) => {
|
||||
let chatOptions = {
|
||||
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
|
||||
rolls: rolls,
|
||||
flavor: rolltype,
|
||||
rollMode: game.settings.get("core", "rollMode"),
|
||||
content: html,
|
||||
};
|
||||
|
||||
ChatMessage.create(chatOptions);
|
||||
});
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
export async function roll_one_to_onehundred() {
|
||||
// Construct the Roll instance
|
||||
let baseroll = await new Roll("1d100 + @characterBonus", {characterBonus: this.characterBonus}).roll({async: true});
|
||||
let rolltype = "Roll Type: 1-100";
|
||||
|
||||
// Log the Roll to Chat
|
||||
let chatOptions = {
|
||||
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
|
||||
rolls: [baseroll],
|
||||
flavor: rolltype,
|
||||
rollMode: game.settings.get("core", "rollMode")
|
||||
};
|
||||
|
||||
ChatMessage.create(chatOptions);
|
||||
this.close();
|
||||
};
|
||||
|
||||
export async function roll_low_open_ended() {
|
||||
// Construct the Roll instance
|
||||
let baseroll = await new Roll("1d100").roll({async: true});
|
||||
console.log(baseroll.result);
|
||||
let rolltype = "Roll Type: Low Open-Ended";
|
||||
|
||||
switch (true) {
|
||||
case (baseroll.result < 6):
|
||||
this.processLowOpenEndedRoll(baseroll, rolltype);
|
||||
break;
|
||||
case (baseroll.result === 66):
|
||||
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
|
||||
break;
|
||||
default:
|
||||
this.processOpenEndedRoll(baseroll, rolltype);
|
||||
}
|
||||
}
|
||||
|
||||
export async function roll_high_open_ended() {
|
||||
// Construct the Roll instance
|
||||
let baseroll = await new Roll("1d100").roll({async: true});
|
||||
console.log(baseroll.result);
|
||||
let rolltype = "Roll Type: High Open-Ended";
|
||||
switch (true) {
|
||||
case (baseroll.result === 66):
|
||||
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
|
||||
break;
|
||||
case (baseroll.result > 95):
|
||||
this.processHighOpenEndedRoll(baseroll, rolltype);
|
||||
break;
|
||||
default:
|
||||
this.processOpenEndedRoll(baseroll, rolltype);
|
||||
}
|
||||
}
|
||||
|
||||
export async function roll_open_ended() {
|
||||
// Construct the Roll instance
|
||||
let baseroll = await new Roll("1d100").roll({async: true});
|
||||
console.log(baseroll.result);
|
||||
let rolltype = "Roll Type: Open-Ended";
|
||||
switch (true) {
|
||||
case (baseroll.result < 6):
|
||||
this.processLowOpenEndedRoll(baseroll, rolltype);
|
||||
break;
|
||||
case (baseroll.result === 66):
|
||||
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
|
||||
break;
|
||||
case (baseroll.result > 95):
|
||||
this.processHighOpenEndedRoll(baseroll, rolltype);
|
||||
break;
|
||||
default:
|
||||
this.processOpenEndedRoll(baseroll, rolltype);
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ export default class RMSSSkillSheet extends ItemSheet {
|
||||
async getData() {
|
||||
const baseData = await super.getData();
|
||||
|
||||
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
|
||||
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, { async: true });
|
||||
|
||||
// Get a list of the parent item's skill categories for the dropdown
|
||||
let ownedSkillCategories = this.prepareSkillCategoryValues();
|
||||
@ -51,16 +51,16 @@ export default class RMSSSkillSheet extends ItemSheet {
|
||||
html.find(".skillsheet-newrank").click(ev => {
|
||||
switch (ev.currentTarget.getAttribute("value")) {
|
||||
case "0":
|
||||
this.object.update({system: {new_ranks: { value: 1 }}});
|
||||
this.object.update({ system: { new_ranks: { value: 1 } } });
|
||||
break;
|
||||
case "1":
|
||||
this.object.update({system: {new_ranks: { value: 2 }}});
|
||||
this.object.update({ system: { new_ranks: { value: 2 } } });
|
||||
break;
|
||||
case "2":
|
||||
this.object.update({system: {new_ranks: { value: 3 }}});
|
||||
this.object.update({ system: { new_ranks: { value: 3 } } });
|
||||
break;
|
||||
case "3":
|
||||
this.object.update({system: {new_ranks: { value: 0 }}});
|
||||
this.object.update({ system: { new_ranks: { value: 0 } } });
|
||||
break;
|
||||
}
|
||||
});
|
||||
@ -70,13 +70,11 @@ export default class RMSSSkillSheet extends ItemSheet {
|
||||
// If this Skill is owned then we will return a list of Skill Categories and allow them to choose
|
||||
// Otherwise we'll just return 'Skill has no owner'
|
||||
prepareSkillCategoryValues() {
|
||||
let skillNoOwner = {None: "Skill Has No Owner"};
|
||||
let skillNoOwner = { None: "Skill Has No Owner" };
|
||||
|
||||
if (this.item.isEmbedded === null) {
|
||||
if (!this.item.isEmbedded) {
|
||||
return (skillNoOwner);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
const skillCategories = this.item.parent.getOwnedItemsByType("skill_category");
|
||||
return (skillCategories);
|
||||
}
|
||||
@ -100,8 +98,7 @@ export default class RMSSSkillSheet extends ItemSheet {
|
||||
if (this.item.isEmbedded === null) {
|
||||
console.log("Skill has no owner");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
const items = this.object.parent.items;
|
||||
|
||||
for (const item of items) {
|
||||
|
@ -1 +1 @@
|
||||
MANIFEST-000006
|
||||
MANIFEST-000056
|
||||
|
@ -1,8 +1,8 @@
|
||||
2024/07/26-13:01:33.184951 7f70fa0006c0 Recovering log #4
|
||||
2024/07/26-13:01:33.276590 7f70fa0006c0 Delete type=0 #4
|
||||
2024/07/26-13:01:33.276711 7f70fa0006c0 Delete type=3 #2
|
||||
2024/07/26-14:15:40.712242 7f70f3e006c0 Level-0 table #9: started
|
||||
2024/07/26-14:15:40.712297 7f70f3e006c0 Level-0 table #9: 0 bytes OK
|
||||
2024/07/26-14:15:40.750893 7f70f3e006c0 Delete type=0 #7
|
||||
2024/07/26-14:15:40.806643 7f70f3e006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/07/26-14:15:40.863267 7f70f3e006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/02-16:48:51.596152 7f2b120006c0 Recovering log #54
|
||||
2024/08/02-16:48:51.607028 7f2b120006c0 Delete type=3 #52
|
||||
2024/08/02-16:48:51.607119 7f2b120006c0 Delete type=0 #54
|
||||
2024/08/02-17:06:25.130824 7f2b110006c0 Level-0 table #59: started
|
||||
2024/08/02-17:06:25.130880 7f2b110006c0 Level-0 table #59: 0 bytes OK
|
||||
2024/08/02-17:06:25.137382 7f2b110006c0 Delete type=0 #57
|
||||
2024/08/02-17:06:25.160338 7f2b110006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/02-17:06:25.160385 7f2b110006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
|
@ -1,5 +1,8 @@
|
||||
2024/07/26-09:38:09.968297 7f70fa0006c0 Delete type=3 #1
|
||||
2024/07/26-09:40:38.576572 7f70f3e006c0 Level-0 table #5: started
|
||||
2024/07/26-09:40:38.595934 7f70f3e006c0 Level-0 table #5: 24247 bytes OK
|
||||
2024/07/26-09:40:38.633153 7f70f3e006c0 Delete type=0 #3
|
||||
2024/07/26-09:40:38.675601 7f70f3e006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/02-16:41:04.243624 7f2b134006c0 Recovering log #50
|
||||
2024/08/02-16:41:04.298794 7f2b134006c0 Delete type=3 #48
|
||||
2024/08/02-16:41:04.298940 7f2b134006c0 Delete type=0 #50
|
||||
2024/08/02-16:47:53.296999 7f2b110006c0 Level-0 table #55: started
|
||||
2024/08/02-16:47:53.297027 7f2b110006c0 Level-0 table #55: 0 bytes OK
|
||||
2024/08/02-16:47:53.302866 7f2b110006c0 Delete type=0 #53
|
||||
2024/08/02-16:47:53.310260 7f2b110006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/02-16:47:53.310311 7f2b110006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
BIN
packs/skill_categories/MANIFEST-000056
Normal file
BIN
packs/skill_categories/MANIFEST-000056
Normal file
Binary file not shown.
15
rmss.css
15
rmss.css
@ -41,6 +41,10 @@
|
||||
border-bottom: 1px solid;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
|
||||
}
|
||||
.skill-box {
|
||||
margin-left: 1.2rem;
|
||||
background-color: lightgrey;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
}
|
||||
@ -199,7 +203,6 @@
|
||||
padding-bottom: 3px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.skills-grid-container > div:nth-child(22n+1),
|
||||
@ -221,7 +224,6 @@
|
||||
padding-bottom: 3px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
|
||||
}
|
||||
@ -522,8 +524,13 @@
|
||||
}
|
||||
.roll-button-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.roll-button {
|
||||
margin-top: 2px;
|
||||
width: 96px;
|
||||
max-width: 96px;
|
||||
}
|
||||
.sheet form {
|
||||
display: flex;
|
||||
|
57
rmss.js
57
rmss.js
@ -52,7 +52,7 @@ async function preloadHandlebarsTemplates() {
|
||||
// registerGetSceneControlButtonsHook();
|
||||
|
||||
// Hook the init function and set up our system
|
||||
Hooks.once("init", function() {
|
||||
Hooks.once("init", function () {
|
||||
console.log("rmss | Initialising Rolemaster Standard System");
|
||||
|
||||
// Load our custom actor and item classes
|
||||
@ -74,7 +74,7 @@ Hooks.once("init", function() {
|
||||
CONFIG.fontDefinitions["PragRoman"] = {
|
||||
editor: true,
|
||||
fonts: [
|
||||
{urls: ["systems/fvtt-rolemaster-frp/assets/fonts/PragRoman.woff2"]}
|
||||
{ urls: ["systems/fvtt-rolemaster-frp/assets/fonts/PragRoman.woff2"] }
|
||||
]
|
||||
};
|
||||
|
||||
@ -91,35 +91,64 @@ Hooks.once("init", function() {
|
||||
console.log("rmss | Registering RMSS sheets");
|
||||
|
||||
// Items
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSItemSheet, {makeDefault: true, label: "rmss.entity_sheet.item", types: ["item"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSArmorSheet, {makeDefault: true, label: "rmss.entity_sheet.armor", types: ["armor"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSTransportSheet, {makeDefault: true, label: "rmss.entity_sheet.transport", types: ["transport"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSWeaponSheet, {makeDefault: true, label: "rmss.entity_sheet.weapon", types: ["weapon"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSHerbOrPoisonSheet, {makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ["herb_or_poison"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSItemSheet, { makeDefault: true, label: "rmss.entity_sheet.item", types: ["item"] });
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSArmorSheet, { makeDefault: true, label: "rmss.entity_sheet.armor", types: ["armor"] });
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSTransportSheet, { makeDefault: true, label: "rmss.entity_sheet.transport", types: ["transport"] });
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSWeaponSheet, { makeDefault: true, label: "rmss.entity_sheet.weapon", types: ["weapon"] });
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSHerbOrPoisonSheet, { makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ["herb_or_poison"] });
|
||||
|
||||
// Spells
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSpellSheet, {makeDefault: true, label: "rmss.entity_sheet.spell", types: ["spell"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSpellSheet, { makeDefault: true, label: "rmss.entity_sheet.spell", types: ["spell"] });
|
||||
|
||||
// Skills
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillCategorySheet, {makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ["skill_category"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillSheet, {makeDefault: true, label: "rmss.entity_sheet.skill", types: ["skill"]});
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillCategorySheet, { makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ["skill_category"] });
|
||||
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillSheet, { makeDefault: true, label: "rmss.entity_sheet.skill", types: ["skill"] });
|
||||
|
||||
// Actors
|
||||
Actors.registerSheet("fvtt-rolemaster-frp", RMSSPlayerSheet, {makeDefault: true, label: "rmss.entity_sheet.player_characrer", types: ["character"]});
|
||||
Actors.registerSheet("fvtt-rolemaster-frp", RMSSPlayerSheet, { makeDefault: true, label: "rmss.entity_sheet.player_characrer", types: ["character"] });
|
||||
|
||||
// Preload Handlebars Templates
|
||||
console.log("rmss | Preloading Handlebars Templates");
|
||||
preloadHandlebarsTemplates();
|
||||
|
||||
// Handlebars Helpers
|
||||
Handlebars.registerHelper("switch", function(value, options) {
|
||||
Handlebars.registerHelper('count', function (list) {
|
||||
return list.length;
|
||||
})
|
||||
Handlebars.registerHelper('includes', function (array, val) {
|
||||
return array.includes(val);
|
||||
})
|
||||
Handlebars.registerHelper('upper', function (text) {
|
||||
return text.toUpperCase();
|
||||
})
|
||||
Handlebars.registerHelper('lower', function (text) {
|
||||
return text.toLowerCase()
|
||||
})
|
||||
Handlebars.registerHelper('upperFirst', function (text) {
|
||||
if (typeof text !== 'string') return text
|
||||
return text.charAt(0).toUpperCase() + text.slice(1)
|
||||
})
|
||||
Handlebars.registerHelper('notEmpty', function (list) {
|
||||
return list.length > 0;
|
||||
})
|
||||
Handlebars.registerHelper('mul', function (a, b) {
|
||||
return parseInt(a) * parseInt(b);
|
||||
})
|
||||
Handlebars.registerHelper("switch", function (value, options) {
|
||||
this.switch_value = value;
|
||||
return options.fn(this);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("case", function(value, options) {
|
||||
Handlebars.registerHelper("case", function (value, options) {
|
||||
if (value === this.switch_value) {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
// Handle v12 removal of this helper
|
||||
Handlebars.registerHelper('select', function (selected, options) {
|
||||
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
|
||||
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
|
||||
const html = options.fn(this);
|
||||
return html.replace(rgx, "$& selected");
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "fvtt-rolemaster-frp",
|
||||
"id": "fvtt-rolemaster-frp",
|
||||
"title": "Rolemaster FRP System",
|
||||
"description": "The Rolemaster FRP system for FoundryVTT.",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/raw/branch/develop/rmss/system.json",
|
||||
"manifest": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/raw/branch/develop/system.json",
|
||||
"download": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/archive/v12.0.5.zip",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cynicide",
|
||||
@ -13,7 +14,7 @@
|
||||
"email": ""
|
||||
}
|
||||
],
|
||||
"version": "12.0.0",
|
||||
"version": "12.0.5",
|
||||
"compatibility": {
|
||||
"minimum": "12",
|
||||
"verified": "12"
|
||||
|
@ -222,6 +222,14 @@
|
||||
},
|
||||
"character": {
|
||||
"templates": ["background", "stats", "resistance_rolls", "armor_info", "fixed_info", "race_stat_fixed_info", "role_traits", "money", "description"],
|
||||
"modifiers": {
|
||||
"woundsModifier": 0
|
||||
},
|
||||
"state": {
|
||||
"stunned": false,
|
||||
"prone": false,
|
||||
"noparry": false
|
||||
},
|
||||
"attributes": {
|
||||
"level": {
|
||||
"value": 1
|
||||
@ -318,6 +326,7 @@
|
||||
"special_bonus_2": 0,
|
||||
"total_bonus": 0,
|
||||
"favorite": false,
|
||||
"bonus_progression": "standard",
|
||||
"designation": "None"
|
||||
},
|
||||
"skill_category": {
|
||||
@ -339,6 +348,7 @@
|
||||
"special_bonus_1": 0,
|
||||
"special_bonus_2": 0,
|
||||
"total_bonus": 0,
|
||||
"bonus_progression": "standard",
|
||||
"favorite": false
|
||||
},
|
||||
"spell": {
|
||||
|
@ -1,28 +1,70 @@
|
||||
<div class="dice-roll">
|
||||
<div class="dice-result">
|
||||
Original Roll:
|
||||
<h4 class="dice-total" >{{ baseroll.result }}</h4>
|
||||
Rolling for : {{name}}
|
||||
</div>
|
||||
{{#if highopen }}
|
||||
<div class=dice-result>
|
||||
Rolled over 95 - High Open-Ended!
|
||||
{{#each opeendedresults as |rollresult|}}
|
||||
<h4 class="dice-total" >{{ rollresult }}</h4>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if lowopen }}
|
||||
<div class=dice-result>
|
||||
Rolled under 6 - Low Open-Ended!
|
||||
{{#each opeendedresults as |rollresult|}}
|
||||
<h4 class="dice-total" >{{ rollresult }}</h4>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if difficulty}}
|
||||
<div class=dice-result>
|
||||
Difficulty : {{difficulty}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if combatSituation}}
|
||||
<div class=dice-result>
|
||||
Combat situation : {{combatSituation}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if stunnedModifier}}
|
||||
<div class=dice-result>
|
||||
Stunned : {{stunnedModifier}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if hitsPerRound}}
|
||||
<div class=dice-result>
|
||||
Hits/round malus : {{hitsPerRound}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if lightningModifier}}
|
||||
<div class=dice-result>
|
||||
Lightning modifierLight : {{lightningModifier}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if darknessModifier}}
|
||||
<div class=dice-result>
|
||||
Darkness modifierDark : {{darknessModifier}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if woundsModifier}}
|
||||
<div class="dice-result">
|
||||
<div>% of hits malus : {{woundsModifier}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="dice-result">
|
||||
Total:
|
||||
<h4 class="dice-total" >{{ total }}</h4>
|
||||
Total of d100 rolls:
|
||||
<h4 class="dice-total">{{totalRolls}}<br>
|
||||
({{#each rolls as |roll|}}{{roll.total}}{{#unless @last}}, {{/unless}}{{/each}})</h4>
|
||||
</div>
|
||||
<div class=dice-result>
|
||||
Character Bonus : {{characterBonus}}
|
||||
</div>
|
||||
|
||||
<div class="dice-result">
|
||||
Total :
|
||||
<h4 class="dice-total">{{totalFinal}}</h4>
|
||||
</div>
|
||||
</div>
|
@ -15,7 +15,10 @@
|
||||
<button type="button" class="import-skillcats" title="Import" acotr_id="">{{ localize "rmss.pc_sheet.import_skillcat" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#each skillcat as |skill_category id|}}
|
||||
<div class="skillcat-grid-container">
|
||||
|
||||
<div>{{skill_category.name}}</div>
|
||||
<div>{{skill_category.system.applicable_stats}}</div>
|
||||
<div>{{skill_category.system.development_cost}}</div>
|
||||
@ -39,5 +42,12 @@
|
||||
<a class="item-delete item" title="Delete Category" data-item-id="{{skill_category._id}}"><i class="fas fa-trash"></i></a>
|
||||
<a class="item-roll" title="Roll Check" data-item-id="{{skill_category._id}}"><i class="fas fa-dice"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if (count skill_category.skills)}}
|
||||
<div class="skill-box">
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html" }}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{/each}}
|
||||
</div>
|
@ -10,9 +10,12 @@
|
||||
<div class="skills-grid-heading">{{ localize "rmss.pc_sheet_skills.special_bonus" }}</div>
|
||||
<div class="skills-grid-heading">{{ localize "rmss.pc_sheet_skills.total_bonus" }}</div>
|
||||
<div class="skills-grid-heading">
|
||||
<!--<a class="item-create" title="Create Skill" data-type="skill"><i class="fas fa-plus"></i>{{ localize "rmss.pc_sheet_skills.add_skill" }}</a>-->
|
||||
<a class="item-create" title="Create Skill" data-type="skill"><i class="fas fa-plus"></i>{{ localize "rmss.pc_sheet_skills.add_skill" }}</a>
|
||||
</div>
|
||||
{{#each playerskill as |skill id|}}
|
||||
</div>
|
||||
|
||||
{{#each skills as |skill id|}}
|
||||
<div class="skills-grid-container">
|
||||
{{#if skill.system.favorite}}
|
||||
<div><a class="skill-favorite" data-item-id="{{skill._id}}"><i class="fa-regular fa-square-check"></i></a></div>
|
||||
{{else}}
|
||||
@ -35,9 +38,11 @@
|
||||
<div>{{skill.system.special_bonus_1}}</div>
|
||||
<div>{{skill.system.special_bonus_2}}</div>
|
||||
<div>{{skill.system.total_bonus}}</div>
|
||||
<div>
|
||||
<div >
|
||||
<a class="item-edit" title="Edit Skill" data-item-id="{{skill._id}}"><i class="fas fa-edit"></i></a>
|
||||
<a class="item-delete" title="Delete Skill" data-item-id="{{skill._id}}"><i class="fas fa-trash"></i></a>
|
||||
<a class="item-roll" title="Roll Check" data-item-id="{{skill._id}}"><i class="fas fa-dice"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{/each}}
|
||||
</div>
|
@ -19,6 +19,7 @@
|
||||
<div class="resource-entry">
|
||||
{{ localize "rmss.player_character.resources.hits" }}
|
||||
<h4><input name="system.attributes.hits.current" type="Number" value="{{system.attributes.hits.current}}"/>/<input name="system.attributes.hits.max" type="Number" value="{{system.attributes.hits.max}}"/></h4>
|
||||
<div>Wounds Modifier : {{system.modifiers.woundsModifier}}</div>
|
||||
</div>
|
||||
|
||||
<div class="resource-entry">
|
||||
@ -70,9 +71,9 @@
|
||||
{{!-- Default tab is specified in actor-sheet.mjs --}}
|
||||
<a class="item" data-tab="Record">{{ localize "rmss.pc_sheet_tabs.record" }}</a>
|
||||
<a class="item" data-tab="SkillCategory">{{ localize "rmss.pc_sheet_tabs.skill_categories" }}</a>
|
||||
<a class="item" data-tab="Skills">{{ localize "rmss.pc_sheet_tabs.skills" }}</a>
|
||||
<a class="item" data-tab="Equipment">{{ localize "rmss.pc_sheet_tabs.equipment" }}</a>
|
||||
<a class="item" data-tab="Spells">{{ localize "rmss.pc_sheet_tabs.spells" }}</a>
|
||||
<a class="item" data-tab="Background">{{ localize "rmss.pc_sheet_tabs.background" }}</a>
|
||||
<a class="item" data-tab="StatusRecord">{{ localize "rmss.pc_sheet_tabs.status_record" }}</a>
|
||||
<a class="item" data-tab="ExperiencePoints">{{ localize "rmss.pc_sheet_tabs.experience_points" }}</a>
|
||||
</nav>
|
||||
@ -84,14 +85,16 @@
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fixed-info.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-armor-info.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-resistance.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-race-stat-fixed-info.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-role-traits.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-background-info.html" }}
|
||||
</div>
|
||||
|
||||
<div class="stat-container">
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-stats.html" }}
|
||||
|
||||
<div class="favorite-container">
|
||||
<span class="label-name">Stunned : </span><input type="checkbox" name="system.state.stunned" {{checked system.state.stunned}}/>
|
||||
<span class="label-name">Prone : </span><input type="checkbox" name="system.state.prone" {{checked system.state.prone}}/>
|
||||
</div>
|
||||
|
||||
<div class="favorite-container">
|
||||
<h2>Favorite Skills</h2>
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-skills.html" }}
|
||||
@ -103,8 +106,6 @@
|
||||
{{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -112,10 +113,6 @@
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skill-categories.html" }}
|
||||
</div>
|
||||
|
||||
<div class="tab skills" data-group="primary" data-tab="Skills">
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html" }}
|
||||
</div>
|
||||
|
||||
<div class="tab equipment" data-group="primary" data-tab="Equipment">
|
||||
<div class="container">
|
||||
<div class="equipment-container">
|
||||
@ -140,6 +137,19 @@
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-spells.html" }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab background" data-group="primary" data-tab="Background">
|
||||
<div class="container">
|
||||
<div class="fixed-info-container">
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-race-stat-fixed-info.html" }}
|
||||
</div>
|
||||
<div class="fixed-info-container">
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-role-traits.html" }}
|
||||
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-background-info.html" }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</section>
|
||||
</form>
|
||||
|
||||
|
@ -2,26 +2,95 @@
|
||||
<div class="dice-roller-container">
|
||||
<div class="dice-roller-options">
|
||||
<div class="dice-roller-item">
|
||||
<div>Rolling for:</div><div>{{itemName}}</div>
|
||||
<div>Rolling for:</div>
|
||||
<div>{{itemName}}</div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<div>Character Bonus:</div><div>{{characterBonus}}</div>
|
||||
<div>Character Bonus:</div>
|
||||
<div>{{characterBonus}}</div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<div>Misc Bonus:</div><div><input name="miscBonus" value="0" /></div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<div>Select Roll Type:</div>
|
||||
<div>Difficulty:</div>
|
||||
<div>
|
||||
<select name="rollType" value="None" itemid="blah">
|
||||
{{#each selectOptions as |option|}}
|
||||
<option value="{{option.value}}" {{#if option.selected}}selected{{/if}}>{{option.text}}</option>
|
||||
{{/each}}
|
||||
<select name="difficulty">
|
||||
{{selectOptions config.difficulties selected="0" valueKey="value" labelKey="label"}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>% of hits taken malus:</div>
|
||||
<div>{{woundsModifier}}</div>
|
||||
</div>
|
||||
|
||||
{{#if isStunned}}
|
||||
<div class="dice-roller-item">
|
||||
<div>Stunned:</div>
|
||||
<div>{{stunnedModifier}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>Combat situations:</div>
|
||||
<div>
|
||||
<select name="combatSituation">
|
||||
{{#select combatSituation}}
|
||||
{{#each config.combatSituations as |situation|}}
|
||||
<option value="{{situation.modifier}}">{{situation.label}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>Hits/round taken:</div>
|
||||
<div>
|
||||
<select name="hitsPerRound">
|
||||
{{#select hitsPerRound}}
|
||||
{{#each config.hitsPerRound as |hit|}}
|
||||
<option value="{{hit.modifier}}">{{hit.label}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>Lightning, if required:</div>
|
||||
<div>
|
||||
<select name="lightningModifier">
|
||||
{{#select lightningModifier}}
|
||||
{{#each config.lightOrDarknessModifiers as |lightning|}}
|
||||
<option value="{{lightning.modifierLight}}">{{lightning.label}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>Darkness, if advantageous:</div>
|
||||
<div>
|
||||
<select name="darknessModifier">
|
||||
{{#select lightningModifier}}
|
||||
{{#each config.lightOrDarknessModifiers as |darkness|}}
|
||||
<option value="{{darkness.modifierDark}}">{{darkness.label}}</option>
|
||||
{{/each}}
|
||||
{{/select}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dice-roller-item">
|
||||
<div>Misc Bonus:</div>
|
||||
<div><input name="miscBonus" value="0" /></div>
|
||||
</div>
|
||||
<div class="roll-button-container">
|
||||
<button type="submit">Roll</button>
|
||||
{{#each selectOptions as |option|}}
|
||||
<button type="submit" class="roll-button" data-value="{{option.value}}">{{option.text}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -4,6 +4,11 @@
|
||||
<h1><input name="name" type="text" value="{{item.name}}" placeholder="{{ localize 'Name' }}"/></h1>
|
||||
</header>
|
||||
<div class="sheet-content">
|
||||
<div>Rank Bonus Progression
|
||||
<select name="system.bonus_progression" value="{{system.bonus_progression}}" itemid="{{ item._id }}">
|
||||
{{selectOptions config.rankBonusProgressionList selected=system.bonus_progression valueAttr="key" labelAttr="label"}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="applicable-stats-grid-container">
|
||||
<div>
|
||||
Applicable Stat 1
|
||||
|
@ -4,6 +4,11 @@
|
||||
<h1><input name="name" type="text" value="{{item.name}}" placeholder="{{ localize 'Name' }}"/></h1>
|
||||
</header>
|
||||
<div class="sheet-content">
|
||||
<div>Rank Bonus Progression
|
||||
<select name="system.bonus_progression" value="{{system.bonus_progression}}" itemid="{{ item._id }}">
|
||||
{{selectOptions config.rankBonusProgressionList selected=system.bonus_progression valueAttr="key" labelAttr="label"}}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
Skill Category
|
||||
<select name="system.category" class="app-stat-selector" value="{{system.category}}" itemid="{{ item._id }}">
|
||||
|
Reference in New Issue
Block a user