diff --git a/module/config.js b/module/config.js index e5c3546..7b3aa51 100644 --- a/module/config.js +++ b/module/config.js @@ -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" } diff --git a/module/rmfrp-fumble-tables.js b/module/rmfrp-fumble-tables.js index 9d90b4f..1a8ead8 100644 --- a/module/rmfrp-fumble-tables.js +++ b/module/rmfrp-fumble-tables.js @@ -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.", diff --git a/module/rmfrp-process-table.js b/module/rmfrp-process-table.js index 8a1bb03..f8eedb5 100644 --- a/module/rmfrp-process-table.js +++ b/module/rmfrp-process-table.js @@ -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,19 +26,22 @@ export class RMFRPProcessTable { if (value < min) { min = value minKey = element.result - } else { - let range = element.result.split("-"); - if (Number(range[0]) > max) { - max = Number(range[0]) - maxKey = element.result - } - if (Number(range[1]) < min) { - min = Number(range[1]) - minKey = element.result - } } + } else if (element.result && element.result.includes("-")) { + let range = element.result.split("-"); + if (Number(range[0]) > max) { + max = Number(range[0]) + maxKey = element.result + } + if (Number(range[1]) < min) { + 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)) { - return element[String(armorValue)]; - } else { + if (Number(element.result) ) { + if ( Number(element.result) == Number(roll) ) { + return element[String(armorValue)]; + } + } 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 + } + } diff --git a/module/sheets/apps/rmfrp_dice_roller.js b/module/sheets/apps/rmfrp_dice_roller.js index 0655630..cb873d5 100644 --- a/module/sheets/apps/rmfrp_dice_roller.js +++ b/module/sheets/apps/rmfrp_dice_roller.js @@ -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, diff --git a/module/sheets/items/rmfrp_weapon_sheet.js b/module/sheets/items/rmfrp_weapon_sheet.js index e11a142..2464a84 100644 --- a/module/sheets/items/rmfrp_weapon_sheet.js +++ b/module/sheets/items/rmfrp_weapon_sheet.js @@ -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) diff --git a/packs/skill_categories/000194.log b/packs/skill_categories/000206.log similarity index 100% rename from packs/skill_categories/000194.log rename to packs/skill_categories/000206.log diff --git a/packs/skill_categories/CURRENT b/packs/skill_categories/CURRENT index e84a99e..e75c8d4 100644 --- a/packs/skill_categories/CURRENT +++ b/packs/skill_categories/CURRENT @@ -1 +1 @@ -MANIFEST-000192 +MANIFEST-000204 diff --git a/packs/skill_categories/LOG b/packs/skill_categories/LOG index c000bf1..c1bc075 100644 --- a/packs/skill_categories/LOG +++ b/packs/skill_categories/LOG @@ -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) diff --git a/packs/skill_categories/LOG.old b/packs/skill_categories/LOG.old index 49af7aa..e2a1600 100644 --- a/packs/skill_categories/LOG.old +++ b/packs/skill_categories/LOG.old @@ -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) diff --git a/packs/skill_categories/MANIFEST-000192 b/packs/skill_categories/MANIFEST-000204 similarity index 72% rename from packs/skill_categories/MANIFEST-000192 rename to packs/skill_categories/MANIFEST-000204 index 4e70adc..e136670 100644 Binary files a/packs/skill_categories/MANIFEST-000192 and b/packs/skill_categories/MANIFEST-000204 differ diff --git a/packs/skills/000100.log b/packs/skills/000112.log similarity index 100% rename from packs/skills/000100.log rename to packs/skills/000112.log diff --git a/packs/skills/CURRENT b/packs/skills/CURRENT index 95395b2..a451d53 100644 --- a/packs/skills/CURRENT +++ b/packs/skills/CURRENT @@ -1 +1 @@ -MANIFEST-000098 +MANIFEST-000110 diff --git a/packs/skills/LOG b/packs/skills/LOG index 4537913..0cb3859 100644 --- a/packs/skills/LOG +++ b/packs/skills/LOG @@ -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) diff --git a/packs/skills/LOG.old b/packs/skills/LOG.old index 20e4940..7ac1779 100644 --- a/packs/skills/LOG.old +++ b/packs/skills/LOG.old @@ -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) diff --git a/packs/skills/MANIFEST-000098 b/packs/skills/MANIFEST-000110 similarity index 73% rename from packs/skills/MANIFEST-000098 rename to packs/skills/MANIFEST-000110 index 78e3b29..da7ca8d 100644 Binary files a/packs/skills/MANIFEST-000098 and b/packs/skills/MANIFEST-000110 differ diff --git a/templates/chat/chat_dice_roll.html b/templates/chat/chat_dice_roll.html index d793697..152d397 100644 --- a/templates/chat/chat_dice_roll.html +++ b/templates/chat/chat_dice_roll.html @@ -2,6 +2,13 @@
Rolling for : {{name}}
+ + {{#if weapon}} +
+ With Weapon : {{weapon.name}} +
+ {{/if}} + {{#if highopen }}
Rolled over 95 - High Open-Ended! @@ -46,7 +53,7 @@
Darkness modifierDark : {{darknessModifier}}
- {{/if}} + {{/if}} {{#if woundsModifier}}
@@ -57,7 +64,7 @@
Total of d100 rolls:

{{totalRolls}}
- ({{#each rolls as |roll|}}{{roll.total}}{{#unless @last}}, {{/unless}}{{/each}})

+ ({{#each rolls as |roll|}}{{roll.total}}{{#unless @last}}, {{/unless}}{{/each}})
Character Bonus : {{characterBonus}} @@ -67,4 +74,73 @@ Total :

{{totalFinal}}

+ + {{#if attackResult}} +
+ Damage result : +

{{attackResult}}

+
+ {{/if}} + + {{#if fumbleResult}} +
+ Fumble !!!: {{fumbleResult}} +
+ {{/if}} + + {{#if criticalResult}} +
+ Critical {{criticalResult.key}}: {{criticalResult.description}} +
+ + {{#each criticalResult.effects as |effect|}} + {{#if effect.cannot_parry}} +
+ Cannot parry +
+ {{/if}} + {{#if effect.damage}} +
+ Damage : {{effect.damage}} +
+ {{/if}} + {{#if effect.must_parry}} +
+ Must parry +
+ {{/if}} + {{#if effect.mustparry_duration}} +
+ Must parry for {{effect.mustparry_duration}} rounds +
+ {{/if}} + {{#if effect.mustparry_value}} +
+ Must parry with a value of {{effect.mustparry_value}} +
+ {{/if}} + {{#if effect.round_bonus_duration}} +
+ Bonus for {{effect.round_bonus_duration}} rounds +
+ {{/if}} + {{#if effect.round_penalty_duration}} +
+ Penalty for {{effect.round_penalty_duration}} rounds +
+ {{/if}} + {{#if effect.stunned}} +
+ Stunned +
+ {{/if}} + {{#if effect.wounds_per_round}} +
+ Wounds per round : {{effect.wounds_per_round}} +
+ {{/if}} +
+ {{/each}} + {{/if}} +
\ No newline at end of file diff --git a/templates/sheets/apps/app_dice_roller.html b/templates/sheets/apps/app_dice_roller.html index 9cbec0d..68f9dc0 100644 --- a/templates/sheets/apps/app_dice_roller.html +++ b/templates/sheets/apps/app_dice_roller.html @@ -86,6 +86,22 @@
Misc Bonus:
+ + {{#if weapon}} +
+
Target armor class:
+
+ +
+ {{/if}} +
+
{{#each selectOptions as |option|}} diff --git a/templates/sheets/items/rmfrp-weapon-sheet.html b/templates/sheets/items/rmfrp-weapon-sheet.html index d1fd1a0..e67f487 100644 --- a/templates/sheets/items/rmfrp-weapon-sheet.html +++ b/templates/sheets/items/rmfrp-weapon-sheet.html @@ -88,7 +88,15 @@ {{selectOptions fumbleTables selected=system.fumble_table nameAttr="key" valueAttr="key" labelAttr="name"}} - + {{#if (eq system.fumble_table "fumble_non_weapon")}} + + {{else}} + + {{/if}}