Added system to skill category import

Initial Exhaustion Calculations
Fix for Skill Categories with two stats
Added Racial Bonuses for Resistances
This commit is contained in:
Anthony Murphy
2022-10-25 22:03:59 +11:00
parent 8bc535cf35
commit 53c5b2ee6e
33 changed files with 1432 additions and 1065 deletions

4
rmss/.gitignore vendored
View File

@ -1 +1,3 @@
node_modules/
node_modules/
.jshintrc
.eslintrc

View File

@ -0,0 +1 @@
<svg style="height: 512px; width: 512px;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g class="" style="" transform="translate(0,0)"><path d="M488 348.78h-70.24l-15.1 87.44-48.78-87.44H169v-50h190v-157h129zm-145-273v207H158.13l-48.79 87.47-15.11-87.47H24v-207zM136.724 215.324c0-10.139-12.257-15.214-19.425-8.046-7.168 7.168-2.093 19.426 8.046 19.426 6.285 0 11.38-5.095 11.38-11.38zm60.945 0c-.068-10.12-12.32-15.122-19.452-7.943-7.131 7.18-2.047 19.399 8.073 19.399 6.314 0 11.422-5.141 11.38-11.456zm60.945 0c0-10.139-12.257-15.214-19.425-8.046-7.169 7.168-2.093 19.426 8.046 19.426 6.284 0 11.38-5.095 11.38-11.38z" fill="#fff" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 680 B

View File

@ -33,6 +33,9 @@
"stat_total": "Total"
}
},
"pc_sheet": {
"import_skillcat": "Import"
},
"pc_sheet_tabs": {
"record": "Record",
"skill_categories": "Skill Categories",
@ -128,10 +131,11 @@
"prof_bonus": "Prof Bonus",
"special_bonus": "Special Bonus",
"total_bonus": "Total Bonus",
"add_skillcat": "Add Skill Category"
"import_skillcat": "Import Skill Categories"
},
"pc_sheet_items": {
"equipped": "Equipped",
"worn": "Worn",
"favorite": "Favorite",
"quantity": "Quantity",
"item_name": "Item Name",
@ -149,6 +153,11 @@
"range": "Range",
"type": "Type"
},
"pc_sheet_language": {
"name": "Name",
"spoken": "Spoken",
"written": "Written"
},
"entity_sheet": {
"spell": "RMSS Spell",
"weapon": "RMSS Weapon",
@ -171,6 +180,7 @@
"cp": "Copper Pieces"
},
"item": {
"worn": "Worn",
"description": "Other Notes",
"quantity": "Quantity",
"weight": "Weight",
@ -245,6 +255,11 @@
"special_bonus_2": "Special Bonus 2:",
"total_bonus": "Total Bonus:",
"description": "Description:"
},
"language": {
"spoken": "Spoken",
"written": "Written",
"description": "Description"
}
}
}

View File

@ -1,6 +1,6 @@
.items-grid-container {
display: grid;
grid-template-columns: [name] 30% [quantity] 17% [weight] 17% [cost] 18% [controls] 18%;
grid-template-columns: [worn] 10% [name] 30% [quantity] 15% [weight] 15% [cost] 15% [controls] 15%;
}
.items-grid-container > div {
@ -16,11 +16,12 @@
justify-content: center;
}
.items-grid-container > div:nth-child(10n+1),
.items-grid-container > div:nth-child(10n+2),
.items-grid-container > div:nth-child(10n+3),
.items-grid-container > div:nth-child(10n+4),
.items-grid-container > div:nth-child(10n+5)
.items-grid-container > div:nth-child(12n+1),
.items-grid-container > div:nth-child(12n+2),
.items-grid-container > div:nth-child(12n+3),
.items-grid-container > div:nth-child(12n+4),
.items-grid-container > div:nth-child(12n+5),
.items-grid-container > div:nth-child(12n+6)
{
font-family: Signika, sans-serif;
font-size: 12px;

View File

@ -0,0 +1,18 @@
.resistances-grid-container {
outline: 1px solid; /* use instead of border */
margin-top: 1px;
margin-left: 1px;
padding: 5px;
display: grid;
grid-template-columns: [Name] 40% [Value] 20% [Race_Mod] 20% [Total] 20%;
}
.resistances-grid-heading {
font-weight: bold;
border-bottom: 1px solid;
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
}
.resistance-input {
width: 50%
}

View File

@ -27,6 +27,12 @@
padding: 1px;
}
.settings-button, .playersheet-settings {
font-family: Signika, sans-serif;
font-size: 12px;
margin-right: 6px
}
// Resource Elements in Headers
.resource-container {
@ -133,6 +139,7 @@
padding: 5px;
}
// Remove Me
.resistance-block {
outline: 1px solid; /* use instead of border */
margin-top: 1px;

View File

@ -9,6 +9,7 @@
@import "./actor-sheet/actor-sheet-armor.less";
@import "./actor-sheet/actor-sheet-herbs.less";
@import "./actor-sheet/actor-sheet-spells.less";
@import "./actor-sheet/actor-sheet-resistances.less";
//Skill Category Sheet

View File

@ -1,11 +1,11 @@
.skillcat-name, .skill-name, .item-name, .spell-name, .equipable-name{
.skillcat-name, .skill-name, .item-name, .spell-name, .equipable-name {
font-family: Signika, sans-serif;
font-size: 12px;
font-weight: bold;
text-align: center;
}
.skillcat-entry, .skill-entry, .item-entry, .spell-entry, .equipable-entry{
.skillcat-entry, .skill-entry, .item-entry, .spell-entry, .equipable-entry {
font-family: Signika, sans-serif;
font-size: 12px;
text-align: center;

View File

@ -1,60 +1,60 @@
export const rmss = {};
rmss.curreny_type = {
mp: "rmss.curreny_type.mp",
pp: "rmss.curreny_type.pp",
gp: "rmss.curreny_type.gp",
sp: "rmss.curreny_type.sp",
bp: "rmss.curreny_type.bp",
cp: "rmss.curreny_type.cp"
mp: "rmss.curreny_type.mp",
pp: "rmss.curreny_type.pp",
gp: "rmss.curreny_type.gp",
sp: "rmss.curreny_type.sp",
bp: "rmss.curreny_type.bp",
cp: "rmss.curreny_type.cp"
};
rmss.stats = {
agility: {
fullname: "Agility",
shortname: "Ag"
},
constitution: {
fullname: "Constitution",
shortname: "Co"
},
memory: {
fullname: "Memory",
shortname: "Me"
},
reasoning: {
fullname: "Reasoning",
shortname: "Re"
},
self_discipline: {
fullname: "Self Discipline",
shortname: "SD"
},
empathy: {
fullname: "Empathy",
shortname: "Em"
},
intuition: {
fullname: "Intuition",
shortname: "In"
},
presence: {
fullname: "Presence",
shortname: "Pr"
},
quickness: {
fullname: "Quickness",
shortname: "Qu"
},
strength: {
fullname: "Strength",
shortname: "St"
}
agility: {
fullname: "Agility",
shortname: "Ag"
},
constitution: {
fullname: "Constitution",
shortname: "Co"
},
memory: {
fullname: "Memory",
shortname: "Me"
},
reasoning: {
fullname: "Reasoning",
shortname: "Re"
},
self_discipline: {
fullname: "Self Discipline",
shortname: "SD"
},
empathy: {
fullname: "Empathy",
shortname: "Em"
},
intuition: {
fullname: "Intuition",
shortname: "In"
},
presence: {
fullname: "Presence",
shortname: "Pr"
},
quickness: {
fullname: "Quickness",
shortname: "Qu"
},
strength: {
fullname: "Strength",
shortname: "St"
}
};
rmss.skill_designations = {
None: "None",
Occupational: "Occupational",
Everyman: "Everyman",
Restricted: "Restricted"
None: "None",
Occupational: "Occupational",
Everyman: "Everyman",
Restricted: "Restricted"
};

View File

@ -1,5 +1,5 @@
export class RMSSActor extends Actor {
/** @override */
prepareData() {
// Prepare data for the actor. Calling the super version of this executes
@ -8,83 +8,157 @@ export class RMSSActor extends Actor {
// prepareDerivedData().
super.prepareData();
}
prepareDerivedData() {
const actorData = this;
const systemData = actorData.system;
const flags = actorData.flags.rmss || {};
// Make separate methods for each Actor type (character, npc, etc.) to keep
// things organized.
this._prepareCharacterData(actorData);
this._prepareNpcData(actorData);
}
/**
* Prepare Character type specific data
*/
* Prepare Character specific data.
* @param {Actor} actorData The NPC Object to prepare data for
*/
_prepareCharacterData(actorData) {
if (actorData.type !== 'character') return;
if (actorData.type !== "character") return;
// Calculate Stat Bonuses for the Actor
this.calculateStatBonuses(actorData);
// Calculate Resistance Rolls for the Actor
this.calculateResistanceRolls(actorData);
// Iterate through and apply Stat bonuses for Skill Category Items
this.calculateSkillCategoryStatBonuses();
// Iterate through and apply Skill Category Bonuses for Skill items
this.calculateSkillBonuses();
}
/**
* Prepare NPC type specific data.
*/
* Prepare NPC specific data.
* @param {Actor} actorData The NPC Object to prepare data for
*/
_prepareNpcData(actorData) {
if (actorData.type !== 'npc') return;
if (actorData.type !== "npc") return;
// Make modifications to data here. For example:
const data = actorData.data;
}
// Tally each stat bonus and populate the total field.
// Tally each stat bonus and populate the total field.
calculateStatBonuses(actorData) {
const systemData = actorData.system;
actorData.system.stats.agility.stat_bonus = Number(systemData.stats.agility.racial_bonus)+Number(systemData.stats.agility.special_bonus)+Number(systemData.stats.agility.basic_bonus);
actorData.system.stats.constitution.stat_bonus = Number(systemData.stats.constitution.racial_bonus)+Number(systemData.stats.constitution.special_bonus)+Number(systemData.stats.constitution.basic_bonus);
actorData.system.stats.memory.stat_bonus = Number(systemData.stats.memory.racial_bonus)+Number(systemData.stats.memory.special_bonus)+Number(systemData.stats.memory.basic_bonus);
actorData.system.stats.reasoning.stat_bonus = Number(systemData.stats.reasoning.racial_bonus)+Number(systemData.stats.reasoning.special_bonus)+Number(systemData.stats.reasoning.basic_bonus);
actorData.system.stats.self_discipline.stat_bonus = Number(systemData.stats.self_discipline.racial_bonus)+Number(systemData.stats.self_discipline.special_bonus)+Number(systemData.stats.self_discipline.basic_bonus);
actorData.system.stats.empathy.stat_bonus = Number(systemData.stats.empathy.racial_bonus)+Number(systemData.stats.empathy.special_bonus)+Number(systemData.stats.empathy.basic_bonus);
actorData.system.stats.intuition.stat_bonus = Number(systemData.stats.intuition.racial_bonus)+Number(systemData.stats.intuition.special_bonus)+Number(systemData.stats.intuition.basic_bonus);
actorData.system.stats.presence.stat_bonus = Number(systemData.stats.presence.racial_bonus)+Number(systemData.stats.presence.special_bonus)+Number(systemData.stats.presence.basic_bonus);
actorData.system.stats.quickness.stat_bonus = Number(systemData.stats.quickness.racial_bonus)+Number(systemData.stats.quickness.special_bonus)+Number(systemData.stats.quickness.basic_bonus);
actorData.system.stats.strength.stat_bonus = Number(systemData.stats.strength.racial_bonus)+Number(systemData.stats.strength.special_bonus)+Number(systemData.stats.strength.basic_bonus);
actorData.system.stats.agility.stat_bonus = Number(systemData.stats.agility.racial_bonus)
+ Number(systemData.stats.agility.special_bonus)
+ Number(systemData.stats.agility.basic_bonus);
actorData.system.stats.constitution.stat_bonus = Number(systemData.stats.constitution.racial_bonus)
+ Number(systemData.stats.constitution.special_bonus)
+ Number(systemData.stats.constitution.basic_bonus);
actorData.system.stats.memory.stat_bonus = Number(systemData.stats.memory.racial_bonus)
+ Number(systemData.stats.memory.special_bonus)
+ Number(systemData.stats.memory.basic_bonus);
actorData.system.stats.reasoning.stat_bonus = Number(systemData.stats.reasoning.racial_bonus)
+ Number(systemData.stats.reasoning.special_bonus)
+ Number(systemData.stats.reasoning.basic_bonus);
actorData.system.stats.self_discipline.stat_bonus = Number(systemData.stats.self_discipline.racial_bonus)
+ Number(systemData.stats.self_discipline.special_bonus)
+ Number(systemData.stats.self_discipline.basic_bonus);
actorData.system.stats.empathy.stat_bonus = Number(systemData.stats.empathy.racial_bonus)
+ Number(systemData.stats.empathy.special_bonus)
+ Number(systemData.stats.empathy.basic_bonus);
actorData.system.stats.intuition.stat_bonus = Number(systemData.stats.intuition.racial_bonus)
+ Number(systemData.stats.intuition.special_bonus)
+ Number(systemData.stats.intuition.basic_bonus);
actorData.system.stats.presence.stat_bonus = Number(systemData.stats.presence.racial_bonus)
+ Number(systemData.stats.presence.special_bonus)
+ Number(systemData.stats.presence.basic_bonus);
actorData.system.stats.quickness.stat_bonus = Number(systemData.stats.quickness.racial_bonus)
+ Number(systemData.stats.quickness.special_bonus)
+ Number(systemData.stats.quickness.basic_bonus);
actorData.system.stats.strength.stat_bonus = Number(systemData.stats.strength.racial_bonus)
+ Number(systemData.stats.strength.special_bonus)
+ Number(systemData.stats.strength.basic_bonus);
}
// Calculate each Resistance Roll with the formula on the character sheet.
calculateResistanceRolls(actorData) { // TODO: Add Racial modifiers to resistance
// Calculate each Resistance Roll with the formula on the character sheet.
calculateResistanceRolls(actorData) {
const systemData = actorData.system;
actorData.system.resistance_rolls.essence = Number(systemData.stats.empathy.stat_bonus * 3);
actorData.system.resistance_rolls.channeling = Number(systemData.stats.intuition.stat_bonus * 3);
actorData.system.resistance_rolls.mentalism = Number(systemData.stats.presence.stat_bonus * 3);
actorData.system.resistance_rolls.fear = Number(systemData.stats.self_discipline.stat_bonus * 3);
actorData.system.resistance_rolls.poison_disease = Number(systemData.stats.constitution.stat_bonus * 3);
actorData.system.resistance_rolls.chann_ess = Number(systemData.stats.intuition.stat_bonus) + Number(systemData.stats.empathy.stat_bonus);
actorData.system.resistance_rolls.chann_ment = Number(systemData.stats.intuition.stat_bonus) + Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.ess_ment = Number(systemData.stats.empathy.stat_bonus) + Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.arcane = Number(systemData.stats.empathy.stat_bonus) + Number(systemData.stats.intuition.stat_bonus) + Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.essence.value = Number(systemData.stats.empathy.stat_bonus * 3);
actorData.system.resistance_rolls.channeling.value = Number(systemData.stats.intuition.stat_bonus * 3);
actorData.system.resistance_rolls.mentalism.value = Number(systemData.stats.presence.stat_bonus * 3);
actorData.system.resistance_rolls.fear.value = Number(systemData.stats.self_discipline.stat_bonus * 3);
actorData.system.resistance_rolls.poison_disease.value = Number(systemData.stats.constitution.stat_bonus * 3);
actorData.system.resistance_rolls.chann_ess.value = Number(systemData.stats.intuition.stat_bonus)
+ Number(systemData.stats.empathy.stat_bonus);
actorData.system.resistance_rolls.chann_ment.value = Number(systemData.stats.intuition.stat_bonus)
+ Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.ess_ment.value = Number(systemData.stats.empathy.stat_bonus)
+ Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.arcane.value = Number(systemData.stats.empathy.stat_bonus)
+ Number(systemData.stats.intuition.stat_bonus)
+ Number(systemData.stats.presence.stat_bonus);
actorData.system.resistance_rolls.essence.total = actorData.system.resistance_rolls.essence.value
+ actorData.system.resistance_rolls.essence.race_mod;
actorData.system.resistance_rolls.channeling.total = actorData.system.resistance_rolls.channeling.value
+ actorData.system.resistance_rolls.channeling.race_mod;
actorData.system.resistance_rolls.mentalism.total = actorData.system.resistance_rolls.mentalism.value
+ actorData.system.resistance_rolls.mentalism.race_mod;
actorData.system.resistance_rolls.fear.total = actorData.system.resistance_rolls.fear.value
+ actorData.system.resistance_rolls.fear.race_mod;
actorData.system.resistance_rolls.poison_disease.total = actorData.system.resistance_rolls.poison_disease.value
+ actorData.system.resistance_rolls.poison_disease.race_mod;
actorData.system.resistance_rolls.chann_ess.total = actorData.system.resistance_rolls.chann_ess.value
+ actorData.system.resistance_rolls.chann_ess.race_mod;
actorData.system.resistance_rolls.chann_ment.total = actorData.system.resistance_rolls.chann_ment.value
+ actorData.system.resistance_rolls.chann_ment.race_mod;
actorData.system.resistance_rolls.ess_ment.total = actorData.system.resistance_rolls.ess_ment.value
+ actorData.system.resistance_rolls.ess_ment.race_mod;
actorData.system.resistance_rolls.arcane.total = actorData.system.resistance_rolls.arcane.value
+ actorData.system.resistance_rolls.arcane.race_mod;
}
calculateSkillBonuses() {
for (const item of this.items) {
if (item.type === "skill") {
console.log("rmss | actor.js | Calculating skill bonus for Skill: " + item.name);
console.log("rmss | actor.js | Updating Skill Category Bonus for Skill: " + item.name);
console.log(`rmss | actor.js | Calculating skill bonus for Skill: ${item.name}`);
console.log(`rmss | actor.js | Updating Skill Category Bonus for Skill: ${item.name}`);
item.calculateSelectedSkillCategoryBonus(item);
console.log("rmss | actor.js | Updating Skill Total Bonus for Skill: " + item.name);
console.log(`rmss | actor.js | Updating Skill Total Bonus for Skill: ${item.name}`);
item.calculateSkillTotalBonus(item);
}
}
@ -94,25 +168,25 @@ export class RMSSActor extends Actor {
calculateSkillCategoryStatBonuses() {
for (const item of this.items) {
if (item.type === "skill_category") {
console.log("rmss | actor.js | Calculating Skill Category Stat Bonuses for: " + item.name);
// Get all the applicable stats for this skill category
var app_stat_1 = item.system.app_stat_1;
var app_stat_2 = item.system.app_stat_2;
var app_stat_3 = item.system.app_stat_3;
console.log(`rmss | actor.js | Calculating Skill Category Stat Bonuses for: ${item.name}`);
// Get all the applicable stats for this skill category
let app_stat_1 = item.system.app_stat_1;
let app_stat_2 = item.system.app_stat_2;
let app_stat_3 = item.system.app_stat_3;
// If the first one is None we don't need to do anything further
if (app_stat_1 === "None") {
continue;
}
else
{
var applicable_stat_bonus = 0;
var app_stat_1_found = false;
var app_stat_2_found = false;
var app_stat_3_found = false;
}
else
{
let applicable_stat_bonus = 0;
let app_stat_1_found = false;
let app_stat_2_found = false;
let app_stat_3_found = false;
// 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
@ -130,11 +204,25 @@ export class RMSSActor extends Actor {
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus;
}
}
//console.log("Applicable Stat Bonus: " + applicable_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);
}
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);
}
@ -148,15 +236,13 @@ export class RMSSActor extends Actor {
// This is the format that the select helper on the skill sheet needs
getOwnedItemsByType(item_type) {
var ownedItems = {None: "None"};
console.log("rmss | actor.js | Getting owned " + item_type + " for: " + this.name);
for (const item of this.items) {
let ownedItems = {None: "None"};
console.log(`rmss | actor.js | Getting owned ${item_type} for: ${this.name}`);
for (const item of this.items) {
if (item.type === item_type) {
ownedItems[item._id] = item.name;
}
}
return(ownedItems);
return (ownedItems);
}
}
}

View File

@ -1,117 +1,118 @@
export class RMSSItem extends Item {
export class RMSSItem extends Item {
/** @override */
prepareData() {
// Prepare data for the item. Calling the super version of this executes
// the following, in order: data reset (to clear active effects),
// prepareBaseData(), prepareEmbeddedDocuments() (including active effects),
// prepareDerivedData().
console.log("rmss | item.js | prepareData for:" + this.name);
super.prepareData();
}
/** @override */
prepareData() {
// Prepare data for the item. Calling the super version of this executes
// the following, in order: data reset (to clear active effects),
// prepareBaseData(), prepareEmbeddedDocuments() (including active effects),
// prepareDerivedData().
console.log(`rmss | item.js | prepareData for: ${this.name}`);
super.prepareData();
}
// Set the icon images for newly created images.
async _preCreate(data, options, userId) {
await super._preCreate(data, options, userId);
// Do not set on copied items if they have a custom Icon.
if (!data.name.includes("(Copy)"))
{
if (this.type == "armor") {
await this.updateSource({img: "systems/rmss/assets/default/armor.svg"});
}
else if (this.type == "weapon") {
await this.updateSource({img: "systems/rmss/assets/default/weapon.svg"});
}
else if (this.type == "skill") {
await this.updateSource({img: "systems/rmss/assets/default/skill.svg"});
}
else if (this.type == "skill_category") {
await this.updateSource({img: "systems/rmss/assets/default/skill_category.svg"});
}
else if (this.type == "spell") {
await this.updateSource({img: "systems/rmss/assets/default/spell.svg"});
}
else if (this.type == "herb_or_poison") {
await this.updateSource({img: "systems/rmss/assets/default/herb_or_poison.svg"});
}
else if (this.type == "transport") {
await this.updateSource({img: "systems/rmss/assets/default/transport.svg"});
}
}
}
prepareDerivedData() {
const itemData = this;
const systemData = itemData.system;
const flags = itemData.flags.rmss || {};
// Make separate methods for each item type to keep things organized.
if (itemData.type === 'skill') {
this._prepareSkillCategoryData(itemData);
}
if (itemData.type === 'skill') {
this._prepareSkillData(itemData);
}
// Set the icon images for newly created images.
async _preCreate(data, options, userId) {
await super._preCreate(data, options, userId);
// Do not set on copied items if they have a custom Icon.
if (!data.name.includes("(Copy)"))
{
if (this.type === "armor") {
await this.updateSource({img: "systems/rmss/assets/default/armor.svg"});
}
else if (this.type === "weapon") {
await this.updateSource({img: "systems/rmss/assets/default/weapon.svg"});
}
else if (this.type === "skill") {
await this.updateSource({img: "systems/rmss/assets/default/skill.svg"});
}
else if (this.type === "skill_category") {
await this.updateSource({img: "systems/rmss/assets/default/skill_category.svg"});
}
else if (this.type === "spell") {
await this.updateSource({img: "systems/rmss/assets/default/spell.svg"});
}
else if (this.type === "herb_or_poison") {
await this.updateSource({img: "systems/rmss/assets/default/herb_or_poison.svg"});
}
else if (this.type === "transport") {
await this.updateSource({img: "systems/rmss/assets/default/transport.svg"});
}
}
}
_prepareSkillCategoryData(itemData) {
if (itemData.type !== 'skill_category') return;
console.log("rmss | item.js | Preparing Skill Category Data for: " + itemData.name);
// Calculate Skill Category Total Bonus
this.calculateSkillCategoryTotalBonus(itemData);
prepareDerivedData() {
const itemData = this;
const systemData = itemData.system;
const flags = itemData.flags.rmss || {};
// Make separate methods for each item type to keep things organized.
if (itemData.type === "skill") {
this._prepareSkillCategoryData(itemData);
}
_prepareSkillData(itemData) {
if (itemData.type !== 'skill') return;
console.log("rmss | item.js | Preparing Skill Data for: " + itemData.name);
// Make modifications to data here. For example:
const systemData = itemData.system;
// Calculate Skill Category Bonus
this.calculateSelectedSkillCategoryBonus(itemData);
// Calculate Skill Total Bonus
this.calculateSkillTotalBonus(itemData);
if (itemData.type === "skill") {
this._prepareSkillData(itemData);
}
}
calculateSkillCategoryTotalBonus(itemData) {
if (this.type === "skill_category") {
console.log("rmss | item.js | Calculating Skill Category Total Bonus for: " + itemData.name);
const systemData = itemData.system;
itemData.system.total_bonus = Number(systemData.rank_bonus)+Number(systemData.stat_bonus)+Number(systemData.prof_bonus)+Number(systemData.special_bonus_1)+Number(systemData.special_bonus_2);
_prepareSkillCategoryData(itemData) {
if (itemData.type !== "skill_category") return;
console.log(`rmss | item.js | Preparing Skill Category Data for: ${itemData.name}`);
// Calculate Skill Category Total Bonus
this.calculateSkillCategoryTotalBonus(itemData);
}
}
_prepareSkillData(itemData) {
if (itemData.type !== "skill") return;
console.log(`rmss | item.js | Preparing Skill Data for: ${itemData.name}`);
// Make modifications to data here. For example:
// const systemData = itemData.system;
// Calculate Skill Category Bonus
this.calculateSelectedSkillCategoryBonus(itemData);
// Calculate Skill Total Bonus
this.calculateSkillTotalBonus(itemData);
}
calculateSkillCategoryTotalBonus(itemData) {
if (this.type === "skill_category") {
console.log(`rmss | item.js | Calculating Skill Category Total Bonus for: ${itemData.name}`);
const systemData = itemData.system;
itemData.system.total_bonus = Number(systemData.rank_bonus)
+ Number(systemData.stat_bonus)
+ Number(systemData.prof_bonus)
+ Number(systemData.special_bonus_1)
+ Number(systemData.special_bonus_2);
}
}
calculateSkillTotalBonus(itemData) {
if (this.type === "skill") {
const systemData = itemData.system;
console.log("rmss | item.js | Calculating Skill Total Bonus for: " + itemData.name)
itemData.system.total_bonus = Number(systemData.rank_bonus)+Number(systemData.category_bonus)+Number(systemData.item_bonus)+Number(systemData.special_bonus_1)+Number(systemData.special_bonus_2);
}
calculateSkillTotalBonus(itemData) {
if (this.type === "skill") {
const systemData = itemData.system;
console.log(`rmss | item.js | Calculating Skill Total Bonus for: ${itemData.name}`);
itemData.system.total_bonus = Number(systemData.rank_bonus)
+ Number(systemData.category_bonus)
+ Number(systemData.item_bonus)
+ Number(systemData.special_bonus_1)
+ Number(systemData.special_bonus_2);
}
}
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.");
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;
}
}
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.`);
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;
}
}
}
}
}
}

View File

@ -1,306 +1,390 @@
export default class RMSSPlayerSheet extends ActorSheet {
// Override Default Options, Set CSS Classes, Set Default Sheet, Set up Sheet Tabs
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
template: "systems/rmss/templates/sheets/actors/rmss-character-sheet.html",
classes: ["rmss", "sheet", "actor"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "features" }]
});
}
// Make the data available to the sheet template
getData() {
const context = super.getData();
// Use a safe clone of the actor data for further operations.
const actorData = this.actor.toObject(false);
// Add the actor's data to context.data for easier access, as well as flags.
context.system = actorData.system;
context.flags = actorData.flags;
// Prepare character data and items.
if (actorData.type == 'character') {
this._prepareItems(context);
this._prepareCharacterData(context);
}
// Prepare NPC data and items.
if (actorData.type == 'npc') {
this._prepareItems(context);
}
return context;
}
//Override this method to check for duplicates when things are dragged to the sheet
// We don't want duplicate skills and skill categories.
async _onDropItem(event, data) {
// Reconstruct the item from the event
const newitem = await Item.implementation.fromDropData(data);
const itemData = newitem.toObject();
// To Do: Seperate Skills and Skill Categories. Increment Counts for items
if (itemData.type === "skill_category"){
// Override Default Options, Set CSS Classes, Set Default Sheet, Set up Sheet Tabs
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 860,
height: 780,
template: "systems/rmss/templates/sheets/actors/rmss-character-sheet.html",
classes: ["rmss", "sheet", "actor"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "features" }]
});
}
// Get the already owned Items from the actor and push into an array
const owneditems = this.object.getOwnedItemsByType("skill_category");
// Make the data available to the sheet template
async getData() {
const context = super.getData();
var ownedskillcatlist = Object.values(owneditems);
// Check if the dragged item is not in the array and not owned
if (!ownedskillcatlist.includes(itemData.name)) {
console.log("Not Owned!");
super._onDropItem(event, data);
}
} else if ( itemData.type === "skill") {
// Get the already owned Items from the actor and push into an array
const owneditems = this.object.getOwnedItemsByType("skill");
// Use a safe clone of the actor data for further operations.
const actorData = this.actor.toObject(false);
var ownedskilllist = Object.values(owneditems);
let enrichedDescription = await TextEditor.enrichHTML(this.actor.system.description, {async: true});
// Check if the dragged item is not in the array and not owned
if (!ownedskilllist.includes(itemData.name)) {
console.log("Not Owned!");
super._onDropItem(event, data);
}
}
else {
super._onDropItem(event, data);
}
// Add the actor's data to context.data for easier access, as well as flags.
context.system = actorData.system;
context.flags = actorData.flags;
context.enrichedDescription = enrichedDescription;
// Prepare character data and items.
if (actorData.type === "character") {
this._prepareItems(context);
this._prepareCharacterData(context);
}
_prepareCharacterData(context) {
// Prepare NPC data and items.
if (actorData.type === "npc") {
this._prepareItems(context);
}
_prepareItems(context) {
console.log("rmss | rmss_player_sheet.js | Preparing items for: "+ this.name);
// Initialize containers.
const gear = [];
const playerskill= [];
const skillcat = [];
const weapons = [];
const armor = [];
const herbs = [];
const spells = [];
const equipables = [];
// Iterate through items, allocating to containers
for (let i of context.items) {
i.img = i.img || DEFAULT_TOKEN;
// Append to gear.
if (i.type === 'item') {
gear.push(i);
}
else if (i.type === 'weapon') {
weapons.push(i);
}
else if (i.type === 'herb_or_poison') {
herbs.push(i);
}
// Append to skill categories.
else if (i.type === 'skill_category') {
skillcat.push(i);
}
// Append to playerskill
else if (i.type === 'skill') {
playerskill.push(i);
}
else if (i.type === 'armor') {
armor.push(i);
}
else if (i.type === 'spell') {
spells.push(i);
}
}
// Sort Skill/Skillcat Arrays
skillcat.sort(function (a, b){
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
return context;
}
playerskill.sort(function (a, b){
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
// Override this method to check for duplicates when things are dragged to the sheet
// We don't want duplicate skills and skill categories.
async _onDropItem(event, data) {
// Assign and return
context.gear = gear;
context.skillcat = skillcat;
context.playerskill = playerskill;
context.weapons = weapons;
context.armor = armor;
context.herbs = herbs;
context.spells = spells;
// Reconstruct the item from the event
const newitem = await Item.implementation.fromDropData(data);
const itemData = newitem.toObject();
// To Do: Seperate Skills and Skill Categories. Increment Counts for items
if (itemData.type === "skill_category") {
// Get the already owned Items from the actor and push into an array
const owneditems = this.object.getOwnedItemsByType("skill_category");
let ownedskillcatlist = Object.values(owneditems);
// Check if the dragged item is not in the array and not owned
if (!ownedskillcatlist.includes(itemData.name)) {
console.log("Not Owned!");
super._onDropItem(event, data);
}
} else if ( itemData.type === "skill") {
// Get the already owned Items from the actor and push into an array
const owneditems = this.object.getOwnedItemsByType("skill");
let ownedskilllist = Object.values(owneditems);
// Check if the dragged item is not in the array and not owned
if (!ownedskilllist.includes(itemData.name)) {
console.log("Not Owned!");
super._onDropItem(event, data);
}
}
activateListeners(html) {
super.activateListeners(html);
// Render the item sheet for viewing/editing prior to the editable check.
html.find('.item-edit').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
//console.log(this);
item.sheet.render(true);
});
// -------------------------------------------------------------
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
// Add Item
html.find('.item-create').click(this._onItemCreate.bind(this));
// Delete Item
html.find('.item-delete').click(ev => {
console.log(ev.currentTarget.getAttribute("data-item-id"));
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
item.delete();
});
// Check/Uncheck Favorite Skill
html.find('.skill-favorite').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log("Before change: " + item.system.favorite);
if (item.system.favorite === true) {
console.log("Setting False");
item.update({system: {"favorite": false}});
} else {
console.log("Setting True");
item.update({system: {"favorite": true}});
}
console.log("After change: " + item.system.favorite);
});
// Check/Uncheck Favorite Spell
html.find('.spell-favorite').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log("Before change: " + item.system.favorite);
if (item.system.favorite === true) {
console.log("Setting False");
item.update({system: {"favorite": false}});
} else {
console.log("Setting True");
item.update({system: {"favorite": true}});
}
console.log("After change: " + item.system.favorite);
});
// Equip/Unequip Item
html.find('.equippable').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log("Before change: " + item.system.equipped);
if (item.system.equipped === true) {
console.log("Setting False");
item.update({system: {"equipped": false}});
} else {
console.log("Setting True");
item.update({system: {"equipped": true}});
}
console.log("After change: " + item.system.equipped);
});
// Change New Ranks value when clicked in player sheet. From 0-3.
html.find('.skill-newrank').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log("Firing in the Player Sheet");
console.log(ev.currentTarget.getAttribute("value"));
console.log(ev.currentTarget.getAttribute("data-item-id"));
switch(ev.currentTarget.getAttribute("value")) {
case "0":
console.log("Skill NewRanks is 0 setting to 1");
item.update({system: {new_ranks:{ "value": 1 }}});
break;
case "1":
console.log("Skill NewRanks is 1 setting to 2");
item.update({system: {new_ranks:{ "value": 2 }}});
break;
case "2":
console.log("Skill NewRanks is 2 setting to 3");
item.update({system: {new_ranks:{ "value": 3 }}});
break;
case "3":
console.log("Skill NewRanks is 3 setting to 0");
item.update({system: {new_ranks:{ "value": 0 }}});
break;
}
});
// Change New Ranks value when clicked in player sheet. From 0-3.
html.find('.skillcategory-newrank').click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log("Firing in the Player Sheet");
console.log(ev.currentTarget.getAttribute("value"));
console.log(ev.currentTarget.getAttribute("data-item-id"));
switch(ev.currentTarget.getAttribute("value")) {
case "0":
console.log("Skill Category NewRanks is 0 setting to 1");
item.update({system: {new_ranks:{ "value": 1 }}});
break;
case "1":
console.log("Skill Category NewRanks is 1 setting to 2");
item.update({system: {new_ranks:{ "value": 2 }}});
break;
case "2":
console.log("Skill Category NewRanks is 2 setting to 3");
item.update({system: {new_ranks:{ "value": 3 }}});
break;
case "3":
console.log("Skill Category NewRanks is 3 setting to 0");
item.update({system: {new_ranks:{ "value": 0 }}});
break;
}
});
else {
super._onDropItem(event, data);
}
async _onItemCreate(event) {
event.preventDefault();
const header = event.currentTarget;
// Get the type of item to create.
const type = header.dataset.type;
// Grab any data associated with this control.
const data = duplicate(header.dataset);
// Initialize a default name.
const name = `New ${type.capitalize()}`;
// Prepare the item object.
const itemData = {
name: name,
type: type,
data: data
};
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data.type;
// Finally, create the item!
return await Item.create(itemData, {parent: this.actor});
}
_prepareCharacterData(context) {
// Calculate Power Point Exhaustion
let powerpointPercentage = (Number(context.system.attributes.power_points.current) / Number(context.system.attributes.power_points.max)) * 100;
console.log(true);
switch (true) {
case (powerpointPercentage < 25):
context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -30 ";
break;
case (powerpointPercentage < 50):
context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -20 ";
break;
case (powerpointPercentage < 75):
console.log("Less than 75");
context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: -10 ";
break;
default:
console.log("Setting Default");
context.system.attributes.power_points.modifier = "PP Exhaustion Penalty: 0 ";
}
}
// Calculate Exhaustion Point Penalty
let exhaustionPercentage = (Number(context.system.attributes.exhaustion_points.current) / Number(context.system.attributes.exhaustion_points.max)) * 100;
console.log(true);
switch (true) {
case (exhaustionPercentage < 1):
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -100 ";
break;
case (exhaustionPercentage < 10):
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -60 ";
break;
case (exhaustionPercentage < 25):
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -30 ";
break;
case (exhaustionPercentage < 50):
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -15 ";
break;
case (exhaustionPercentage < 75):
console.log("Less than 75");
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: -5 ";
break;
default:
console.log("Setting Default");
context.system.attributes.exhaustion_points.modifier = "Exhaustion Penalty: 0 ";
}
}
_prepareItems(context) {
console.log(`rmss | rmss_player_sheet.js | Preparing items for: ${this.name}`);
// Initialize containers.
const gear = [];
const playerskill= [];
const skillcat = [];
const weapons = [];
const armor = [];
const herbs = [];
const spells = [];
const equipables = [];
// Iterate through items, allocating to containers
for (let i of context.items) {
i.img = i.img || DEFAULT_TOKEN;
// Append to gear.
if (i.type === "item") {
gear.push(i);
}
else if (i.type === "weapon") {
weapons.push(i);
}
else if (i.type === "herb_or_poison") {
herbs.push(i);
}
// Append to skill categories.
else if (i.type === "skill_category") {
skillcat.push(i);
}
// Append to playerskill
else if (i.type === "skill") {
playerskill.push(i);
}
else if (i.type === "armor") {
armor.push(i);
}
else if (i.type === "spell") {
spells.push(i);
}
}
// Sort Skill/Skillcat Arrays
skillcat.sort(function(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
playerskill.sort(function(a, b) {
if (a.name < b.name) {
return -1;
}
if (a.name > b.name) {
return 1;
}
return 0;
});
// Assign and return
context.gear = gear;
context.skillcat = skillcat;
context.playerskill = playerskill;
context.weapons = weapons;
context.armor = armor;
context.herbs = herbs;
context.spells = spells;
}
async renderCharacterSettings(data) {
console.log(data);
const configSheet = await renderTemplate("systems/rmss/templates/sheets/actors/dialogs/actor-settings.html", data);
return (configSheet);
}
activateListeners(html) {
super.activateListeners(html);
// Render the item sheet for viewing/editing prior to the editable check.
html.find(".item-edit").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
item.sheet.render(true);
});
// -------------------------------------------------------------
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
// Add Item
html.find(".item-create").click(this._onItemCreate.bind(this));
// Delete Item
html.find(".item-delete").click(ev => {
console.log(ev.currentTarget.getAttribute("data-item-id"));
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
item.delete();
});
// Show Sheet Settings
html.find(".import-skillcats").click(async ev => {
let selectOptions = {};
for (const pack of game.packs) {
selectOptions[pack.metadata.id] = pack.metadata.label;
}
new game.rmss.applications.RMSSActorSheetConfig(selectOptions, this.actor).render(true);
});
// Check/Uncheck Favorite Skill
html.find(".skill-favorite").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log(`Before change: ${item.system.favorite}`);
if (item.system.favorite === true) {
console.log("Setting False");
item.update({system: {favorite: false}});
} else {
console.log("Setting True");
item.update({system: {favorite: true}});
}
console.log(`After change: ${item.system.favorite}`);
});
// Check/Uncheck Favorite Spell
html.find(".spell-favorite").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log(`Before change: ${item.system.favorite}`);
if (item.system.favorite === true) {
console.log("Setting False");
item.update({system: {favorite: false}});
} else {
console.log("Setting True");
item.update({system: {favorite: true}});
}
console.log(`After change: ${item.system.favorite}`);
});
// Equip/Unequip Weapon/Armor
html.find(".equippable").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log(`Before change: ${item.system.equipped}`);
if (item.system.equipped === true) {
console.log("Setting False");
item.update({system: {equipped: false}});
} else {
console.log("Setting True");
item.update({system: {equipped: true}});
}
console.log(`After change: ${item.system.equipped}`);
});
// Wear/Remove Item
html.find(".wearable").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log(item);
console.log(`Before change: ${item.system.equipped}`);
if (item.system.worn === true) {
console.log("Setting False");
item.update({system: {worn: false}});
} else {
console.log("Setting True");
item.update({system: {worn: true}});
}
console.log(`After change: ${item.system.equipped}`);
});
// Change New Ranks value when clicked in player sheet. From 0-3.
html.find(".skill-newrank").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log("Firing in the Player Sheet");
console.log(ev.currentTarget.getAttribute("value"));
console.log(ev.currentTarget.getAttribute("data-item-id"));
switch (ev.currentTarget.getAttribute("value")) {
case "0":
console.log("Skill NewRanks is 0 setting to 1");
item.update({system: {new_ranks: { value: 1 }}});
break;
case "1":
console.log("Skill NewRanks is 1 setting to 2");
item.update({system: {new_ranks: { value: 2 }}});
break;
case "2":
console.log("Skill NewRanks is 2 setting to 3");
item.update({system: {new_ranks: { value: 3 }}});
break;
case "3":
console.log("Skill NewRanks is 3 setting to 0");
item.update({system: {new_ranks: { value: 0 }}});
break;
}
});
// Change New Ranks value when clicked in player sheet. From 0-3.
html.find(".skillcategory-newrank").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
console.log("Firing in the Player Sheet");
console.log(ev.currentTarget.getAttribute("value"));
console.log(ev.currentTarget.getAttribute("data-item-id"));
switch (ev.currentTarget.getAttribute("value")) {
case "0":
console.log("Skill Category NewRanks is 0 setting to 1");
item.update({system: {new_ranks: { value: 1 }}});
break;
case "1":
console.log("Skill Category NewRanks is 1 setting to 2");
item.update({system: {new_ranks: { value: 2 }}});
break;
case "2":
console.log("Skill Category NewRanks is 2 setting to 3");
item.update({system: {new_ranks: { value: 3 }}});
break;
case "3":
console.log("Skill Category NewRanks is 3 setting to 0");
item.update({system: {new_ranks: { value: 0 }}});
break;
}
});
}
async _onItemCreate(event) {
event.preventDefault();
const header = event.currentTarget;
// Get the type of item to create.
const type = header.dataset.type;
// Grab any data associated with this control.
const data = duplicate(header.dataset);
// Initialize a default name.
const name = `New ${type.capitalize()}`;
// Prepare the item object.
const itemData = {
name: name,
type: type,
data: data
};
// Remove the type from the dataset since it's in the itemData.type prop.
delete itemData.data.type;
// Finally, create the item!
return await Item.create(itemData, {parent: this.actor});
}
}

View File

@ -0,0 +1,55 @@
export default class RMSSActorSheetConfig extends FormApplication {
constructor(selectOptions, character) {
super();
this.selectOptions = selectOptions;
this.character = character;
}
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["form"],
popOut: true,
template: "systems/rmss/templates/sheets/actors/apps/actor-settings.html"
});
}
getData() {
// Send data to the template
return {
selectOptions: this.selectOptions
};
}
activateListeners(html) {
super.activateListeners(html);
}
async _updateObject(event, formData) {
console.log("Deleting Old Skill Categories.");
for (const item of this.character.items) {
if (item.type === "skill_category") {
item.delete();
}
}
const pack = game.packs.get(formData.selectOptions);
const skillCategoryData = await pack.getIndex();
console.log("Importing New Skill Categories.");
for (const sc of skillCategoryData) {
const newitem = await pack.getDocument(sc._id);
let newDocuments = [];
if (newitem.type === "skill_category") {
console.log(newitem);
newDocuments.push(newitem);
}
if (newDocuments.length > 0) {
await Item.createDocuments(newDocuments, {parent: this.character});
}
}
}
}

View File

@ -1,36 +1,36 @@
// Our Item Sheet extends the default
export default class RMSSArmorSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-armor-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/items/rmss-armor-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-armor-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/items/rmss-armor-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -1,36 +1,36 @@
// Our Item Sheet extends the default
export default class RMSSHerbAndPoisonSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-herb-or-poison-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/items/rmss-herb-or-poison-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-herb-or-poison-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/items/rmss-herb-or-poison-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -1,36 +1,36 @@
// Our Item Sheet extends the default
export default class RMSSItemSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-item-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/items/rmss-item-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-item-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/items/rmss-item-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -1,36 +1,36 @@
// Our Item Sheet extends the default
export default class RMSSTransportSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-transport-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/items/rmss-transport-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-transport-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/items/rmss-transport-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -1,36 +1,36 @@
// Our Item Sheet extends the default
export default class RMSSWeaponSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-weapon-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/items/rmss-weapon-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/items/rmss-weapon-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/items/rmss-weapon-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -1,132 +1,133 @@
// Our Item Sheet extends the default
export default class RMSSSkillCategorySheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 580,
height: 440,
template: "systems/rmss/templates/sheets/skills/rmss-skill-category-sheet.html",
classes: ["rmss", "sheet", "item"]
});
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 580,
height: 440,
template: "systems/rmss/templates/sheets/skills/rmss-skill-category-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/skills/rmss-skill-category-sheet.html";
}
// Make the data available to the sheet template
async getData() {
const context = await super.getData();
// Get a list of stats that can be used as applicable stats
let applicableStatList = this.prepareApplicableStatNames(CONFIG);
// Get the currently selected value for all three applicable stats
let firstApplicableStat = this.prepareApplicableSelectedStat("app_stat_1");
let secondApplicableStat = this.prepareApplicableSelectedStat("app_stat_2");
let thirdApplicableStat = this.prepareApplicableSelectedStat("app_stat_3");
// Build and apply the display string for Applicable Stats
let applicableStatText =
this.buildApplicableStatsText(firstApplicableStat, secondApplicableStat, thirdApplicableStat);
context.item.system.applicable_stats = applicableStatText;
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: context.item,
system: context.item.system,
config: CONFIG.rmss,
applicable_stat_list: applicableStatList,
applicable_stat_1_selected: firstApplicableStat,
applicable_stat_2_selected: secondApplicableStat,
applicable_stat_3_selected: thirdApplicableStat,
enrichedDescription: enrichedDescription
};
return sheetData;
}
async _setApplicableStat(item, ev) {
// Build a JSON Object from the selected tag value and selected name (item data attribute key)
let updateKey = ev.currentTarget.getAttribute("name");
let updateData = ev.target.value;
// Update Item Data
await item.update({[updateKey]: updateData});
}
// Each Skill Category can have up to three Applicable Stats that apply to it. We need to get a list of
// the Stat Shortnames from Config so the user can select which stats are applicable to this Skill Category
prepareApplicableStatNames(config) {
let applicableStatList = {None: "None"};
for (const item in config.rmss.stats) {
applicableStatList[config.rmss.stats[item].shortname] = config.rmss.stats[item].shortname;
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/skills/rmss-skill-category-sheet.html`;
return applicableStatList;
}
// Get the values for the currently selected Applicable Stat so we can display it on the Skill Category Sheet
// If nothing is selected return an empty string.
prepareApplicableSelectedStat(appStat) {
let applicableStatSelected = "";
applicableStatSelected = this.item.system[appStat];
return applicableStatSelected;
}
// The character sheet has an information field that displays the applicable stats in the following format
// St/Ag/St. This method checks the current applicable stats and builds that field so
// it can be displayed to the user.
buildApplicableStatsText(firstAppStat, secondAppStat, thirdAppStat) {
if (firstAppStat === "None") {
return ("None");
}
else if (firstAppStat !== "None" && secondAppStat === "None") {
return (firstAppStat);
}
else if (firstAppStat !== "None" && secondAppStat !== "None" && thirdAppStat === "None" ) {
return (`${firstAppStat}/${secondAppStat}`);
}
else if (firstAppStat !== "None" && secondAppStat !== "None" && thirdAppStat !== "None" ) {
return (`${firstAppStat}/${secondAppStat}/${thirdAppStat}`);
}
else {
return ("None");
}
}
// Make the data available to the sheet template
async getData() {
const context = await super.getData();
activateListeners(html) {
super.activateListeners(html);
// Get a list of stats that can be used as applicable stats
var applicableStatList = this.prepareApplicableStatNames(CONFIG);
// -------------------------------------------------------------
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
//Get the currently selected value for all three applicable stats
var firstApplicableStat = this.prepareApplicableSelectedStat("app_stat_1");
var secondApplicableStat = this.prepareApplicableSelectedStat("app_stat_2");
var thirdApplicableStat = this.prepareApplicableSelectedStat("app_stat_3");
// Every time the user selects one of the Applicable Stat dropdowns
// fire an event to change the value in the Skill Category
html.find(".stat-selector").change(ev => {
this._setApplicableStat(this.item, ev);
});
// Build and apply the display string for Applicable Stats
var applicableStatText = this.buildApplicableStatsText(firstApplicableStat, secondApplicableStat, thirdApplicableStat);
context.item.system.applicable_stats = applicableStatText;
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: context.item,
system: context.item.system,
config: CONFIG.rmss,
applicable_stat_list: applicableStatList,
applicable_stat_1_selected: firstApplicableStat,
applicable_stat_2_selected: secondApplicableStat,
applicable_stat_3_selected: thirdApplicableStat,
enrichedDescription: enrichedDescription
};
return sheetData;
}
async _setApplicableStat(item, ev) {
// Build a JSON Object from the selected tag value and selected name (item data attribute key)
var updateKey = ev.currentTarget.getAttribute("name");
var updateData = ev.target.value;
// Update Item Data
await item.update({[updateKey]: updateData});
}
// Each Skill Category can have up to three Applicable Stats that apply to it. We need to get a list of
// the Stat Shortnames from Config so the user can select which stats are applicable to this Skill Category
prepareApplicableStatNames(config) {
var applicableStatList = {None: "None"};
for (const item in config.rmss.stats) {
applicableStatList[config.rmss.stats[item].shortname] = config.rmss.stats[item].shortname;
}
return applicableStatList;
}
// Get the values for the currently selected Applicable Stat so we can display it on the Skill Category Sheet
// If nothing is selected return an empty string.
prepareApplicableSelectedStat(appStat) {
var applicableStatSelected = "";
applicableStatSelected = this.item.system[appStat];
return applicableStatSelected;
}
// The character sheet has an information field that displays the applicable stats in the following format
// St/Ag/St. This method checks the current applicable stats and builds that field so
// it can be displayed to the user.
buildApplicableStatsText(firstAppStat, secondAppStat, thirdAppStat) {
if (firstAppStat === "None") {
return("None");
}
else if (firstAppStat !== "None" && secondAppStat === "None") {
return(firstAppStat);
}
else if (firstAppStat !== "None" && secondAppStat !== "None" && thirdAppStat === "None" ) {
return(firstAppStat + "/" + secondAppStat );
}
else if (firstAppStat !== "None" && secondAppStat !== "None" && thirdAppStat !== "None" ) {
return(firstAppStat + "/" + secondAppStat + "/" + thirdAppStat );
}
else {
return("None");
}
}
activateListeners(html) {
super.activateListeners(html);
// -------------------------------------------------------------
// Everything below here is only needed if the sheet is editable
if (!this.isEditable) return;
// Every time the user selects one of the Applicable Stat dropdowns
// fire an event to change the value in the Skill Category
html.find('.stat-selector').change(ev => {
this._setApplicableStat(this.item, ev);
});
// Catch the event when the user clicks one of the New Ranks Checkboxes in a Skill Category.
// It will increment by one or wrap back to zero on a value of three
html.find('.skillcategorysheet-newrank').click(ev => {
switch(ev.currentTarget.getAttribute("value")) {
case "0":
this.object.update({system: {new_ranks:{ "value": 1 }}});
break;
case "1":
this.object.update({system: {new_ranks:{ "value": 2 }}});
break;
case "2":
this.object.update({system: {new_ranks:{ "value": 3 }}});
break;
case "3":
this.object.update({system: {new_ranks:{ "value": 0 }}});
break;
}
});
}
}
// Catch the event when the user clicks one of the New Ranks Checkboxes in a Skill Category.
// It will increment by one or wrap back to zero on a value of three
html.find(".skillcategorysheet-newrank").click(ev => {
switch (ev.currentTarget.getAttribute("value")) {
case "0":
this.object.update({system: {new_ranks: { value: 1 }}});
break;
case "1":
this.object.update({system: {new_ranks: { value: 2 }}});
break;
case "2":
this.object.update({system: {new_ranks: { value: 3 }}});
break;
case "3":
this.object.update({system: {new_ranks: { value: 0 }}});
break;
}
});
}
}

View File

@ -1,115 +1,115 @@
// Our Item Sheet extends the default
export default class RMSSSkillSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/skills/rmss-skill-sheet.html",
classes: ["rmss", "sheet", "item"]
});
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
template: "systems/rmss/templates/sheets/skills/rmss-skill-sheet.html",
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/skills/rmss-skill-sheet.html";
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
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();
// Figure out if a valid Skill Category is already selected
let selectedSkillCategory = this.prepareSelectedSkillCategory(ownedSkillCategories, this.object.system.category);
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
owned_skillcats: ownedSkillCategories,
enrichedDescription: enrichedDescription,
selected_skillcat: selectedSkillCategory,
designations: CONFIG.rmss.skill_designations
};
return sheetData;
}
activateListeners(html) {
super.activateListeners(html);
// Catch the event when the user clicks one of the New Ranks Checkboxes in a Skill.
// It will increment by one or wrap back to zero on a value of three
html.find(".skillsheet-newrank").click(ev => {
switch (ev.currentTarget.getAttribute("value")) {
case "0":
this.object.update({system: {new_ranks: { value: 1 }}});
break;
case "1":
this.object.update({system: {new_ranks: { value: 2 }}});
break;
case "2":
this.object.update({system: {new_ranks: { value: 3 }}});
break;
case "3":
this.object.update({system: {new_ranks: { value: 0 }}});
break;
}
});
}
// Skills are related to Skill Categories so we need something to allow the user to choose that relationship
// 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);
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/skills/rmss-skill-sheet.html`;
else
{
const skillCategories = this.item.parent.getOwnedItemsByType("skill_category");
return (skillCategories);
}
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// 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)) {
return (selectedSkillCategory);
} else {
return (defaultSelectedCategory);
}
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Populate the Skill Category Bonus field on the Skill Sheet.
// 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;
// Get a list of the parent item's skill categories for the dropdown
var ownedSkillCategories = this.prepareSkillCategoryValues();
// Figure out if a valid Skill Category is already selected
var selectedSkillCategory = this.prepareSelectedSkillCategory(ownedSkillCategories, this.object.system.category);
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
owned_skillcats: ownedSkillCategories,
enrichedDescription: enrichedDescription,
selected_skillcat: selectedSkillCategory,
designations: CONFIG.rmss.skill_designations
};
return sheetData;
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;
}
activateListeners(html) {
super.activateListeners(html);
// Catch the event when the user clicks one of the New Ranks Checkboxes in a Skill.
// It will increment by one or wrap back to zero on a value of three
html.find('.skillsheet-newrank').click(ev => {
switch(ev.currentTarget.getAttribute("value")) {
case "0":
this.object.update({system: {new_ranks:{ "value": 1 }}});
break;
case "1":
this.object.update({system: {new_ranks:{ "value": 2 }}});
break;
case "2":
this.object.update({system: {new_ranks:{ "value": 3 }}});
break;
case "3":
this.object.update({system: {new_ranks:{ "value": 0 }}});
break;
}
});
}
}
// Skills are related to Skill Categories so we need something to allow the user to choose that relationship
// 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() {
var skillNoOwner = {None: "Skill Has No Owner", };
if (this.item.isEmbedded === null) {
return(skillNoOwner);
}
else
{
const skillCategories = this.item.parent.getOwnedItemsByType("skill_category");
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) {
var defaultSelectedCategory = "None";
if (Object.keys(ownedSkillCategories).includes(selectedSkillCategory)) {
return(selectedSkillCategory);
} else {
return(defaultSelectedCategory);
}
}
// Populate the Skill Category Bonus field on the Skill Sheet.
// Iterate through the owned skill categories and if one of them matches the item id of currently select 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;
}
}
}
}
}
}
}

View File

@ -1,35 +1,35 @@
// Our Item Sheet extends the default
export default class RMSSSpellSheet extends ItemSheet {
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
classes: ["rmss", "sheet", "item"]
});
}
// If our sheet is called here it is.
get template() {
return `systems/rmss/templates/sheets/spells/rmss-spell-sheet.html`;
}
// Set the height and width
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
width: 530,
height: 440,
classes: ["rmss", "sheet", "item"]
});
}
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
// If our sheet is called here it is.
get template() {
return "systems/rmss/templates/sheets/spells/rmss-spell-sheet.html";
}
var enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
// Make the data available to the sheet template
async getData() {
const baseData = await super.getData();
let sheetData = {
owner: this.item.isOwner,
editable :this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
let enrichedDescription = await TextEditor.enrichHTML(this.item.system.description, {async: true});
return sheetData;
}
}
let sheetData = {
owner: this.item.isOwner,
editable: this.isEditable,
item: baseData.item,
system: baseData.item.system,
config: CONFIG.rmss,
enrichedDescription: enrichedDescription
};
return sheetData;
}
}

View File

@ -65,6 +65,12 @@
align-items: center;
padding: 1px;
}
.settings-button,
.playersheet-settings {
font-family: Signika, sans-serif;
font-size: 12px;
margin-right: 6px;
}
.resource-container {
display: flex;
flex-direction: row;
@ -231,7 +237,7 @@
}
.items-grid-container {
display: grid;
grid-template-columns: [name] 30% [quantity] 17% [weight] 17% [cost] 18% [controls] 18%;
grid-template-columns: [worn] 10% [name] 30% [quantity] 15% [weight] 15% [cost] 15% [controls] 15%;
}
.items-grid-container > div {
font-family: Signika, sans-serif;
@ -245,11 +251,12 @@
flex-direction: row;
justify-content: center;
}
.items-grid-container > div:nth-child(10n+1),
.items-grid-container > div:nth-child(10n+2),
.items-grid-container > div:nth-child(10n+3),
.items-grid-container > div:nth-child(10n+4),
.items-grid-container > div:nth-child(10n+5) {
.items-grid-container > div:nth-child(12n+1),
.items-grid-container > div:nth-child(12n+2),
.items-grid-container > div:nth-child(12n+3),
.items-grid-container > div:nth-child(12n+4),
.items-grid-container > div:nth-child(12n+5),
.items-grid-container > div:nth-child(12n+6) {
font-family: Signika, sans-serif;
font-size: 12px;
text-align: center;
@ -431,6 +438,23 @@
border-bottom: 1px solid;
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
}
.resistances-grid-container {
outline: 1px solid;
/* use instead of border */
margin-top: 1px;
margin-left: 1px;
padding: 5px;
display: grid;
grid-template-columns: [Name] 40% [Value] 20% [Race_Mod] 20% [Total] 20%;
}
.resistances-grid-heading {
font-weight: bold;
border-bottom: 1px solid;
background-image: linear-gradient(rgba(0, 0, 0, 0.1) 0 0);
}
.resistance-input {
width: 50%;
}
.skillcat-name,
.skill-name,
.item-name,

View File

@ -1,14 +1,11 @@
// Import Configuration Object
console.log("rmss | Importing configuration javascript");
import {rmss} from "./module/config.js";
import { rmss } from "./module/config.js";
// Import document classes.
console.log("rmss | Importing document classes");
import { RMSSActor } from "./module/documents/actor.js";
import { RMSSItem } from "./module/documents/item.js";
// Import Sheets
console.log("rmss | Importing actor and item sheet");
import RMSSItemSheet from "./module/sheets/items/rmss_item_sheet.js";
import RMSSArmorSheet from "./module/sheets/items/rmss_armor_sheet.js";
import RMSSTransportSheet from "./module/sheets/items/rmss_transport_sheet.js";
@ -19,8 +16,9 @@ import RMSSSkillCategorySheet from "./module/sheets/skills/rmss_skill_category_s
import RMSSSkillSheet from "./module/sheets/skills/rmss_skill_sheet.js";
import RMSSPlayerSheet from "./module/sheets/actors/rmss_player_sheet.js";
import RMSSActorSheetConfig from "./module/sheets/actors/rmss_player_sheet_config.js";
// Preload handlebars templates for character sheets
/** Preload handlebars templates for character sheets */
async function preloadHandlebarsTemplates() {
const templatePaths = [
"systems/rmss/templates/sheets/actors/parts/actor-stats.html",
@ -42,68 +40,72 @@ async function preloadHandlebarsTemplates() {
"systems/rmss/templates/sheets/actors/parts/actor-herbs.html",
"systems/rmss/templates/sheets/actors/parts/actor-spells.html",
"systems/rmss/templates/sheets/actors/parts/actor-fav-spells.html",
"systems/rmss/templates/sheets/actors/parts/actor-fav-items.html"
"systems/rmss/templates/sheets/actors/parts/actor-fav-items.html",
"systems/rmss/templates/sheets/actors/apps/actor-settings.html"
];
return loadTemplates(templatePaths);
}
// 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
console.log("rmss | Loading Rolemaster Actor and Item classes");
game.rmss = {
RMSSActor,
RMSSItem
RMSSItem,
applications: {
RMSSActorSheetConfig
}
};
// Define custom Document classes
CONFIG.Actor.documentClass = RMSSActor;
CONFIG.Item.documentClass = RMSSItem;
// Make Config Data Available
CONFIG.rmss = rmss;
// Unregister Default Sheets
console.log("rmss | Unregistering core sheets");
Items.unregisterSheet("core", ItemSheet);
Actors.unregisterSheet("core", ActorSheet);
// Register RMSS Sheets
console.log("rmss | Registering RMSS sheets");
// Items
Items.registerSheet("rmss", RMSSItemSheet, {makeDefault: true, label: "rmss.entity_sheet.item", types: ['item']});
Items.registerSheet("rmss", RMSSArmorSheet, {makeDefault: true, label: "rmss.entity_sheet.armor", types: ['armor']});
Items.registerSheet("rmss", RMSSTransportSheet, {makeDefault: true, label: "rmss.entity_sheet.transport", types: ['transport']});
Items.registerSheet("rmss", RMSSWeaponSheet, {makeDefault: true, label: "rmss.entity_sheet.weapon", types: ['weapon']});
Items.registerSheet("rmss", RMSSHerbOrPoisonSheet, {makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ['herb_or_poison']});
Items.registerSheet("rmss", RMSSItemSheet, {makeDefault: true, label: "rmss.entity_sheet.item", types: ["item"]});
Items.registerSheet("rmss", RMSSArmorSheet, {makeDefault: true, label: "rmss.entity_sheet.armor", types: ["armor"]});
Items.registerSheet("rmss", RMSSTransportSheet, {makeDefault: true, label: "rmss.entity_sheet.transport", types: ["transport"]});
Items.registerSheet("rmss", RMSSWeaponSheet, {makeDefault: true, label: "rmss.entity_sheet.weapon", types: ["weapon"]});
Items.registerSheet("rmss", RMSSHerbOrPoisonSheet, {makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ["herb_or_poison"]});
// Spells
Items.registerSheet("rmss", RMSSSpellSheet, {makeDefault: true, label: "rmss.entity_sheet.spell", types: ['spell']});
Items.registerSheet("rmss", RMSSSpellSheet, {makeDefault: true, label: "rmss.entity_sheet.spell", types: ["spell"]});
// Skills
Items.registerSheet("rmss", RMSSSkillCategorySheet, {makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ['skill_category']});
Items.registerSheet("rmss", RMSSSkillSheet, {makeDefault: true, label: "rmss.entity_sheet.skill", types: ['skill']});
Items.registerSheet("rmss", RMSSSkillCategorySheet, {makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ["skill_category"]});
Items.registerSheet("rmss", RMSSSkillSheet, {makeDefault: true, label: "rmss.entity_sheet.skill", types: ["skill"]});
// Actors
Actors.registerSheet("rmss", RMSSPlayerSheet, {makeDefault: true, label: "rmss.entity_sheet.player_characrer", types: ['character']});
Actors.registerSheet("rmss", 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("switch", function(value, options) {
this.switch_value = value;
return options.fn(this);
});
Handlebars.registerHelper('case', function(value, options) {
if (value == this.switch_value) {
Handlebars.registerHelper("case", function(value, options) {
if (value === this.switch_value) {
return options.fn(this);
}
});
});
});

View File

@ -3,7 +3,7 @@
"title": "Rolemaster Standard System",
"description": "The Rolemaster Standard System system for FoundryVTT.",
"author": "Cynicide",
"version": "0.0.2",
"version": "0.0.3",
"minimumCoreVersion": "0.8.6",
"compatibleCoreVersion": "10",
"esmodules":[

View File

@ -54,15 +54,51 @@
},
"resistance_rolls": {
"resistance_rolls": {
"channeling": 0,
"essence": 0,
"mentalism": 0,
"chann_ess": 0,
"chann_ment": 0,
"ess_ment": 0,
"arcane": 0,
"poison_disease": 0,
"fear": 0
"channeling": {
"value": 0,
"race_mod": 0,
"total": 0
},
"essence": {
"value": 0,
"race_mod": 0,
"total": 0
},
"mentalism": {
"value": 0,
"race_mod": 0,
"total": 0
},
"chann_ess": {
"value": 0,
"race_mod": 0,
"total": 0
},
"chann_ment": {
"value": 0,
"race_mod": 0,
"total": 0
},
"ess_ment": {
"value": 0,
"race_mod": 0,
"total": 0
},
"arcane": {
"value": 0,
"race_mod": 0,
"total": 0
},
"poison_disease": {
"value": 0,
"race_mod": 0,
"total": 0
},
"fear": {
"value": 0,
"race_mod": 0,
"total": 0
}
}
},
"background": {
@ -184,9 +220,8 @@
}
}
},
"character": {
"templates": ["background", "stats", "resistance_rolls", "armor_info", "fixed_info", "race_stat_fixed_info", "role_traits", "money"],
"templates": ["background", "stats", "resistance_rolls", "armor_info", "fixed_info", "race_stat_fixed_info", "role_traits", "money", "description"],
"attributes": {
"level": {
"value": 1
@ -206,11 +241,12 @@
"experience_points": {
"value": 0
}
}
},
"description": ""
}
},
"Item": {
"types": ["item", "skill_category", "skill", "armor", "weapon", "transport", "herb_or_poison", "spell"],
"types": ["item", "skill_category", "skill", "armor", "weapon", "transport", "herb_or_poison", "spell", "language"],
"templates": {
"base": {
"description": "Description here."
@ -218,6 +254,7 @@
},
"item": {
"templates": ["base"],
"worn": false,
"quantity": 1,
"weight": 0,
"cost": 0,
@ -270,7 +307,7 @@
"category" : "",
"ranks": 0,
"new_ranks": {
"value": [0],
"value": 0,
"max": 3,
"max_default": 3
},

View File

@ -0,0 +1,17 @@
<form>
<div>
<h3>Import Skill Categories</h3>
<div>
WARNING: This will erase your existing Skill Categories and import all Skill Categories from the selected Compendium.
</div>
<div>
Select Compendium:
<select name="selectOptions" class="compendium-selector" value="None" itemid="blah">
{{selectOptions selectOptions}}
</select></div>
<div>
<button class="import-skillcats" title="Import">Import</button>
</div>
</div>
</form>

View File

@ -2,6 +2,7 @@
<!-- LOCALIZE THE LAST STRINGS IN THIS PAGE. ALSO SKILLS AND SKILL CATEGORIES-->
<div class="items-grid-heading">{{ localize "rmss.pc_sheet_items.item_name" }}</div>
<div class="items-grid-heading">{{ localize "rmss.pc_sheet_items.worn" }}</div>
<div class="items-grid-heading">{{ localize "rmss.pc_sheet_items.quantity" }}</div>
<div class="items-grid-heading">{{ localize "rmss.pc_sheet_items.weight" }}</div>
<div class="items-grid-heading">{{ localize "rmss.pc_sheet_items.cost" }}</div>
@ -10,6 +11,11 @@
</div>
{{#each gear as |item id|}}
<div>{{item.name}}</div>
{{#if item.system.worn}}
<div><a class="wearable" data-item-id="{{item._id}}"><i class="fa-regular fa-square-check"></i></a></div>
{{else}}
<div><a class="wearable" data-item-id="{{item._id}}"><i class="fa-regular fa-square"></i></a></div>
{{/if}}
<div>{{item.system.quantity}}</div>
<div>{{item.system.weight}}</div>
<div>{{item.system.cost}}</div>

View File

@ -0,0 +1,19 @@
<table>
<th><div class="language-name language-headeritem">{{ localize "rmss.pc_sheet_language.name" }}</div></th>
<th><div class="language-entry language-headeritem">{{ localize "rmss.pc_sheet_language.spoken" }}</div></th>
<th><div class="language-entry language-headeritem">{{ localize "rmss.pc_sheet_language.written" }}</div></th>
<th><div class="language-entry language-headeritem"> </div></th>
{{#each languages as |language id|}}
<tr class="item" data-item-id="{{language._id}}">
<td><div class="language-name">
<h4>{{language.name}}</h4>
</div></td>
<td><div class="language-entry item-prop">{{language.system.spoken}}</div></td>
<td><div class="language-entry item-prop">{{language.system.written}}</div></td>
<td><div class="language-entry item-prop">
<a class="item-edit" title="Edit Language" data-item-id="{{language._id}}"><i class="fas fa-edit"></i></a>
<a class="item-delete" title="Delete Language" data-item-id="{{language._id}}"><i class="fas fa-trash"></i></a>
</div></td>
</tr>
{{/each}}
</table>

View File

@ -1,84 +1,53 @@
<section class="resistance-block">
<ol class="labels-list">
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.channeling" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.channeling}}</h4>
</div>
</li>
<section class="resistances-grid-container">
<div class="resistances-grid-heading">Name</div>
<div class="resistances-grid-heading">Value</div>
<div class="resistances-grid-heading">Racial Mod</div>
<div class="resistances-grid-heading">Total</div>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.essence" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.essence}}</h4>
</div>
</li>
<div>{{ localize "rmss.pc_sheet_resistances.channeling" }}</div>
<div>{{system.resistance_rolls.channeling.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.channeling.race_mod" value="{{system.resistance_rolls.channeling.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.channeling.total}}</div>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.mentalism" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.mentalism}}</h4>
</div>
</li>
<div>{{ localize "rmss.pc_sheet_resistances.essence" }}</div>
<div>{{system.resistance_rolls.essence.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.essence.race_mod" value="{{system.resistance_rolls.essence.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.essence.total}}</div>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.chann_ess" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.chann_ess}}</h4>
</div>
</li>
<div>{{ localize "rmss.pc_sheet_resistances.mentalism" }}</div>
<div>{{system.resistance_rolls.mentalism.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.mentalism.race_mod" value="{{system.resistance_rolls.mentalism.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.mentalism.total}}</div>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.chann_ment" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.chann_ment}}</h4>
</div>
</li>
<div>{{ localize "rmss.pc_sheet_resistances.chann_ess" }}</div>
<div>{{system.resistance_rolls.chann_ess.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.chann_ess.race_mod" value="{{system.resistance_rolls.chann_ess.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.chann_ess.total}}</div>
<div>{{ localize "rmss.pc_sheet_resistances.chann_ment" }}</div>
<div>{{system.resistance_rolls.chann_ment.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.chann_ment.race_mod" value="{{system.resistance_rolls.chann_ment.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.chann_ment.total}}</div>
<div>{{ localize "rmss.pc_sheet_resistances.ess_ment" }}</div>
<div>{{system.resistance_rolls.ess_ment.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.ess_ment.race_mod" value="{{system.resistance_rolls.ess_ment.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.ess_ment.total}}</div>
<div>{{ localize "rmss.pc_sheet_resistances.arcane" }}</div>
<div>{{system.resistance_rolls.arcane.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.arcane.race_mod" value="{{system.resistance_rolls.arcane.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.arcane.total}}</div>
<div>{{ localize "rmss.pc_sheet_resistances.poison_disease" }}</div>
<div>{{system.resistance_rolls.poison_disease.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.poison_disease.race_mod" value="{{system.resistance_rolls.poison_disease.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.poison_disease.total}}</div>
<div>{{ localize "rmss.pc_sheet_resistances.fear" }}</div>
<div>{{system.resistance_rolls.fear.value}}</div>
<div class="resistance-input"><input type="text" name="system.resistance_rolls.fear.race_mod" value="{{system.resistance_rolls.fear.race_mod}}" data-dtype="Number"/></div>
<div>{{system.resistance_rolls.fear.total}}</div>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.ess_ment" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.ess_ment}}</h4>
</div>
</li>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.arcane" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.arcane}}</h4>
</div>
</li>
<li class="stat flexrow" >
<div class="label-name">
<h4>{{ localize "rmss.pc_sheet_resistances.poison_disease" }}</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.poison_disease}}</h4>
</div>
</li>
<li class="stat flexrow" >
<div class="label-name">
<h4>Fear</h4>
</div>
<div class="label-name">
<h4>{{system.resistance_rolls.fear}}</h4>
</div>
</li>
</ol>
</section>

View File

@ -11,7 +11,9 @@
<div class="skillcat-grid-heading">{{ localize "rmss.pc_sheet_skill_categories.special_bonus" }}</div>
<div class="skillcat-grid-heading">{{ localize "rmss.pc_sheet_skill_categories.total_bonus" }}</div>
<div class="skillcat-grid-heading">
<!-- <a class="item-create" title="Create Skill Category" data-type="skill_category"><i class="fas fa-plus"></i>{{ localize "rmss.pc_sheet_skill_categories.add_skillcat" }}</a>-->
<div class="settings-button">
<button type="button" class="import-skillcats" title="Import" acotr_id="">{{ localize "rmss.pc_sheet.import_skillcat" }}</button>
</div>
</div>
{{#each skillcat as |skill_category id|}}
<div>{{skill_category.name}}</div>

View File

@ -6,9 +6,10 @@
<div class="container">
<!-- Actor Icon Section-->
<div class="actor-icon">
<img src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="64" width="64"/>
<div>
<div class="actor-icon">
<img src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="64" width="64"/>
</div>
</div>
<!-- Resource Boxes Section-->
@ -17,17 +18,27 @@
<div class="resource-entry">
{{ localize "rmss.player_character.resources.hits" }}
<h4><input name="system.attributes.hits.current" type="text" value="{{system.attributes.hits.current}}"/>/<input name="system.attributes.hits.max" type="text" value="{{system.attributes.hits.max}}"/></h4>
<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>
<div class="resource-entry">
{{ localize "rmss.player_character.resources.exhaustion_points" }}
<h4><input name="system.attributes.exhaustion_points.current" type="text" value="{{system.attributes.exhaustion_points.current}}"/>/<input name="system.attributes.exhaustion_points.max" type="text" value="{{system.attributes.exhaustion_points.max}}"/></h4>
<div class="exhaustion-resources">
{{ localize "rmss.player_character.resources.exhaustion_points" }}
<h4><input name="system.attributes.exhaustion_points.current" type="Number" value="{{system.attributes.exhaustion_points.current}}"/>/<input name="system.attributes.exhaustion_points.max" type="Number" value="{{system.attributes.exhaustion_points.max}}"/></h4>
</div>
<div class="exhaustion-modifier">
<label>{{system.attributes.exhaustion_points.modifier}}</label>
</div>
</div>
<div class="resource-entry">
{{ localize "rmss.player_character.resources.power_points" }}
<h4><input name="system.attributes.power_points.current" type="text" value="{{system.attributes.power_points.current}}"/>/<input name="system.attributes.power_points.max" type="text" value="{{system.attributes.power_points.max}}"/></h4>
<div class="pp-resources">
{{ localize "rmss.player_character.resources.power_points" }}
<h4><input name="system.attributes.power_points.current" type="Number" value="{{system.attributes.power_points.current}}"/>/<input name="system.attributes.power_points.max" type="Number" value="{{system.attributes.power_points.max}}"/></h4>
</div>
<div class="pp-exhaustion">
<label>{{system.attributes.power_points.modifier}}</label>
</div>
</div>
</div>
@ -41,12 +52,12 @@
<div class="header-text flexrow">
<label for="level">{{ localize "rmss.player_character.level" }}</label>
<input name="level" type="text" value="{{system.attributes.level.value}}"/>
<input name="system.attributes.level.value" type="text" value="{{system.attributes.level.value}}"/>
</div>
<div class="header-text flexrow">
<label for="experience">{{ localize "rmss.player_character.experience" }}</label>
<input name="experience" type="text" value="{{system.attributes.experience_points.value}}"/>
<input name="system.attributes.experience_points.value" type="text" value="{{system.attributes.experience_points.value}}"/>
</div>
</div>
@ -88,6 +99,8 @@
{{> "systems/rmss/templates/sheets/actors/parts/actor-fav-spells.html" }}
<h2>Equipped Items</h2>
{{> "systems/rmss/templates/sheets/actors/parts/actor-fav-items.html" }}
<h2>Description</h2>
{{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}
</div>
</div>

View File

@ -7,11 +7,15 @@
<div>
<table>
<tr>
<th>{{localize "rmss.item.worn"}}</th>
<th>{{localize "rmss.item.quantity"}}</th>
<th>{{localize "rmss.item.weight"}}</th>
<th>{{localize "rmss.item.cost"}}</th>
<th>{{localize "rmss.item.prod_time"}}</th>
</tr>
<td>
<input type="checkbox" name="system.worn" {{checked system.worn}}/>
</td>
<td>
<input name="system.quantity" type="text" value="{{system.quantity}}" data-dtype="Number"/>
</td>