Rework roll window

This commit is contained in:
LeRatierBretonnien 2024-07-29 09:28:42 +02:00
parent 3ba8fdd641
commit e25c51a570
21 changed files with 449 additions and 373 deletions

View File

@ -1,4 +1,5 @@
{ {
"rmss": { "rmss": {
"player_character": { "player_character": {
"name": "Name:", "name": "Name:",
@ -43,7 +44,8 @@
"equipment": "Equipment", "equipment": "Equipment",
"spells": "Spells", "spells": "Spells",
"status_record": "Status Record", "status_record": "Status Record",
"experience_points": "Experience Points" "experience_points": "Experience Points",
"background": "Background"
}, },
"pc_sheet_fixed_info": { "pc_sheet_fixed_info": {
"race": "Race:", "race": "Race:",

View File

@ -15,6 +15,11 @@
.roll-button-container { .roll-button-container {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
justify-content: flex-end; justify-content: flex-start;
}
.roll-button {
margin-top: 2px;
width: 96px;
max-width: 96px;
} }

View File

@ -1,6 +1,6 @@
export const rmss = {}; export const rmss = {};
rmss.curreny_type = { rmss.currency_type = {
mp: "rmss.curreny_type.mp", mp: "rmss.curreny_type.mp",
pp: "rmss.curreny_type.pp", pp: "rmss.curreny_type.pp",
gp: "rmss.curreny_type.gp", gp: "rmss.curreny_type.gp",
@ -9,6 +9,43 @@ rmss.curreny_type = {
cp: "rmss.curreny_type.cp" cp: "rmss.curreny_type.cp"
}; };
rmss.difficulties = {
routine: {key: "routine", label:"Routine (+30)", value: 30},
easy: {key: "easy", label:"Easy (+20)", value: 20},
light: {key: "light", label:"Light (+10)", value: 10},
medium: {key: "medium", label:"Medium (0)", value: 0},
hard: {key: "hard", label:"Hard (-10)", value: -10},
very_hard: {key: "very_hard", label:"Very Hard (-20)", value: -20},
extremely_hard: {key: "extremely_hard", label:"Extremely Hard (-30)", value: -30},
sheer_folly: {key: "sheer_folly", label:"Sheer Folly (-50)", value: -50},
absurd: {key: "absurd", label:"Absurd (-70)", value: -70},
};
rmss.combatSituations = [
{key: "none", label:"None (0)", modifier: 0},
{key: "melee", label:"Melee environment (-20)", modifier: -20},
{key: "missile", label:"Under missile fire (-10)", modifier: -10},
];
rmss.lightOrDarknessModifiers = [
{key: "none", label:"None", modifierLight: 0, modifierDark: 0},
{key: "noshadows", label:"No shadows", modifierLight: 10, modifierDark: -30},
{key: "lightshadows", label:"Light shadows", modifierLight: 5, modifierDark: -20},
{key: "mediumshadows", label:"Medium shadows", modifierLight: 0, modifierDark: 0},
{key: "heavyshadows", label:"Heavy shadows", modifierLight: -10, modifierDark: 10},
{key: "dark", label:"Darkness", modifierLight: -25, modifierDark: 30},
{key: "pitchblack", label:"Pitch black", modifierLight: -40, modifierDark: 40},
]
rmss.hitsPerRound = [
{key: "none", label:"None", modifier: 0},
{key: "one", label:"One", modifier: -5},
{key: "two", label:"Two", modifier: -10},
{key: "three", label:"Three", modifier: -20},
{key: "four", label:"Four", modifier: -25},
{key: "five", label:"Five", modifier: -30},
]
rmss.stats = { rmss.stats = {
agility: { agility: {
fullname: "Agility", fullname: "Agility",

View File

@ -40,6 +40,31 @@ export class RMSSActor extends Actor {
// Iterate through and apply Skill Category Bonuses for Skill items // Iterate through and apply Skill Category Bonuses for Skill items
this.calculateSkillBonuses(); this.calculateSkillBonuses();
this.computeWoundsMalus();
}
getStunnedModifier() {
if (this.system.state.stunned) {
return Math.min(-50 + (3*this.system.stats.self_discipline.stat_bonus), 0)
} else {
return 0;
}
}
computeWoundsMalus() {
// Compute % of wounds
let percent = 100 - (this.system.attributes.hits.current*100/this.system.attributes.hits.max);
let modifier = 0;
if (percent > 25 && percent < 50) {
modifier = -10;
} else if (percent >= 51 && percent < 75) {
modifier = -20;
} else if (percent >= 76) {
modifier = -30;
}
this.system.modifiers.woundsModifier = modifier;
console.log(`rmss | actor.js | Wounds Malus: ${this.system.modifiers.woundsModifier} ${percent}`);
} }
/** /**
@ -233,52 +258,36 @@ export class RMSSActor extends Actor {
} }
else else
{ {
let applicable_stat_bonus = 0; let applicable_stat_bonuses = [];
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 // Iterate through the applicable stats and find their full names
for (const stat in CONFIG.rmss.stats) { for (const stat in CONFIG.rmss.stats) {
// If the configured App Stat matches the one of the stats in config // If the configured App Stat matches the one of the stats in config
if (app_stat_1 === CONFIG.rmss.stats[stat].shortname) { if (app_stat_1 === CONFIG.rmss.stats[stat].shortname) {
app_stat_1_found = true; // Add the Stat Bonus to the array
// Get the Stat Bonus applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus;
} }
if (app_stat_2 === CONFIG.rmss.stats[stat].shortname) { if (app_stat_2 === CONFIG.rmss.stats[stat].shortname) {
app_stat_2_found = true; // Add the Stat Bonus to the array
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus; applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
} }
if (app_stat_3 === CONFIG.rmss.stats[stat].shortname) { if (app_stat_3 === CONFIG.rmss.stats[stat].shortname) {
app_stat_3_found = true; // Add the Stat Bonus to the array
applicable_stat_bonus = applicable_stat_bonus + this.system.stats[stat].stat_bonus; applicable_stat_bonuses.push(this.system.stats[stat].stat_bonus);
} }
} }
// Compute the total bonus for the applicable stats
if (app_stat_1_found === true && app_stat_2_found === true && app_stat_3_found === true) { let applicable_stat_bonus = 0;
for (const bonus of applicable_stat_bonuses) {
applicable_stat_bonus += bonus;
}
// Apply the update if we found stat bonuses for every applicable stat // Apply the update if we found stat bonuses for every applicable stat
if ( item.system.stat_bonus != applicable_stat_bonus ) {
item.system.stat_bonus = applicable_stat_bonus; item.system.stat_bonus = applicable_stat_bonus;
}
// Update the total in the Item // Update the total in the Item
item.calculateSkillCategoryTotalBonus(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);
}
}
} }
} }
} }

View File

@ -217,7 +217,7 @@ export default class RMSSPlayerSheet extends ActorSheet {
html.find(".item-roll").click(ev => { html.find(".item-roll").click(ev => {
const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id")); const item = this.actor.items.get(ev.currentTarget.getAttribute("data-item-id"));
new game.rmss.applications.RMSSToolsDiceRoller(item.name, item.system.total_bonus).render(true); new game.rmss.applications.RMSSToolsDiceRoller(item, this.actor).render(true);
}); });
// ------------------------------------------------------------- // -------------------------------------------------------------

View File

@ -1,27 +1,17 @@
import {
roll_one_to_onehundred,
roll_low_open_ended,
roll_high_open_ended,
roll_open_ended
} from "./rmss_dice_roller_rolls.js";
import {
getOpenEndedRollModifier,
processOpenEndedSixtySixRoll,
processOpenEndedRoll,
processHighOpenEndedRoll,
processLowOpenEndedRoll
} from "./rmss_dice_roller_processing.js";
export default class RMSSToolsDiceRoller extends FormApplication { export default class RMSSToolsDiceRoller extends FormApplication {
constructor(itemName, characterBonus) { constructor(item, actor) {
super(); super();
this.itemName = itemName; this.item = foundry.utils.duplicate(item);
this.characterBonus = characterBonus; this.actor = actor;
this.itemName = item.name;
this.characterBonus = Number(item.system.total_bonus);
this.stunnedModifier = actor.getStunnedModifier()
this.rollType = [ this.rollType = [
{value: "one_to_onehundred", text: "1-100", selected: false}, { value: "one_to_onehundred", text: "1-100", selected: false },
{value: "open_ended", text: "Open-Ended", selected: true}, { value: "open_ended", text: "Open-Ended", selected: true },
{value: "high_open_ended", text: "High Open-Ended", selected: false}, { value: "high_open_ended", text: "High Open-Ended", selected: false },
{value: "low_open_ended", text: "Low Open-Ended", selected: false} { value: "low_open_ended", text: "Low Open-Ended", selected: false }
]; ];
} }
@ -30,8 +20,8 @@ export default class RMSSToolsDiceRoller extends FormApplication {
classes: ["form"], classes: ["form"],
title: "Rolemaster Dice Roller", title: "Rolemaster Dice Roller",
popOut: true, popOut: true,
width: 380, width: 480,
height: 210, height: 440,
template: "systems/fvtt-rolemaster-frp/templates/sheets/apps/app_dice_roller.html" template: "systems/fvtt-rolemaster-frp/templates/sheets/apps/app_dice_roller.html"
}); });
} }
@ -42,6 +32,15 @@ export default class RMSSToolsDiceRoller extends FormApplication {
itemName: this.itemName, itemName: this.itemName,
characterBonus: this.characterBonus, characterBonus: this.characterBonus,
selectOptions: this.rollType, selectOptions: this.rollType,
woundsModifier: this.actor.system.modifiers.woundsModifier,
config: CONFIG.rmss,
difficulty: 0,
combatSituation: 0,
lightningModifier: 0,
darknessModifier: 0,
hitsPerRound: 0,
isStunned: this.actor.system.state.stunned,
stunnedModifier: this.stunnedModifier
}; };
} }
@ -53,33 +52,112 @@ export default class RMSSToolsDiceRoller extends FormApplication {
console.log("Rolling Dice"); console.log("Rolling Dice");
console.log(formData); console.log(formData);
console.log(event); console.log(event);
switch (formData.rollType) { this.roll(event.submitter?.dataset?.value, formData);
case "one_to_onehundred": }
this.roll_one_to_onehundred();
/* -------------------------------------------- */
async showDiceSoNice(roll, rollMode) {
if (game.modules.get("dice-so-nice")?.active) {
if (game.dice3d) {
let whisper = null;
let blind = false;
rollMode = rollMode ?? game.settings.get("core", "rollMode");
switch (rollMode) {
case "blindroll": //GM only
blind = true;
case "gmroll": //GM + rolling player
whisper = this.getUsers(user => user.isGM);
break; break;
case "open_ended": case "roll": //everybody
this.roll_open_ended(); whisper = this.getUsers(user => user.active);
break; break;
case "high_open_ended": case "selfroll":
this.roll_high_open_ended(); whisper = [game.user.id];
break;
case "low_open_ended":
this.roll_low_open_ended();
break; break;
} }
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
} }
}
}
/* -------------------------------------------- */
async roll(rollKey, formData) {
let baseRoll = await new Roll("1d100").roll();
await this.showDiceSoNice(baseRoll, game.settings.get("core", "rollMode"))
let rollType = this.rollType.find(r => r.value == rollKey)?.text;
let rollData = {
name: this.itemName,
rollKey: rollKey,
rollType: rollType,
difficulty: Number(formData.difficulty),
combatSituation: Number(formData?.combatSituation || 0),
lightningModifier: Number(formData?.lightningModifier || 0),
darknessModifier: Number(formData?.darknessModifier || 0),
characterBonus: Number(this.characterBonus),
woundsModifier: Number(this.actor.system.modifiers.woundsModifier),
hitsPerRound: Number(formData.hitsPerRound),
isStunned: this.actor.system.state.stunned,
stunnedModifier: this.stunnedModifier,
rolls: [baseRoll],
}
if (baseRoll.result == 66) {
rollData.content = "You rolled a 66!";
}
// Process the for low open ended rolls
if (rollKey === "open_ended" || rollKey === "low_open_ended") {
if (baseRoll.result < 6) {
rollData.lowopen = true
let newRoll = await new Roll("-1d100").roll();
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
rollData.rolls.push(newRoll);
while (newRoll.result > 95) {
newRoll = await new Roll("-1d100").roll();
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
rollData.rolls.push(newRoll);
}
}
}
// Process the for high open ended rolls
if (rollKey === "open_ended" || rollKey === "high_open_ended") {
if (baseRoll.result > 95) {
rollData.highopen = true
let newRoll = await new Roll("1d100").roll();
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
rollData.rolls.push(newRoll);
while (newRoll.result > 95) {
newRoll = await new Roll("1d100").roll();
await this.showDiceSoNice(newRoll, game.settings.get("core", "rollMode"))
rollData.rolls.push(newRoll);
}
}
}
// Compute total of rolls
rollData.totalRolls = rollData.rolls.reduce((acc, roll) => Number(acc) + Number(roll.result), 0);
rollData.totalFinal = rollData.totalRolls + Number(rollData.combatSituation) +
Number(rollData.lightningModifier) +
Number(rollData.darknessModifier) +
Number(this.actor.system.modifiers.woundsModifier) +
Number(formData.difficulty) +
Number(rollData.hitsPerRound) +
Number(rollData.stunnedModifier) +
Number(this.characterBonus);
console.log(">>> Roll Data: ", rollData);
// Define the Chat Message Template
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
// Pass the Data through to be used in the Chat Message
let chatData = rollData
// Render the Rolls to the Chat Window
renderTemplate(chatTemplate, chatData).then((html) => {
let chatOptions = {
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
flavor: rollType,
rollMode: game.settings.get("core", "rollMode"),
content: html,
};
ChatMessage.create(chatOptions);
});
}
} }
RMSSToolsDiceRoller.prototype.roll_one_to_onehundred = roll_one_to_onehundred;
RMSSToolsDiceRoller.prototype.roll_low_open_ended = roll_low_open_ended;
RMSSToolsDiceRoller.prototype.roll_high_open_ended = roll_high_open_ended;
RMSSToolsDiceRoller.prototype.roll_open_ended = roll_open_ended;
RMSSToolsDiceRoller.prototype.getOpenEndedRollModifier =
getOpenEndedRollModifier;
RMSSToolsDiceRoller.prototype.processOpenEndedSixtySixRoll =
processOpenEndedSixtySixRoll;
RMSSToolsDiceRoller.prototype.processOpenEndedRoll = processOpenEndedRoll;
RMSSToolsDiceRoller.prototype.processHighOpenEndedRoll =
processHighOpenEndedRoll;
RMSSToolsDiceRoller.prototype.processLowOpenEndedRoll = processLowOpenEndedRoll;

View File

@ -1,131 +0,0 @@
export async function getOpenEndedRollModifier() {
return await new Roll("1d100x>95").roll();
}
export function processOpenEndedSixtySixRoll(baseroll, rolltype) {
// Log the Roll to Chat
let chatOptions = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
rolls: [baseroll],
flavor: rolltype,
rollMode: game.settings.get("core", "rollMode"),
content: "You rolled a 66!",
};
ChatMessage.create(chatOptions);
}
export function processOpenEndedRoll(baseroll, rolltype) {
// Define the Chat Message Template
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
// Pass the Data through to be used in the Chat Message
let chatData = {
baseroll: baseroll,
total: baseroll.result,
highopen: false,
lowopen: false,
};
// Render the Rolls to the Chat Window
renderTemplate(chatTemplate, chatData).then((html) => {
let chatOptions = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
rolls: [baseroll],
flavor: rolltype,
rollMode: game.settings.get("core", "rollMode"),
content: html,
};
ChatMessage.create(chatOptions);
});
}
export async function processHighOpenEndedRoll(baseroll, rolltype) {
// Get the Base Roll followed by the High Open Ended Roll
let originalRoll = baseroll;
let openendedRoll = await this.getOpenEndedRollModifier();
// Create a rolls array for Dice So Nice integration.
let rolls = [originalRoll, openendedRoll];
// Create an Array to hold the High Open Ended Roll Results and set the total to base roll
let openendedResults = [];
let total = Number(originalRoll.result);
// Each time the High Open Ended Roll is triggered add the result to an array and add it to the total.
for (const rollResult of openendedRoll.dice[0].results) {
openendedResults.push(rollResult.result);
total = total + Number(rollResult.result);
}
// Define the Chat Message Template
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
// Pass the Data through to be used in the Chat Message
let chatData = {
baseroll: baseroll,
opeendedresults: [openendedResults],
highopen: true,
lowopen: false,
total: total,
};
// Render the Rolls to the Chat Window
renderTemplate(chatTemplate, chatData).then((html) => {
let chatOptions = {
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
rolls: rolls,
flavor: rolltype,
rollMode: game.settings.get("core", "rollMode"),
content: html,
};
ChatMessage.create(chatOptions);
});
}
export async function processLowOpenEndedRoll(baseroll, rolltype) {
// Get the Base Roll followed by the Low Open Ended Roll
let originalRoll = baseroll;
let openendedRoll = await this.getOpenEndedRollModifier();
// Create a rolls array for Dice So Nice integration.
let rolls = [originalRoll, openendedRoll];
// Create an Array to hold the Low Open Ended Roll Results and set the total to base roll
let openendedResults = [];
let total = Number(originalRoll.result);
// Each time the Low Open Ended Roll is triggered add the result to an array and subtract it from the total.
for (const rollResult of openendedRoll.dice[0].results) {
openendedResults.push(rollResult.result);
total = total - Number(rollResult.result);
}
// Define the Chat Message Template
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
// Pass the Data through to be used in the Chat Message
let chatData = {
baseroll: baseroll,
rolls: rolls,
opeendedresults: [openendedResults],
highopen: false,
lowopen: true,
total: total,
};
// Render the Rolls to the Chat Window
renderTemplate(chatTemplate, chatData).then((html) => {
let chatOptions = {
style: CONST.CHAT_MESSAGE_STYLES.ROLL,
rolls: rolls,
flavor: rolltype,
rollMode: game.settings.get("core", "rollMode"),
content: html,
};
ChatMessage.create(chatOptions);
});
}

View File

@ -1,71 +0,0 @@
export async function roll_one_to_onehundred() {
// Construct the Roll instance
let baseroll = await new Roll("1d100 + @characterBonus", {characterBonus: this.characterBonus}).roll({async: true});
let rolltype = "Roll Type: 1-100";
// Log the Roll to Chat
let chatOptions = {
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
rolls: [baseroll],
flavor: rolltype,
rollMode: game.settings.get("core", "rollMode")
};
ChatMessage.create(chatOptions);
this.close();
};
export async function roll_low_open_ended() {
// Construct the Roll instance
let baseroll = await new Roll("1d100").roll({async: true});
console.log(baseroll.result);
let rolltype = "Roll Type: Low Open-Ended";
switch (true) {
case (baseroll.result < 6):
this.processLowOpenEndedRoll(baseroll, rolltype);
break;
case (baseroll.result === 66):
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
break;
default:
this.processOpenEndedRoll(baseroll, rolltype);
}
}
export async function roll_high_open_ended() {
// Construct the Roll instance
let baseroll = await new Roll("1d100").roll({async: true});
console.log(baseroll.result);
let rolltype = "Roll Type: High Open-Ended";
switch (true) {
case (baseroll.result === 66):
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
break;
case (baseroll.result > 95):
this.processHighOpenEndedRoll(baseroll, rolltype);
break;
default:
this.processOpenEndedRoll(baseroll, rolltype);
}
}
export async function roll_open_ended() {
// Construct the Roll instance
let baseroll = await new Roll("1d100").roll({async: true});
console.log(baseroll.result);
let rolltype = "Roll Type: Open-Ended";
switch (true) {
case (baseroll.result < 6):
this.processLowOpenEndedRoll(baseroll, rolltype);
break;
case (baseroll.result === 66):
this.processOpenEndedSixtySixRoll(baseroll, rolltype);
break;
case (baseroll.result > 95):
this.processHighOpenEndedRoll(baseroll, rolltype);
break;
default:
this.processOpenEndedRoll(baseroll, rolltype);
}
}

View File

@ -1 +1 @@
MANIFEST-000010 MANIFEST-000036

View File

@ -1,8 +1,8 @@
2024/07/26-14:23:44.308792 7f70f96006c0 Recovering log #8 2024/07/28-21:56:25.081245 7f61a16006c0 Recovering log #34
2024/07/26-14:23:44.319859 7f70f96006c0 Delete type=3 #6 2024/07/28-21:56:25.092625 7f61a16006c0 Delete type=3 #32
2024/07/26-14:23:44.320012 7f70f96006c0 Delete type=0 #8 2024/07/28-21:56:25.092815 7f61a16006c0 Delete type=0 #34
2024/07/26-18:27:58.297420 7f70f3e006c0 Level-0 table #13: started 2024/07/28-21:58:38.763455 7f619e8006c0 Level-0 table #39: started
2024/07/26-18:27:58.297474 7f70f3e006c0 Level-0 table #13: 0 bytes OK 2024/07/28-21:58:38.763505 7f619e8006c0 Level-0 table #39: 0 bytes OK
2024/07/26-18:27:58.371139 7f70f3e006c0 Delete type=0 #11 2024/07/28-21:58:38.770667 7f619e8006c0 Delete type=0 #37
2024/07/26-18:27:58.497430 7f70f3e006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end) 2024/07/28-21:58:38.788630 7f619e8006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2024/07/26-18:27:58.497486 7f70f3e006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end) 2024/07/28-21:58:38.788705 7f619e8006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)

View File

@ -1,8 +1,8 @@
2024/07/26-13:01:33.184951 7f70fa0006c0 Recovering log #4 2024/07/28-20:52:49.342374 7f61a0c006c0 Recovering log #30
2024/07/26-13:01:33.276590 7f70fa0006c0 Delete type=0 #4 2024/07/28-20:52:49.352664 7f61a0c006c0 Delete type=3 #28
2024/07/26-13:01:33.276711 7f70fa0006c0 Delete type=3 #2 2024/07/28-20:52:49.352840 7f61a0c006c0 Delete type=0 #30
2024/07/26-14:15:40.712242 7f70f3e006c0 Level-0 table #9: started 2024/07/28-21:24:37.661095 7f619e8006c0 Level-0 table #35: started
2024/07/26-14:15:40.712297 7f70f3e006c0 Level-0 table #9: 0 bytes OK 2024/07/28-21:24:37.661145 7f619e8006c0 Level-0 table #35: 0 bytes OK
2024/07/26-14:15:40.750893 7f70f3e006c0 Delete type=0 #7 2024/07/28-21:24:37.667298 7f619e8006c0 Delete type=0 #33
2024/07/26-14:15:40.806643 7f70f3e006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end) 2024/07/28-21:24:37.684364 7f619e8006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2024/07/26-14:15:40.863267 7f70f3e006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end) 2024/07/28-21:24:37.684461 7f619e8006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)

Binary file not shown.

View File

@ -522,8 +522,13 @@
} }
.roll-button-container { .roll-button-container {
display: flex; display: flex;
flex-direction: column; flex-direction: row;
justify-content: flex-end; justify-content: flex-start;
}
.roll-button {
margin-top: 2px;
width: 96px;
max-width: 96px;
} }
.sheet form { .sheet form {
display: flex; display: flex;

34
rmss.js
View File

@ -52,7 +52,7 @@ async function preloadHandlebarsTemplates() {
// registerGetSceneControlButtonsHook(); // registerGetSceneControlButtonsHook();
// Hook the init function and set up our system // Hook the init function and set up our system
Hooks.once("init", function() { Hooks.once("init", function () {
console.log("rmss | Initialising Rolemaster Standard System"); console.log("rmss | Initialising Rolemaster Standard System");
// Load our custom actor and item classes // Load our custom actor and item classes
@ -74,7 +74,7 @@ Hooks.once("init", function() {
CONFIG.fontDefinitions["PragRoman"] = { CONFIG.fontDefinitions["PragRoman"] = {
editor: true, editor: true,
fonts: [ fonts: [
{urls: ["systems/fvtt-rolemaster-frp/assets/fonts/PragRoman.woff2"]} { urls: ["systems/fvtt-rolemaster-frp/assets/fonts/PragRoman.woff2"] }
] ]
}; };
@ -91,35 +91,43 @@ Hooks.once("init", function() {
console.log("rmss | Registering RMSS sheets"); console.log("rmss | Registering RMSS sheets");
// Items // Items
Items.registerSheet("fvtt-rolemaster-frp", RMSSItemSheet, {makeDefault: true, label: "rmss.entity_sheet.item", types: ["item"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSItemSheet, { makeDefault: true, label: "rmss.entity_sheet.item", types: ["item"] });
Items.registerSheet("fvtt-rolemaster-frp", RMSSArmorSheet, {makeDefault: true, label: "rmss.entity_sheet.armor", types: ["armor"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSArmorSheet, { makeDefault: true, label: "rmss.entity_sheet.armor", types: ["armor"] });
Items.registerSheet("fvtt-rolemaster-frp", RMSSTransportSheet, {makeDefault: true, label: "rmss.entity_sheet.transport", types: ["transport"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSTransportSheet, { makeDefault: true, label: "rmss.entity_sheet.transport", types: ["transport"] });
Items.registerSheet("fvtt-rolemaster-frp", RMSSWeaponSheet, {makeDefault: true, label: "rmss.entity_sheet.weapon", types: ["weapon"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSWeaponSheet, { makeDefault: true, label: "rmss.entity_sheet.weapon", types: ["weapon"] });
Items.registerSheet("fvtt-rolemaster-frp", RMSSHerbOrPoisonSheet, {makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ["herb_or_poison"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSHerbOrPoisonSheet, { makeDefault: true, label: "rmss.entity_sheet.herb_or_poison", types: ["herb_or_poison"] });
// Spells // Spells
Items.registerSheet("fvtt-rolemaster-frp", RMSSSpellSheet, {makeDefault: true, label: "rmss.entity_sheet.spell", types: ["spell"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSSpellSheet, { makeDefault: true, label: "rmss.entity_sheet.spell", types: ["spell"] });
// Skills // Skills
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillCategorySheet, {makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ["skill_category"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillCategorySheet, { makeDefault: true, label: "rmss.entity_sheet.skill_category", types: ["skill_category"] });
Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillSheet, {makeDefault: true, label: "rmss.entity_sheet.skill", types: ["skill"]}); Items.registerSheet("fvtt-rolemaster-frp", RMSSSkillSheet, { makeDefault: true, label: "rmss.entity_sheet.skill", types: ["skill"] });
// Actors // Actors
Actors.registerSheet("fvtt-rolemaster-frp", RMSSPlayerSheet, {makeDefault: true, label: "rmss.entity_sheet.player_characrer", types: ["character"]}); Actors.registerSheet("fvtt-rolemaster-frp", RMSSPlayerSheet, { makeDefault: true, label: "rmss.entity_sheet.player_characrer", types: ["character"] });
// Preload Handlebars Templates // Preload Handlebars Templates
console.log("rmss | Preloading Handlebars Templates"); console.log("rmss | Preloading Handlebars Templates");
preloadHandlebarsTemplates(); preloadHandlebarsTemplates();
// Handlebars Helpers // Handlebars Helpers
Handlebars.registerHelper("switch", function(value, options) { Handlebars.registerHelper("switch", function (value, options) {
this.switch_value = value; this.switch_value = value;
return options.fn(this); return options.fn(this);
}); });
Handlebars.registerHelper("case", function(value, options) { Handlebars.registerHelper("case", function (value, options) {
if (value === this.switch_value) { if (value === this.switch_value) {
return options.fn(this); return options.fn(this);
} }
}); });
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
}); });

View File

@ -3,7 +3,7 @@
"title": "Rolemaster FRP System", "title": "Rolemaster FRP System",
"description": "The Rolemaster FRP system for FoundryVTT.", "description": "The Rolemaster FRP system for FoundryVTT.",
"manifest": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/raw/branch/develop/system.json", "manifest": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/raw/branch/develop/system.json",
"download": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/archive/v12.0.1.zip", "download": "https://www.uberwald.me/gitea/public/fvtt-rolemaster-frp/archive/v12.0.3.zip",
"authors": [ "authors": [
{ {
"name": "Cynicide", "name": "Cynicide",
@ -14,7 +14,7 @@
"email": "" "email": ""
} }
], ],
"version": "12.0.1", "version": "12.0.3",
"compatibility": { "compatibility": {
"minimum": "12", "minimum": "12",
"verified": "12" "verified": "12"

View File

@ -222,6 +222,14 @@
}, },
"character": { "character": {
"templates": ["background", "stats", "resistance_rolls", "armor_info", "fixed_info", "race_stat_fixed_info", "role_traits", "money", "description"], "templates": ["background", "stats", "resistance_rolls", "armor_info", "fixed_info", "race_stat_fixed_info", "role_traits", "money", "description"],
"modifiers": {
"woundsModifier": 0
},
"state": {
"stunned": false,
"prone": false,
"noparry": false
},
"attributes": { "attributes": {
"level": { "level": {
"value": 1 "value": 1

View File

@ -1,28 +1,70 @@
<div class="dice-roll"> <div class="dice-roll">
<div class="dice-result"> <div class="dice-result">
Original Roll: Rolling for : {{name}}
<h4 class="dice-total" >{{ baseroll.result }}</h4>
</div> </div>
{{#if highopen }} {{#if highopen }}
<div class=dice-result> <div class=dice-result>
Rolled over 95 - High Open-Ended! Rolled over 95 - High Open-Ended!
{{#each opeendedresults as |rollresult|}}
<h4 class="dice-total" >{{ rollresult }}</h4>
{{/each}}
</div> </div>
{{/if}} {{/if}}
{{#if lowopen }} {{#if lowopen }}
<div class=dice-result> <div class=dice-result>
Rolled under 6 - Low Open-Ended! Rolled under 6 - Low Open-Ended!
{{#each opeendedresults as |rollresult|}} </div>
<h4 class="dice-total" >{{ rollresult }}</h4> {{/if}}
{{/each}}
{{#if difficulty}}
<div class=dice-result>
Difficulty : {{difficulty}}
</div>
{{/if}}
{{#if combatSituation}}
<div class=dice-result>
Combat situation : {{combatSituation}}
</div>
{{/if}}
{{#if stunnedModifier}}
<div class=dice-result>
Stunned : {{stunnedModifier}}
</div>
{{/if}}
{{#if hitsPerRound}}
<div class=dice-result>
Hits/round malus : {{hitsPerRound}}
</div>
{{/if}}
{{#if lightningModifier}}
<div class=dice-result>
Lightning modifierLight : {{lightningModifier}}
</div>
{{/if}}
{{#if darknessModifier}}
<div class=dice-result>
Darkness modifierDark : {{darknessModifier}}
</div>
{{/if}}
{{#if woundsModifier}}
<div class="dice-result">
<div>% of hits malus : {{woundsModifier}}</div>
</div> </div>
{{/if}} {{/if}}
<div class="dice-result"> <div class="dice-result">
Total: Total of d100 rolls:
<h4 class="dice-total" >{{ total }}</h4> <h4 class="dice-total">{{totalRolls}}<br>
({{#each rolls as |roll|}}{{roll.total}}{{#unless @last}}, {{/unless}}{{/each}})</h4>
</div>
<div class=dice-result>
Character Bonus : {{characterBonus}}
</div>
<div class="dice-result">
Total :
<h4 class="dice-total">{{totalFinal}}</h4>
</div> </div>
</div> </div>

View File

@ -19,6 +19,7 @@
<div class="resource-entry"> <div class="resource-entry">
{{ localize "rmss.player_character.resources.hits" }} {{ localize "rmss.player_character.resources.hits" }}
<h4><input name="system.attributes.hits.current" type="Number" value="{{system.attributes.hits.current}}"/>/<input name="system.attributes.hits.max" type="Number" value="{{system.attributes.hits.max}}"/></h4> <h4><input name="system.attributes.hits.current" type="Number" value="{{system.attributes.hits.current}}"/>/<input name="system.attributes.hits.max" type="Number" value="{{system.attributes.hits.max}}"/></h4>
<div>Wounds Modifier : {{system.modifiers.woundsModifier}}</div>
</div> </div>
<div class="resource-entry"> <div class="resource-entry">
@ -73,6 +74,7 @@
<a class="item" data-tab="Skills">{{ localize "rmss.pc_sheet_tabs.skills" }}</a> <a class="item" data-tab="Skills">{{ localize "rmss.pc_sheet_tabs.skills" }}</a>
<a class="item" data-tab="Equipment">{{ localize "rmss.pc_sheet_tabs.equipment" }}</a> <a class="item" data-tab="Equipment">{{ localize "rmss.pc_sheet_tabs.equipment" }}</a>
<a class="item" data-tab="Spells">{{ localize "rmss.pc_sheet_tabs.spells" }}</a> <a class="item" data-tab="Spells">{{ localize "rmss.pc_sheet_tabs.spells" }}</a>
<a class="item" data-tab="Background">{{ localize "rmss.pc_sheet_tabs.background" }}</a>
<a class="item" data-tab="StatusRecord">{{ localize "rmss.pc_sheet_tabs.status_record" }}</a> <a class="item" data-tab="StatusRecord">{{ localize "rmss.pc_sheet_tabs.status_record" }}</a>
<a class="item" data-tab="ExperiencePoints">{{ localize "rmss.pc_sheet_tabs.experience_points" }}</a> <a class="item" data-tab="ExperiencePoints">{{ localize "rmss.pc_sheet_tabs.experience_points" }}</a>
</nav> </nav>
@ -84,14 +86,16 @@
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fixed-info.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fixed-info.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-armor-info.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-armor-info.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-resistance.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-resistance.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-race-stat-fixed-info.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-role-traits.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-background-info.html" }}
</div> </div>
<div class="stat-container"> <div class="stat-container">
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-stats.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-stats.html" }}
<div class="favorite-container">
<span class="label-name">Stunned : </span><input type="checkbox" name="system.state.stunned" {{checked system.state.stunned}}/>
<span class="label-name">Prone : </span><input type="checkbox" name="system.state.prone" {{checked system.state.prone}}/>
</div>
<div class="favorite-container"> <div class="favorite-container">
<h2>Favorite Skills</h2> <h2>Favorite Skills</h2>
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-skills.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-fav-skills.html" }}
@ -103,8 +107,6 @@
{{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}} {{editor enrichedDescription target="system.description" button=true owner=owner editable=editable}}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
@ -140,6 +142,19 @@
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-spells.html" }} {{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-spells.html" }}
</div> </div>
</div> </div>
<div class="tab background" data-group="primary" data-tab="Background">
<div class="container">
<div class="fixed-info-container">
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-race-stat-fixed-info.html" }}
</div>
<div class="fixed-info-container">
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-role-traits.html" }}
{{> "systems/fvtt-rolemaster-frp/templates/sheets/actors/parts/actor-background-info.html" }}
</div>
</div>
</div>
</section> </section>
</form> </form>

View File

@ -2,26 +2,95 @@
<div class="dice-roller-container"> <div class="dice-roller-container">
<div class="dice-roller-options"> <div class="dice-roller-options">
<div class="dice-roller-item"> <div class="dice-roller-item">
<div>Rolling for:</div><div>{{itemName}}</div> <div>Rolling for:</div>
<div>{{itemName}}</div>
</div> </div>
<div class="dice-roller-item"> <div class="dice-roller-item">
<div>Character Bonus:</div><div>{{characterBonus}}</div> <div>Character Bonus:</div>
<div>{{characterBonus}}</div>
</div> </div>
<div class="dice-roller-item"> <div class="dice-roller-item">
<div>Misc Bonus:</div><div><input name="miscBonus" value="0" /></div> <div>Difficulty:</div>
</div>
<div class="dice-roller-item">
<div>Select Roll Type:</div>
<div> <div>
<select name="rollType" value="None" itemid="blah"> <select name="difficulty">
{{#each selectOptions as |option|}} {{selectOptions config.difficulties selected="0" valueKey="value" labelKey="label"}}
<option value="{{option.value}}" {{#if option.selected}}selected{{/if}}>{{option.text}}</option>
{{/each}}
</select> </select>
</div> </div>
</div> </div>
<div class="dice-roller-item">
<div>% of hits taken malus:</div>
<div>{{woundsModifier}}</div>
</div>
{{#if isStunned}}
<div class="dice-roller-item">
<div>Stunned:</div>
<div>{{stunnedModifier}}</div>
</div>
{{/if}}
<div class="dice-roller-item">
<div>Combat situations:</div>
<div>
<select name="combatSituation">
{{#select combatSituation}}
{{#each config.combatSituations as |situation|}}
<option value="{{situation.modifier}}">{{situation.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
<div class="dice-roller-item">
<div>Hits/round taken:</div>
<div>
<select name="hitsPerRound">
{{#select hitsPerRound}}
{{#each config.hitsPerRound as |hit|}}
<option value="{{hit.modifier}}">{{hit.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
<div class="dice-roller-item">
<div>Lightning, if required:</div>
<div>
<select name="lightningModifier">
{{#select lightningModifier}}
{{#each config.lightOrDarknessModifiers as |lightning|}}
<option value="{{lightning.modifierLight}}">{{lightning.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
<div class="dice-roller-item">
<div>Darkness, if advantageous:</div>
<div>
<select name="darknessModifier">
{{#select lightningModifier}}
{{#each config.lightOrDarknessModifiers as |darkness|}}
<option value="{{darkness.modifierDark}}">{{darkness.label}}</option>
{{/each}}
{{/select}}
</select>
</div>
</div>
<div class="dice-roller-item">
<div>Misc Bonus:</div>
<div><input name="miscBonus" value="0" /></div>
</div>
<div class="roll-button-container"> <div class="roll-button-container">
<button type="submit">Roll</button> {{#each selectOptions as |option|}}
<button type="submit" class="roll-button" data-value="{{option.value}}">{{option.text}}</button>
{{/each}}
</div>
</div> </div>
</div> </div>
</form> </form>