+
@@ -1931,7 +1946,7 @@ in the game in "Superior".
(Current ranks -, bonus -)
-
+
@@ -1978,7 +1993,7 @@ in the game in "Superior".
(Current ranks -, bonus -)
-
+
@@ -2516,6 +2531,17 @@ in the game in "Superior".
+
+ y Initiative
+
+
+
+
+
+
+
+
@@ -2648,12 +2674,10 @@ Name
-
@@ -2789,6 +2813,17 @@ Name
+
+ y Initiative
+
+
+
+
+
+
+
+
@@ -2805,15 +2840,7 @@ Name
Attacks
-
- y Initiative
-
-
-
-
-
-
+
@@ -3012,8 +3039,8 @@ Name
- F:
- RI:
+ Range Increment:
+ Fmbl
Str:
@@ -3265,6 +3292,21 @@ Name
+
y
+ Battle Styles •
+
+
+
+
+
+
+
y
+ Discipline Styles •
+
+
+
+
+
+
+
y
+ Combat Styles •
+
+
+
+
+
+
Disarm •
@@ -5573,7 +5645,7 @@ Sheet Version:
-Revision a5c921d705bc3559670ea2bb4fdd0ef28a1bbe44
+Revision b29e6a3f1b8c2c2f18a89550163ac8a31028b97d
@@ -5705,6 +5777,12 @@ const categories = [
aname: 'battleexpertise',
zerominimum: true,
skills: [
+ { display: 'Battle Styles',
+ aname: 'battlestyle',
+ category: 'battleexpertise',
+ expertise: true,
+ dynamicspecializations: 'Style',
+ },
{ display: 'Maneuvering in Armor',
aname: 'maneuveringinarmor',
category: 'battleexpertise',
@@ -5757,6 +5835,12 @@ const categories = [
category: 'bodydiscipline',
stat: 'st',
},
+ { display: 'Discipline Styles',
+ aname: 'disciplinestyle',
+ category: 'bodydiscipline',
+ expertise: true,
+ dynamicspecializations: 'Style',
+ },
]
},
{ display: 'Brawn',
@@ -5790,6 +5874,12 @@ const categories = [
category: 'combatexpertise',
expertise: true,
},
+ { display: 'Combat Styles',
+ aname: 'combatstyle',
+ category: 'combatexpertise',
+ expertise: true,
+ dynamicspecializations: 'Style',
+ },
{ display: 'Disarm',
aname: 'disarm',
category: 'combatexpertise',
@@ -8106,7 +8196,7 @@ function getSubtlePenalty(realm, type, trickery, subtle, voice, hands, enc, meta
// Voice
if (pentable[voice] < 0) {
penalty += pentable[voice];
- log += ` ${pentable[voice]}&nbs[;[${voiceNames[voice]}]`;
+ log += ` ${pentable[voice]} [${voiceNames[voice]}]`;
}
if (penalty < 0 && trickery > 0) {
@@ -8769,6 +8859,7 @@ onCheck("mancerchange:repeating_cmskill_animalhandling_specializations_cmskillra
onCheck("mancerchange:repeating_cmskill_riding_specializations_cmskillranks", changeSkillPurchase);
onCheck("mancerchange:cmskillperceptionranks", changeSkillPurchase);
onCheck("mancerchange:cmskilltrackingranks", changeSkillPurchase);
+onCheck("mancerchange:repeating_cmskill_battlestyle_specializations_cmskillranks", changeSkillPurchase);
onCheck("mancerchange:cmskillmaneuveringinarmorranks", changeSkillPurchase);
onCheck("mancerchange:cmskillmountedcombatranks", changeSkillPurchase);
onCheck("mancerchange:cmskillprotectranks", changeSkillPurchase);
@@ -8778,10 +8869,12 @@ onCheck("mancerchange:cmskilladrenaldefenseranks", changeSkillPurchase);
onCheck("mancerchange:cmskilladrenalfocusranks", changeSkillPurchase);
onCheck("mancerchange:cmskilladrenalspeedranks", changeSkillPurchase);
onCheck("mancerchange:cmskilladrenalstrengthranks", changeSkillPurchase);
+onCheck("mancerchange:repeating_cmskill_disciplinestyle_specializations_cmskillranks", changeSkillPurchase);
onCheck("mancerchange:cmskillbodydevelopmentranks", changeSkillPurchase);
onCheck("mancerchange:cmskillfortituderanks", changeSkillPurchase);
onCheck("mancerchange:cmskillweighttrainingranks", changeSkillPurchase);
onCheck("mancerchange:cmskillblindfightingranks", changeSkillPurchase);
+onCheck("mancerchange:repeating_cmskill_combatstyle_specializations_cmskillranks", changeSkillPurchase);
onCheck("mancerchange:cmskilldisarmranks", changeSkillPurchase);
onCheck("mancerchange:cmskillfootworkranks", changeSkillPurchase);
onCheck("mancerchange:cmskillmultipleattacksranks", changeSkillPurchase);
@@ -9112,6 +9205,10 @@ function levelUpStart(_) {
console.log("********** Level up start **********");
pendingInfo();
RMUCosts.reset();
+ const data = getCharmancerData();
+
+ let previous_level = parseIntDefault(data.levelup.values.current_level);
+
getAttrsPending(["level", "xp", "xplevel", "dp_misc", "dp_used_misc"], (ev) => {
// If we are at any level but 0, we get 2 free statgains.
const level = parseIntDefault(ev.level, 0);
@@ -9131,6 +9228,7 @@ function levelUpStart(_) {
/**/
const dpavil = Math.min(85, dpreceived - dpspent);
+ setAttrsPending({"current_level": level});
setCharmancerText({"dpinfo": `${dpavil} ` +
`(= Total received ${dpreceived} ` +
` (Level ${newlevel} * 60) + ` +
@@ -9166,7 +9264,6 @@ function levelUpStart(_) {
// So we need to get the profession & Costs
- const data = getCharmancerData();
dpspent = 0;
@@ -9238,6 +9335,10 @@ function levelUpStart(_) {
addPendingFunction('Talents add', () => {
const data = getCharmancerData();
+ console.log("data.level.values.current_level");
+ if (previous_level != parseIntDefault(data.levelup.values.current_level, 0)) {
+ return;
+ }
for (obj of savedtalents) {
addRepeatingSection('added_talents', 'talent', (id) => {
setCharmancerOptions(`${id}_talent`, "Category:Talent",
@@ -10274,6 +10375,7 @@ function systemRollStats(min, powerlevel) {
rollupdates.powerlevel = `Power Level reroll < ${min}`;
}
finishRoll(roll.rollId, rollupdates);
+ addPendingFunction("Rollstats updated stats", updateStatOptions);
setAttrsPending(sheetupdates);
});
}
@@ -10750,25 +10852,22 @@ onCheck("mancerfinish:newcharacter", (ev) => {
// Culture
addPendingFunction("CMFinish: Culture data", () =>{
- console.log("Set culture data");
- showChoices(["message-save-culture"]);
- const culture = cleanCompendiumName(data.race.values.culture);
+ showChoices(["message-save-culture"]);
+ const culture = cleanCompendiumName(data.race.values.culture);
- setAttrsPending({culture: culture});
+ setAttrsPending({culture: culture});
});
// Stats
addPendingFunction("CMFinish: Stat data", () => {
- console.log("Set stats");
- showChoices(["message-save-stats"]);
- const update = RMUStats.createStatsFinalize(data)
- setAttrsPending(update)
+ showChoices(["message-save-stats"]);
+ const update = RMUStats.createStatsFinalize(data)
+ setAttrsPending(update)
});
addPendingFunction("CMFinish: Stat cache", RMUSkills.updateStatCache);
// Knacks
addPendingFunction("CMFinish: Knacks", () => {
- console.log("Set Knacks and profession bonuses");
const values = data.knacks.values;
const profinfo = data.profession.data.profession;
const skills = profinfo["data-knacks"];
@@ -10786,7 +10885,6 @@ onCheck("mancerfinish:newcharacter", (ev) => {
// Culture Development
addPendingFunction("CMFinish: Culture ranks", () => {
- console.log("Saving cultural ranks");
RMUCultures.createCultureFinalize(
cleanCompendiumName(data.race.values.culture),
getCharmancerData());
@@ -10824,11 +10922,6 @@ onCheck("mancerfinish:newcharacter", (ev) => {
}
});
-
- addPendingFunction("CMFinish: Save Weapon Costs", () => {
-
- });
-
addPendingFunction("CMFinish: update all skills", RMUSkills.updateAllSkills);
addPendingFunction("CMFinish: Front page", updateFrontPage);
@@ -12779,7 +12872,6 @@ J E + C + B
let desc = sevcode + "-description";
if (attacks.knownCrits[type]) {
- console.log(attacks.knownCrits[type][index]);
// Grab all the other fields in a critical
let results = {}
const crit = attacks.knownCrits[type][index]
@@ -12797,9 +12889,9 @@ J E + C + B
return;
}
getCompendiumPage("Criticals:" + attacks.critsToName[type], (data) => {
+ // FIXME: Handle erros here
let result = JSON.parse(data.data['data-critical'])
// Save this
- console.log(result);
attacks.knownCrits[type] = result;
attacks.getCritical(severity, type, index, donefn)
});
@@ -13288,20 +13380,22 @@ J E + C + B
"|Impact|Krush|Puncture|Slash|Steam|Strikes|Subdual|Sweeps|Unbalance}]]]}}" +
"{\{degree=[[0[?{Degree|A,0|B,1|C,2|D,3|E,4}]]]}}" +
"{\{result=[[0]]}}" +
+ "{\{injurystring=[[0]]}}" +
"{\{effect=[[0]]}}";
- console.log(roll_string);
startRoll(roll_string, roll => {
const type = attacks.getDataFromRoll(roll.results.type.expression);
const degree = parseInt(attacks.getDataFromRoll(roll.results.degree.expression));
const croll = roll.results.roll.result
const index = hitLocation[croll].rollindex;
- console.log(degree, type, index);
- attacks.getCritical(degree, type, index, (desc, effect) => {
- console.log("desc", desc);
- console.log("effect", effect);
+ const loc = {}
+ loc.hitlocation = hitLocation[croll].location;
+ loc.side = (croll & 1) ? "Left" : "Right";
+ attacks.getCritical(degree, type, index, (desc, effect, critinfo) => {
+ const injurystring = injury.updateInjuryString(0, critinfo, 'attacker', loc);
finishRoll(roll.rollId, {
type: type,
degree: numericToCritCode(degree),
+ injurystring: injurystring,
result: desc,
effect: effect});
});
@@ -13611,6 +13705,37 @@ function handleBleed(currentphase, bleedlist) {
return total;
}
+/**
+ * Generic handler for the status list updates. Called once per phase.
+ *
+ * {
+ * name: "Bleed" or "Blur" // required
+ * remaining: N, *count down in phases; until deleted if not set
+ * phase: X, The phase the activity happens. If no phase we are just a count down
+ * }
+ *
+ *
+ */
+function handleStatusListUpdate(statuslist, currentphase) {
+ if (!statuslist || typeof(statuslist) != 'array') {
+ return;
+ }
+
+ // Shift current phase to 1..4
+ currentphase = (currentphase - 1) % 4 + 1;
+
+ for (let st of statuslist) {
+ if (st.remaining) {
+ // Reduce by 1
+ st.remaining --;
+ if (st.remaining == 0) {
+
+ }
+ }
+ }
+
+}
+
function roundString(phases) {
let roundstr = '';
if (phases == 0) {
@@ -13631,11 +13756,20 @@ function roundString(phases) {
return roundstr;
}
-// FIXME: for now just assuming 1AP per click
+/**
+ * Update fields based on a status.
+ *
+ * We track free actions, stuns and bleeds specially.
+ *
+ * Stuns are special as they don't cool down together - instead just
+ * the worst.
+ * FIXME: Join these into a single infrastrucure.
+ */
function doTurn() {
getAttrs(["character_name", "currentphase", "actionapperphase",
"bleedlist", "hp", "freeactionphase",
- "statusstagger", "statusstun75", "statusstun50", "statusstun25"],
+ "statusstagger", "statusstun75", "statusstun50", "statusstun25",
+ "statuslist"],
(turn) => {
console.log("End of turn updates", turn);
const apperphase = parseIntDefault(turn.actionapperphase, 1);
@@ -13645,6 +13779,11 @@ function doTurn() {
const round = Math.floor((currentphase + 3) / 4);
const name = turn.character_name;
const updates = {};
+ let statuslist = []
+ if (turn.statuslist) {
+ statuslist = JSON.parse(turn.statuslist);
+ }
+
let statusstagger = parseIntDefault(turn.statusstagger, 0);
let statusstun75 = parseIntDefault(turn.statusstun75, 0);
let statusstun50 = parseIntDefault(turn.statusstun50, 0);
@@ -13661,6 +13800,8 @@ function doTurn() {
}
}
+// handleGeneralStatus(currentphase, statuslist);
+
if (freeactionphase == currentphase) {
sendMessage(`${name} has a free action available`);
updates.aptrack_freeused = 0;
@@ -13691,7 +13832,7 @@ function doTurn() {
}
currentphase = currentphase + 1;
- }
+ } // End the per AP advance
updates.statuseffect = 0; // Default
if (statusstagger) {
diff --git a/RolemasterUnified_Official/sheet.json b/RolemasterUnified_Official/sheet.json
index f85981f5ab..e38ebf32ff 100644
--- a/RolemasterUnified_Official/sheet.json
+++ b/RolemasterUnified_Official/sheet.json
@@ -8,5 +8,5 @@
"legacy": false,
"printable": true,
"compendium": "RMU",
- "version": "1728971311"
+ "version": "1729610352"
}
diff --git a/RolemasterUnified_Official/translation.json b/RolemasterUnified_Official/translation.json
index a74dfa29ac..dc7042d088 100644
--- a/RolemasterUnified_Official/translation.json
+++ b/RolemasterUnified_Official/translation.json
@@ -36,6 +36,7 @@
"bard": "Bard",
"base": "Base",
"battleexpertise": "Battle Expertise",
+ "battlestyle": "Battle Styles",
"beak": "Beak",
"bite": "Bite",
"blacksmith": "Blacksmith",
@@ -61,6 +62,7 @@
"closed": "Closed",
"co": "Co",
"combatexpertise": "Combat Expertise",
+ "combatstyle": "Combat Styles",
"combattraining": "Combat Training",
"composition": "Composition",
"concealment": "Concealment",
@@ -83,6 +85,7 @@
"destruction": "Destruction",
"directedspell": "Directed Spell",
"disarm": "Disarm",
+ "disciplinestyle": "Discipline Styles",
"drawingpainting": "Drawing/Painting",
"druid": "Druid",
"duping": "Duping",
diff --git a/RolemasterUnified_Official/updates.md b/RolemasterUnified_Official/updates.md
index 581259d493..20f1f4370e 100644
--- a/RolemasterUnified_Official/updates.md
+++ b/RolemasterUnified_Official/updates.md
@@ -1,3 +1,15 @@
+# Next
+
+- Spells: Fix a nbs[ instead of a space
+- Less message spew during creation.
+- Less message spew during attacks.
+- Fix actions code to not break level up
+- Attacks small layout changes.
+- Heading for feats of strength
+- Move New Combat to the status block
+- move EP near level.
+- CC updates.
+
# 2024-10-15
- Start of Power Level support
@@ -10,6 +22,8 @@
- More messages when injuries are applied.
- Make checkboxes a standard size,
- NPC upload button on the front page.
+- Directly rolled crits now have injury string
+
# 2024-10-8