Weapon attack management

This commit is contained in:
LeRatierBretonnien 2025-01-18 18:14:52 +01:00
parent 729b7882b8
commit b47adc936d
18 changed files with 407 additions and 148 deletions

View File

@ -125,6 +125,25 @@ rmfrp.skill_designations = {
Restricted: "Restricted"
};
rmfrp.fumble_table = {
rmfrp.armor_values = {
"1": "1",
"2": "2",
"3": "3",
"4": "4",
"5": "5",
"6": "6",
"7": "7",
"8": "8",
"9": "9",
"10": "10",
"11": "11",
"12": "12",
"13": "13",
"14": "14",
"15": "15",
"16": "16",
"17": "17",
"18": "18",
"19": "19",
"20": "20"
}

View File

@ -1,122 +1,108 @@
export const RMFRP_FUMBLES = {
fumble_non_weapon: [
{
"Score": "01-25",
"MA STRIKES": "Target is VERY fast. Lose the opportunity to attack.",
"MA Sweeps": "Your grip on foe's arm is tenuous at best. Try again next round.",
"score": "01-25",
"ma-strikes": "Target is VERY fast. Lose the opportunity to attack.",
"ma-sweeps": "Your grip on foe's arm is tenuous at best. Try again next round.",
"brawling": "You stop for a breather. Try again next round.",
"animal": "Your foe's defenses seem more formidable. Try again next round."
},
{
"Score": "26-30",
"MA STRIKES": "Stumble on your own two feet. Take the rest of the round to regain balance.",
"MA Sweeps": "Your attack is weak and off-balanced. Spend the remainder of the round recovering.",
"score": "26-30",
"ma-strikes": "Stumble on your own two feet. Take the rest of the round to regain balance.",
"ma-sweeps": "Your attack is weak and off-balanced. Spend the remainder of the round recovering.",
"brawling": "You are distracted by that rather attractive person over there. Lose your opportunity to attack.",
"animal": "His sudden movement surprised you. You lose the opportunity to attack."
},
{
"Score": "31-40",
"MA STRIKES": "You thought you knew what you were doing. Spend the remainder of the round remembering how to do that move.",
"MA Sweeps": "You stub your toe during delivery. You fail to connect and spend the remainder of this round stunned.",
"score": "31-40",
"ma-strikes": "You thought you knew what you were doing. Spend the remainder of the round remembering how to do that move.",
"ma-sweeps": "You stub your toe during delivery. You fail to connect and spend the remainder of this round stunned.",
"brawling": "The object you were holding is suddenly shattered! You are stunned for the remainder of this round.",
"animal": "You attack too quickly, coming away with only cloth. You are stunned the remainder of the round."
},
{
"Score": "41-50",
"MA STRIKES": "Overextend yourself. Spend next round parrying while your muscles recover.",
"MA Sweeps": "You lose your balance during the throw. You must parry for two rounds while you recover.",
"score": "41-50",
"ma-strikes": "Overextend yourself. Spend next round parrying while your muscles recover.",
"ma-sweeps": "You lose your balance during the throw. You must parry for two rounds while you recover.",
"brawling": "You duck just in time! Spend the next round parrying while you find a new opening.",
"animal": "You realize that this foe may be too much. You must attack a different foe next round."
},
{
"Score": "51-60",
"MA STRIKES": "In the flurry, you have forgotten your best moves. May only make Strike I attacks for two rounds.",
"MA Sweeps": "Ill-timed sweep results in your attempt to trip the ground. This stuns you for two rounds.",
"score": "51-60",
"ma-strikes": "In the flurry, you have forgotten your best moves. May only make Strike I attacks for two rounds.",
"ma-sweeps": "Ill-timed sweep results in your attempt to trip the ground. This stuns you for two rounds.",
"brawling": "There was a chair here a minute ago! You may only make Small attacks for the next two rounds.",
"animal": "You must change opponents next round. In addition, you can only make Small attacks for two rounds."
},
{
"Score": "61-65",
"MA STRIKES": "Mistake in attack causes awkward position and slight muscle spasms. You must parry for two rounds.",
"MA Sweeps": "Foe's deft move leaves you trying to throw the air. You must parry for two rounds while looking for the right opening.",
"score": "61-65",
"ma-strikes": "Mistake in attack causes awkward position and slight muscle spasms. You must parry for two rounds.",
"ma-sweeps": "Foe's deft move leaves you trying to throw the air. You must parry for two rounds while looking for the right opening.",
"brawling": "Your attack misses widely. You nearly trip yourself and stagger. You must parry for two rounds while you recover.",
"animal": "You are confused. All attacks for the next three rounds are at half offense while you orient."
},
{
"Score": 66,
"MA STRIKES": "What were you thinking! You strike the nearest solid object that isn't your opponent. Give yourself an 'A' Krush critical.",
"MA Sweeps": "Acrobatic move leaves you flat on your back! Take an 'A' Krush critical.",
"score": 66,
"ma-strikes": "What were you thinking! You strike the nearest solid object that isn't your opponent. Give yourself an 'A' Krush critical.",
"ma-sweeps": "Acrobatic move leaves you flat on your back! Take an 'A' Krush critical.",
"brawling": "Someone blindsides you just as you were about to strike! Take an 'A' Brawling critical.",
"animal": "The wind changes and you smell food! You must disengage and seek out an easier source of food!"
},
{
"Score": "67-70",
"MA STRIKES": "Bad positioning. You must parry for two rounds while you recover.",
"MA Sweeps": "Foe is just too powerful! You contemplate your last last lesson while parrying for the next two rounds.",
"score": "67-70",
"ma-strikes": "Bad positioning. You must parry for two rounds while you recover.",
"ma-sweeps": "Foe is just too powerful! You contemplate your last last lesson while parrying for the next two rounds.",
"brawling": "You catch a chair that someone threw. You can only parry for two rounds while you get unentangled from the furniture.",
"animal": "You are distracted by a fly that keeps buzzing your head. You can only use half your normal attack ability for two rounds."
},
{
"Score": "71-80",
"MA STRIKES": "Attempt at an advanced technique stuns you for the remainder of the round and next round.",
"MA Sweeps": "Foe easily avoids your clumsy sweep. You are out of position and are stunned and unable to parry for one round.",
"score": "71-80",
"ma-strikes": "Attempt at an advanced technique stuns you for the remainder of the round and next round.",
"ma-sweeps": "Foe easily avoids your clumsy sweep. You are out of position and are stunned and unable to parry for one round.",
"brawling": "Your pugilistic attempts are humorous. You are stunned for two rounds as you punch that post when your foe ducks.",
"animal": "That shiney piece of metal keeps distracting you. You suffer a -50 for two rounds."
},
{
"Score": "81-85",
"MA STRIKES": "Your knee connects with foe's solid bone, causing an interesting sensation. You are stunned for one round and unable to parry for two rounds.",
"MA Sweeps": "You've suddenly forgotten the follow though move on that throw. You lose three rounds of action while trying to remember it.",
"score": "81-85",
"ma-strikes": "Your knee connects with foe's solid bone, causing an interesting sensation. You are stunned for one round and unable to parry for two rounds.",
"ma-sweeps": "You've suddenly forgotten the follow though move on that throw. You lose three rounds of action while trying to remember it.",
"brawling": "The crowd pushes you into the wall. You lose three rounds of action as you seek to get free of the crowd.",
"animal": "Was that your babies crying? Suffer a\n-50 for three rounds before you you discover it was that mocking bird again."
},
{
"Score": "",
"MA STRIKES": "",
"MA Sweeps": "",
"brawling": "",
"animal": ""
},
{
"Score": "86-90",
"MA STRIKES": "You \"know\" that your strike was amazing. However, foe is lucky to have blocked it. You are stunned for two rounds by his intuition.",
"MA Sweeps": "You suddenly understand what your teacher has been telling you all those years! You are stunned for two rounds. Go ahead; reminisce.",
"score": "86-90",
"ma-strikes": "You \"know\" that your strike was amazing. However, foe is lucky to have blocked it. You are stunned for two rounds by his intuition.",
"ma-sweeps": "You suddenly understand what your teacher has been telling you all those years! You are stunned for two rounds. Go ahead; reminisce.",
"brawling": "Was that someone flying overhead? You are stunned for two rounds as a large object just passed over your head.",
"animal": "You are intimidated by foe's sudden surge of strength. Perhaps this was a bad idea. Suffer a -50 for two rounds while you seek a way to disengage."
},
{
"Score": "",
"MA STRIKES": "",
"MA Sweeps": "",
"brawling": "",
"animal": ""
},
{
"Score": "91-95",
"MA STRIKES": "You twist your ankle in a recovery. You fall and manage to stun yourself in the process.",
"MA Sweeps": "Your \"graceful\" sweep results in your own fall. You are stunned for two rounds, though you quickly jump to your feet.",
"score": "91-95",
"ma-strikes": "You twist your ankle in a recovery. You fall and manage to stun yourself in the process.",
"ma-sweeps": "Your \"graceful\" sweep results in your own fall. You are stunned for two rounds, though you quickly jump to your feet.",
"brawling": "You slip on a wet spot on the floor. You go down hard. You are stunned for two rounds while you crawl for cover.",
"animal": "Your unexected jump surprised not only your foe, but also yourself. You land wrong. Take an 'A' Krush critical."
},
{
"Score": "96-99",
"MA STRIKES": "In the excitement, you try to make your two feet be in three places at once. You fall, stunning yourself for three rounds. You are unable to parry for two rounds.",
"MA Sweeps": "Your indecision causes you to attempt two different throws at once. You are stunned and unable to parry for three rounds. Quick thinking!",
"score": "96-99",
"ma-strikes": "In the excitement, you try to make your two feet be in three places at once. You fall, stunning yourself for three rounds. You are unable to parry for two rounds.",
"ma-sweeps": "Your indecision causes you to attempt two different throws at once. You are stunned and unable to parry for three rounds. Quick thinking!",
"brawling": "As you duck a blow, you lose your footing. You fall down, stunned for three rounds and unable to parry for two.",
"animal": "You duck to one side to avoid foe's attack. Unfortunately, you get tangled up in the underbrush. You suffer a -50 to all actions for three rounds."
},
{
"Score": 100,
"MA STRIKES": "You forget even the most basic of moves. You throw yourself at your opponent, giving yourself a 'B' Krush critical.",
"MA Sweeps": "Awkward sweep results in you going down and slamming your head. You are stunned and unable to parry for 6 rounds.",
"score": 100,
"ma-strikes": "You forget even the most basic of moves. You throw yourself at your opponent, giving yourself a 'B' Krush critical.",
"ma-sweeps": "Awkward sweep results in you going down and slamming your head. You are stunned and unable to parry for 6 rounds.",
"brawling": "Someone unexpectedly slams into your back. You hit your head on a table as you fall. You are stunned and unable to parry for 6 rounds.",
"animal": "Run away! You must turn tail and run. Survival instincts say its time to leave the scene. Foe gets an attack at your back as you leave."
}
],
"fumble_weapon": [
fumble_weapon: [
{
"Score": "01-25",
"One-handed": "Your palm is sweaty. Maybe you will improve.",
"score": "01-25",
"one-handed": "Your palm is sweaty. Maybe you will improve.",
"two-handed": "My that weapon is heavy! You lose the opportunity to take a swing.",
"polearms": "You snag your own clothes and lose the opportunity to take a swing.",
"mounted": "Your mount's tack tangles your weapon. You lose the opportunity to take a strike.",
@ -124,8 +110,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Sweat trickles into your eye. You elect not to attack. Good choice."
},
{
"Score": "26-30",
"One-handed": "Klutzy. Drop your weapon. Spend two rounds recovering it; or draw a new one next round.",
"score": "26-30",
"one-handed": "Klutzy. Drop your weapon. Spend two rounds recovering it; or draw a new one next round.",
"two-handed": "Your weapon flies. Take four rounds to recover it; or draw a new one next round.",
"polearms": "Fumble your delivery and your weapon is out of position. You lose the option to attack.",
"mounted": "Can't find the right angle. You lose 2 rounds of attack (but can still parry).",
@ -133,8 +119,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your ten thumbs just cannot handle loading. You must reload your weapon."
},
{
"Score": "31-40",
"One-handed": "Your feet get tangled. You miss the opportunity to get in that vital blow.",
"score": "31-40",
"one-handed": "Your feet get tangled. You miss the opportunity to get in that vital blow.",
"two-handed": "Your mind is wandering. Spend the rest of the round clearing your head.",
"polearms": "You just look clumsy. Your feet are sliding. You are stunned for one round.",
"mounted": "You slip in the saddle. You lose 2 rounds of attack (but can still parry).",
@ -142,8 +128,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your ammunition slips away. You must reload."
},
{
"Score": "31-40",
"One-handed": "You are over-extended and strain a muscle. Take 1d5 hits.",
"score": "31-40",
"one-handed": "You are over-extended and strain a muscle. Take 1d5 hits.",
"two-handed": "Stumble over an imaginary dead turtle. You lose 2 rounds of attack, but you can still parry.",
"polearms": "Your weapon is spinning for two rounds. You can still parry at -10.",
"mounted": "Your mount dodges an unseen foe. You are stunned for 2 rounds.",
@ -151,8 +137,8 @@ export const RMFRP_FUMBLES = {
"Missile": "You notice that your ammunition is faulty. After removing it you discover you were wrong. Reload it."
},
{
"Score": "51-60",
"One-handed": "You try to impress your opponent with a spin manuever. Too bad. Lose two rounds while you recover.",
"score": "51-60",
"one-handed": "You try to impress your opponent with a spin manuever. Too bad. Lose two rounds while you recover.",
"two-handed": "Your combination of acrobatics and attacks is unimpressive. Lose two rounds of attacks, but you can still parry.",
"polearms": "You stagger into a nearby fixed object. You are stunned and unable to parry for two rounds.",
"mounted": "You lose your grip on your weapon. Luckily, it is tangled in your mount's tack. Your lack of grace stuns you for three rounds.",
@ -160,8 +146,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your ammunition keeps jumping off of your weapon! Try melee next time."
},
{
"Score": "61-65",
"One-handed": "You snag your clothes with your weapon, causing it to slip from your hand. Spend two rounds juggling it.",
"score": "61-65",
"one-handed": "You snag your clothes with your weapon, causing it to slip from your hand. Spend two rounds juggling it.",
"two-handed": "Your weapon flies from your hands, but you are able to catch it before it flies totally away. Lose two rounds of attack.",
"polearms": "Your shaft tangles in your legs. You almost fall down in an impressive feat of entangling. Your next attack is at -20.",
"mounted": "Your poor mount stumbles. You are stunned for two rounds.",
@ -169,8 +155,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your weapon slips from your hands. Spend two rounds recovering it; or draw a new weapon."
},
{
"Score": 67,
"One-handed": "You execute a perfect attack—against closest ally (yourself if no one else is around). Ally takes 1d10 hits and a 'B' critical.",
"score": 67,
"one-handed": "You execute a perfect attack—against closest ally (yourself if no one else is around). Ally takes 1d10 hits and a 'B' critical.",
"two-handed": "Acrobatic manuever leaves you flat on your back. Take 2d10 hits and an 'E' Krush critical.",
"polearms": "Your weapon must check for breakage as you slam it into the ground! You are stunned for six rounds because of the impact.",
"mounted": "Your swing slices the tack of your mount. You and your saddle take your leave of the poor beast. Take an 'A' Krush critical.",
@ -178,8 +164,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Take an 'A' Krush critical from the sudden release. Your weapon snaps cleanly into two pieces."
},
{
"Score": "67-70",
"One-handed": "You trip over that uneven surface. Spend two rounds staggering. You can still parry.",
"score": "67-70",
"one-handed": "You trip over that uneven surface. Spend two rounds staggering. You can still parry.",
"two-handed": "You gracefully drop your weapon to the ground. You are able to kick it back into your hand, but you lose two rounds while doing it.",
"polearms": "Your weapon seems to have a mind of it's own! Your next attack is at -50 as your try and get it under control.",
"mounted": "Your tack has loosened! You suddenly slip sideways. You are stunned for two rounds.",
@ -187,8 +173,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your grip fails you and your weapon flies from your hands. Spend two rounds recovering it; or draw a new weapon."
},
{
"Score": "71-80",
"One-handed": "You are distracted by that pixie in the corner. You lose 2 rounds of attacks.",
"score": "71-80",
"one-handed": "You are distracted by that pixie in the corner. You lose 2 rounds of attacks.",
"two-handed": "You strain your shoulders in a mighty swing (that misses). You are stunned for two rounds.",
"polearms": "Your ineptitude is obvious to all. You lose 3 rounds of attacks and are stunned for 2 rounds.",
"mounted": "Your weapon goes straight into the ground (check for breakage).",
@ -196,8 +182,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your bowstring breaks! Draw a new weapon or put a new string on this one."
},
{
"Score": "81-85",
"One-handed": "You are suddenly very winded. Take two rounds to relax.",
"score": "81-85",
"one-handed": "You are suddenly very winded. Take two rounds to relax.",
"two-handed": "You lose your grip as you begin your swing. Your weapon is trying to slip away. Spend three rounds gaining control. You can still parry.",
"polearms": "Clumsy move narrowly misses your own head. You misses your own head. You are stunned and unable to parry for three rounds (try a bow next time).",
"mounted": "Your weapon flies out of your hand! Draw a new one.",
@ -205,8 +191,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your weapon bites back when you fire. Your shot misses everything, but you are stunned and unable to parry for three rounds."
},
{
"Score": "86-90",
"One-handed": "Hopefully, you will learn that dancing is not appropriate in combat. Your are stunned for two rounds by your lack of ability.",
"score": "86-90",
"one-handed": "Hopefully, you will learn that dancing is not appropriate in combat. Your are stunned for two rounds by your lack of ability.",
"two-handed": "You pulled something on that last swing and now it begins to hurt! You are stunned for three rounds while you recover.",
"polearms": "There it goes! Your weapon skitters away. Take six rounds to recover it; or draw a new one.",
"mounted": "Your weapon must check for breakage as it hits the hardest part of your foe. You take 2d10 hits from the blast.",
@ -214,8 +200,8 @@ export const RMFRP_FUMBLES = {
"Missile": "You release too soon! Your arrow falls 3d10 feet short of the target. In addition, you spend two rounds trying to finds more ammunition."
},
{
"Score": "91-95",
"One-handed": "You fall down as your swing goes wide. You are stunned for three rounds.",
"score": "91-95",
"one-handed": "You fall down as your swing goes wide. You are stunned for three rounds.",
"two-handed": "You fall and narrowly miss gutting yourself! You are stunned for four rounds.",
"polearms": "You fall and smack your head on the ground. You are down for four rounds and stunned for three.",
"mounted": "Your mount bucks unexpectedly just as you were about to swing. You find yourself stunned and unable to parry for three rounds.",
@ -223,8 +209,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your shot goes astray as you slip and fall during your release. You are stunned for six rounds and unable to parry for two rounds."
},
{
"Score": "96-99",
"One-handed": "The excitement is just too much! Your momentary frenzy leaves you stunned and unable to parry for three rounds.",
"score": "96-99",
"one-handed": "The excitement is just too much! Your momentary frenzy leaves you stunned and unable to parry for three rounds.",
"two-handed": "You trip and fall. You are down for four rounds and unable to parry for three.",
"polearms": "Your shoulder doesn't bend that way! You are stunned and unable to parry for three rounds. You now fight at -25.",
"mounted": "Your mount jumps wildly. You take 4d10 hits from the impact and are stunned and unable to parry for six rounds.",
@ -232,8 +218,8 @@ export const RMFRP_FUMBLES = {
"Missile": "Your weapon shatters (as you don't realize your own strength)! You are stunned for 4 rounds."
},
{
"Score": 100,
"One-handed": "You attempt to maim yourself. Take a 'D' critical.",
"score": 100,
"one-handed": "You attempt to maim yourself. Take a 'D' critical.",
"two-handed": "Worst move seen in ages! You are out for 2 days with a groin injury. There is a 50% chance your foes will be out for 3 rounds, laughing.",
"polearms": "Your weapon breaks and one end hits you in the head. You are stunned and unable to parry for six rounds.",
"mounted": "You can't stay on your mount! You fall and take a 'D' crush critical.",

View File

@ -16,8 +16,7 @@ export class RMFRPProcessTable {
let minKey = "";
let max = Number.MIN_SAFE_INTEGER;
let maxKey = "";
for (let resultData of tableData) {
let element = resultData["result"];
for (let element of tableData) {
if (Number(element.result)) {
let value = Number(element.result)
if (value > max) {
@ -27,7 +26,8 @@ export class RMFRPProcessTable {
if (value < min) {
min = value
minKey = element.result
} else {
}
} else if (element.result && element.result.includes("-")) {
let range = element.result.split("-");
if (Number(range[0]) > max) {
max = Number(range[0])
@ -37,9 +37,11 @@ export class RMFRPProcessTable {
min = Number(range[1])
minKey = element.result
}
} else {
console.error(`Element is not a number or a range`, element)
}
}
}
this.rmfrpTablesDef[table] = {
key: table,
name: RMFRPUtility.capitalizeFirstLetters(table.replace(/_/g, " ")),
@ -61,34 +63,42 @@ export class RMFRPProcessTable {
getAttackRollResult(tableKey, roll, armorValue) {
roll = Number(roll);
if (isNaN(roll)) {
console.error(`Roll ${roll} is not a number`)
return undefined;
}
let table = this.rmfrpTables[tableKey]
let tableDef = this.rmfrpTablesDef[tableKey]
let tableDef = this.rmfrpTablesDef.find(t => t.key == tableKey)
if (!table || !tableDef) {
console.error(`Table ${tableKey} not found`)
return undefined;
}
// Check min and max values
if (roll < tableDef.min) {
// return the min value
return table.find((element) => {
let elem = element.result == tableDef.minKey;
let elem = table.find((element) => element.result == tableDef.minKey);
if (elem) {
return elem[String(armorValue)];
});
} else {
console.error(`Element ${tableDef.minKey} not found in table ${tableKey}`)
}
}
if (roll > tableDef.max) {
// return the min value
return table.find((element) => {
let elem = element.result == tableDef.maxKey;
// return the max value
let elem = table.find((element) => element.result == tableDef.maxKey);
if (elem) {
return elem[String(armorValue)];
});
} else {
console.error(`Element ${tableDef.maxKey} not found in table ${tableKey}`)
}
}
return table.find((element) => {
if (Number(element.result) && Number(element.result) == Number(roll)) {
if (Number(element.result) ) {
if ( Number(element.result) == Number(roll) ) {
return element[String(armorValue)];
} else {
}
} else if (element.result && element.result.includes("-")) {
// Split the result into a range
let range = element.result.split("-");
if (Number(roll) >= Number(range[0]) && Number(roll) <= Number(range[1])) {
@ -98,6 +108,30 @@ export class RMFRPProcessTable {
});
}
buildFumbleNonWeaponChoices() {
let nonWeapon = CONFIG.rmfrp.fumbles.fumble_non_weapon[0]
let fumblesChoice = []
for (let key in nonWeapon) {
if (key === "score") {
continue;
}
fumblesChoice.push({ key: key, name: RMFRPUtility.capitalizeFirstLetters(key) })
}
return fumblesChoice
}
buildFumbleWeaponChoices() {
let weapon = CONFIG.rmfrp.fumbles.fumble_weapon[0]
let fumblesChoice = []
for (let key in weapon) {
if (key === "score") {
continue;
}
fumblesChoice.push({ key: key, name: RMFRPUtility.capitalizeFirstLetters(key) })
}
return fumblesChoice
}
getFumbleDef() {
let fumbles = []
for (let key in CONFIG.rmfrp.fumbles) {
@ -114,4 +148,58 @@ export class RMFRPProcessTable {
return criticals
}
async getFumbleRollResult(fumble_table, fumble_column) {
let table = CONFIG.rmfrp.fumbles[fumble_table]
if (!table) {
ui.notifications.error("Fumble table not found: " + fumble_table);
console.error(`Fumble table ${fumble_table} not found`)
return undefined;
}
let roll = new Roll("1d100")
await roll.evaluate()
let score = roll.total
// Search the result
for (let fumbleDef of table) {
if (Number(fumbleDef.score) ) {
if (Number(fumbleDef.score) == score) {
return fumbleDef[fumble_column]
}
} else {
// Score is XX-YY so split it to get the range values
let range = fumbleDef.score.split("-")
if (Number(range[0]) <= score && score <= Number(range[1])) {
return fumbleDef[fumble_column]
}
}
}
return null
}
async getCriticalResult(tableKey, criticalKey) {
let table = CONFIG.rmfrp.criticals[tableKey]
if (!table) {
console.error(`Critical table ${tableKey} not found`)
return undefined;
}
let roll = new Roll("1d100")
await roll.evaluate()
let score = roll.total
console.log("Critical Roll: ", score)
// Search the result
for (let criticalDef of table.criticals) {
if (Number(criticalDef.score) ) {
if (Number(criticalDef.score) == score) {
return criticalDef.levels[criticalKey.toUpperCase()]
}
} else {
// Score is XX-YY so split it to get the range values
let range = criticalDef.score.split("-")
if (Number(range[0]) <= score && score <= Number(range[1])) {
return criticalDef.levels[criticalKey.toUpperCase()]
}
}
}
return null
}
}

View File

@ -1,5 +1,6 @@
export default class RMFRPToolsDiceRoller extends FormApplication {
constructor(item, actor) {
super();
this.item = foundry.utils.duplicate(item);
@ -13,6 +14,18 @@ export default class RMFRPToolsDiceRoller extends FormApplication {
{ value: "high_open_ended", text: "High Open-Ended", selected: false },
{ value: "low_open_ended", text: "Low Open-Ended", selected: false }
];
// Process weapon case
if (this.item.type == "skill" && this.item.system.category.includes("Weapon")) {
let weapon = this.actor.items.find(i => i.type == "weapon" && this.item._id == i.system.skill);
if ( !weapon ) {
ui.notifications.error("Weapon not found for skill: " + this.item.name);
return
}
this.weapon = weapon
this.characterBonus += Number(weapon.system.weapon_bonus);
}
}
static get defaultOptions() {
@ -27,12 +40,15 @@ export default class RMFRPToolsDiceRoller extends FormApplication {
}
getData() {
// Send data to the template
return {
itemName: this.itemName,
characterBonus: this.characterBonus,
selectOptions: this.rollType,
woundsModifier: this.actor.system.modifiers.woundsModifier,
weapon: this?.weapon,
targetArmorClass: 1,
config: CONFIG.rmfrp,
difficulty: 0,
combatSituation: 0,
@ -87,9 +103,11 @@ export default class RMFRPToolsDiceRoller extends FormApplication {
let rollType = this.rollType.find(r => r.value == rollKey)?.text;
let rollData = {
name: this.itemName,
weapon: this?.weapon,
rollKey: rollKey,
rollType: rollType,
difficulty: Number(formData.difficulty),
targetArmorClass: Number(formData?.targetArmorClass || 1),
combatSituation: Number(formData?.combatSituation || 0),
lightningModifier: Number(formData?.lightningModifier || 0),
darknessModifier: Number(formData?.darknessModifier || 0),
@ -143,15 +161,61 @@ export default class RMFRPToolsDiceRoller extends FormApplication {
Number(this.characterBonus);
console.log(">>> Roll Data: ", rollData);
// Manage weapon table
if (this.weapon) {
let hasFumble = false
if ( rollData.totalRolls <= this.weapon.system.fumble_value ) {
hasFumble = true
}
let attackResult = game.rmfrp.attackTables.getAttackRollResult(this.weapon.system.attack_table, rollData.totalFinal, rollData.targetArmorClass)
if ( !attackResult) {
ui.notifications.error("Attack table not found: " + this.weapon.system.attack_table);
return
}
if (typeof attackResult == "object") { // Why ?????
attackResult = attackResult[String(rollData.targetArmorClass)];
}
console.log("Attack Result: ", attackResult);
rollData.attackResult = attackResult;
// Is it a a critical ?
let critical = attackResult.match(/(\d+)(\w)?(\w)?/);
if (critical && critical[2]) {
if ( critical[2] === "F") {
hasFumble = true
} else {
let criticalTable = this.weapon.system.critical_table
if ( !criticalTable ) {
ui.notifications.error("Critical table not found for weapon: " + this.weapon.name);
return
}
let criticalResult = await game.rmfrp.attackTables.getCriticalResult(criticalTable, critical[2]);
rollData.criticalResult = criticalResult;
console.log("Critical Result: ", criticalResult);
}
}
if (hasFumble) {
let fumbleResult = await game.rmfrp.attackTables.getFumbleRollResult(this.weapon.system.fumble_table, this.weapon.system.fumble_column)
if ( !fumbleResult) {
ui.notifications.error("Fumble table not found: " + this.weapon.system.attack_table);
return
}
rollData.fumbleResult = fumbleResult;
}
}
// Define the Chat Message Template
let chatTemplate = "systems/fvtt-rolemaster-frp/templates/chat/chat_dice_roll.html";
console.log("Final rollData", rollData)
// 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,

View File

@ -32,6 +32,8 @@ export default class RMFRPWeaponSheet extends ItemSheet {
attackTables: game.rmfrp.attackTables.getTableDef(),
fumbleTables: game.rmfrp.attackTables.getFumbleDef(),
criticalTables: game.rmfrp.attackTables.getCriticalDef(),
fumblesWeapon: game.rmfrp.attackTables.buildFumbleWeaponChoices(),
fumblesNonWeapon: game.rmfrp.attackTables.buildFumbleNonWeaponChoices(),
enrichedDescription: enrichedDescription
}
console.log("Parent", this.object)

View File

@ -1 +1 @@
MANIFEST-000192
MANIFEST-000204

View File

@ -1,8 +1,8 @@
2025/01/04-18:37:04.663636 7f7cdeffd6c0 Recovering log #190
2025/01/04-18:37:04.673494 7f7cdeffd6c0 Delete type=3 #188
2025/01/04-18:37:04.673551 7f7cdeffd6c0 Delete type=0 #190
2025/01/04-20:40:34.823558 7f7cde3ff6c0 Level-0 table #195: started
2025/01/04-20:40:34.823594 7f7cde3ff6c0 Level-0 table #195: 0 bytes OK
2025/01/04-20:40:34.829971 7f7cde3ff6c0 Delete type=0 #193
2025/01/04-20:40:34.836351 7f7cde3ff6c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2025/01/04-20:40:34.848580 7f7cde3ff6c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2025/01/18-15:51:04.184298 7f3b911f96c0 Recovering log #202
2025/01/18-15:51:04.200991 7f3b911f96c0 Delete type=3 #200
2025/01/18-15:51:04.201070 7f3b911f96c0 Delete type=0 #202
2025/01/18-18:14:32.987104 7f3b8b3ff6c0 Level-0 table #207: started
2025/01/18-18:14:32.987144 7f3b8b3ff6c0 Level-0 table #207: 0 bytes OK
2025/01/18-18:14:32.993171 7f3b8b3ff6c0 Delete type=0 #205
2025/01/18-18:14:33.006820 7f3b8b3ff6c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2025/01/18-18:14:33.006858 7f3b8b3ff6c0 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/10/20-13:37:02.626902 7f6d6fe006c0 Recovering log #186
2024/10/20-13:37:02.677174 7f6d6fe006c0 Delete type=3 #184
2024/10/20-13:37:02.677257 7f6d6fe006c0 Delete type=0 #186
2024/10/20-18:19:58.494225 7f6d6d6006c0 Level-0 table #191: started
2024/10/20-18:19:58.494287 7f6d6d6006c0 Level-0 table #191: 0 bytes OK
2024/10/20-18:19:58.501124 7f6d6d6006c0 Delete type=0 #189
2024/10/20-18:19:58.515079 7f6d6d6006c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2024/10/20-18:19:58.530691 7f6d6d6006c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2025/01/18-00:13:31.909270 7f3b909f86c0 Recovering log #198
2025/01/18-00:13:31.918640 7f3b909f86c0 Delete type=3 #196
2025/01/18-00:13:31.918730 7f3b909f86c0 Delete type=0 #198
2025/01/18-00:56:43.140225 7f3b8b3ff6c0 Level-0 table #203: started
2025/01/18-00:56:43.140265 7f3b8b3ff6c0 Level-0 table #203: 0 bytes OK
2025/01/18-00:56:43.176621 7f3b8b3ff6c0 Delete type=0 #201
2025/01/18-00:56:43.215350 7f3b8b3ff6c0 Manual compaction at level-0 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)
2025/01/18-00:56:43.274615 7f3b8b3ff6c0 Manual compaction at level-1 from '!items!1HevhbCbvMonyQXe' @ 72057594037927935 : 1 .. '!items!yRIFroc5VC9Oj3qY' @ 0 : 0; will stop at (end)

View File

@ -1 +1 @@
MANIFEST-000098
MANIFEST-000110

View File

@ -1,8 +1,8 @@
2025/01/04-18:37:04.680052 7f7ce4bfa6c0 Recovering log #96
2025/01/04-18:37:04.690789 7f7ce4bfa6c0 Delete type=3 #94
2025/01/04-18:37:04.690842 7f7ce4bfa6c0 Delete type=0 #96
2025/01/04-20:40:34.830075 7f7cde3ff6c0 Level-0 table #101: started
2025/01/04-20:40:34.830104 7f7cde3ff6c0 Level-0 table #101: 0 bytes OK
2025/01/04-20:40:34.836160 7f7cde3ff6c0 Delete type=0 #99
2025/01/04-20:40:34.836362 7f7cde3ff6c0 Manual compaction at level-0 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2025/01/04-20:40:34.848596 7f7cde3ff6c0 Manual compaction at level-1 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2025/01/18-15:51:04.203957 7f3b919fa6c0 Recovering log #108
2025/01/18-15:51:04.219103 7f3b919fa6c0 Delete type=3 #106
2025/01/18-15:51:04.219174 7f3b919fa6c0 Delete type=0 #108
2025/01/18-18:14:33.000727 7f3b8b3ff6c0 Level-0 table #113: started
2025/01/18-18:14:33.000756 7f3b8b3ff6c0 Level-0 table #113: 0 bytes OK
2025/01/18-18:14:33.006724 7f3b8b3ff6c0 Delete type=0 #111
2025/01/18-18:14:33.006839 7f3b8b3ff6c0 Manual compaction at level-0 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2025/01/18-18:14:33.006865 7f3b8b3ff6c0 Manual compaction at level-1 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)

View File

@ -1,8 +1,8 @@
2024/10/20-13:37:02.691373 7f6d6e0006c0 Recovering log #92
2024/10/20-13:37:02.785568 7f6d6e0006c0 Delete type=3 #90
2024/10/20-13:37:02.785678 7f6d6e0006c0 Delete type=0 #92
2024/10/20-18:19:58.508330 7f6d6d6006c0 Level-0 table #97: started
2024/10/20-18:19:58.508379 7f6d6d6006c0 Level-0 table #97: 0 bytes OK
2024/10/20-18:19:58.514650 7f6d6d6006c0 Delete type=0 #95
2024/10/20-18:19:58.515134 7f6d6d6006c0 Manual compaction at level-0 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2024/10/20-18:19:58.530714 7f6d6d6006c0 Manual compaction at level-1 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2025/01/18-00:13:31.922156 7f3b919fa6c0 Recovering log #104
2025/01/18-00:13:31.932378 7f3b919fa6c0 Delete type=3 #102
2025/01/18-00:13:31.932448 7f3b919fa6c0 Delete type=0 #104
2025/01/18-00:56:43.176725 7f3b8b3ff6c0 Level-0 table #109: started
2025/01/18-00:56:43.176750 7f3b8b3ff6c0 Level-0 table #109: 0 bytes OK
2025/01/18-00:56:43.215224 7f3b8b3ff6c0 Delete type=0 #107
2025/01/18-00:56:43.215359 7f3b8b3ff6c0 Manual compaction at level-0 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)
2025/01/18-00:56:43.274599 7f3b8b3ff6c0 Manual compaction at level-1 from '!folders!Lr9SCthdWWHecwEI' @ 72057594037927935 : 1 .. '!items!zvdsAxlRZnL6gqms' @ 0 : 0; will stop at (end)

View File

@ -2,6 +2,13 @@
<div class="dice-result">
Rolling for : {{name}}
</div>
{{#if weapon}}
<div class="dice-result">
With Weapon : {{weapon.name}}
</div>
{{/if}}
{{#if highopen }}
<div class=dice-result>
Rolled over 95 - High Open-Ended!
@ -67,4 +74,73 @@
Total :
<h4 class="dice-total">{{totalFinal}}</h4>
</div>
{{#if attackResult}}
<div class="dice-result">
Damage result :
<h4 class="dice-total">{{attackResult}}</h4>
</div>
{{/if}}
{{#if fumbleResult}}
<div class="dice-result">
<strong>Fumble !!!: {{fumbleResult}}</strong>
</div>
{{/if}}
{{#if criticalResult}}
<div class="dice-result">
Critical {{criticalResult.key}}: {{criticalResult.description}}
</div>
{{#each criticalResult.effects as |effect|}}
{{#if effect.cannot_parry}}
<div class="dice-result">
Cannot parry
</div>
{{/if}}
{{#if effect.damage}}
<div class="dice-result">
Damage : {{effect.damage}}
</div>
{{/if}}
{{#if effect.must_parry}}
<div class="dice-result">
Must parry
</div>
{{/if}}
{{#if effect.mustparry_duration}}
<div class="dice-result">
Must parry for {{effect.mustparry_duration}} rounds
</div>
{{/if}}
{{#if effect.mustparry_value}}
<div class="dice-result">
Must parry with a value of {{effect.mustparry_value}}
</div>
{{/if}}
{{#if effect.round_bonus_duration}}
<div class="dice-result">
Bonus for {{effect.round_bonus_duration}} rounds
</div>
{{/if}}
{{#if effect.round_penalty_duration}}
<div class="dice-result">
Penalty for {{effect.round_penalty_duration}} rounds
</div>
{{/if}}
{{#if effect.stunned}}
<div class="dice-result">
Stunned
</div>
{{/if}}
{{#if effect.wounds_per_round}}
<div class="dice-result">
Wounds per round : {{effect.wounds_per_round}}
</div>
{{/if}}
</div>
{{/each}}
{{/if}}
</div>

View File

@ -86,6 +86,22 @@
<div>Misc Bonus:</div>
<div><input name="miscBonus" value="0" /></div>
</div>
{{#if weapon}}
<div class="dice-roller-item">
<div>Target armor class:</div>
<div>
<select name="targetArmorClass">
{{#select targetArmorClass}}
{{#each config.armor_values as |value key|}}
<option value="{{key}}">{{value}}</option>
{{/each}}
{{/select}}
</select>
</div>
{{/if}}
</div>
<div class="roll-button-container">
{{#each selectOptions as |option|}}
<button type="submit" class="roll-button" data-value="{{option.value}}">{{option.text}}</button>

View File

@ -88,7 +88,15 @@
{{selectOptions fumbleTables selected=system.fumble_table nameAttr="key" valueAttr="key" labelAttr="name"}}
</select>
<td>
<input class="short-input" name="system.fumble_column" type="text" value="{{system.fumble_column}}" data-dtype="String"/>
{{#if (eq system.fumble_table "fumble_non_weapon")}}
<select class="long-input" name="system.fumble_column" type="text" value="{{system.fumble_column}}" data-dtype="String">
{{selectOptions fumblesNonWeapon selected=system.fumble_column nameAttr="key" valueAttr="key" labelAttr="name"}}
</select>
{{else}}
<select class="long-input" name="system.fumble_column" type="text" value="{{system.fumble_column}}" data-dtype="String">
{{selectOptions fumblesWeapon selected=system.fumble_column nameAttr="key" valueAttr="key" labelAttr="name"}}
</select>
{{/if}}
</td>
</td>
</table>