Compare commits
13 Commits
Author | SHA1 | Date | |
---|---|---|---|
c11f7d23a8 | |||
98e6b70b1b | |||
6597334682 | |||
534fcb04fb | |||
8be95c20bd | |||
cba4394a37 | |||
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:",
|
||||
|
@ -46,4 +46,8 @@
|
||||
font-weight: bold;
|
||||
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);
|
||||
}
|
||||
|
@ -27,4 +27,7 @@
|
||||
font-family: Signika, sans-serif;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.select-fixed-width {
|
||||
width: 100px;
|
||||
}
|
@ -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,66 @@ 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.gameSystems = [
|
||||
{key: "common", label:"Common"},
|
||||
{key: "merp", label:"Middle Earth Role Playing (MERP)"},
|
||||
{key: "rmfrp", label:"Rolemaster Fantasy Role Playing (RMFRP)"},
|
||||
];
|
||||
|
||||
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"},
|
||||
{key: "race", label:"Linked to Race"},
|
||||
]
|
||||
|
||||
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,51 +258,35 @@ 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) {
|
||||
// Apply the update if we found stat bonuses for every applicable stat
|
||||
item.system.stat_bonus = applicable_stat_bonus;
|
||||
|
||||
// Update the total in the Item
|
||||
item.calculateSkillCategoryTotalBonus(item);
|
||||
// Compute the total bonus for the applicable stats
|
||||
let applicable_stat_bonus = 0;
|
||||
for (const bonus of applicable_stat_bonuses) {
|
||||
applicable_stat_bonus += bonus;
|
||||
}
|
||||
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
|
||||
// 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 === 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);
|
||||
}
|
||||
// Update the total in the Item
|
||||
item.calculateSkillCategoryTotalBonus(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { RFRPUtility } from "../rfrp-utility.js";
|
||||
|
||||
export class RMSSItem extends Item {
|
||||
|
||||
/** @override */
|
||||
@ -100,21 +102,13 @@ export class RMSSItem extends Item {
|
||||
}
|
||||
|
||||
calculateSelectedSkillCategoryBonus(itemData) {
|
||||
if (this.isEmbedded === null) {
|
||||
console.log(`rmss | item.js | Skill ${this.name} has no owner. Not calculating Skill Category bonus`);
|
||||
}
|
||||
else
|
||||
{
|
||||
const items = this.parent?.items;
|
||||
console.log(`rmss | item.js | Skill ${this.name} has owner, calculating skill category bonus.`);
|
||||
if (items) {
|
||||
for (const item of items) {
|
||||
if (item.type === "skill_category" && item._id === itemData.system.category) {
|
||||
console.log(`rmss | item.js | Calculating Skill Category bonus for skill: ${this.name}`);
|
||||
this.system.category_bonus = item.system.total_bonus;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Find the relevant skill category
|
||||
let skillC = this.parent?.items || RFRPUtility.getSkillCategories();
|
||||
if (skillC) {
|
||||
let item = skillC.find(it => it.type == "skill_category" && it.name.toLowerCase() == itemData.system.category.toLowerCase());
|
||||
this.system.category_bonus = item.system.total_bonus;
|
||||
} else {
|
||||
ui.notifications.warn("No Skill Categories found. Please create a Skill Category.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
197
module/rfrp-utility.js
Normal file
197
module/rfrp-utility.js
Normal file
@ -0,0 +1,197 @@
|
||||
/* -------------------------------------------- */
|
||||
export class RFRPUtility {
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async init() {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async ready() {
|
||||
this.registerSettings();
|
||||
|
||||
this.gameSystem = game.settings.get("fvtt-rolemaster-frp", "game_system");
|
||||
|
||||
const skillCategories = await RFRPUtility.loadCompendium("fvtt-rolemaster-frp.skill_categories")
|
||||
this.skillCategories = skillCategories.map(i => i.toObject()).filter( i => i.system.game_system == "common" || i.system.game_system == this.gameSystem);
|
||||
// Sort skill categories by name
|
||||
this.skillCategories.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getSkillCategories() {
|
||||
return this.skillCategories
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static registerSettings() {
|
||||
game.settings.register("fvtt-rolemaster-frp", "game_system", {
|
||||
name: "Game System",
|
||||
hint: "List of Game Systems",
|
||||
scope: "world",
|
||||
default: "rmfrp",
|
||||
requiresReload: true,
|
||||
type: String,
|
||||
config: true,
|
||||
choices: {
|
||||
rmfrp: "Rolemaster Fantasy Role Playing (RMFRP)",
|
||||
merp: "Middle Earth Role Playing (MERP)"
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendiumData(compendium) {
|
||||
const pack = game.packs.get(compendium);
|
||||
return await pack?.getDocuments() ?? [];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendium(compendium, filter = item => true) {
|
||||
let compendiumData = await RFRPUtility.loadCompendiumData(compendium);
|
||||
return compendiumData.filter(filter);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static removeChatMessageId(messageId) {
|
||||
if (messageId) {
|
||||
game.messages.get(messageId)?.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static findChatMessageId(current) {
|
||||
return RFRPUtility.getChatMessageId(HeritiersUtility.findChatMessage(current));
|
||||
}
|
||||
|
||||
static getChatMessageId(node) {
|
||||
return node?.attributes.getNamedItem('data-message-id')?.value;
|
||||
}
|
||||
|
||||
static findChatMessage(current) {
|
||||
return RFRPUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'))
|
||||
}
|
||||
|
||||
static findNodeMatching(current, predicate) {
|
||||
if (current) {
|
||||
if (predicate(current)) {
|
||||
return current;
|
||||
}
|
||||
return RFRPUtility.findNodeMatching(current.parentElement, predicate);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getUsers(filter) {
|
||||
return game.users.filter(filter).map(user => user._id);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getWhisperRecipients(rollMode, name) {
|
||||
switch (rollMode) {
|
||||
case "blindroll": return this.getUsers(user => user.isGM);
|
||||
case "gmroll": return this.getWhisperRecipientsAndGMs(name);
|
||||
case "selfroll": return [game.user.id];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getWhisperRecipientsAndGMs(name) {
|
||||
let recep1 = ChatMessage.getWhisperRecipients(name) || [];
|
||||
return recep1.concat(ChatMessage.getWhisperRecipients('GM'));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static blindMessageToGM(chatOptions) {
|
||||
let chatGM = foundry.utils.duplicate(chatOptions);
|
||||
chatGM.whisper = this.getUsers(user => user.isGM);
|
||||
chatGM.content = "Blinde message of " + game.user.name + "<br>" + chatOptions.content;
|
||||
console.log("blindMessageToGM", chatGM);
|
||||
game.socket.emit("system.fvtt-rolemaster-frp", { msg: "msg_gm_chat_message", data: chatGM });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async searchItem(dataItem) {
|
||||
let item
|
||||
if (dataItem.pack) {
|
||||
let id = dataItem.id || dataItem._id
|
||||
let items = await this.loadCompendium(dataItem.pack, item => item.id == id)
|
||||
item = items[0] || undefined
|
||||
} else {
|
||||
item = game.items.get(dataItem.id)
|
||||
}
|
||||
return item
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static loadHandlebarsTemplates() {
|
||||
const templatePaths = [
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-stats.html",
|
||||
"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",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skill-categories.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-items.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-weapons.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-money.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skill-categories.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-armor.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-herbs.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-spells.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-spells.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-items.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/apps/app_skill_category_importer.html"
|
||||
];
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static loadHandlebarsHelpers() {
|
||||
|
||||
// Handlebars Helpers
|
||||
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) {
|
||||
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");
|
||||
});
|
||||
}
|
||||
}
|
@ -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.toLowerCase() === s.name.toLowerCase()) {
|
||||
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("ACTOR CONTEXT", 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();
|
||||
break;
|
||||
case "open_ended":
|
||||
this.roll_open_ended();
|
||||
break;
|
||||
case "high_open_ended":
|
||||
this.roll_high_open_ended();
|
||||
break;
|
||||
case "low_open_ended":
|
||||
this.roll_low_open_ended();
|
||||
break;
|
||||
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 "roll": //everybody
|
||||
whisper = this.getUsers(user => user.active);
|
||||
break;
|
||||
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);
|
||||
}
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
import { RFRPUtility } from "../../rfrp-utility.js";
|
||||
|
||||
// Our Item Sheet extends the default
|
||||
export default class RMSSSkillSheet extends ItemSheet {
|
||||
|
||||
@ -20,7 +22,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 +53,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,23 +72,20 @@ 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"};
|
||||
|
||||
if (this.item.isEmbedded === null) {
|
||||
return (skillNoOwner);
|
||||
}
|
||||
else
|
||||
{
|
||||
const skillCategories = this.item.parent.getOwnedItemsByType("skill_category");
|
||||
return (skillCategories);
|
||||
let skillCategories = RFRPUtility.getSkillCategories();
|
||||
if (this.item.isEmbedded) {
|
||||
skillCategories = this.item.parent.items.filter(it => it.type == "skill_category");
|
||||
}
|
||||
//console.log("CATEG", skillCategories);
|
||||
return (skillCategories);
|
||||
}
|
||||
|
||||
// Determine which Skill Category is selected and test that it is in the current list of categories.
|
||||
// If it isn't set it to None.
|
||||
prepareSelectedSkillCategory(ownedSkillCategories, selectedSkillCategory) {
|
||||
let defaultSelectedCategory = "None";
|
||||
if (Object.keys(ownedSkillCategories).includes(selectedSkillCategory)) {
|
||||
let skillC = ownedSkillCategories.find(it => it.name.toLowerCase() == selectedSkillCategory.toLowerCase());
|
||||
if (skillC) {
|
||||
return (selectedSkillCategory);
|
||||
} else {
|
||||
return (defaultSelectedCategory);
|
||||
@ -97,19 +96,14 @@ export default class RMSSSkillSheet extends ItemSheet {
|
||||
// Iterate through the owned skill categories and if one of them matches the item id of currently
|
||||
// selected skill category then set the Skill Category Bonus field to the Total Bonus field of the Skill Category
|
||||
prepareSelectedSkillCategoryBonus(selected_skillcat) {
|
||||
if (this.item.isEmbedded === null) {
|
||||
console.log("Skill has no owner");
|
||||
}
|
||||
else
|
||||
{
|
||||
const items = this.object.parent.items;
|
||||
|
||||
for (const item of items) {
|
||||
if (item.type === "skill_category" && item._id === selected_skillcat) {
|
||||
console.log(`rmss | rmss_skill_sheet | Calculating Skill Category bonus for skill: ${this.object.name}`);
|
||||
this.object.system.category_bonus = item.system.total_bonus;
|
||||
}
|
||||
let skillC = this.parent?.items || RFRPUtility.getSkillCategories();
|
||||
if (skillC) {
|
||||
let item = skillC.find(it => it.type == "skill_category" && it.name.toLowerCase() == itemData.system.category.toLowerCase());
|
||||
if (item) {
|
||||
this.system.category_bonus = item.system.total_bonus;
|
||||
return
|
||||
}
|
||||
}
|
||||
ui.notifications.warn("No Skill Categories found for " + this.name + ". Please create and link a Skill Category.");
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1 +1 @@
|
||||
MANIFEST-000006
|
||||
MANIFEST-000076
|
||||
|
@ -1,8 +1,15 @@
|
||||
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/08-04:58:23.767734 7f33996006c0 Recovering log #74
|
||||
2024/08/08-04:58:23.828546 7f33996006c0 Delete type=3 #72
|
||||
2024/08/08-04:58:23.828601 7f33996006c0 Delete type=0 #74
|
||||
2024/08/08-05:04:31.857707 7f33978006c0 Level-0 table #79: started
|
||||
2024/08/08-05:04:31.861026 7f33978006c0 Level-0 table #79: 24481 bytes OK
|
||||
2024/08/08-05:04:31.868635 7f33978006c0 Delete type=0 #77
|
||||
2024/08/08-05:04:31.903805 7f33978006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/08-05:04:31.903951 7f33978006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at '!items!yRIFroc5VC9Oj3qY' @ 136 : 1
|
||||
2024/08/08-05:04:31.903973 7f33978006c0 Compacting 1@1 + 1@2 files
|
||||
2024/08/08-05:04:31.907992 7f33978006c0 Generated table #80@1: 56 keys, 24845 bytes
|
||||
2024/08/08-05:04:31.908019 7f33978006c0 Compacted 1@1 + 1@2 files => 24845 bytes
|
||||
2024/08/08-05:04:31.914722 7f33978006c0 compacted to: files[ 0 0 1 0 0 0 0 ]
|
||||
2024/08/08-05:04:31.914879 7f33978006c0 Delete type=2 #5
|
||||
2024/08/08-05:04:31.915115 7f33978006c0 Delete type=2 #79
|
||||
2024/08/08-05:04:31.933903 7f33978006c0 Manual compaction at level-1 from '!items!yRIFroc5VC9Oj3qY' @ 136 : 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/07-23:07:46.117612 7f33982006c0 Recovering log #70
|
||||
2024/08/07-23:07:46.128384 7f33982006c0 Delete type=3 #68
|
||||
2024/08/07-23:07:46.128478 7f33982006c0 Delete type=0 #70
|
||||
2024/08/07-23:08:55.204549 7f33978006c0 Level-0 table #75: started
|
||||
2024/08/07-23:08:55.204589 7f33978006c0 Level-0 table #75: 0 bytes OK
|
||||
2024/08/07-23:08:55.210948 7f33978006c0 Delete type=0 #73
|
||||
2024/08/07-23:08:55.211205 7f33978006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
2024/08/07-23:08:55.238982 7f33978006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
|
||||
|
Binary file not shown.
18
rmss.css
18
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);
|
||||
}
|
||||
@ -492,6 +494,9 @@
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
.select-fixed-width {
|
||||
width: 100px;
|
||||
}
|
||||
.applicable-stats-grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: [app-stat-1] 33% [app-stat-2] 33% [app-stat-3] 33%;
|
||||
@ -522,8 +527,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;
|
||||
|
74
rmss.js
74
rmss.js
@ -19,40 +19,13 @@ import RMSSSkillSheet from "./module/sheets/skills/rmss_skill_sheet.js";
|
||||
import RMSSPlayerSheet from "./module/sheets/actors/rmss_player_sheet.js";
|
||||
import RMSSToolsSCImporter from "./module/sheets/apps/rmss_import_skill_categories.js";
|
||||
import RMSSToolsDiceRoller from "./module/sheets/apps/rmss_dice_roller.js";
|
||||
|
||||
/** Preload handlebars templates for character sheets */
|
||||
async function preloadHandlebarsTemplates() {
|
||||
const templatePaths = [
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-stats.html",
|
||||
"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",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skill-categories.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-items.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-weapons.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-money.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skill-categories.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-skills.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-armor.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-herbs.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-spells.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-spells.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-items.html",
|
||||
"systems/fvtt-rolemaster-frp/templates/sheets/apps/app_skill_category_importer.html"
|
||||
];
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
import { RFRPUtility } from "./module/rfrp-utility.js";
|
||||
|
||||
// Register Scene Controls
|
||||
// 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 +47,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 +64,30 @@ 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();
|
||||
RFRPUtility.loadHandlebarsTemplates();
|
||||
RFRPUtility.loadHandlebarsHelpers();
|
||||
|
||||
// Handlebars Helpers
|
||||
Handlebars.registerHelper("switch", function(value, options) {
|
||||
this.switch_value = value;
|
||||
return options.fn(this);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper("case", function(value, options) {
|
||||
if (value === this.switch_value) {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Hooks.once("ready", async function () {
|
||||
console.log("rmss | Ready");
|
||||
|
||||
// Load Utility
|
||||
await RFRPUtility.ready();
|
||||
})
|
||||
|
@ -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.10.zip",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Cynicide",
|
||||
@ -13,7 +14,7 @@
|
||||
"email": ""
|
||||
}
|
||||
],
|
||||
"version": "12.0.0",
|
||||
"version": "12.0.10",
|
||||
"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
|
||||
@ -305,6 +313,7 @@
|
||||
"skill": {
|
||||
"templates": ["base"],
|
||||
"category" : "",
|
||||
"game_system": "common",
|
||||
"ranks": 0,
|
||||
"new_ranks": {
|
||||
"value": 0,
|
||||
@ -318,11 +327,13 @@
|
||||
"special_bonus_2": 0,
|
||||
"total_bonus": 0,
|
||||
"favorite": false,
|
||||
"bonus_progression": "standard",
|
||||
"designation": "None"
|
||||
},
|
||||
"skill_category": {
|
||||
"templates": ["base"],
|
||||
"applicable_stats": "None",
|
||||
"game_system": "common",
|
||||
"app_stat_1": "None",
|
||||
"app_stat_2": "None",
|
||||
"app_stat_3": "None",
|
||||
@ -339,6 +350,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>
|
||||
</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}}
|
||||
<div class="dice-result">
|
||||
Rolling for : {{name}}
|
||||
</div>
|
||||
{{#if highopen }}
|
||||
<div class=dice-result>
|
||||
Rolled over 95 - High Open-Ended!
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if lowopen }}
|
||||
<div class=dice-result>
|
||||
Rolled under 6 - Low Open-Ended!
|
||||
</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}}
|
||||
|
||||
<div class="dice-result">
|
||||
Total:
|
||||
<h4 class="dice-total" >{{ total }}</h4>
|
||||
</div>
|
||||
{{#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 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,10 +10,13 @@
|
||||
<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|}}
|
||||
{{#if skill.system.favorite}}
|
||||
</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}}
|
||||
<div><a class="skill-favorite" data-item-id="{{skill._id}}"><i class="fa-regular fa-square"></i></a></div>
|
||||
@ -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>
|
||||
|
||||
|
@ -1,27 +1,96 @@
|
||||
<form>
|
||||
<div class="dice-roller-container">
|
||||
<div class="dice-roller-options">
|
||||
<div class="dice-roller-item">
|
||||
<div>Rolling for:</div><div>{{itemName}}</div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<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>
|
||||
<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>
|
||||
</div>
|
||||
<div class="dice-roller-container">
|
||||
<div class="dice-roller-options">
|
||||
<div class="dice-roller-item">
|
||||
<div>Rolling for:</div>
|
||||
<div>{{itemName}}</div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<div>Character Bonus:</div>
|
||||
<div>{{characterBonus}}</div>
|
||||
</div>
|
||||
<div class="dice-roller-item">
|
||||
<div>Difficulty:</div>
|
||||
<div>
|
||||
<select name="difficulty">
|
||||
{{selectOptions config.difficulties selected="0" valueKey="value" labelKey="label"}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="roll-button-container">
|
||||
<button type="submit">Roll</button>
|
||||
</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">
|
||||
{{#each selectOptions as |option|}}
|
||||
<button type="submit" class="roll-button" data-value="{{option.value}}">{{option.text}}</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
@ -4,7 +4,19 @@
|
||||
<h1><input name="name" type="text" value="{{item.name}}" placeholder="{{ localize 'Name' }}"/></h1>
|
||||
</header>
|
||||
<div class="sheet-content">
|
||||
<div class="applicable-stats-grid-container">
|
||||
<div class="flexrow">
|
||||
<div>Rank Bonus Progression
|
||||
<select class="select-fixed-width" 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>Game system
|
||||
<select class="select-fixed-width" name="system.game_system" value="{{system.game_system}}" itemid="{{ item._id }}">
|
||||
{{selectOptions config.gameSystems selected=system.game_system valueAttr="key" labelAttr="label"}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="applicable-stats-grid-container">
|
||||
<div>
|
||||
Applicable Stat 1
|
||||
<select name="system.app_stat_1" class="app-stat-selector" value="{{system.app_stat_1}}" itemid="{{ item._id }}">
|
||||
|
@ -4,10 +4,22 @@
|
||||
<h1><input name="name" type="text" value="{{item.name}}" placeholder="{{ localize 'Name' }}"/></h1>
|
||||
</header>
|
||||
<div class="sheet-content">
|
||||
<div>
|
||||
<div class="flexrow">
|
||||
<div>Rank Bonus Progression
|
||||
<select class="select-fixed-width" 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>Game system
|
||||
<select class="select-fixed-width" name="system.game_system" value="{{system.game_system}}" itemid="{{ item._id }}">
|
||||
{{selectOptions config.gameSystems selected=system.game_system valueAttr="key" labelAttr="label"}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
Skill Category
|
||||
<select name="system.category" class="app-stat-selector" value="{{system.category}}" itemid="{{ item._id }}">
|
||||
{{selectOptions owned_skillcats selected=selected_skillcat }}
|
||||
<select name="system.category" class="app-stat-selector" value="{{system.category}}">
|
||||
{{selectOptions owned_skillcats selected=selected_skillcat nameAttr="name" valueAttr="name" labelAttr="name"}}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
|
Reference in New Issue
Block a user